summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-25 15:14:41 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-25 15:14:41 +0000
commitb5ba9f3a669e68503666852be6e3158f03526733 (patch)
treeaf8828e1df0f3e051eb29c58c7d958cd177e474d /gcc
parenta85413a6ac28d432734c514cd140ee039daad06b (diff)
downloadppe42-gcc-b5ba9f3a669e68503666852be6e3158f03526733.tar.gz
ppe42-gcc-b5ba9f3a669e68503666852be6e3158f03526733.zip
* invoke.texi (-fstrict-aliasing): Document.
* rtl.texi (MEM_ALIAS_SET): Document. * flags.h (flag_strict_aliasing): Declare. * toplev.c (flag_strict_aliasing): Define. (f_options): Add -strict-aliasing. (main): Set flag_strict_aliasing if -O2 or higher. * tree.h (tree_type): Add alias_set field. (TYPE_ALIAS_SET): New macro. (TYPE_ALIAS_SET_KNOWN_P): Likewise. (get_alias_set): Declare. * tree.c (lang_get_alias_set): Define. (make_node): Initialize TYPE_ALIAS_SET. (get_alias_set): New function. * print-tree.c (print_node): Dump the alias set for a type. * c-tree.h (c_get_alias_set): Declare. * c-common.c (c_get_alias_set): New function. * c-decl.c (init_decl_processing): Set lang_get_alias_set. * expr.c (protect_from_queue): Propogage alias sets. (expand_assignment): Calculate alias set for new MEMs. (expand_expr): Likewise. * function.c (put_var_into_stack): Likewise. (put_reg_into_stack): Likewise. (gen_mem_addressof): Likewise. (assign_parms): Likewise. * stmt.c (expand_decl): Likewise. * varasm.c (make_decl_rtl): Eliminate redundant clearing of DECL_RTL. Calculate alias set for new MEMs. * rtl.def (REG): Add dummy operand. (MEM): Add extra operand to store the MEM_ALIAS_SET. * rtl.h (MEM_ALIAS_SET): New macro. (gen_rtx_MEM): Declare. * emit-rtl.c (gen_rtx_MEM): New function. * gengenrtl.c (sepcial_rtx): Make MEMs special. * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): New macro. (DIFFERENT_ALIAS_SETS_P): Likewise. (canon_rtx): Propogate the alias set to the new MEM. (true_dependence): Check the alias sets. (anti_dependence): Likewise. (output_dependence): Likewise. * explow.c (stabilize): Progoate alias sets. * integrate.c (copy_rtx_and_substitute): Likewise. * final.c (alter_subreg): Make sure not to leave MEM_IN_STRUCT_P in an unpredictable state. Propogate alias sets. * reload1.c (reload): Clear MEM_ALIAS_SET for new MEMs about which we have no alias information. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20719 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog54
-rw-r--r--gcc/alias.c32
-rw-r--r--gcc/c-common.c87
-rw-r--r--gcc/c-decl.c2
-rw-r--r--gcc/c-tree.h1
-rw-r--r--gcc/emit-rtl.c14
-rw-r--r--gcc/explow.c5
-rw-r--r--gcc/expr.c12
-rw-r--r--gcc/final.c2
-rw-r--r--gcc/flags.h6
-rw-r--r--gcc/function.c4
-rw-r--r--gcc/gengenrtl.c3
-rw-r--r--gcc/integrate.c1
-rw-r--r--gcc/invoke.texi53
-rw-r--r--gcc/print-tree.c1
-rw-r--r--gcc/reload1.c3
-rw-r--r--gcc/rtl.def22
-rw-r--r--gcc/rtl.h17
-rw-r--r--gcc/rtl.texi15
-rw-r--r--gcc/stmt.c2
-rw-r--r--gcc/toplev.c10
-rw-r--r--gcc/tree.c21
-rw-r--r--gcc/tree.h15
-rw-r--r--gcc/varasm.c5
24 files changed, 369 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7360bff192f..b9ada6d0851 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,57 @@
+Thu Jun 25 15:08:16 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * invoke.texi (-fstrict-aliasing): Document.
+ * rtl.texi (MEM_ALIAS_SET): Document.
+
+ * flags.h (flag_strict_aliasing): Declare.
+ * toplev.c (flag_strict_aliasing): Define.
+ (f_options): Add -strict-aliasing.
+ (main): Set flag_strict_aliasing if -O2 or higher.
+
+ * tree.h (tree_type): Add alias_set field.
+ (TYPE_ALIAS_SET): New macro.
+ (TYPE_ALIAS_SET_KNOWN_P): Likewise.
+ (get_alias_set): Declare.
+ * tree.c (lang_get_alias_set): Define.
+ (make_node): Initialize TYPE_ALIAS_SET.
+ (get_alias_set): New function.
+ * print-tree.c (print_node): Dump the alias set for a type.
+
+ * c-tree.h (c_get_alias_set): Declare.
+ * c-common.c (c_get_alias_set): New function.
+ * c-decl.c (init_decl_processing): Set lang_get_alias_set.
+
+ * expr.c (protect_from_queue): Propogage alias sets.
+ (expand_assignment): Calculate alias set for new MEMs.
+ (expand_expr): Likewise.
+ * function.c (put_var_into_stack): Likewise.
+ (put_reg_into_stack): Likewise.
+ (gen_mem_addressof): Likewise.
+ (assign_parms): Likewise.
+ * stmt.c (expand_decl): Likewise.
+ * varasm.c (make_decl_rtl): Eliminate redundant clearing of
+ DECL_RTL. Calculate alias set for new MEMs.
+
+ * rtl.def (REG): Add dummy operand.
+ (MEM): Add extra operand to store the MEM_ALIAS_SET.
+ * rtl.h (MEM_ALIAS_SET): New macro.
+ (gen_rtx_MEM): Declare.
+ * emit-rtl.c (gen_rtx_MEM): New function.
+ * gengenrtl.c (sepcial_rtx): Make MEMs special.
+
+ * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): New macro.
+ (DIFFERENT_ALIAS_SETS_P): Likewise.
+ (canon_rtx): Propogate the alias set to the new MEM.
+ (true_dependence): Check the alias sets.
+ (anti_dependence): Likewise.
+ (output_dependence): Likewise.
+ * explow.c (stabilize): Progoate alias sets.
+ * integrate.c (copy_rtx_and_substitute): Likewise.
+ * final.c (alter_subreg): Make sure not to leave MEM_IN_STRUCT_P
+ in an unpredictable state. Propogate alias sets.
+ * reload1.c (reload): Clear MEM_ALIAS_SET for new MEMs about which
+ we have no alias information.
+
Thu Jun 25 16:59:18 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* except.h (CATCH_ALL_TYPE): Definition moved to eh-common.h.
diff --git a/gcc/alias.c b/gcc/alias.c
index 99df4fa8ccf..ab65bc4d8ea 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -42,6 +42,28 @@ static rtx find_base_value PROTO((rtx));
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
+/* Perform a basic sanity check. Namely, that there are
+ no alias sets if we're not doing strict aliasing. This helps
+ to catch bugs whereby someone uses PUT_CODE, but doesn't clear
+ MEM_ALIAS_SET, or where a MEM is allocated in some way other
+ than by the use of gen_rtx_MEM, and the MEM_ALIAS_SET is not
+ cleared. */
+#ifdef ENABLE_CHECKING
+#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) \
+ (!flag_strict_aliasing \
+ && (MEM_ALIAS_SET (MEM1) || MEM_ALIAS_SET (MEM2)) \
+ ? (abort (), 0) : 0)
+#else
+#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) 0
+#endif
+
+/* Returns nonzero if MEM1 and MEM2 do not alias because they are in
+ different alias sets. */
+#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
+ (CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2), \
+ MEM_ALIAS_SET (MEM1) && MEM_ALIAS_SET (MEM2) \
+ && MEM_ALIAS_SET (MEM1) != MEM_ALIAS_SET (MEM2))
+
/* Cap the number of passes we make over the insns propagating alias
information through set chains.
@@ -372,6 +394,7 @@ canon_rtx (x)
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
x = new;
}
}
@@ -874,6 +897,9 @@ true_dependence (mem, mem_mode, x, varies)
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
+ if (DIFFERENT_ALIAS_SETS_P (x, mem))
+ return 0;
+
/* If X is an unchanging read, then it can't possibly conflict with any
non-unchanging store. It may conflict with an unchanging write though,
because there may be a single store to this address to initialize it.
@@ -947,6 +973,9 @@ anti_dependence (mem, x)
x = canon_rtx (x);
mem = canon_rtx (mem);
+ if (DIFFERENT_ALIAS_SETS_P (x, mem))
+ return 0;
+
x_addr = XEXP (x, 0);
mem_addr = XEXP (mem, 0);
@@ -978,6 +1007,9 @@ output_dependence (mem, x)
x = canon_rtx (x);
mem = canon_rtx (mem);
+ if (DIFFERENT_ALIAS_SETS_P (x, mem))
+ return 0;
+
return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
SIZE_FOR_MODE (x), XEXP (x, 0), 0)
&& ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 9a8d0731bdd..245fedb97be 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -2880,3 +2880,90 @@ c_build_type_variant (type, constp, volatilep)
TYPE_DOMAIN (type));
return build_type_variant (type, constp, volatilep);
}
+
+/* Return the typed-based alias set for T, which may be an expression
+ or a type. */
+
+int
+c_get_alias_set (t)
+ tree t;
+{
+ static int next_set = 0;
+ tree type;
+
+ if (t == error_mark_node)
+ return 0;
+
+ type = (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ ? t : TREE_TYPE (t);
+
+ if (type == error_mark_node)
+ return 0;
+
+ if (TYPE_ALIAS_SET_KNOWN_P (type))
+ /* If we've already calculated the value, just return it. */
+ return TYPE_ALIAS_SET (type);
+
+ if (TREE_CODE (t) == BIT_FIELD_REF)
+ /* Perhaps reads and writes to this piece of data alias fields
+ neighboring the bitfield. Perhaps that's impossible. For now,
+ let's just assume that bitfields can alias everything, which is
+ the conservative assumption. */
+ return 0;
+ if (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
+ /* Permit type-punning when accessing a union, provided the
+ access is directly through the union. For example, this code does
+ not permit taking the address of a union member and then
+ storing through it. Even the type-punning allowed here is a
+ GCC extension, albeit a common and useful one; the C standard
+ says that such accesses have implementation-defined behavior. */
+ return 0;
+ else if (TYPE_MAIN_VARIANT (type) != type)
+ {
+ /* The C standard specifically allows aliasing between
+ cv-qualified variants of types. */
+ TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
+ return TYPE_ALIAS_SET (type);
+ }
+ else if (TREE_CODE (type) == INTEGER_TYPE)
+ {
+ tree signed_variant;
+
+ /* The C standard specifically allows aliasing between signed and
+ unsigned variants of the same type. We treat the signed
+ variant as canonical. */
+ signed_variant = signed_type (type);
+
+ if (signed_variant != type)
+ {
+ TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
+ return TYPE_ALIAS_SET (type);
+ }
+ else if (signed_variant == signed_char_type_node)
+ /* The C standard guarantess that any object may be accessed
+ via an lvalue that has character type. We don't have to
+ check for unsigned_char_type_node or char_type_node because
+ we are specifically looking at the signed variant. */
+ {
+ TYPE_ALIAS_SET (type) = 0;
+ return TYPE_ALIAS_SET (type);
+ }
+ }
+ else if (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ {
+ /* If TYPE is a struct or union type then we're reading or
+ writing an entire struct. Thus, we don't know anything about
+ aliasing. (In theory, such an access can only alias objects
+ whose type is the same as one of the fields, recursively, but
+ we don't yet make any use of that information.) */
+ TYPE_ALIAS_SET (type) = 0;
+ return TYPE_ALIAS_SET (type);
+ }
+
+ /* TYPE is something we haven't seen before. Put it in a new alias
+ set. */
+ TYPE_ALIAS_SET (type) = ++next_set;
+ return TYPE_ALIAS_SET (type);
+}
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 51a18c5a0dd..15eb740b976 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -3513,6 +3513,8 @@ init_decl_processing ()
init_iterators ();
incomplete_decl_finalize_hook = finish_incomplete_decl;
+
+ lang_get_alias_set = &c_get_alias_set;
}
/* Return a definition for a builtin function named NAME and whose data type
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 6ec4f674e25..3a9f4f83b78 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -164,6 +164,7 @@ extern void declare_function_name PROTO((void));
extern void decl_attributes PROTO((tree, tree, tree));
extern void init_function_format_info PROTO((void));
extern void check_function_format PROTO((tree, tree, tree));
+extern int c_get_alias_set PROTO((tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 854b9892e2b..8f1b50188bf 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -301,6 +301,20 @@ gen_rtx_REG (mode, regno)
return gen_rtx_raw_REG (mode, regno);
}
+rtx
+gen_rtx_MEM (mode, addr)
+ enum machine_mode mode;
+ rtx addr;
+{
+ rtx rt = gen_rtx_raw_MEM (mode, addr);
+
+ /* This field is not cleared by the mere allocation of the rtx, so
+ we clear it here. */
+ MEM_ALIAS_SET (rt) = 0;
+
+ return rt;
+}
+
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
** This routine generates an RTX of the size specified by
diff --git a/gcc/explow.c b/gcc/explow.c
index 7c74d6a620f..cd50563be52 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -592,6 +592,11 @@ stabilize (x)
MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
+
+ /* Since the new MEM is just like the old X, it can alias only
+ the things that X could. */
+ MEM_ALIAS_SET (mem) = MEM_ALIAS_SET (x);
+
return mem;
}
return x;
diff --git a/gcc/expr.c b/gcc/expr.c
index 91134d393ca..bc19068afaa 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -415,6 +415,7 @@ protect_from_queue (x, modify)
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
+ MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
if (QUEUED_INSN (y))
{
@@ -3063,7 +3064,11 @@ expand_assignment (to, from, want_value, suggest_reg)
Don't re-expand if it was expanded already (in COMPONENT_REF case). */
if (to_rtx == 0)
- to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
+ {
+ to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
+ if (GET_CODE (to_rtx) == MEM)
+ MEM_ALIAS_SET (to_rtx) = get_alias_set (to);
+ }
/* Don't move directly into a return register. */
if (TREE_CODE (to) == RESULT_DECL && GET_CODE (to_rtx) == REG)
@@ -5719,6 +5724,7 @@ expand_expr (exp, target, tmode, modifier)
&& AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
MEM_IN_STRUCT_P (temp) = 1;
MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
+ MEM_ALIAS_SET (temp) = get_alias_set (exp);
/* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY
here, because, in C and C++, the fact that a location is accessed
@@ -6094,6 +6100,10 @@ expand_expr (exp, target, tmode, modifier)
op0 = change_address (op0, mode1,
plus_constant (XEXP (op0, 0),
(bitpos / BITS_PER_UNIT)));
+
+ if (GET_CODE (op0) == MEM)
+ MEM_ALIAS_SET (op0) = get_alias_set (exp);
+
if (GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), alignment);
diff --git a/gcc/final.c b/gcc/final.c
index ca6c22037d8..794bedf70b1 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3020,6 +3020,8 @@ alter_subreg (x)
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
+ MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (y);
+ MEM_ALIAS_SET (x) = MEM_ALIAS_SET (y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
}
diff --git a/gcc/flags.h b/gcc/flags.h
index 2b670054eb6..2b62325bb29 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -432,6 +432,12 @@ extern int flag_pack_struct;
The value is ignored if flag_alias_check is 0. */
extern int flag_argument_noalias;
+/* Nonzero if we should do (language-dependent) alias analysis.
+ Typically, this analysis will assume that expressions of certain
+ types do not alias expressions of certain other types. Only used
+ if alias analysis (in general) is enabled. */
+extern int flag_strict_aliasing;
+
/* Emit code to check for stack overflow; also may cause large objects
to be allocated dynamically. */
extern int flag_stack_check;
diff --git a/gcc/function.c b/gcc/function.c
index f8e3cd40667..f3d33d0cc39 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -1466,6 +1466,7 @@ put_var_into_stack (decl)
/* Change the CONCAT into a combined MEM for both parts. */
PUT_CODE (reg, MEM);
MEM_VOLATILE_P (reg) = MEM_VOLATILE_P (XEXP (reg, 0));
+ MEM_ALIAS_SET (reg) = get_alias_set (decl);
/* The two parts are in memory order already.
Use the lower parts address as ours. */
@@ -1538,6 +1539,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
case it was set for other reasons. For instance, it is set for
__builtin_va_alist. */
MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type) | MEM_IN_STRUCT_P (new);
+ MEM_ALIAS_SET (reg) = get_alias_set (type);
/* Now make sure that all refs to the variable, previously made
when it was a register, are fixed up to be valid again. */
@@ -2735,6 +2737,7 @@ gen_mem_addressof (reg, decl)
PUT_MODE (reg, DECL_MODE (decl));
MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
+ MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type));
@@ -3908,6 +3911,7 @@ assign_parms (fndecl, second_time)
is readonly. */
MEM_IN_STRUCT_P (stack_parm) = aggregate;
RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
+ MEM_ALIAS_SET (stack_parm) = get_alias_set (parm);
}
/* If this parameter was passed both in registers and in the stack,
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index a8daeae465b..ade07ff4b6c 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -129,7 +129,8 @@ special_rtx (idx)
int idx;
{
return (strcmp (defs[idx].enumname, "CONST_INT") == 0
- || strcmp (defs[idx].enumname, "REG") == 0);
+ || strcmp (defs[idx].enumname, "REG") == 0
+ || strcmp (defs[idx].enumname, "MEM") == 0);
}
static void
diff --git a/gcc/integrate.c b/gcc/integrate.c
index a7fb3d7eb8b..38a900a9768 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -2688,6 +2688,7 @@ copy_rtx_and_substitute (orig, map)
XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
+ MEM_ALIAS_SET (copy) = MEM_ALIAS_SET (orig);
/* If doing function inlining, this MEM might not be const in the
function that it is being inlined into, and thus may not be
diff --git a/gcc/invoke.texi b/gcc/invoke.texi
index 56bdfdbae47..3bc197f9b66 100644
--- a/gcc/invoke.texi
+++ b/gcc/invoke.texi
@@ -156,7 +156,7 @@ in the following sections.
-frerun-cse-after-loop -frerun-loop-opt -fschedule-insns
-fschedule-insns2 -fstrength-reduce -fthread-jumps
-funroll-all-loops -funroll-loops
--fmove-all-movables -freduce-all-givs
+-fmove-all-movables -freduce-all-givs -fstrict-aliasing
-O -O0 -O1 -O2 -O3 -Os
@end smallexample
@@ -2419,6 +2419,57 @@ Some machines only support 2 operands per instruction. On such
machines, GNU CC might have to do extra copies. The @samp{-fregmove}
option overrides the default for the machine to do the copy before
register allocation.
+
+@item -fstrict-aliasing
+Allows the compiler to assume the strictest aliasing rules applicable to
+the language being compiled. For C (and C++), this activates
+optimizations based on the type of expressions. In particular, an
+object of one type is assumed never to reside at the same address as an
+object of a different type, unless the types are almost the same. For
+example, an @code{unsigned int} can alias an @code{int}, but not a
+@code{void*} or a @code{double}. A character type may alias any other
+type.
+
+Pay special attention to code like this:
+@example
+union a_union @{
+ int i;
+ double d;
+@};
+
+int f() @{
+ a_union t;
+ t.d = 3.0;
+ return t.i;
+@}
+@end example
+The practice of reading from a different union member than the one most
+recently written to (called ``type-punning'') is common. Even with
+@samp{-fstrict-aliasing}, type-punning is allowed, provided the memory
+is accessed through the union type. So, the code above will work as
+expected. However, this code might not:
+@example
+int f() @{
+ a_union t;
+ int* ip;
+ t.d = 3.0;
+ ip = &t.i;
+ return *ip;
+@}
+@end example
+
+This option is not enabled by default at any optimization level because
+it is new and has yet to be subjected to thorough testing. You may
+of course enable it manually with @samp{-fstrict-aliasing}.
+
+@ifset INTERNALS
+Every language that wishes to perform language-specific alias analysis
+should define a function that computes, given an @code{tree}
+node, an alias set for the node. Nodes in different alias sets are not
+allowed to alias. For an example, see the C front-end function
+@code{c_get_alias_set}.
+@end ifset
+
@end table
@node Preprocessor Options
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 6674a18aa8d..6163b1ff91c 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -479,6 +479,7 @@ print_node (file, prefix, node, indent)
fprintf (file, " align %d", TYPE_ALIGN (node));
fprintf (file, " symtab %d", TYPE_SYMTAB_ADDRESS (node));
+ fprintf (file, " alias set %d", TYPE_ALIAS_SET (node));
print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 9acf695679a..9601691f9f9 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -2095,6 +2095,9 @@ reload (first, global, dumpfile)
XEXP (reg, 0) = addr;
REG_USERVAR_P (reg) = 0;
MEM_IN_STRUCT_P (reg) = in_struct;
+ /* We have no alias information about this newly created
+ MEM. */
+ MEM_ALIAS_SET (reg) = 0;
PUT_CODE (reg, MEM);
}
else if (reg_equiv_mem[i])
diff --git a/gcc/rtl.def b/gcc/rtl.def
index e219e87c042..a00d3f1d7c5 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -537,10 +537,16 @@ DEF_RTL_EXPR(CONST, "const", "e", 'o')
by a SET whose first operand is (PC). */
DEF_RTL_EXPR(PC, "pc", "", 'o')
-/* A register. The "operand" is the register number, accessed
- with the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
- than a hardware register is being referred to. */
-DEF_RTL_EXPR(REG, "reg", "i", 'o')
+/* A register. The "operand" is the register number, accessed with
+ the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
+ than a hardware register is being referred to. The second operand
+ doesn't really exist. Unfortunately, however, the compiler
+ implicitly assumes that a REG can be transformed in place into a
+ MEM, and therefore that a REG is at least as big as a MEM. To
+ avoid this memory overhead, which is likely to be substantial,
+ search for uses of PUT_CODE that turn REGs into MEMs, and fix them
+ somehow. Then, the trailing `0' can be removed here. */
+DEF_RTL_EXPR(REG, "reg", "i0", 'o')
/* A scratch register. This represents a register used only within a
single insn. It will be turned into a REG during register allocation
@@ -578,9 +584,11 @@ DEF_RTL_EXPR(STRICT_LOW_PART, "strict_low_part", "e", 'x')
in DECL_RTLs and during RTL generation, but not in the insn chain. */
DEF_RTL_EXPR(CONCAT, "concat", "ee", 'o')
-/* A memory location; operand is the address.
- Can be nested inside a VOLATILE. */
-DEF_RTL_EXPR(MEM, "mem", "e", 'o')
+/* A memory location; operand is the address. Can be nested inside a
+ VOLATILE. The second operand is the alias set to which this MEM
+ belongs. We use `0' instead of `i' for this field so that the
+ field need not be specified in machine descriptions. */
+DEF_RTL_EXPR(MEM, "mem", "e0", 'o')
/* Reference to an assembler label in the code for this function.
The operand is a CODE_LABEL found in the insn chain.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index bee83bbc0d8..af85d823738 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -561,6 +561,17 @@ extern char *note_insn_name[];
/* For a MEM rtx, 1 if it refers to a field of an aggregate. */
#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
+/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
+ set, and may alias anything. Otherwise, the MEM can only alias
+ MEMs in the same alias set. This value is set in a
+ language-dependent manner in the front-end, and should not be
+ altered in the back-end. These set numbers are tested for zero,
+ and compared for equality; they have no other significance. In
+ some front-ends, these numbers may correspond in some way to types,
+ or other language-level entities, but they need not, and the
+ back-end makes no such assumptions. */
+#define MEM_ALIAS_SET(RTX) (XINT (RTX, 1))
+
/* For a LABEL_REF, 1 means that this reference is to a label outside the
loop containing the reference. */
#define LABEL_OUTSIDE_LOOP_P(RTX) ((RTX)->in_struct)
@@ -1057,11 +1068,13 @@ extern rtx static_chain_incoming_rtx;
#include "genrtl.h"
#endif
-/* There are two RTL codes that require special attention; the generation
- functions included above do the raw handling. */
+/* There are some RTL codes that require special attention; the
+ generation functions included above do the raw handling. If you
+ add to this list, modify special_rtx in gengenrtl.c as well. */
extern rtx gen_rtx_CONST_INT PROTO((enum machine_mode, HOST_WIDE_INT));
extern rtx gen_rtx_REG PROTO((enum machine_mode, int));
+extern rtx gen_rtx_MEM PROTO((enum machine_mode, rtx));
/* We need the cast here to ensure that we get the same result both with
and without prototypes. */
diff --git a/gcc/rtl.texi b/gcc/rtl.texi
index 0127fcea456..4d5139956dc 100644
--- a/gcc/rtl.texi
+++ b/gcc/rtl.texi
@@ -287,9 +287,9 @@ to access them.
@section Flags in an RTL Expression
@cindex flags in RTL expression
-RTL expressions contain several flags (one-bit bitfields) that are used
-in certain types of expression. Most often they are accessed with the
-following macros:
+RTL expressions contain several flags (one-bit bitfields) and other
+values that are used in certain types of expression. Most often they
+are accessed with the following macros:
@table @code
@findex MEM_VOLATILE_P
@@ -310,6 +310,15 @@ structure, union or array, or to a component of one. Zero for
references to a scalar variable or through a pointer to a scalar.
Stored in the @code{in_struct} field and printed as @samp{/s}.
+@findex MEM_ALIAS_SET
+@item MEM_ALIAS_SET (@var{x})
+In @code{mem} expressions, the alias set to which @var{x} belongs. If
+zero, @var{x} is not in any alias set, and may alias anything. If
+nonzero, @var{x} may only alias objects in the same alias set. This
+value is set (in a language-specific manner) by the front-end. This
+field is not a bit-field; it is in an integer, found as the second
+argument to the @code{mem}.
+
@findex REG_LOOP_TEST_P
@cindex @code{reg} and @samp{/s}
@cindex @code{in_struct}, in @code{reg}
diff --git a/gcc/stmt.c b/gcc/stmt.c
index feeea171693..43cf7f82ec2 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -3178,6 +3178,8 @@ expand_decl (decl)
if (flag_float_store && TREE_CODE (type) == REAL_TYPE)
MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
#endif
+
+ MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl);
}
else
/* Dynamic-size object: must push space on the stack. */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 42d3616e359..d51dc60eb95 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -711,6 +711,12 @@ int flag_regmove = 0;
This defaults to 0 for C. */
int flag_argument_noalias = 0;
+/* Nonzero if we should do (language-dependent) alias analysis.
+ Typically, this analysis will assume that expressions of certain
+ types do not alias expressions of certain other types. Only used
+ if alias analysis (in general) is enabled. */
+int flag_strict_aliasing = 0;
+
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@@ -782,6 +788,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
{"argument-alias", &flag_argument_noalias, 0},
{"argument-noalias", &flag_argument_noalias, 1},
{"argument-noalias-global", &flag_argument_noalias, 2},
+ {"strict-aliasing", &flag_strict_aliasing, 1},
{"check-memory-usage", &flag_check_memory_usage, 1},
{"prefix-function-name", &flag_prefix_function_name, 1}
};
@@ -3839,6 +3846,9 @@ main (argc, argv, envp)
flag_schedule_insns_after_reload = 1;
#endif
flag_regmove = 1;
+ /* We don't set flag_strict_aliasing here because we're still
+ testing the functionality. After it has been tested, it
+ should be turned on here. */
}
if (optimize >= 3)
diff --git a/gcc/tree.c b/gcc/tree.c
index baf4551cadd..de5a1791af1 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -261,6 +261,10 @@ static int next_decl_uid;
/* Unique id for next type created. */
static int next_type_uid = 1;
+/* The language-specific function for alias analysis. If NULL, the
+ language does not do any special alias analysis. */
+int (*lang_get_alias_set) PROTO((tree));
+
/* Here is how primitive or already-canonicalized types' hash
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
@@ -1112,6 +1116,9 @@ make_node (code)
#ifdef SET_DEFAULT_TYPE_ATTRIBUTES
SET_DEFAULT_TYPE_ATTRIBUTES (t);
#endif
+ /* Note that we have not yet computed the alias set for this
+ type. */
+ TYPE_ALIAS_SET (t) = -1;
break;
case 'c':
@@ -5019,3 +5026,17 @@ expr_check (node, ignored, file, line, nofatal)
return node;
}
#endif
+
+/* Return the alias set for T, which may be either a type or an
+ expression. */
+
+int get_alias_set (t)
+ tree t;
+{
+ if (!flag_strict_aliasing || !lang_get_alias_set)
+ /* If we're not doing any lanaguage-specific alias analysis, just
+ assume everything aliases everything else. */
+ return 0;
+ else
+ return (*lang_get_alias_set) (t);
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 62b31687490..be62730706b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -776,6 +776,18 @@ struct tree_block
#define TYPE_OBSTACK(NODE) (TYPE_CHECK (NODE)->type.obstack)
#define TYPE_LANG_SPECIFIC(NODE) (TYPE_CHECK (NODE)->type.lang_specific)
+/* The (language-specific) typed-based alias set for this type.
+ Objects whose TYPE_ALIAS_SETs are different cannot alias each
+ other. If the TYPE_ALIAS_SET is -1, no alias set has yet been
+ assigned to this type. If the TYPE_ALIAS_SET is 0, objects of this
+ type can alias objects of any type. */
+#define TYPE_ALIAS_SET(NODE) (TYPE_CHECK (NODE)->type.alias_set)
+
+/* Nonzero iff the typed-based alias set for this type has been
+ calculated. */
+#define TYPE_ALIAS_SET_KNOWN_P(NODE) \
+ (TYPE_CHECK (NODE)->type.alias_set != -1)
+
/* A TREE_LIST of IDENTIFIER nodes of the attributes that apply
to this type. */
#define TYPE_ATTRIBUTES(NODE) (TYPE_CHECK (NODE)->type.attributes)
@@ -870,6 +882,7 @@ struct tree_type
union tree_node *noncopied_parts;
union tree_node *context;
struct obstack *obstack;
+ int alias_set;
/* Points to a structure whose details depend on the language in use. */
struct lang_type *lang_specific;
};
@@ -1811,6 +1824,8 @@ extern tree get_file_function_name PROTO((int));
extern tree get_set_constructor_bits PROTO((tree, char *, int));
extern tree get_set_constructor_bytes PROTO((tree,
unsigned char *, int));
+extern int get_alias_set PROTO((tree));
+extern int (*lang_get_alias_set) PROTO((tree));
/* In stmt.c */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 760aa773e0c..4ba0e08d187 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -662,8 +662,6 @@ make_decl_rtl (decl, asmspec, top_level)
same DECL node. Don't discard the RTL already made. */
if (DECL_RTL (decl) == 0)
{
- DECL_RTL (decl) = 0;
-
/* First detect errors in declaring global registers. */
if (TREE_CODE (decl) != FUNCTION_DECL
&& DECL_REGISTER (decl) && reg_number == -1)
@@ -767,7 +765,8 @@ make_decl_rtl (decl, asmspec, top_level)
DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl),
gen_rtx_SYMBOL_REF (Pmode, name));
-
+ MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl);
+
/* If this variable is to be treated as volatile, show its
tree node has side effects. If it has side effects, either
because of this test or from TREE_THIS_VOLATILE also
OpenPOWER on IntegriCloud