invoke.texi (-fstrict-aliasing): Document.
authorMark Mitchell <mark@markmitchell.com>
Thu, 25 Jun 1998 15:14:41 +0000 (15:14 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 25 Jun 1998 15:14:41 +0000 (15:14 +0000)
* 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.

From-SVN: r20719

24 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/c-common.c
gcc/c-decl.c
gcc/c-tree.h
gcc/emit-rtl.c
gcc/explow.c
gcc/expr.c
gcc/final.c
gcc/flags.h
gcc/function.c
gcc/gengenrtl.c
gcc/integrate.c
gcc/invoke.texi
gcc/print-tree.c
gcc/reload1.c
gcc/rtl.def
gcc/rtl.h
gcc/rtl.texi
gcc/stmt.c
gcc/toplev.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index 7360bff192f33afa4c022f53ba338d9e421647e6..b9ada6d08513366c6814a57af848dfd70e27ebd1 100644 (file)
@@ -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.
index 99df4fa8ccf11bdeb8eb46791f3c12dc6ae2abdc..ab65bc4d8eacbd06045ce543ef1f64831b9ec117 100644 (file)
@@ -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)
index 9a8d0731bdd2b9b928dfe9eece21d14a9bc59104..245fedb97be344908cf20188f8d18c6bd3a29403 100644 (file)
@@ -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);
+}
index 51a18c5a0dd437f6ff9aa487030a444579354ed3..15eb740b976002264e5924d3770198a6e1ec83d1 100644 (file)
@@ -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
index 6ec4f674e252a0e83153562e37f5e2b9c8e4504c..3a9f4f83b7866db97e492a7871d443fdea224cde 100644 (file)
@@ -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));
index 854b9892e2b7331e5965b24e89b20b4e24f1f573..8f1b50188bf8d06c53e27e437efcf08089f28f30 100644 (file)
@@ -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
index 7c74d6a620f4a18cb1007e4c10ff49883943a1c9..cd50563be526bd72213e101bc0b50c339a9f1da9 100644 (file)
@@ -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;
index 91134d393caaacb657e4995fd6d32e78c992a78b..bc19068afaa88e007e21098ea152bc19b5cc8200 100644 (file)
@@ -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);
 
index ca6c22037d8720aa03d8535cd695807ea592acdc..794bedf70b1dc78e64b6140384413850cea4e391 100644 (file)
@@ -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);
     }
 
index 2b670054eb6bbd9c2d2ac4bb57b5656b02509d3c..2b62325bb2960ae1e05f0aa38dc80984d86d3ede 100644 (file)
@@ -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;
index f8e3cd40667537bcd3b8301210ae4ebf2ef455cc..f3d33d0cc399b6d9bf1e46e39b039744c230f949 100644 (file)
@@ -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,
index a8daeae465b7530b9dda14d1a6c410996d6cf01f..ade07ff4b6c63285831f47150254f467484b6f9b 100644 (file)
@@ -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
index a7fb3d7eb8b6177155c4f233cf1253203066f6c4..38a900a9768351ecbf37d7f9d38ba6f60768b929 100644 (file)
@@ -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
index 56bdfdbae4742c8da7316cbcad14f402ef215ce6..3bc197f9b667eb9ae5190f987f5a38d2d658515a 100644 (file)
@@ -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
index 6674a18aa8d55427051964242e8a406a05597ed5..6163b1ff91cc3ffc9a36a23ebef0e1bd5ec5271a 100644 (file)
@@ -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);
 
index 9acf695679af997c1eeeeaeb54b59e649b963f53..9601691f9f9f4fa384f441ac1e499098397139c7 100644 (file)
@@ -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])
index e219e87c0422a21384aafe671b21f36f9a78a348..a00d3f1d7c57adcd9bfd5616f3aeba9fea71e6e1 100644 (file)
@@ -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.
index bee83bbc0d8d6a9a4ebaedc97cc4ff9a75cfbd48..af85d823738eaa89cff28b6a696be2d3b1cc7629 100644 (file)
--- 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.  */
index 0127fcea456965d66c3bd49ab9daeac1e165cea3..4d5139956dc9b1870931d4a42beb2d39ec3dcaed 100644 (file)
@@ -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}
index feeea1716936dd76f0e71ce6d81ce32833fcf2f9..43cf7f82ec264e75e5a6dc7d500f721e244da0d5 100644 (file)
@@ -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.  */
index 42d3616e3590b6881f33b84edf4f0f1db1c33987..d51dc60eb95ff4e3a20cda616028253254684789 100644 (file)
@@ -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)
index baf4551cadda32f55fd0fb2e227fcf58aa152499..de5a1791af1e7d16ff515a63c12d8b4611032941 100644 (file)
@@ -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);
+}
index 62b316874907eca05c446ea5fe8d9f13027c8fdc..be62730706b05db3b954b4363cf547a1a4ffa617 100644 (file)
@@ -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));
 \f
 /* In stmt.c */
 
index 760aa773e0c243c4440d0fbea41c47980f344fd0..4ba0e08d187b80a428af63df5fbe4753fd56fd6d 100644 (file)
@@ -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