OSDN Git Service

* function.c (keep_stack_depressed): Don't use delete_insn.
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 1 Oct 2001 11:00:47 +0000 (11:00 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 1 Oct 2001 11:00:47 +0000 (11:00 +0000)
* expr.h (set_mem_alias_set): Move decl to here.
* rtl.h (mem_attrs): New typedef and struct.
(union rtunion_def): Add field for mem_attrs.
(X0MEMATTR, MEM_ATTRS): New macros.
(MEM_ALIAS_SET): Use MEM_ATTRS.
(MEM_DECL, MEM_OFFSET, MEM_SIZE, MEM_ALIGN): New macros.
(MEM_COPY_ATTRIBUTES): Copy MEM_ATTRS.
(set_mem_alias_set): Delete decl from here.

* alias.c (set_mem_alias_set): Delete from here.
* emit-rtl.c (mem_attrs_htab): New variable.
(rtx_htab_mark, rtx_htab_mark_1): Deleted.
(mem_attrs_htab_hash, mem_attrs_htab_eq): New functions.
(mem_attrs_mark, get_mem_attrs): Likewise.
(gen_rtx_MEM): Clear MEM_ATTRS.
(set_mem_attributes): Move to here.
(set_mem_alias_set): Likewise, and call get_mem_attrs.
(init_emit_once): const_int_htab now deletable htab.
Initialize mem_attrs_htab.
* explow.c (set_mem_attributes): Delete from here.
* function.c (put_var_into_stack): Clear MEM_ATTRS.
(gen_mem_addressof): Likewise; rework to use set_mem_attributes.
* ggc-common.c (ggc_mark_rtx_children, case MEM): New case.
* reload1.c (reload): Rework changing REG to MEM.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45922 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/alias.c
gcc/emit-rtl.c
gcc/explow.c
gcc/expr.h
gcc/function.c
gcc/ggc-common.c
gcc/reload1.c
gcc/rtl.h

index 4507428..8993b5a 100644 (file)
@@ -1,3 +1,32 @@
+Mon Oct  1 06:43:41 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * function.c (keep_stack_depressed): Don't use delete_insn.
+
+       * expr.h (set_mem_alias_set): Move decl to here.
+       * rtl.h (mem_attrs): New typedef and struct.
+       (union rtunion_def): Add field for mem_attrs.
+       (X0MEMATTR, MEM_ATTRS): New macros.
+       (MEM_ALIAS_SET): Use MEM_ATTRS.
+       (MEM_DECL, MEM_OFFSET, MEM_SIZE, MEM_ALIGN): New macros.
+       (MEM_COPY_ATTRIBUTES): Copy MEM_ATTRS.
+       (set_mem_alias_set): Delete decl from here.
+       
+       * alias.c (set_mem_alias_set): Delete from here.
+       * emit-rtl.c (mem_attrs_htab): New variable.
+       (rtx_htab_mark, rtx_htab_mark_1): Deleted.
+       (mem_attrs_htab_hash, mem_attrs_htab_eq): New functions.
+       (mem_attrs_mark, get_mem_attrs): Likewise.
+       (gen_rtx_MEM): Clear MEM_ATTRS.
+       (set_mem_attributes): Move to here.
+       (set_mem_alias_set): Likewise, and call get_mem_attrs.
+       (init_emit_once): const_int_htab now deletable htab.
+       Initialize mem_attrs_htab.
+       * explow.c (set_mem_attributes): Delete from here.
+       * function.c (put_var_into_stack): Clear MEM_ATTRS.
+       (gen_mem_addressof): Likewise; rework to use set_mem_attributes.
+       * ggc-common.c (ggc_mark_rtx_children, case MEM): New case.
+       * reload1.c (reload): Rework changing REG to MEM.
+
 2001-09-30  H.J. Lu <hjl@gnu.org>
 
        * acconfig.h (PREFIX_INCLUDE_DIR): New variable.
index abb593a..bf7c5e3 100644 (file)
@@ -276,24 +276,6 @@ alias_sets_conflict_p (set1, set2)
   return 0;
 }
 \f
-/* Set the alias set of MEM to SET.  */
-
-void
-set_mem_alias_set (mem, set)
-     rtx mem;
-     HOST_WIDE_INT set;
-{
-  /* We would like to do this test but can't yet since when converting a
-     REG to a MEM, the alias set field is undefined.  */
-#if 0
-  /* If the new and old alias sets don't conflict, something is wrong.  */
-  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
-    abort ();
-#endif
-
-  MEM_ALIAS_SET (mem) = set;
-}
-\f
 /* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
    has any readonly fields.  If any of the fields have types that
    contain readonly fields, return true as well.  */
index f33df26..eeb5128 100644 (file)
@@ -144,6 +144,9 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
 
 static htab_t const_int_htab;
 
+/* A hash table storing memory attribute structures.  */
+static htab_t mem_attrs_htab;
+
 /* start_sequence and gen_sequence can make a lot of rtx expressions which are
    shortly thrown away.  We use two mechanisms to prevent this waste:
 
@@ -182,13 +185,16 @@ static void mark_label_nuses              PARAMS ((rtx));
 static hashval_t const_int_htab_hash    PARAMS ((const void *));
 static int const_int_htab_eq            PARAMS ((const void *,
                                                 const void *));
-static int rtx_htab_mark_1              PARAMS ((void **, void *));
-static void rtx_htab_mark               PARAMS ((void *));
+static hashval_t mem_attrs_htab_hash    PARAMS ((const void *));
+static int mem_attrs_htab_eq            PARAMS ((const void *,
+                                                const void *));
+static void mem_attrs_mark             PARAMS ((const void *));
+static mem_attrs *get_mem_attrs                PARAMS ((HOST_WIDE_INT, tree, rtx,
+                                                rtx, unsigned int));
 
 /* Probability of the conditional branch currently proceeded by try_split.
    Set to -1 otherwise.  */
 int split_branch_probability = -1;
-
 \f
 /* Returns a hash code for X (which is a really a CONST_INT).  */
 
@@ -211,26 +217,83 @@ const_int_htab_eq (x, y)
   return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y));
 }
 
-/* Mark the hash-table element X (which is really a pointer to an
-   rtx).  */
+/* Returns a hash code for X (which is a really a mem_attrs *).  */
+
+static hashval_t
+mem_attrs_htab_hash (x)
+     const void *x;
+{
+  mem_attrs *p = (mem_attrs *) x;
+
+  return (p->alias ^ (p->align * 1000)
+         ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
+         ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
+         ^ (long) p->decl);
+}
+
+/* Returns non-zero if the value represented by X (which is really a
+   mem_attrs *) is the same as that given by Y (which is also really a
+   mem_attrs *).  */
 
 static int
-rtx_htab_mark_1 (x, data)
-     void **x;
-     void *data ATTRIBUTE_UNUSED;
+mem_attrs_htab_eq (x, y)
+     const void *x;
+     const void *y;
 {
-  ggc_mark_rtx (*x);
-  return 1;
+  mem_attrs *p = (mem_attrs *) x;
+  mem_attrs *q = (mem_attrs *) y;
+
+  return (p->alias == q->alias && p->decl == q->decl && p->offset == q->offset
+         && p->size == q->size && p->align == q->align);
 }
 
-/* Mark all the elements of HTAB (which is really an htab_t full of
-   rtxs).  */
+/* This routine is called when we determine that we need a mem_attrs entry.
+   It marks the associated decl and RTL as being used, if present.  */
 
 static void
-rtx_htab_mark (htab)
-     void *htab;
+mem_attrs_mark (x)
+     const void *x;
 {
-  htab_traverse (*((htab_t *) htab), rtx_htab_mark_1, NULL);
+  mem_attrs *p = (mem_attrs *) x;
+
+  if (p->decl)
+    ggc_mark_tree (p->decl);
+
+  if (p->offset)
+    ggc_mark_rtx (p->offset);
+
+  if (p->size)
+    ggc_mark_rtx (p->size);
+}
+
+/* Allocate a new mem_attrs structure and insert it into the hash table if
+   one identical to it is not already in the table.  */
+
+static mem_attrs *
+get_mem_attrs (alias, decl, offset, size, align)
+     HOST_WIDE_INT alias;
+     tree decl;
+     rtx offset;
+     rtx size;
+     unsigned int align;
+{
+  mem_attrs attrs;
+  void **slot;
+
+  attrs.alias = alias;
+  attrs.decl = decl;
+  attrs.offset = offset;
+  attrs.size = size;
+  attrs.align = align;
+
+  slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT);
+  if (*slot == 0)
+    {
+      *slot = ggc_alloc (sizeof (mem_attrs));
+      memcpy (*slot, &attrs, sizeof (mem_attrs));
+    }
+
+  return *slot;
 }
 
 /* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
@@ -350,7 +413,7 @@ gen_rtx_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;
+  MEM_ATTRS (rt) = 0;
 
   return rt;
 }
@@ -377,9 +440,9 @@ gen_rtx_SUBREG (mode, reg, offset)
   return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
 }
 
-/* Generate a SUBREG representing the least-significant part
- * of REG if MODE is smaller than mode of REG, otherwise
- * paradoxical SUBREG.  */
+/* Generate a SUBREG representing the least-significant part of REG if MODE
+   is smaller than mode of REG, otherwise paradoxical SUBREG.  */
+
 rtx
 gen_lowpart_SUBREG (mode, reg)
      enum machine_mode mode;
@@ -556,7 +619,6 @@ gen_rtvec_v (n, argp)
 
   return rt_val;
 }
-
 \f
 /* Generate a REG rtx for a new pseudo register of mode MODE.
    This pseudo is assigned the next sequential register number.  */
@@ -1569,6 +1631,103 @@ reverse_comparison (insn)
     }
 }
 \f
+
+/* Given REF, a MEM, and T, either the type of X or the expression
+   corresponding to REF, set the memory attributes.  OBJECTP is nonzero
+   if we are making a new object of this type.  */
+
+void
+set_mem_attributes (ref, t, objectp)
+     rtx ref;
+     tree t;
+     int objectp;
+{
+  tree type;
+
+  /* It can happen that type_for_mode was given a mode for which there
+     is no language-level type.  In which case it returns NULL, which
+     we can see here.  */
+  if (t == NULL_TREE)
+    return;
+
+  type = TYPE_P (t) ? t : TREE_TYPE (t);
+
+  /* Get the alias set from the expression or type (perhaps using a
+     front-end routine) and then copy bits from the type.  */
+
+  /* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY (type)
+     here, because, in C and C++, the fact that a location is accessed
+     through a const expression does not mean that the value there can
+     never change.  */
+
+  /* If we have already set DECL_RTL = ref, get_alias_set will get the
+     wrong answer, as it assumes that DECL_RTL already has the right alias
+     info.  Callers should not set DECL_RTL until after the call to
+     set_mem_attributes.  */
+  if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
+    abort ();
+
+  set_mem_alias_set (ref, get_alias_set (t));
+
+  MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
+  MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
+
+  /* If we are making an object of this type, we know that it is a scalar if
+     the type is not an aggregate.  */
+  if (objectp && ! AGGREGATE_TYPE_P (type))
+    MEM_SCALAR_P (ref) = 1;
+
+  /* If T is a type, this is all we can do.  Otherwise, we may be able
+     to deduce some more information about the expression.  */
+  if (TYPE_P (t))
+    return;
+
+  maybe_set_unchanging (ref, t);
+  if (TREE_THIS_VOLATILE (t))
+    MEM_VOLATILE_P (ref) = 1;
+
+  /* Now see if we can say more about whether it's an aggregate or
+     scalar.  If we already know it's an aggregate, don't bother.  */
+  if (MEM_IN_STRUCT_P (ref))
+    return;
+
+  /* Now remove any NOPs: they don't change what the underlying object is.
+     Likewise for SAVE_EXPR.  */
+  while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
+        || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  /* Since we already know the type isn't an aggregate, if this is a decl,
+     it must be a scalar.  Or if it is a reference into an aggregate,
+     this is part of an aggregate.   Otherwise we don't know.  */
+  if (DECL_P (t))
+    MEM_SCALAR_P (ref) = 1;
+  else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
+          || TREE_CODE (t) == ARRAY_RANGE_REF
+          || TREE_CODE (t) == BIT_FIELD_REF)
+    MEM_IN_STRUCT_P (ref) = 1;
+}
+
+/* Set the alias set of MEM to SET.  */
+
+void
+set_mem_alias_set (mem, set)
+     rtx mem;
+     HOST_WIDE_INT set;
+{
+  /* It would be nice to enable this check, but we can't quite yet.  */
+#if 0
+#ifdef ENABLE_CHECKING 
+  /* If the new and old alias sets don't conflict, something is wrong.  */
+  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
+    abort ();
+#endif
+#endif
+
+  MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
+                                  MEM_SIZE (mem), MEM_ALIGN (mem));
+}
+\f
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address changed to ADDR.
    (VOIDmode means don't change the mode.
@@ -4281,11 +4440,14 @@ init_emit_once (line_numbers)
   enum machine_mode mode;
   enum machine_mode double_mode;
 
-  /* Initialize the CONST_INT hash table.  */
+  /* Initialize the CONST_INT and memory attribute hash tables.  */
   const_int_htab = htab_create (37, const_int_htab_hash,
                                const_int_htab_eq, NULL);
-  ggc_add_root (&const_int_htab, 1, sizeof (const_int_htab),
-               rtx_htab_mark);
+  ggc_add_deletable_htab (const_int_htab, 0, 0);
+
+  mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
+                               mem_attrs_htab_eq, NULL);
+  ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark);
 
   no_line_numbers = ! line_numbers;
 
index d01067d..85c3a7d 100644 (file)
@@ -642,82 +642,6 @@ maybe_set_unchanging (ref, t)
       || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
     RTX_UNCHANGING_P (ref) = 1;
 }
-
-/* Given REF, a MEM, and T, either the type of X or the expression
-   corresponding to REF, set the memory attributes.  OBJECTP is nonzero
-   if we are making a new object of this type.  */
-
-void
-set_mem_attributes (ref, t, objectp)
-     rtx ref;
-     tree t;
-     int objectp;
-{
-  tree type;
-
-  /* It can happen that type_for_mode was given a mode for which there
-     is no language-level type.  In which case it returns NULL, which
-     we can see here.  */
-  if (t == NULL_TREE)
-    return;
-
-  type = TYPE_P (t) ? t : TREE_TYPE (t);
-
-  /* Get the alias set from the expression or type (perhaps using a
-     front-end routine) and then copy bits from the type.  */
-
-  /* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY (type)
-     here, because, in C and C++, the fact that a location is accessed
-     through a const expression does not mean that the value there can
-     never change.  */
-
-  /* If we have already set DECL_RTL = ref, get_alias_set will get the
-     wrong answer, as it assumes that DECL_RTL already has the right alias
-     info.  Callers should not set DECL_RTL until after the call to
-     set_mem_attributes.  */
-  if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
-    abort ();
-
-  set_mem_alias_set (ref, get_alias_set (t));
-
-  MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
-  MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
-
-  /* If we are making an object of this type, we know that it is a scalar if
-     the type is not an aggregate.  */
-  if (objectp && ! AGGREGATE_TYPE_P (type))
-    MEM_SCALAR_P (ref) = 1;
-
-  /* If T is a type, this is all we can do.  Otherwise, we may be able
-     to deduce some more information about the expression.  */
-  if (TYPE_P (t))
-    return;
-
-  maybe_set_unchanging (ref, t);
-  if (TREE_THIS_VOLATILE (t))
-    MEM_VOLATILE_P (ref) = 1;
-
-  /* Now see if we can say more about whether it's an aggregate or
-     scalar.  If we already know it's an aggregate, don't bother.  */
-  if (MEM_IN_STRUCT_P (ref))
-    return;
-
-  /* Now remove any NOPs: they don't change what the underlying object is.
-     Likewise for SAVE_EXPR.  */
-  while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
-        || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
-    t = TREE_OPERAND (t, 0);
-
-  /* Since we already know the type isn't an aggregate, if this is a decl,
-     it must be a scalar.  Or if it is a reference into an aggregate,
-     this is part of an aggregate.   Otherwise we don't know.  */
-  if (DECL_P (t))
-    MEM_SCALAR_P (ref) = 1;
-  else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
-          || TREE_CODE (t) == ARRAY_RANGE_REF
-          || TREE_CODE (t) == BIT_FIELD_REF)
-    MEM_IN_STRUCT_P (ref) = 1;
-}
 \f
 /* Return a modified copy of X with its memory address copied
    into a temporary register to protect it from side effects.
index e340b8b..9addf7f 100644 (file)
@@ -602,6 +602,9 @@ extern rtx memory_address PARAMS ((enum machine_mode, rtx));
 /* Like `memory_address' but pretent `flag_force_addr' is 0.  */
 extern rtx memory_address_noforce PARAMS ((enum machine_mode, rtx));
 
+/* Set the alias set of MEM to SET.  */
+extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
+
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address changed to ADDR.
    (VOIDmode means don't change the mode.
index c6fa510..fed2b3b 100644 (file)
@@ -1406,6 +1406,7 @@ put_var_into_stack (decl)
 
       /* Change the CONCAT into a combined MEM for both parts.  */
       PUT_CODE (reg, MEM);
+      MEM_ATTRS (reg) = 0;
 
       /* set_mem_attributes uses DECL_RTL to avoid re-generating of
          already computed alias sets.  Here we want to re-generate.  */
@@ -1476,6 +1477,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
   PUT_CODE (reg, MEM);
   PUT_MODE (reg, decl_mode);
   XEXP (reg, 0) = XEXP (new, 0);
+  MEM_ATTRS (reg) = 0;
   /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */
   MEM_VOLATILE_P (reg) = volatile_p;
 
@@ -1490,6 +1492,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
                           AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
       set_mem_alias_set (reg, get_alias_set (type));
     }
+
   if (used_p)
     schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
 }
@@ -2840,29 +2843,35 @@ gen_mem_addressof (reg, decl)
   RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
 
   PUT_CODE (reg, MEM);
+  MEM_ATTRS (reg) = 0;
   XEXP (reg, 0) = r;
+
   if (decl)
     {
       tree type = TREE_TYPE (decl);
       enum machine_mode decl_mode
        = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
           : DECL_MODE (decl));
+      rtx decl_rtl = decl ? DECL_RTL_IF_SET (decl) : 0;
 
       PUT_MODE (reg, decl_mode);
-      MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
-      MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
+
+      /* Clear DECL_RTL momentarily so functions below will work
+        properly, then set it again.  */
+      if (decl_rtl == reg)
+       SET_DECL_RTL (decl, 0);
+
+      set_mem_attributes (reg, decl, 1);
       set_mem_alias_set (reg, set);
 
+      if (decl_rtl == reg)
+       SET_DECL_RTL (decl, reg);
+
       if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
        fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
     }
   else
-    {
-      /* We have no alias information about this newly created MEM.  */
-      set_mem_alias_set (reg, 0);
-
-      fixup_var_refs (reg, GET_MODE (reg), 0, 0);
-    }
+    fixup_var_refs (reg, GET_MODE (reg), 0, 0);
 
   return reg;
 }
@@ -7141,8 +7150,11 @@ keep_stack_depressed (seq)
          else
            sp_modified_unknown = 1;
 
-         /* Don't allow the SP modification to happen.  */
-         delete_insn (insn);
+         /* Don't allow the SP modification to happen.  We don't call
+            delete_insn here since INSN isn't in any chain.  */
+         PUT_CODE (insn, NOTE);
+         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+         NOTE_SOURCE_FILE (insn) = 0;
        }
       else if (reg_referenced_p (stack_pointer_rtx, PATTERN (insn)))
        {
index 80de380..53057c8 100644 (file)
@@ -298,6 +298,9 @@ ggc_mark_rtx_children (r)
         have any right poking our noses in?  */
       switch (code)
        {
+       case MEM:
+         ggc_mark (MEM_ATTRS (r));
+         break;
        case JUMP_INSN:
          ggc_mark_rtx (JUMP_LABEL (r));
          break;
index bc3456f..7828bf5 100644 (file)
@@ -1130,16 +1130,6 @@ reload (first, global)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
       rtx addr = 0;
-      int in_struct = 0;
-      int is_scalar = 0;
-      int is_readonly = 0;
-
-      if (reg_equiv_memory_loc[i])
-       {
-         in_struct = MEM_IN_STRUCT_P (reg_equiv_memory_loc[i]);
-         is_scalar = MEM_SCALAR_P (reg_equiv_memory_loc[i]);
-         is_readonly = RTX_UNCHANGING_P (reg_equiv_memory_loc[i]);
-       }
 
       if (reg_equiv_mem[i])
        addr = XEXP (reg_equiv_mem[i], 0);
@@ -1152,15 +1142,18 @@ reload (first, global)
          if (reg_renumber[i] < 0)
            {
              rtx reg = regno_reg_rtx[i];
+
              PUT_CODE (reg, MEM);
              XEXP (reg, 0) = addr;
              REG_USERVAR_P (reg) = 0;
-             RTX_UNCHANGING_P (reg) = is_readonly;
-             MEM_IN_STRUCT_P (reg) = in_struct;
-             MEM_SCALAR_P (reg) = is_scalar;
-             /* We have no alias information about this newly created
-                MEM.  */
-             set_mem_alias_set (reg, 0);
+             if (reg_equiv_memory_loc[i])
+               MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
+             else
+               {
+                 RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
+                   = MEM_SCALAR_P (reg) = 0;
+                 MEM_ATTRS (reg) = 0;
+               }
            }
          else if (reg_equiv_mem[i])
            XEXP (reg_equiv_mem[i], 0) = addr;
index d9b9294..983036f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -31,8 +31,8 @@ struct function;
 #undef ABS /* Likewise.  */
 #undef PC /* Likewise.  */
 
-/* Value used by some passes to "recognize" noop moves as valid instructions.
- */
+/* Value used by some passes to "recognize" noop moves as valid
instructions. */
 #define NOOP_MOVE_INSN_CODE    INT_MAX
 
 /* Register Transfer Language EXPRESSIONS CODES */
@@ -71,16 +71,33 @@ typedef struct
   unsigned min_align: 8;
   /* Flags: */
   unsigned base_after_vec: 1; /* BASE is after the ADDR_DIFF_VEC.  */
-  unsigned min_after_vec: 1;  /* minimum address target label is after the ADDR_DIFF_VEC.  */
-  unsigned max_after_vec: 1;  /* maximum address target label is after the ADDR_DIFF_VEC.  */
-  unsigned min_after_base: 1; /* minimum address target label is after BASE.  */
-  unsigned max_after_base: 1; /* maximum address target label is after BASE.  */
+  unsigned min_after_vec: 1;  /* minimum address target label is
+                                after the ADDR_DIFF_VEC.  */
+  unsigned max_after_vec: 1;  /* maximum address target label is
+                                after the ADDR_DIFF_VEC.  */
+  unsigned min_after_base: 1; /* minimum address target label is
+                                after BASE.  */
+  unsigned max_after_base: 1; /* maximum address target label is
+                                after BASE.  */
   /* Set by the actual branch shortening process - ONLY WHEN OPTIMIZING - : */
   unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned.  */
   unsigned : 2;
   unsigned scale : 8;
 } addr_diff_vec_flags;
 
+/* Structure used to describe the attributes of a MEM.  These are hashed
+   so MEMs that the same attributes share a data structure.  This means
+   they cannot be modified in place.  If any element is nonzero, it means
+   the value of the corresponding attribute is unknown.  */
+typedef struct
+{
+  HOST_WIDE_INT alias;         /* Memory alias set. */
+  tree decl;                   /* decl corresponding to MEM. */
+  rtx offset;                  /* Offset from start of DECL, as CONST_INT. */
+  rtx size;                    /* Size in bytes, as a CONST_INT.  */
+  unsigned int align;          /* Alignment of MEM in bytes.  */
+} mem_attrs;
+
 /* Common union for an element of an rtx.  */
 
 typedef union rtunion_def
@@ -97,6 +114,7 @@ typedef union rtunion_def
   struct bitmap_head_def *rtbit;
   tree rttree;
   struct basic_block_def *bb;
+  mem_attrs *rtmem;
 } rtunion;
 
 /* RTL expression ("rtx").  */
@@ -340,6 +358,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
 #define X0BBDEF(RTX, N)           (RTL_CHECK1(RTX, N, '0').bb)
 #define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
 #define X0CSELIB(RTX, N)   (RTL_CHECK1(RTX, N, '0').rt_cselib)
+#define X0MEMATTR(RTX, N)  (RTL_CHECK1(RTX, N, '0').rtmem)
 
 #define XCWINT(RTX, N, C)     (RTL_CHECKC1(RTX, N, C).rtwint)
 #define XCINT(RTX, N, C)      (RTL_CHECKC1(RTX, N, C).rtint)
@@ -862,6 +881,10 @@ extern unsigned int subreg_regno   PARAMS ((rtx));
     }                                          \
 } while (0)
 
+/* The memory attribute block.  We provide access macros for each value
+   in the block and provide defaults if none specified.  */
+#define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)
+
 /* 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
@@ -871,15 +894,30 @@ extern unsigned int subreg_regno  PARAMS ((rtx));
    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) XCWINT(RTX, 1, MEM)
+#define MEM_ALIAS_SET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->alias)
+
+/* For a MEM rtx, the decl it is known to refer to, if it is known to
+   refer to part of a DECL.  */
+#define MEM_DECL(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->decl)
+
+/* For a MEM rtx, the offset from the start of MEM_DECL, if known, as a
+   RTX that is always a CONST_INT.  */
+#define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
+
+/* For a MEM rtx, the size in bytes of the MEM, if known, as an RTX that
+   is always a CONST_INT.  */
+#define MEM_SIZE(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->size)
+
+/* For a MEM rtx, the alignment in bytes.  */
+#define MEM_ALIGN(RTX) (MEM_ATTRS (RTX) == 0 ? 1 : MEM_ATTRS (RTX)->align)
 
 /* Copy the attributes that apply to memory locations from RHS to LHS.  */
 #define MEM_COPY_ATTRIBUTES(LHS, RHS)                  \
   (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS),                \
    MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS),      \
    MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS),            \
-   MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS),          \
-   RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS))
+   RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS),    \
+   MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
 
 /* For a LABEL_REF, 1 means that this reference is to a label outside the
    loop containing the reference.  */
@@ -2010,7 +2048,6 @@ extern void init_alias_once               PARAMS ((void));
 extern void init_alias_analysis                PARAMS ((void));
 extern void end_alias_analysis         PARAMS ((void));
 extern rtx addr_side_effect_eval       PARAMS ((rtx, int, int));
-extern void set_mem_alias_set          PARAMS ((rtx, HOST_WIDE_INT));
 
 /* In sibcall.c */
 typedef enum {