The following patch caches the ao_ref (the meta-data used by
the "gimple" alias oracle) in MEM_ATTRs, inheriting the existing
MEM_EXPR and MEM_ALIAS_SET fields.  This reduces the load
on the get_ref_base_and_extent and the get_alias_set calls
that are eventually done when rtx_refs_may_alias_p dispatches
to the "gimple" alias oracle from the RTL oracle.  Especially
for cases where we do nearly O (n^2) queries this reduces
the work we spend significantly.

RFC because this enlarges the mem_attrs struct from 40 to
80 bytes (on x86_64).

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Comments?

Thanks,
Richard.

Enlarges struct mem_attrs from 40 to 80 bytes on x86_64

2014-02-13  Richard Biener  <rguent...@suse.de>

        * tree-ssa-alias.h (struct ao_ref): Mark GTY(()).
        * rtl.h: Include tree-ssa-alias.h.
        (struct mem_attrs): Add ao_ref mem member and make it
        provide expr and alias.
        (MEM_ALIAS_SET): Adjust.
        (MEM_EXPR): Likewise.
        * alias.c (ao_ref_from_mem): Adjust and cache the result
        in mem_attrs.mem.
        * emit-rtl.c (mem_attrs_htab_hash): Adjust.
        (mem_attrs_eq_p): Likewise.
        (set_mem_attributes_minus_bitpos): Likewise.
        (set_mem_alias_set): Likewise.
        (set_mem_expr): Likewise.
        (change_address): Likewise.
        (adjust_address_1): Likewise.
        (widen_memory_access): Likewise.
        (get_spill_slot_decl): Likewise.
        (set_mem_attrs_for_spill): Likewise.

Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig   2014-02-11 14:36:04.592802934 +0100
--- gcc/tree-ssa-alias.h        2014-02-13 13:56:01.591071306 +0100
*************** struct GTY(()) pt_solution
*** 64,70 ****
  /* Simplified and cached information about a memory reference tree.
     Used by the alias-oracle internally and externally in alternate
     interfaces.  */
! struct ao_ref
  {
    /* The original full memory reference tree or NULL_TREE if that is
       not available.  */
--- 64,70 ----
  /* Simplified and cached information about a memory reference tree.
     Used by the alias-oracle internally and externally in alternate
     interfaces.  */
! struct GTY(()) ao_ref
  {
    /* The original full memory reference tree or NULL_TREE if that is
       not available.  */
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h.orig      2014-02-11 14:36:04.592802934 +0100
--- gcc/rtl.h   2014-02-13 13:56:01.604071305 +0100
*************** along with GCC; see the file COPYING3.
*** 29,34 ****
--- 29,35 ----
  #include "alias.h"
  #include "hashtab.h"
  #include "flags.h"
+ #include "tree-ssa-alias.h"
  
  /* Value used by some passes to "recognize" noop moves as valid
   instructions.  */
*************** struct GTY(()) mem_attrs
*** 140,146 ****
    /* The expression that the MEM accesses, or null if not known.
       This expression might be larger than the memory reference itself.
       (In other words, the MEM might access only part of the object.)  */
!   tree expr;
  
    /* The offset of the memory reference from the start of EXPR.
       Only valid if OFFSET_KNOWN_P.  */
--- 141,147 ----
    /* The expression that the MEM accesses, or null if not known.
       This expression might be larger than the memory reference itself.
       (In other words, the MEM might access only part of the object.)  */
!   ao_ref mem;
  
    /* The offset of the memory reference from the start of EXPR.
       Only valid if OFFSET_KNOWN_P.  */
*************** struct GTY(()) mem_attrs
*** 150,158 ****
       SIZE_KNOWN_P.  */
    HOST_WIDE_INT size;
  
-   /* The alias set of the memory reference.  */
-   alias_set_type alias;
- 
    /* The alignment of the reference in bits.  Always a multiple of
       BITS_PER_UNIT.  Note that EXPR may have a stricter alignment
       than the memory reference itself.  */
--- 151,156 ----
*************** do {                                                            
        \
*** 1474,1484 ****
     language-dependent manner in the front-end, and should not be
     altered in the back-end.  These set numbers are tested with
     alias_sets_conflict_p.  */
! #define MEM_ALIAS_SET(RTX) (get_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.  It may also be a COMPONENT_REF.  */
! #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
  
  /* For a MEM rtx, true if its MEM_OFFSET is known.  */
  #define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)
--- 1472,1482 ----
     language-dependent manner in the front-end, and should not be
     altered in the back-end.  These set numbers are tested with
     alias_sets_conflict_p.  */
! #define MEM_ALIAS_SET(RTX) (get_mem_attrs (RTX)->mem.ref_alias_set)
  
  /* For a MEM rtx, the decl it is known to refer to, if it is known to
     refer to part of a DECL.  It may also be a COMPONENT_REF.  */
! #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->mem.ref)
  
  /* For a MEM rtx, true if its MEM_OFFSET is known.  */
  #define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig    2014-02-12 09:59:02.963998777 +0100
--- gcc/alias.c 2014-02-13 13:56:01.625071304 +0100
*************** static GTY (()) vec<alias_set_entry, va_
*** 273,316 ****
  static bool
  ao_ref_from_mem (ao_ref *ref, const_rtx mem)
  {
!   tree expr = MEM_EXPR (mem);
    tree base;
  
!   if (!expr)
      return false;
  
-   ao_ref_init (ref, expr);
- 
    /* Get the base of the reference and see if we have to reject or
       adjust it.  */
!   base = ao_ref_base (ref);
!   if (base == NULL_TREE)
!     return false;
! 
!   /* The tree oracle doesn't like bases that are neither decls
!      nor indirect references of SSA names.  */
!   if (!(DECL_P (base)
!       || (TREE_CODE (base) == MEM_REF
!           && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
!       || (TREE_CODE (base) == TARGET_MEM_REF
!           && TREE_CODE (TMR_BASE (base)) == SSA_NAME)))
!     return false;
! 
!   /* If this is a reference based on a partitioned decl replace the
!      base with a MEM_REF of the pointer representative we
!      created during stack slot partitioning.  */
!   if (TREE_CODE (base) == VAR_DECL
!       && ! is_global_var (base)
!       && cfun->gimple_df->decls_to_pointers != NULL)
      {
!       void *namep;
!       namep = pointer_map_contains (cfun->gimple_df->decls_to_pointers, base);
!       if (namep)
!       ref->base = build_simple_mem_ref (*(tree *)namep);
      }
  
!   ref->ref_alias_set = MEM_ALIAS_SET (mem);
  
    /* If MEM_OFFSET or MEM_SIZE are unknown what we got from MEM_EXPR
       is conservative, so trust it.  */
    if (!MEM_OFFSET_KNOWN_P (mem)
--- 273,319 ----
  static bool
  ao_ref_from_mem (ao_ref *ref, const_rtx mem)
  {
!   mem_attrs *attrs = get_mem_attrs (mem);
    tree base;
  
!   if (!attrs->mem.ref)
      return false;
  
    /* Get the base of the reference and see if we have to reject or
       adjust it.  */
!   if (!attrs->mem.base)
      {
!       base = ao_ref_base (&attrs->mem);
!       if (base == NULL_TREE)
!       return false;
! 
!       /* The tree oracle doesn't like bases that are neither decls
!        nor indirect references of SSA names.  */
!       if (!(DECL_P (base)
!           || (TREE_CODE (base) == MEM_REF
!               && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
!           || (TREE_CODE (base) == TARGET_MEM_REF
!               && TREE_CODE (TMR_BASE (base)) == SSA_NAME)))
!       return false;
! 
!       /* If this is a reference based on a partitioned decl replace the
!        base with a MEM_REF of the pointer representative we
!        created during stack slot partitioning.  */
!       if (TREE_CODE (base) == VAR_DECL
!         && ! is_global_var (base)
!         && cfun->gimple_df->decls_to_pointers != NULL)
!       {
!         void *namep;
!         namep = pointer_map_contains (cfun->gimple_df->decls_to_pointers,
!                                       base);
!         if (namep)
!           attrs->mem.base = build_simple_mem_ref (*(tree *)namep);
!       }
      }
  
!   *ref = attrs->mem;
  
+   /* ??? */
    /* If MEM_OFFSET or MEM_SIZE are unknown what we got from MEM_EXPR
       is conservative, so trust it.  */
    if (!MEM_OFFSET_KNOWN_P (mem)
*************** ao_ref_from_mem (ao_ref *ref, const_rtx
*** 326,332 ****
  
    /* Otherwise continue and refine size and offset we got from analyzing
       MEM_EXPR by using MEM_SIZE and MEM_OFFSET.  */
- 
    ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
    ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
  
--- 329,334 ----
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c.orig 2014-02-11 14:36:04.592802934 +0100
--- gcc/emit-rtl.c      2014-02-13 13:59:43.426056033 +0100
*************** mem_attrs_htab_hash (const void *x)
*** 256,266 ****
  {
    const mem_attrs *const p = (const mem_attrs *) x;
  
!   return (p->alias ^ (p->align * 1000)
          ^ (p->addrspace * 4000)
          ^ ((p->offset_known_p ? p->offset : 0) * 50000)
          ^ ((p->size_known_p ? p->size : 0) * 2500000)
!         ^ (size_t) iterative_hash_expr (p->expr, 0));
  }
  
  /* Return true if the given memory attributes are equal.  */
--- 256,266 ----
  {
    const mem_attrs *const p = (const mem_attrs *) x;
  
!   return (p->mem.ref_alias_set ^ (p->align * 1000)
          ^ (p->addrspace * 4000)
          ^ ((p->offset_known_p ? p->offset : 0) * 50000)
          ^ ((p->size_known_p ? p->size : 0) * 2500000)
!         ^ (size_t) iterative_hash_expr (p->mem.ref, 0));
  }
  
  /* Return true if the given memory attributes are equal.  */
*************** mem_attrs_htab_hash (const void *x)
*** 268,283 ****
  static bool
  mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
  {
!   return (p->alias == q->alias
          && p->offset_known_p == q->offset_known_p
          && (!p->offset_known_p || p->offset == q->offset)
          && p->size_known_p == q->size_known_p
          && (!p->size_known_p || p->size == q->size)
          && p->align == q->align
          && p->addrspace == q->addrspace
!         && (p->expr == q->expr
!             || (p->expr != NULL_TREE && q->expr != NULL_TREE
!                 && operand_equal_p (p->expr, q->expr, 0))));
  }
  
  /* Returns nonzero if the value represented by X (which is really a
--- 268,283 ----
  static bool
  mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
  {
!   return (p->mem.ref_alias_set == q->mem.ref_alias_set
          && p->offset_known_p == q->offset_known_p
          && (!p->offset_known_p || p->offset == q->offset)
          && p->size_known_p == q->size_known_p
          && (!p->size_known_p || p->size == q->size)
          && p->align == q->align
          && p->addrspace == q->addrspace
!         && (p->mem.ref == q->mem.ref
!             || (p->mem.ref != NULL_TREE && q->mem.ref != NULL_TREE
!                 && operand_equal_p (p->mem.ref, q->mem.ref, 0))));
  }
  
  /* Returns nonzero if the value represented by X (which is really a
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1586,1591 ****
--- 1586,1592 ----
    tree type;
    struct mem_attrs attrs, *defattrs, *refattrs;
    addr_space_t as;
+   alias_set_type alias_set;
  
    /* 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
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1607,1613 ****
  
    /* Get the alias set from the expression or type (perhaps using a
       front-end routine) and use it.  */
!   attrs.alias = get_alias_set (t);
  
    MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
--- 1608,1614 ----
  
    /* Get the alias set from the expression or type (perhaps using a
       front-end routine) and use it.  */
!   alias_set = get_alias_set (t);
  
    MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1618,1624 ****
      {
        /* ??? Can this ever happen?  Calling this routine on a MEM that
         already carries memory attributes should probably be invalid.  */
!       attrs.expr = refattrs->expr;
        attrs.offset_known_p = refattrs->offset_known_p;
        attrs.offset = refattrs->offset;
        attrs.size_known_p = refattrs->size_known_p;
--- 1619,1625 ----
      {
        /* ??? Can this ever happen?  Calling this routine on a MEM that
         already carries memory attributes should probably be invalid.  */
!       attrs.mem = refattrs->mem;
        attrs.offset_known_p = refattrs->offset_known_p;
        attrs.offset = refattrs->offset;
        attrs.size_known_p = refattrs->size_known_p;
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1630,1636 ****
    else
      {
        defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
!       gcc_assert (!defattrs->expr);
        gcc_assert (!defattrs->offset_known_p);
  
        /* Respect mode size.  */
--- 1631,1637 ----
    else
      {
        defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
!       gcc_assert (!defattrs->mem.ref);
        gcc_assert (!defattrs->offset_known_p);
  
        /* Respect mode size.  */
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1712,1718 ****
        /* If this is a decl, set the attributes of the MEM from it.  */
        if (DECL_P (t))
        {
!         attrs.expr = t;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
--- 1713,1720 ----
        /* If this is a decl, set the attributes of the MEM from it.  */
        if (DECL_P (t))
        {
!         ao_ref_init (&attrs.mem, t);
!         attrs.mem.ref_alias_set = alias_set;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1726,1732 ****
        /* If this is a field reference, record it.  */
        else if (TREE_CODE (t) == COMPONENT_REF)
        {
!         attrs.expr = t;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
--- 1728,1735 ----
        /* If this is a field reference, record it.  */
        else if (TREE_CODE (t) == COMPONENT_REF)
        {
!         ao_ref_init (&attrs.mem, t);
!         attrs.mem.ref_alias_set = alias_set;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1769,1775 ****
          if (DECL_P (t2)
              || TREE_CODE (t2) == COMPONENT_REF)
            {
!             attrs.expr = t2;
              attrs.offset_known_p = false;
              if (tree_fits_uhwi_p (off_tree))
                {
--- 1772,1779 ----
          if (DECL_P (t2)
              || TREE_CODE (t2) == COMPONENT_REF)
            {
!             ao_ref_init (&attrs.mem, t2);
!             attrs.mem.ref_alias_set = alias_set;
              attrs.offset_known_p = false;
              if (tree_fits_uhwi_p (off_tree))
                {
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1785,1791 ****
        else if (TREE_CODE (t) == MEM_REF 
               || TREE_CODE (t) == TARGET_MEM_REF)
        {
!         attrs.expr = t;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
--- 1789,1796 ----
        else if (TREE_CODE (t) == MEM_REF 
               || TREE_CODE (t) == TARGET_MEM_REF)
        {
!         ao_ref_init (&attrs.mem, t);
!         attrs.mem.ref_alias_set = alias_set;
          attrs.offset_known_p = true;
          attrs.offset = 0;
          apply_bitpos = bitpos;
*************** set_mem_alias_set (rtx mem, alias_set_ty
*** 1839,1845 ****
    /* If the new and old alias sets don't conflict, something is wrong.  */
    gcc_checking_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
    attrs = *get_mem_attrs (mem);
!   attrs.alias = set;
    set_mem_attrs (mem, &attrs);
  }
  
--- 1844,1850 ----
    /* If the new and old alias sets don't conflict, something is wrong.  */
    gcc_checking_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
    attrs = *get_mem_attrs (mem);
!   attrs.mem.ref_alias_set = set;
    set_mem_attrs (mem, &attrs);
  }
  
*************** set_mem_expr (rtx mem, tree expr)
*** 1875,1881 ****
    struct mem_attrs attrs;
  
    attrs = *get_mem_attrs (mem);
!   attrs.expr = expr;
    set_mem_attrs (mem, &attrs);
  }
  
--- 1880,1887 ----
    struct mem_attrs attrs;
  
    attrs = *get_mem_attrs (mem);
!   ao_ref_init (&attrs.mem, expr);
!   attrs.mem.ref_alias_set = MEM_ALIAS_SET (mem);
    set_mem_attrs (mem, &attrs);
  }
  
*************** change_address (rtx memref, enum machine
*** 1981,1987 ****
  
    attrs = *get_mem_attrs (memref);
    defattrs = mode_mem_attrs[(int) mmode];
!   attrs.expr = NULL_TREE;
    attrs.offset_known_p = false;
    attrs.size_known_p = defattrs->size_known_p;
    attrs.size = defattrs->size;
--- 1987,1994 ----
  
    attrs = *get_mem_attrs (memref);
    defattrs = mode_mem_attrs[(int) mmode];
!   ao_ref_init (&attrs.mem, NULL_TREE);
!   attrs.mem.ref_alias_set = MEM_ALIAS_SET (memref);
    attrs.offset_known_p = false;
    attrs.size_known_p = defattrs->size_known_p;
    attrs.size = defattrs->size;
*************** adjust_address_1 (rtx memref, enum machi
*** 2098,2105 ****
    /* Conservatively drop the object if we don't know where we start from.  */
    if (adjust_object && (!attrs.offset_known_p || !attrs.size_known_p))
      {
!       attrs.expr = NULL_TREE;
!       attrs.alias = 0;
      }
  
    /* Compute the new values of the memory attributes due to this adjustment.
--- 2105,2112 ----
    /* Conservatively drop the object if we don't know where we start from.  */
    if (adjust_object && (!attrs.offset_known_p || !attrs.size_known_p))
      {
!       ao_ref_init (&attrs.mem, NULL_TREE);
!       attrs.mem.ref_alias_set = 0;
      }
  
    /* Compute the new values of the memory attributes due to this adjustment.
*************** adjust_address_1 (rtx memref, enum machi
*** 2111,2118 ****
        /* Drop the object if the new left end is not within its bounds.  */
        if (adjust_object && attrs.offset < 0)
        {
!         attrs.expr = NULL_TREE;
!         attrs.alias = 0;
        }
      }
  
--- 2118,2125 ----
        /* Drop the object if the new left end is not within its bounds.  */
        if (adjust_object && attrs.offset < 0)
        {
!         ao_ref_init (&attrs.mem, NULL_TREE);
!         attrs.mem.ref_alias_set = 0;
        }
      }
  
*************** adjust_address_1 (rtx memref, enum machi
*** 2130,2137 ****
        /* Drop the object if the new right end is not within its bounds.  */
        if (adjust_object && (offset + size) > attrs.size)
        {
!         attrs.expr = NULL_TREE;
!         attrs.alias = 0;
        }
        attrs.size_known_p = true;
        attrs.size = size;
--- 2137,2144 ----
        /* Drop the object if the new right end is not within its bounds.  */
        if (adjust_object && (offset + size) > attrs.size)
        {
!         ao_ref_init (&attrs.mem, NULL_TREE);
!         attrs.mem.ref_alias_set = 0;
        }
        attrs.size_known_p = true;
        attrs.size = size;
*************** widen_memory_access (rtx memref, enum ma
*** 2254,2271 ****
    /* If we don't know what offset we were at within the expression, then
       we can't know if we've overstepped the bounds.  */
    if (! attrs.offset_known_p)
!     attrs.expr = NULL_TREE;
  
!   while (attrs.expr)
      {
!       if (TREE_CODE (attrs.expr) == COMPONENT_REF)
        {
!         tree field = TREE_OPERAND (attrs.expr, 1);
!         tree offset = component_ref_field_offset (attrs.expr);
  
          if (! DECL_SIZE_UNIT (field))
            {
!             attrs.expr = NULL_TREE;
              break;
            }
  
--- 2261,2278 ----
    /* If we don't know what offset we were at within the expression, then
       we can't know if we've overstepped the bounds.  */
    if (! attrs.offset_known_p)
!     ao_ref_init (&attrs.mem, NULL_TREE);
  
!   while (attrs.mem.ref)
      {
!       if (TREE_CODE (attrs.mem.ref) == COMPONENT_REF)
        {
!         tree field = TREE_OPERAND (attrs.mem.ref, 1);
!         tree offset = component_ref_field_offset (attrs.mem.ref);
  
          if (! DECL_SIZE_UNIT (field))
            {
!             attrs.mem.ref = NULL_TREE;
              break;
            }
  
*************** widen_memory_access (rtx memref, enum ma
*** 2278,2314 ****
  
          if (! tree_fits_uhwi_p (offset))
            {
!             attrs.expr = NULL_TREE;
              break;
            }
  
!         attrs.expr = TREE_OPERAND (attrs.expr, 0);
          attrs.offset += tree_to_uhwi (offset);
          attrs.offset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
                           / BITS_PER_UNIT);
        }
        /* Similarly for the decl.  */
!       else if (DECL_P (attrs.expr)
!              && DECL_SIZE_UNIT (attrs.expr)
!              && TREE_CODE (DECL_SIZE_UNIT (attrs.expr)) == INTEGER_CST
!              && compare_tree_int (DECL_SIZE_UNIT (attrs.expr), size) >= 0
               && (! attrs.offset_known_p || attrs.offset >= 0))
        break;
        else
        {
          /* The widened memory access overflows the expression, which means
             that it could alias another expression.  Zap it.  */
!         attrs.expr = NULL_TREE;
          break;
        }
      }
  
!   if (! attrs.expr)
      attrs.offset_known_p = false;
  
    /* The widened memory may alias other stuff, so zap the alias set.  */
    /* ??? Maybe use get_alias_set on any remaining expression.  */
!   attrs.alias = 0;
    attrs.size_known_p = true;
    attrs.size = size;
    set_mem_attrs (new_rtx, &attrs);
--- 2285,2328 ----
  
          if (! tree_fits_uhwi_p (offset))
            {
!             attrs.mem.ref = NULL_TREE;
              break;
            }
  
!         attrs.mem.ref = TREE_OPERAND (attrs.mem.ref, 0);
          attrs.offset += tree_to_uhwi (offset);
          attrs.offset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
                           / BITS_PER_UNIT);
        }
        /* Similarly for the decl.  */
!       else if (DECL_P (attrs.mem.ref)
!              && DECL_SIZE_UNIT (attrs.mem.ref)
!              && TREE_CODE (DECL_SIZE_UNIT (attrs.mem.ref)) == INTEGER_CST
!              && compare_tree_int (DECL_SIZE_UNIT (attrs.mem.ref), size) >= 0
               && (! attrs.offset_known_p || attrs.offset >= 0))
        break;
        else
        {
          /* The widened memory access overflows the expression, which means
             that it could alias another expression.  Zap it.  */
!         attrs.mem.ref = NULL_TREE;
          break;
        }
      }
  
!   if (! attrs.mem.ref)
      attrs.offset_known_p = false;
  
+   /* If we have cached the ao_ref already adjust its offset/size.  */
+   if (attrs.mem.base)
+     {
+       attrs.mem.offset += offset;
+       attrs.mem.size = size;
+     }
+ 
    /* The widened memory may alias other stuff, so zap the alias set.  */
    /* ??? Maybe use get_alias_set on any remaining expression.  */
!   attrs.mem.ref_alias_set = 0;
    attrs.size_known_p = true;
    attrs.size = size;
    set_mem_attrs (new_rtx, &attrs);
*************** get_spill_slot_decl (bool force_build_p)
*** 2338,2345 ****
    rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
    MEM_NOTRAP_P (rd) = 1;
    attrs = *mode_mem_attrs[(int) BLKmode];
!   attrs.alias = new_alias_set ();
!   attrs.expr = d;
    set_mem_attrs (rd, &attrs);
    SET_DECL_RTL (d, rd);
  
--- 2352,2359 ----
    rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
    MEM_NOTRAP_P (rd) = 1;
    attrs = *mode_mem_attrs[(int) BLKmode];
!   ao_ref_init (&attrs.mem, d);
!   attrs.mem.ref_alias_set = new_alias_set ();
    set_mem_attrs (rd, &attrs);
    SET_DECL_RTL (d, rd);
  
*************** set_mem_attrs_for_spill (rtx mem)
*** 2359,2366 ****
    rtx addr;
  
    attrs = *get_mem_attrs (mem);
!   attrs.expr = get_spill_slot_decl (true);
!   attrs.alias = MEM_ALIAS_SET (DECL_RTL (attrs.expr));
    attrs.addrspace = ADDR_SPACE_GENERIC;
  
    /* We expect the incoming memory to be of the form:
--- 2373,2380 ----
    rtx addr;
  
    attrs = *get_mem_attrs (mem);
!   ao_ref_init (&attrs.mem, get_spill_slot_decl (true));
!   attrs.mem.ref_alias_set = MEM_ALIAS_SET (DECL_RTL (attrs.mem.ref));
    attrs.addrspace = ADDR_SPACE_GENERIC;
  
    /* We expect the incoming memory to be of the form:

Reply via email to