Patchwork [2/5] Add a set_mem_attrs function

login
register
mail settings
Submitter Richard Sandiford
Date July 17, 2011, 2:29 p.m.
Message ID <87aacdugk1.fsf@firetop.home>
Download mbox | patch
Permalink /patch/105061/
State New
Headers show

Comments

Richard Sandiford - July 17, 2011, 2:29 p.m.
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.

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.
Richard Guenther - July 18, 2011, 9:32 a.m.
On Sun, Jul 17, 2011 at 4:29 PM, Richard Sandiford
<rdsandiford@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;
>  }
>
>

Patch

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;
 }