On Sun, Jul 17, 2011 at 4:29 PM, Richard Sandiford
<rdsandif...@googlemail.com> wrote:
> Internally, emit-rtl.c uses the idiom:
>
>  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
>                                   MEM_OFFSET (mem), size, MEM_ALIGN (mem),
>                                   MEM_ADDR_SPACE (mem), GET_MODE (mem));
>
> where we're reiterating most of the current information and changing
> just one field.  Even when we're changing several fields:
>
>  MEM_ATTRS (new_rtx)
>    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
>                     MEM_ADDR_SPACE (memref), mmode);
>
> it's not immediately obvious what those 0s are.  This patch uses
> gen_mem_attrs to clean this up a bit (I hope) and make patch 5
> a little easier.
>
> The patch also changes the way find_mem_attrs (now set_mem_attrs)
> handles null sizes.  The old code would ignore null sizes when
> checking whether a non-BLKmode reference had the default attributes,
> but it would otherwise keep the size as unknown.  This seems wrong:
> the caller should be providing the actual size.  The only caller
> that didn't was offset_address.
>
> I was tempted to add:
>
>  struct mem_attrs *defattrs;
>
>  defattrs = mode_mem_attrs[(int) GET_MODE (mem)];
>  gcc_assert (!defattrs->size || attrs->size == defattrs->size);
>
> to assert that, when not using BLKmode, the size should match the mode's
> size.  Unfortunately, that isn't possible as things stand: callers like
> expand_assignment expand the inner part of a reference to rtl, then call
> set_mem_attributes_minus_bitpos to set its attributes to those of the
> outer reference.  At this stage, the memory reference still has its
> original (inner) mode.  The mode is only corrected later.
>
> It might be nice to clean that up too, but I'd rather leave it for
> another time.

Ok if there are no comments from others.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * emit-rtl.c (mem_attrs_eq_p): New function, split out from...
>        (mem_attrs_htab_eq): ...here.
>        (find_mem_attrs): Replace with...
>        (set_mem_attrs): ...this function.  Take a mem_attrs structure
>        rather than individual fields.
>        (set_mem_attributes_minus_bitpos, set_mem_alias_set)
>        (set_mem_addr_space, set_mem_align, set_mem_expr, set_mem_offset)
>        (set_mem_size, change_address, adjust_address_1, offset_address)
>        (widen_memory_access, get_spill_slot_decl, set_mem_attrs_for_spill):
>        Update accordingly.
>
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 10:06:49.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 10:06:53.000000000 +0100
> @@ -261,16 +261,11 @@ mem_attrs_htab_hash (const void *x)
>          ^ (size_t) iterative_hash_expr (p->expr, 0));
>  }
>
> -/* Returns nonzero 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 *).  */
> +/* Return true if the given memory attributes are equal.  */
>
> -static int
> -mem_attrs_htab_eq (const void *x, const void *y)
> +static bool
> +mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
>  {
> -  const mem_attrs *const p = (const mem_attrs *) x;
> -  const mem_attrs *const q = (const mem_attrs *) y;
> -
>   return (p->alias == q->alias && p->offset == q->offset
>          && p->size == q->size && p->align == q->align
>          && p->addrspace == q->addrspace
> @@ -279,43 +274,38 @@ mem_attrs_htab_eq (const void *x, const
>                  && operand_equal_p (p->expr, q->expr, 0))));
>  }
>
> -/* Allocate a new mem_attrs structure and insert it into the hash table if
> -   one identical to it is not already in the table.  We are doing this for
> -   MEM of mode MODE.  */
> +/* Returns nonzero 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 mem_attrs *
> -find_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
> -               unsigned int align, addr_space_t addrspace,
> -               enum machine_mode mode)
> +static int
> +mem_attrs_htab_eq (const void *x, const void *y)
>  {
> -  mem_attrs attrs;
> -  void **slot;
> +  return mem_attrs_eq_p ((const mem_attrs *) x, (const mem_attrs *) y);
> +}
>
> -  /* If everything is the default, we can just return zero.
> -     This must match what the corresponding MEM_* macros return when the
> -     field is not present.  */
> -  if (alias == 0 && expr == 0 && offset == 0 && addrspace == 0
> -      && (size == 0
> -         || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
> -      && (STRICT_ALIGNMENT && mode != BLKmode
> -         ? align == GET_MODE_ALIGNMENT (mode) : align == BITS_PER_UNIT))
> -    return 0;
> +/* Set MEM's memory attributes so that they are the same as ATTRS.  */
>
> -  attrs.alias = alias;
> -  attrs.expr = expr;
> -  attrs.offset = offset;
> -  attrs.size = size;
> -  attrs.align = align;
> -  attrs.addrspace = addrspace;
> +static void
> +set_mem_attrs (rtx mem, mem_attrs *attrs)
> +{
> +  void **slot;
> +
> +  /* If everything is the default, we can just clear the attributes.  */
> +  if (mem_attrs_eq_p (attrs, mode_mem_attrs[(int) GET_MODE (mem)]))
> +    {
> +      MEM_ATTRS (mem) = 0;
> +      return;
> +    }
>
> -  slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT);
> +  slot = htab_find_slot (mem_attrs_htab, attrs, INSERT);
>   if (*slot == 0)
>     {
>       *slot = ggc_alloc_mem_attrs ();
> -      memcpy (*slot, &attrs, sizeof (mem_attrs));
> +      memcpy (*slot, attrs, sizeof (mem_attrs));
>     }
>
> -  return (mem_attrs *) *slot;
> +  MEM_ATTRS (mem) = (mem_attrs *) *slot;
>  }
>
>  /* Returns a hash code for X (which is a really a reg_attrs *).  */
> @@ -1553,13 +1543,9 @@ get_mem_align_offset (rtx mem, unsigned
>  set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
>                                 HOST_WIDE_INT bitpos)
>  {
> -  alias_set_type alias;
> -  tree expr = NULL;
> -  rtx offset = NULL_RTX;
> -  rtx size = NULL_RTX;
> -  unsigned int align = BITS_PER_UNIT;
>   HOST_WIDE_INT apply_bitpos = 0;
>   tree type;
> +  struct mem_attrs attrs, *defattrs, *refattrs;
>
>   /* 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
> @@ -1577,9 +1563,11 @@ set_mem_attributes_minus_bitpos (rtx ref
>      set_mem_attributes.  */
>   gcc_assert (!DECL_P (t) || ref != DECL_RTL_IF_SET (t));
>
> +  memset (&attrs, 0, sizeof (attrs));
> +
>   /* Get the alias set from the expression or type (perhaps using a
>      front-end routine) and use it.  */
> -  alias = get_alias_set (t);
> +  attrs.alias = get_alias_set (t);
>
>   MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
>   MEM_IN_STRUCT_P (ref)
> @@ -1594,28 +1582,35 @@ set_mem_attributes_minus_bitpos (rtx ref
>     MEM_SCALAR_P (ref) = 1;
>
>   /* Default values from pre-existing memory attributes if present.  */
> -  if (MEM_ATTRS (ref))
> +  refattrs = MEM_ATTRS (ref);
> +  if (refattrs)
>     {
>       /* ??? Can this ever happen?  Calling this routine on a MEM that
>         already carries memory attributes should probably be invalid.  */
> -      expr = MEM_EXPR (ref);
> -      offset = MEM_OFFSET (ref);
> -      size = MEM_SIZE (ref);
> -      align = MEM_ALIGN (ref);
> +      attrs.expr = refattrs->expr;
> +      attrs.offset = refattrs->offset;
> +      attrs.size = refattrs->size;
> +      attrs.align = refattrs->align;
>     }
>
>   /* Otherwise, default values from the mode of the MEM reference.  */
> -  else if (GET_MODE (ref) != BLKmode)
> +  else
>     {
> +      defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
> +      gcc_assert (!defattrs->expr);
> +      gcc_assert (!defattrs->offset);
> +
>       /* Respect mode size.  */
> -      size = GEN_INT (GET_MODE_SIZE (GET_MODE (ref)));
> +      attrs.size = defattrs->size;
>       /* ??? Is this really necessary?  We probably should always get
>         the size from the type below.  */
>
>       /* Respect mode alignment for STRICT_ALIGNMENT targets if T is a type;
>          if T is an object, always compute the object alignment below.  */
> -      if (STRICT_ALIGNMENT && TYPE_P (t))
> -       align = GET_MODE_ALIGNMENT (GET_MODE (ref));
> +      if (TYPE_P (t))
> +       attrs.align = defattrs->align;
> +      else
> +       attrs.align = BITS_PER_UNIT;
>       /* ??? If T is a type, respecting mode alignment may *also* be wrong
>         e.g. if the type carries an alignment attribute.  Should we be
>         able to simply always use TYPE_ALIGN?  */
> @@ -1624,7 +1619,7 @@ set_mem_attributes_minus_bitpos (rtx ref
>   /* We can set the alignment from the type if we are making an object,
>      this is an INDIRECT_REF, or if TYPE_ALIGN_OK.  */
>   if (objectp || TREE_CODE (t) == INDIRECT_REF || TYPE_ALIGN_OK (type))
> -    align = MAX (align, TYPE_ALIGN (type));
> +    attrs.align = MAX (attrs.align, TYPE_ALIGN (type));
>
>   else if (TREE_CODE (t) == MEM_REF)
>     {
> @@ -1634,12 +1629,13 @@ set_mem_attributes_minus_bitpos (rtx ref
>              || CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))))
>        {
>          if (DECL_P (TREE_OPERAND (op0, 0)))
> -           align = DECL_ALIGN (TREE_OPERAND (op0, 0));
> +           attrs.align = DECL_ALIGN (TREE_OPERAND (op0, 0));
>          else if (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
>            {
> -             align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
> +             attrs.align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
>  #ifdef CONSTANT_ALIGNMENT
> -             align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
> +             attrs.align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0),
> +                                               attrs.align);
>  #endif
>            }
>          if (TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) != 0)
> @@ -1647,23 +1643,23 @@ set_mem_attributes_minus_bitpos (rtx ref
>              unsigned HOST_WIDE_INT ioff
>                = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
>              unsigned HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
> -             align = MIN (aoff, align);
> +             attrs.align = MIN (aoff, attrs.align);
>            }
>        }
>       else
>        /* ??? This isn't fully correct, we can't set the alignment from the
>           type in all cases.  */
> -       align = MAX (align, TYPE_ALIGN (type));
> +       attrs.align = MAX (attrs.align, TYPE_ALIGN (type));
>     }
>
>   else if (TREE_CODE (t) == TARGET_MEM_REF)
>     /* ??? This isn't fully correct, we can't set the alignment from the
>        type in all cases.  */
> -    align = MAX (align, TYPE_ALIGN (type));
> +    attrs.align = MAX (attrs.align, TYPE_ALIGN (type));
>
>   /* If the size is known, we can set that.  */
>   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
> -    size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
> +    attrs.size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
>
>   /* If T is not a type, we may be able to deduce some more information about
>      the expression.  */
> @@ -1700,22 +1696,22 @@ set_mem_attributes_minus_bitpos (rtx ref
>       /* If this is a decl, set the attributes of the MEM from it.  */
>       if (DECL_P (t))
>        {
> -         expr = t;
> -         offset = const0_rtx;
> +         attrs.expr = t;
> +         attrs.offset = const0_rtx;
>          apply_bitpos = bitpos;
> -         size = (DECL_SIZE_UNIT (t)
> -                 && host_integerp (DECL_SIZE_UNIT (t), 1)
> -                 ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
> -         align = DECL_ALIGN (t);
> +         attrs.size = (DECL_SIZE_UNIT (t)
> +                       && host_integerp (DECL_SIZE_UNIT (t), 1)
> +                       ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
> +         attrs.align = DECL_ALIGN (t);
>          align_computed = true;
>        }
>
>       /* If this is a constant, we know the alignment.  */
>       else if (CONSTANT_CLASS_P (t))
>        {
> -         align = TYPE_ALIGN (type);
> +         attrs.align = TYPE_ALIGN (type);
>  #ifdef CONSTANT_ALIGNMENT
> -         align = CONSTANT_ALIGNMENT (t, align);
> +         attrs.align = CONSTANT_ALIGNMENT (t, attrs.align);
>  #endif
>          align_computed = true;
>        }
> @@ -1727,8 +1723,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>       else if (TREE_CODE (t) == COMPONENT_REF
>               && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
>        {
> -         expr = t;
> -         offset = const0_rtx;
> +         attrs.expr = t;
> +         attrs.offset = const0_rtx;
>          apply_bitpos = bitpos;
>          /* ??? Any reason the field size would be different than
>             the size we got from the type?  */
> @@ -1768,27 +1764,27 @@ set_mem_attributes_minus_bitpos (rtx ref
>
>          if (DECL_P (t2))
>            {
> -             expr = t2;
> -             offset = NULL;
> +             attrs.expr = t2;
> +             attrs.offset = NULL;
>              if (host_integerp (off_tree, 1))
>                {
>                  HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1);
>                  HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
> -                 align = DECL_ALIGN (t2);
> -                 if (aoff && (unsigned HOST_WIDE_INT) aoff < align)
> -                   align = aoff;
> +                 attrs.align = DECL_ALIGN (t2);
> +                 if (aoff && (unsigned HOST_WIDE_INT) aoff < attrs.align)
> +                   attrs.align = aoff;
>                  align_computed = true;
> -                 offset = GEN_INT (ioff);
> +                 attrs.offset = GEN_INT (ioff);
>                  apply_bitpos = bitpos;
>                }
>            }
>          else if (TREE_CODE (t2) == COMPONENT_REF)
>            {
> -             expr = t2;
> -             offset = NULL;
> +             attrs.expr = t2;
> +             attrs.offset = NULL;
>              if (host_integerp (off_tree, 1))
>                {
> -                 offset = GEN_INT (tree_low_cst (off_tree, 1));
> +                 attrs.offset = GEN_INT (tree_low_cst (off_tree, 1));
>                  apply_bitpos = bitpos;
>                }
>              /* ??? Any reason the field size would be different than
> @@ -1798,8 +1794,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>          /* If this is an indirect reference, record it.  */
>          else if (TREE_CODE (t) == MEM_REF)
>            {
> -             expr = t;
> -             offset = const0_rtx;
> +             attrs.expr = t;
> +             attrs.offset = const0_rtx;
>              apply_bitpos = bitpos;
>            }
>        }
> @@ -1808,15 +1804,15 @@ set_mem_attributes_minus_bitpos (rtx ref
>       else if (TREE_CODE (t) == MEM_REF
>               || TREE_CODE (t) == TARGET_MEM_REF)
>        {
> -         expr = t;
> -         offset = const0_rtx;
> +         attrs.expr = t;
> +         attrs.offset = const0_rtx;
>          apply_bitpos = bitpos;
>        }
>
>       if (!align_computed && !INDIRECT_REF_P (t))
>        {
>          unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT);
> -         align = MAX (align, obj_align);
> +         attrs.align = MAX (attrs.align, obj_align);
>        }
>     }
>
> @@ -1825,15 +1821,14 @@ set_mem_attributes_minus_bitpos (rtx ref
>      object to contain the negative offset.  */
>   if (apply_bitpos)
>     {
> -      offset = plus_constant (offset, -(apply_bitpos / BITS_PER_UNIT));
> -      if (size)
> -       size = plus_constant (size, apply_bitpos / BITS_PER_UNIT);
> +      attrs.offset = plus_constant (attrs.offset,
> +                                   -(apply_bitpos / BITS_PER_UNIT));
> +      if (attrs.size)
> +       attrs.size = plus_constant (attrs.size, apply_bitpos / BITS_PER_UNIT);
>     }
>
>   /* Now set the attributes we computed above.  */
> -  MEM_ATTRS (ref)
> -    = find_mem_attrs (alias, expr, offset, size, align,
> -                     TYPE_ADDR_SPACE (type), GET_MODE (ref));
> +  set_mem_attrs (ref, &attrs);
>
>   /* If this is already known to be a scalar or aggregate, we are done.  */
>   if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
> @@ -1858,12 +1853,13 @@ set_mem_attributes (rtx ref, tree t, int
>  void
>  set_mem_alias_set (rtx mem, alias_set_type set)
>  {
> +  struct mem_attrs attrs;
> +
>   /* 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)));
> -
> -  MEM_ATTRS (mem) = find_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
> -                                   MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                   MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  attrs = *get_mem_attrs (mem);
> +  attrs.alias = set;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Set the address space of MEM to ADDRSPACE (target-defined).  */
> @@ -1871,9 +1867,11 @@ set_mem_alias_set (rtx mem, alias_set_ty
>  void
>  set_mem_addr_space (rtx mem, addr_space_t addrspace)
>  {
> -  MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                   MEM_OFFSET (mem), MEM_SIZE (mem),
> -                                   MEM_ALIGN (mem), addrspace, GET_MODE 
> (mem));
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.addrspace = addrspace;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Set the alignment of MEM to ALIGN bits.  */
> @@ -1881,9 +1879,11 @@ set_mem_addr_space (rtx mem, addr_space_
>  void
>  set_mem_align (rtx mem, unsigned int align)
>  {
> -  MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                   MEM_OFFSET (mem), MEM_SIZE (mem), align,
> -                                   MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.align = align;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Set the expr for MEM to EXPR.  */
> @@ -1891,10 +1891,11 @@ set_mem_align (rtx mem, unsigned int ali
>  void
>  set_mem_expr (rtx mem, tree expr)
>  {
> -  MEM_ATTRS (mem)
> -    = find_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
> -                     MEM_SIZE (mem), MEM_ALIGN (mem),
> -                     MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.expr = expr;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Set the offset of MEM to OFFSET.  */
> @@ -1902,9 +1903,11 @@ set_mem_expr (rtx mem, tree expr)
>  void
>  set_mem_offset (rtx mem, rtx offset)
>  {
> -  MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                   offset, MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                   MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.offset = offset;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Set the size of MEM to SIZE.  */
> @@ -1912,9 +1915,11 @@ set_mem_offset (rtx mem, rtx offset)
>  void
>  set_mem_size (rtx mem, rtx size)
>  {
> -  MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                   MEM_OFFSET (mem), size, MEM_ALIGN (mem),
> -                                   MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.size = size;
> +  set_mem_attrs (mem, &attrs);
>  }
>
>  /* Return a memory reference like MEMREF, but with its mode changed to MODE
> @@ -1961,31 +1966,28 @@ change_address_1 (rtx memref, enum machi
>  rtx
>  change_address (rtx memref, enum machine_mode mode, rtx addr)
>  {
> -  rtx new_rtx = change_address_1 (memref, mode, addr, 1), size;
> +  rtx new_rtx = change_address_1 (memref, mode, addr, 1);
>   enum machine_mode mmode = GET_MODE (new_rtx);
> -  unsigned int align;
> +  struct mem_attrs attrs, *defattrs;
>
> -  size = mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode));
> -  align = mmode == BLKmode ? BITS_PER_UNIT : GET_MODE_ALIGNMENT (mmode);
> +  attrs = *get_mem_attrs (memref);
> +  defattrs = mode_mem_attrs[(int) mmode];
> +  attrs.expr = defattrs->expr;
> +  attrs.offset = defattrs->offset;
> +  attrs.size = defattrs->size;
> +  attrs.align = defattrs->align;
>
>   /* If there are no changes, just return the original memory reference.  */
>   if (new_rtx == memref)
>     {
> -      if (MEM_ATTRS (memref) == 0
> -         || (MEM_EXPR (memref) == NULL
> -             && MEM_OFFSET (memref) == NULL
> -             && MEM_SIZE (memref) == size
> -             && MEM_ALIGN (memref) == align))
> +      if (mem_attrs_eq_p (get_mem_attrs (memref), &attrs))
>        return new_rtx;
>
>       new_rtx = gen_rtx_MEM (mmode, XEXP (memref, 0));
>       MEM_COPY_ATTRIBUTES (new_rtx, memref);
>     }
>
> -  MEM_ATTRS (new_rtx)
> -    = find_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
> -                     MEM_ADDR_SPACE (memref), mmode);
> -
> +  set_mem_attrs (new_rtx, &attrs);
>   return new_rtx;
>  }
>
> @@ -2001,16 +2003,17 @@ adjust_address_1 (rtx memref, enum machi
>  {
>   rtx addr = XEXP (memref, 0);
>   rtx new_rtx;
> -  rtx memoffset = MEM_OFFSET (memref);
> -  rtx size = 0;
> -  unsigned int memalign = MEM_ALIGN (memref);
> -  addr_space_t as = MEM_ADDR_SPACE (memref);
> -  enum machine_mode address_mode = targetm.addr_space.address_mode (as);
> +  enum machine_mode address_mode;
>   int pbits;
> +  struct mem_attrs attrs, *defattrs;
> +  unsigned HOST_WIDE_INT max_align;
> +
> +  attrs = *get_mem_attrs (memref);
>
>   /* If there are no changes, just return the original memory reference.  */
>   if (mode == GET_MODE (memref) && !offset
> -      && (!validate || memory_address_addr_space_p (mode, addr, as)))
> +      && (!validate || memory_address_addr_space_p (mode, addr,
> +                                                   attrs.addrspace)))
>     return memref;
>
>   /* ??? Prefer to create garbage instead of creating shared rtl.
> @@ -2020,6 +2023,7 @@ adjust_address_1 (rtx memref, enum machi
>
>   /* Convert a possibly large offset to a signed value within the
>      range of the target address space.  */
> +  address_mode = targetm.addr_space.address_mode (attrs.addrspace);
>   pbits = GET_MODE_BITSIZE (address_mode);
>   if (HOST_BITS_PER_WIDE_INT > pbits)
>     {
> @@ -2051,27 +2055,26 @@ adjust_address_1 (rtx memref, enum machi
>
>   /* Compute the new values of the memory attributes due to this adjustment.
>      We add the offsets and update the alignment.  */
> -  if (memoffset)
> -    memoffset = GEN_INT (offset + INTVAL (memoffset));
> +  if (attrs.offset)
> +    attrs.offset = GEN_INT (offset + INTVAL (attrs.offset));
>
>   /* Compute the new alignment by taking the MIN of the alignment and the
>      lowest-order set bit in OFFSET, but don't change the alignment if OFFSET
>      if zero.  */
>   if (offset != 0)
> -    memalign
> -      = MIN (memalign,
> -            (unsigned HOST_WIDE_INT) (offset & -offset) * BITS_PER_UNIT);
> +    {
> +      max_align = (offset & -offset) * BITS_PER_UNIT;
> +      attrs.align = MIN (attrs.align, max_align);
> +    }
>
>   /* We can compute the size in a number of ways.  */
> -  if (GET_MODE (new_rtx) != BLKmode)
> -    size = GEN_INT (GET_MODE_SIZE (GET_MODE (new_rtx)));
> -  else if (MEM_SIZE (memref))
> -    size = plus_constant (MEM_SIZE (memref), -offset);
> -
> -  MEM_ATTRS (new_rtx) = find_mem_attrs (MEM_ALIAS_SET (memref),
> -                                       MEM_EXPR (memref),
> -                                       memoffset, size, memalign, as,
> -                                       GET_MODE (new_rtx));
> +  defattrs = mode_mem_attrs[(int) GET_MODE (new_rtx)];
> +  if (defattrs->size)
> +    attrs.size = defattrs->size;
> +  else if (attrs.size)
> +    attrs.size = plus_constant (attrs.size, -offset);
> +
> +  set_mem_attrs (new_rtx, &attrs);
>
>   /* At some point, we should validate that this offset is within the object,
>      if all the appropriate values are known.  */
> @@ -2099,9 +2102,11 @@ adjust_automodify_address_1 (rtx memref,
>  offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
>  {
>   rtx new_rtx, addr = XEXP (memref, 0);
> -  addr_space_t as = MEM_ADDR_SPACE (memref);
> -  enum machine_mode address_mode = targetm.addr_space.address_mode (as);
> +  enum machine_mode address_mode;
> +  struct mem_attrs attrs;
>
> +  attrs = *get_mem_attrs (memref);
> +  address_mode = targetm.addr_space.address_mode (attrs.addrspace);
>   new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset);
>
>   /* At this point we don't know _why_ the address is invalid.  It
> @@ -2111,7 +2116,8 @@ offset_address (rtx memref, rtx offset,
>      being able to recognize the magic around pic_offset_table_rtx.
>      This stuff is fragile, and is yet another example of why it is
>      bad to expose PIC machinery too early.  */
> -  if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, as)
> +  if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx,
> +                                    attrs.addrspace)
>       && GET_CODE (addr) == PLUS
>       && XEXP (addr, 0) == pic_offset_table_rtx)
>     {
> @@ -2128,10 +2134,10 @@ offset_address (rtx memref, rtx offset,
>
>   /* Update the alignment to reflect the offset.  Reset the offset, which
>      we don't know.  */
> -  MEM_ATTRS (new_rtx)
> -    = find_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
> -                     MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
> -                     as, GET_MODE (new_rtx));
> +  attrs.offset = 0;
> +  attrs.size = mode_mem_attrs[(int) GET_MODE (new_rtx)]->size;
> +  attrs.align = MIN (attrs.align, pow2 * BITS_PER_UNIT);
> +  set_mem_attrs (new_rtx, &attrs);
>   return new_rtx;
>  }
>
> @@ -2166,29 +2172,30 @@ replace_equiv_address_nv (rtx memref, rt
>  widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT 
> offset)
>  {
>   rtx new_rtx = adjust_address_1 (memref, mode, offset, 1, 1);
> -  tree expr = MEM_EXPR (new_rtx);
> -  rtx memoffset = MEM_OFFSET (new_rtx);
> +  struct mem_attrs attrs;
>   unsigned int size = GET_MODE_SIZE (mode);
>
>   /* If there are no changes, just return the original memory reference.  */
>   if (new_rtx == memref)
>     return new_rtx;
>
> +  attrs = *get_mem_attrs (new_rtx);
> +
>   /* 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 (! memoffset)
> -    expr = NULL_TREE;
> +  if (! attrs.offset)
> +    attrs.expr = NULL_TREE;
>
> -  while (expr)
> +  while (attrs.expr)
>     {
> -      if (TREE_CODE (expr) == COMPONENT_REF)
> +      if (TREE_CODE (attrs.expr) == COMPONENT_REF)
>        {
> -         tree field = TREE_OPERAND (expr, 1);
> -         tree offset = component_ref_field_offset (expr);
> +         tree field = TREE_OPERAND (attrs.expr, 1);
> +         tree offset = component_ref_field_offset (attrs.expr);
>
>          if (! DECL_SIZE_UNIT (field))
>            {
> -             expr = NULL_TREE;
> +             attrs.expr = NULL_TREE;
>              break;
>            }
>
> @@ -2196,48 +2203,46 @@ widen_memory_access (rtx memref, enum ma
>             otherwise strip back to the containing structure.  */
>          if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST
>              && compare_tree_int (DECL_SIZE_UNIT (field), size) >= 0
> -             && INTVAL (memoffset) >= 0)
> +             && INTVAL (attrs.offset) >= 0)
>            break;
>
>          if (! host_integerp (offset, 1))
>            {
> -             expr = NULL_TREE;
> +             attrs.expr = NULL_TREE;
>              break;
>            }
>
> -         expr = TREE_OPERAND (expr, 0);
> -         memoffset
> -           = (GEN_INT (INTVAL (memoffset)
> +         attrs.expr = TREE_OPERAND (attrs.expr, 0);
> +         attrs.offset
> +           = (GEN_INT (INTVAL (attrs.offset)
>                        + tree_low_cst (offset, 1)
>                        + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
>                           / BITS_PER_UNIT)));
>        }
>       /* Similarly for the decl.  */
> -      else if (DECL_P (expr)
> -              && DECL_SIZE_UNIT (expr)
> -              && TREE_CODE (DECL_SIZE_UNIT (expr)) == INTEGER_CST
> -              && compare_tree_int (DECL_SIZE_UNIT (expr), size) >= 0
> -              && (! memoffset || INTVAL (memoffset) >= 0))
> +      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 || INTVAL (attrs.offset) >= 0))
>        break;
>       else
>        {
>          /* The widened memory access overflows the expression, which means
>             that it could alias another expression.  Zap it.  */
> -         expr = NULL_TREE;
> +         attrs.expr = NULL_TREE;
>          break;
>        }
>     }
>
> -  if (! expr)
> -    memoffset = NULL_RTX;
> +  if (! attrs.expr)
> +    attrs.offset = NULL_RTX;
>
>   /* The widened memory may alias other stuff, so zap the alias set.  */
>   /* ??? Maybe use get_alias_set on any remaining expression.  */
> -
> -  MEM_ATTRS (new_rtx) = find_mem_attrs (0, expr, memoffset, GEN_INT (size),
> -                                       MEM_ALIGN (new_rtx),
> -                                       MEM_ADDR_SPACE (new_rtx), mode);
> -
> +  attrs.alias = 0;
> +  attrs.size = GEN_INT (size);
> +  set_mem_attrs (new_rtx, &attrs);
>   return new_rtx;
>  }
>
> @@ -2249,6 +2254,7 @@ get_spill_slot_decl (bool force_build_p)
>  {
>   tree d = spill_slot_decl;
>   rtx rd;
> +  struct mem_attrs attrs;
>
>   if (d || !force_build_p)
>     return d;
> @@ -2262,8 +2268,10 @@ get_spill_slot_decl (bool force_build_p)
>
>   rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
>   MEM_NOTRAP_P (rd) = 1;
> -  MEM_ATTRS (rd) = find_mem_attrs (new_alias_set (), d, const0_rtx,
> -                                  NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode);
> +  attrs = *mode_mem_attrs[(int) BLKmode];
> +  attrs.alias = new_alias_set ();
> +  attrs.expr = d;
> +  set_mem_attrs (rd, &attrs);
>   SET_DECL_RTL (d, rd);
>
>   return d;
> @@ -2278,25 +2286,24 @@ get_spill_slot_decl (bool force_build_p)
>  void
>  set_mem_attrs_for_spill (rtx mem)
>  {
> -  alias_set_type alias;
> -  rtx addr, offset;
> -  tree expr;
> +  struct mem_attrs attrs;
> +  rtx addr;
>
> -  expr = get_spill_slot_decl (true);
> -  alias = MEM_ALIAS_SET (DECL_RTL (expr));
> +  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:
>        (mem:MODE (plus (reg sfp) (const_int offset)))
>      with perhaps the plus missing for offset = 0.  */
>   addr = XEXP (mem, 0);
> -  offset = const0_rtx;
> +  attrs.offset = const0_rtx;
>   if (GET_CODE (addr) == PLUS
>       && CONST_INT_P (XEXP (addr, 1)))
> -    offset = XEXP (addr, 1);
> +    attrs.offset = XEXP (addr, 1);
>
> -  MEM_ATTRS (mem) = find_mem_attrs (alias, expr, offset,
> -                                   MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                   ADDR_SPACE_GENERIC, GET_MODE (mem));
> +  set_mem_attrs (mem, &attrs);
>   MEM_NOTRAP_P (mem) = 1;
>  }
>
>

Reply via email to