Patchwork [1/5] Add a mode_mem_attrs array

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

Comments

Richard Sandiford - July 17, 2011, 2:18 p.m.
This patch adds an array, mode_mem_attrs, that gives the default attributes
for a given mode.  The defaults depend on STRICT_ALIGNMENT, which on rs6000
and v850 depends on command-line flags, and which could therefore in
principle be changed by __attribute__((optimize)).  Although we might not
cope with that properly in all cases, it does mean that the new array
rightly belongs in target_rtl; it shouldn't be a run-time-invariant global.

The patch also adds a get_mem_attrs function that always returns
the memory's attributes.  This meant renaming a local emit-rtl.c
function out of the way.  (The next patch changes that function
anyway; I just split it out for "ease" of review.)

Richard


gcc/
	* rtl.h (MEM_ALIAS_SET, MEM_EXPR, MEM_OFFSET, MEM_ADDR_SPACE)
	(MEM_SIZE, MEM_ALIGN): Redefine in terms of get_mem_attrs.
	Provide a dummy definition of MEM_ADDR_SPACE for generators.
	(target_rtl): Add x_mode_mem_attrs.
	(mode_mem_attrs): New macro.
	(get_mem_attrs): New function.
	* emit-rtl.c (get_mem_attrs): Rename to...
	(find_mem_attrs): ...this.
	(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.
	(init_emit_regs): Initialize mode_mem_attrs.
Richard Guenther - July 18, 2011, 9:27 a.m.
On Sun, Jul 17, 2011 at 4:18 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch adds an array, mode_mem_attrs, that gives the default attributes
> for a given mode.  The defaults depend on STRICT_ALIGNMENT, which on rs6000
> and v850 depends on command-line flags, and which could therefore in
> principle be changed by __attribute__((optimize)).  Although we might not
> cope with that properly in all cases, it does mean that the new array
> rightly belongs in target_rtl; it shouldn't be a run-time-invariant global.
>
> The patch also adds a get_mem_attrs function that always returns
> the memory's attributes.  This meant renaming a local emit-rtl.c
> function out of the way.  (The next patch changes that function
> anyway; I just split it out for "ease" of review.)

Looks reasonable - but I'd call find_mem_attrs lookup_mem_attrs instead.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * rtl.h (MEM_ALIAS_SET, MEM_EXPR, MEM_OFFSET, MEM_ADDR_SPACE)
>        (MEM_SIZE, MEM_ALIGN): Redefine in terms of get_mem_attrs.
>        Provide a dummy definition of MEM_ADDR_SPACE for generators.
>        (target_rtl): Add x_mode_mem_attrs.
>        (mode_mem_attrs): New macro.
>        (get_mem_attrs): New function.
>        * emit-rtl.c (get_mem_attrs): Rename to...
>        (find_mem_attrs): ...this.
>        (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.
>        (init_emit_regs): Initialize mode_mem_attrs.
>
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h   2011-07-17 10:03:05.000000000 +0100
> +++ gcc/rtl.h   2011-07-17 10:03:07.000000000 +0100
> @@ -1289,39 +1289,36 @@ #define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1
>    in the block and provide defaults if none specified.  */
>  #define REG_ATTRS(RTX) X0REGATTR (RTX, 2)
>
> +#ifndef GENERATOR_FILE
>  /* For a MEM rtx, the alias set.  If 0, this MEM is not in any alias
>    set, and may alias anything.  Otherwise, the MEM can only alias
>    MEMs in a conflicting alias set.  This value is set in a
>    language-dependent manner in the front-end, and should not be
>    altered in the back-end.  These set numbers are tested with
>    alias_sets_conflict_p.  */
> -#define MEM_ALIAS_SET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->alias)
> +#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) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->expr)
> +#define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
>
>  /* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
>    RTX that is always a CONST_INT.  */
> -#define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
> +#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
>
>  /* For a MEM rtx, the address space.  */
> -#define MEM_ADDR_SPACE(RTX) (MEM_ATTRS (RTX) == 0 ? ADDR_SPACE_GENERIC \
> -                                                 : MEM_ATTRS (RTX)->addrspace)
> +#define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
>
>  /* For a MEM rtx, the size in bytes of the MEM, if known, as an RTX that
>    is always a CONST_INT.  */
> -#define MEM_SIZE(RTX)                                                  \
> -(MEM_ATTRS (RTX) != 0 ? MEM_ATTRS (RTX)->size                          \
> - : GET_MODE (RTX) != BLKmode ? GEN_INT (GET_MODE_SIZE (GET_MODE (RTX)))        \
> - : 0)
> +#define MEM_SIZE(RTX) (get_mem_attrs (RTX)->size)
>
>  /* For a MEM rtx, the alignment in bits.  We can use the alignment of the
>    mode as a default when STRICT_ALIGNMENT, but not if not.  */
> -#define MEM_ALIGN(RTX)                                                 \
> -(MEM_ATTRS (RTX) != 0 ? MEM_ATTRS (RTX)->align                         \
> - : (STRICT_ALIGNMENT && GET_MODE (RTX) != BLKmode                      \
> -    ? GET_MODE_ALIGNMENT (GET_MODE (RTX)) : BITS_PER_UNIT))
> +#define MEM_ALIGN(RTX) (get_mem_attrs (RTX)->align)
> +#else
> +#define MEM_ADDR_SPACE(RTX) ADDR_SPACE_GENERIC
> +#endif
>
>  /* For a REG rtx, the decl it is known to refer to, if it is known to
>    refer to part of a DECL.  */
> @@ -2120,6 +2117,9 @@ struct GTY(()) target_rtl {
>   /* Static hunks of RTL used by the aliasing code; these are treated
>      as persistent to avoid unnecessary RTL allocations.  */
>   rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
> +
> +  /* The default memory attributes for each mode.  */
> +  struct mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
>  };
>
>  extern GTY(()) struct target_rtl default_target_rtl;
> @@ -2137,6 +2137,8 @@ #define return_address_pointer_rtx \
>   (this_target_rtl->x_return_address_pointer_rtx)
>  #define top_of_stack \
>   (this_target_rtl->x_top_of_stack)
> +#define mode_mem_attrs \
> +  (this_target_rtl->x_mode_mem_attrs)
>
>  /* Standard pieces of rtx, to be substituted directly into things.  */
>  #define pc_rtx                  (global_rtl[GR_PC])
> @@ -2151,6 +2153,20 @@ #define frame_pointer_rtx       (global_
>  #define hard_frame_pointer_rtx (global_rtl[GR_HARD_FRAME_POINTER])
>  #define arg_pointer_rtx                (global_rtl[GR_ARG_POINTER])
>
> +#ifndef GENERATOR_FILE
> +/* Return the attributes of a MEM rtx.  */
> +static inline struct mem_attrs *
> +get_mem_attrs (const_rtx x)
> +{
> +  struct mem_attrs *attrs;
> +
> +  attrs = MEM_ATTRS (x);
> +  if (!attrs)
> +    attrs = mode_mem_attrs[(int) GET_MODE (x)];
> +  return attrs;
> +}
> +#endif
> +
>  /* Include the RTL generation functions.  */
>
>  #ifndef GENERATOR_FILE
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 10:03:05.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 10:06:49.000000000 +0100
> @@ -157,8 +157,6 @@ static int const_fixed_htab_eq (const vo
>  static rtx lookup_const_fixed (rtx);
>  static hashval_t mem_attrs_htab_hash (const void *);
>  static int mem_attrs_htab_eq (const void *, const void *);
> -static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int,
> -                                addr_space_t, enum machine_mode);
>  static hashval_t reg_attrs_htab_hash (const void *);
>  static int reg_attrs_htab_eq (const void *, const void *);
>  static reg_attrs *get_reg_attrs (tree, int);
> @@ -286,8 +284,9 @@ mem_attrs_htab_eq (const void *x, const
>    MEM of mode MODE.  */
>
>  static mem_attrs *
> -get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
> -              unsigned int align, addr_space_t addrspace, enum machine_mode mode)
> +find_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
> +               unsigned int align, addr_space_t addrspace,
> +               enum machine_mode mode)
>  {
>   mem_attrs attrs;
>   void **slot;
> @@ -1833,8 +1832,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>
>   /* Now set the attributes we computed above.  */
>   MEM_ATTRS (ref)
> -    = get_mem_attrs (alias, expr, offset, size, align,
> -                    TYPE_ADDR_SPACE (type), GET_MODE (ref));
> +    = find_mem_attrs (alias, expr, offset, size, align,
> +                     TYPE_ADDR_SPACE (type), GET_MODE (ref));
>
>   /* If this is already known to be a scalar or aggregate, we are done.  */
>   if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
> @@ -1862,9 +1861,9 @@ set_mem_alias_set (rtx mem, alias_set_ty
>   /* 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) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
> -                                  MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                  MEM_ADDR_SPACE (mem), GET_MODE (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));
>  }
>
>  /* Set the address space of MEM to ADDRSPACE (target-defined).  */
> @@ -1872,9 +1871,9 @@ set_mem_alias_set (rtx mem, alias_set_ty
>  void
>  set_mem_addr_space (rtx mem, addr_space_t addrspace)
>  {
> -  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                  MEM_OFFSET (mem), MEM_SIZE (mem),
> -                                  MEM_ALIGN (mem), addrspace, GET_MODE (mem));
> +  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));
>  }
>
>  /* Set the alignment of MEM to ALIGN bits.  */
> @@ -1882,9 +1881,9 @@ set_mem_addr_space (rtx mem, addr_space_
>  void
>  set_mem_align (rtx mem, unsigned int align)
>  {
> -  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                  MEM_OFFSET (mem), MEM_SIZE (mem), align,
> -                                  MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  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));
>  }
>
>  /* Set the expr for MEM to EXPR.  */
> @@ -1893,9 +1892,9 @@ set_mem_align (rtx mem, unsigned int ali
>  set_mem_expr (rtx mem, tree expr)
>  {
>   MEM_ATTRS (mem)
> -    = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
> -                    MEM_SIZE (mem), MEM_ALIGN (mem),
> -                    MEM_ADDR_SPACE (mem), GET_MODE (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));
>  }
>
>  /* Set the offset of MEM to OFFSET.  */
> @@ -1903,9 +1902,9 @@ set_mem_expr (rtx mem, tree expr)
>  void
>  set_mem_offset (rtx mem, rtx offset)
>  {
> -  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
> -                                  offset, MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                  MEM_ADDR_SPACE (mem), GET_MODE (mem));
> +  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));
>  }
>
>  /* Set the size of MEM to SIZE.  */
> @@ -1913,9 +1912,9 @@ set_mem_offset (rtx mem, rtx offset)
>  void
>  set_mem_size (rtx mem, rtx size)
>  {
> -  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));
> +  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));
>  }
>
>  /* Return a memory reference like MEMREF, but with its mode changed to MODE
> @@ -1984,8 +1983,8 @@ change_address (rtx memref, enum machine
>     }
>
>   MEM_ATTRS (new_rtx)
> -    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
> -                    MEM_ADDR_SPACE (memref), mmode);
> +    = find_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
> +                     MEM_ADDR_SPACE (memref), mmode);
>
>   return new_rtx;
>  }
> @@ -2069,9 +2068,10 @@ adjust_address_1 (rtx memref, enum machi
>   else if (MEM_SIZE (memref))
>     size = plus_constant (MEM_SIZE (memref), -offset);
>
> -  MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
> -                                      memoffset, size, memalign, as,
> -                                      GET_MODE (new_rtx));
> +  MEM_ATTRS (new_rtx) = find_mem_attrs (MEM_ALIAS_SET (memref),
> +                                       MEM_EXPR (memref),
> +                                       memoffset, size, memalign, as,
> +                                       GET_MODE (new_rtx));
>
>   /* At some point, we should validate that this offset is within the object,
>      if all the appropriate values are known.  */
> @@ -2129,9 +2129,9 @@ 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)
> -    = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
> -                    MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
> -                    as, GET_MODE (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));
>   return new_rtx;
>  }
>
> @@ -2234,9 +2234,9 @@ widen_memory_access (rtx memref, enum ma
>   /* 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) = get_mem_attrs (0, expr, memoffset, GEN_INT (size),
> -                                      MEM_ALIGN (new_rtx),
> -                                      MEM_ADDR_SPACE (new_rtx), mode);
> +  MEM_ATTRS (new_rtx) = find_mem_attrs (0, expr, memoffset, GEN_INT (size),
> +                                       MEM_ALIGN (new_rtx),
> +                                       MEM_ADDR_SPACE (new_rtx), mode);
>
>   return new_rtx;
>  }
> @@ -2262,8 +2262,8 @@ get_spill_slot_decl (bool force_build_p)
>
>   rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
>   MEM_NOTRAP_P (rd) = 1;
> -  MEM_ATTRS (rd) = get_mem_attrs (new_alias_set (), d, const0_rtx,
> -                                 NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode);
> +  MEM_ATTRS (rd) = find_mem_attrs (new_alias_set (), d, const0_rtx,
> +                                  NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode);
>   SET_DECL_RTL (d, rd);
>
>   return d;
> @@ -2294,9 +2294,9 @@ set_mem_attrs_for_spill (rtx mem)
>       && CONST_INT_P (XEXP (addr, 1)))
>     offset = XEXP (addr, 1);
>
> -  MEM_ATTRS (mem) = get_mem_attrs (alias, expr, offset,
> -                                  MEM_SIZE (mem), MEM_ALIGN (mem),
> -                                  ADDR_SPACE_GENERIC, GET_MODE (mem));
> +  MEM_ATTRS (mem) = find_mem_attrs (alias, expr, offset,
> +                                   MEM_SIZE (mem), MEM_ALIGN (mem),
> +                                   ADDR_SPACE_GENERIC, GET_MODE (mem));
>   MEM_NOTRAP_P (mem) = 1;
>  }
>
> @@ -5442,6 +5442,8 @@ gen_rtx_CONST_VECTOR (enum machine_mode
>  init_emit_regs (void)
>  {
>   int i;
> +  enum machine_mode mode;
> +  mem_attrs *attrs;
>
>   /* Reset register attributes */
>   htab_empty (reg_attrs_htab);
> @@ -5483,6 +5485,21 @@ init_emit_regs (void)
>     pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
>   else
>     pic_offset_table_rtx = NULL_RTX;
> +
> +  for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
> +    {
> +      mode = (enum machine_mode) i;
> +      attrs = ggc_alloc_cleared_mem_attrs ();
> +      attrs->align = BITS_PER_UNIT;
> +      attrs->addrspace = ADDR_SPACE_GENERIC;
> +      if (mode != BLKmode)
> +       {
> +         attrs->size = GEN_INT (GET_MODE_SIZE (mode));
> +         if (STRICT_ALIGNMENT)
> +           attrs->align = GET_MODE_ALIGNMENT (mode);
> +       }
> +      mode_mem_attrs[i] = attrs;
> +    }
>  }
>
>  /* Create some permanent unique rtl objects shared between all functions.  */
>

Patch

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2011-07-17 10:03:05.000000000 +0100
+++ gcc/rtl.h	2011-07-17 10:03:07.000000000 +0100
@@ -1289,39 +1289,36 @@  #define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1
    in the block and provide defaults if none specified.  */
 #define REG_ATTRS(RTX) X0REGATTR (RTX, 2)
 
+#ifndef GENERATOR_FILE
 /* For a MEM rtx, the alias set.  If 0, this MEM is not in any alias
    set, and may alias anything.  Otherwise, the MEM can only alias
    MEMs in a conflicting alias set.  This value is set in a
    language-dependent manner in the front-end, and should not be
    altered in the back-end.  These set numbers are tested with
    alias_sets_conflict_p.  */
-#define MEM_ALIAS_SET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->alias)
+#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) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->expr)
+#define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
 
 /* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
    RTX that is always a CONST_INT.  */
-#define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
+#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
 
 /* For a MEM rtx, the address space.  */
-#define MEM_ADDR_SPACE(RTX) (MEM_ATTRS (RTX) == 0 ? ADDR_SPACE_GENERIC \
-						  : MEM_ATTRS (RTX)->addrspace)
+#define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
 
 /* For a MEM rtx, the size in bytes of the MEM, if known, as an RTX that
    is always a CONST_INT.  */
-#define MEM_SIZE(RTX)							\
-(MEM_ATTRS (RTX) != 0 ? MEM_ATTRS (RTX)->size				\
- : GET_MODE (RTX) != BLKmode ? GEN_INT (GET_MODE_SIZE (GET_MODE (RTX)))	\
- : 0)
+#define MEM_SIZE(RTX) (get_mem_attrs (RTX)->size)
 
 /* For a MEM rtx, the alignment in bits.  We can use the alignment of the
    mode as a default when STRICT_ALIGNMENT, but not if not.  */
-#define MEM_ALIGN(RTX)							\
-(MEM_ATTRS (RTX) != 0 ? MEM_ATTRS (RTX)->align				\
- : (STRICT_ALIGNMENT && GET_MODE (RTX) != BLKmode			\
-    ? GET_MODE_ALIGNMENT (GET_MODE (RTX)) : BITS_PER_UNIT))
+#define MEM_ALIGN(RTX) (get_mem_attrs (RTX)->align)
+#else
+#define MEM_ADDR_SPACE(RTX) ADDR_SPACE_GENERIC
+#endif
 
 /* For a REG rtx, the decl it is known to refer to, if it is known to
    refer to part of a DECL.  */
@@ -2120,6 +2117,9 @@  struct GTY(()) target_rtl {
   /* Static hunks of RTL used by the aliasing code; these are treated
      as persistent to avoid unnecessary RTL allocations.  */
   rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
+
+  /* The default memory attributes for each mode.  */
+  struct mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
 };
 
 extern GTY(()) struct target_rtl default_target_rtl;
@@ -2137,6 +2137,8 @@  #define return_address_pointer_rtx \
   (this_target_rtl->x_return_address_pointer_rtx)
 #define top_of_stack \
   (this_target_rtl->x_top_of_stack)
+#define mode_mem_attrs \
+  (this_target_rtl->x_mode_mem_attrs)
 
 /* Standard pieces of rtx, to be substituted directly into things.  */
 #define pc_rtx                  (global_rtl[GR_PC])
@@ -2151,6 +2153,20 @@  #define frame_pointer_rtx       (global_
 #define hard_frame_pointer_rtx	(global_rtl[GR_HARD_FRAME_POINTER])
 #define arg_pointer_rtx		(global_rtl[GR_ARG_POINTER])
 
+#ifndef GENERATOR_FILE
+/* Return the attributes of a MEM rtx.  */
+static inline struct mem_attrs *
+get_mem_attrs (const_rtx x)
+{
+  struct mem_attrs *attrs;
+
+  attrs = MEM_ATTRS (x);
+  if (!attrs)
+    attrs = mode_mem_attrs[(int) GET_MODE (x)];
+  return attrs;
+}
+#endif
+
 /* Include the RTL generation functions.  */
 
 #ifndef GENERATOR_FILE
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2011-07-17 10:03:05.000000000 +0100
+++ gcc/emit-rtl.c	2011-07-17 10:06:49.000000000 +0100
@@ -157,8 +157,6 @@  static int const_fixed_htab_eq (const vo
 static rtx lookup_const_fixed (rtx);
 static hashval_t mem_attrs_htab_hash (const void *);
 static int mem_attrs_htab_eq (const void *, const void *);
-static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int,
-				 addr_space_t, enum machine_mode);
 static hashval_t reg_attrs_htab_hash (const void *);
 static int reg_attrs_htab_eq (const void *, const void *);
 static reg_attrs *get_reg_attrs (tree, int);
@@ -286,8 +284,9 @@  mem_attrs_htab_eq (const void *x, const
    MEM of mode MODE.  */
 
 static mem_attrs *
-get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
-	       unsigned int align, addr_space_t addrspace, enum machine_mode mode)
+find_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
+		unsigned int align, addr_space_t addrspace,
+		enum machine_mode mode)
 {
   mem_attrs attrs;
   void **slot;
@@ -1833,8 +1832,8 @@  set_mem_attributes_minus_bitpos (rtx ref
 
   /* Now set the attributes we computed above.  */
   MEM_ATTRS (ref)
-    = get_mem_attrs (alias, expr, offset, size, align,
-		     TYPE_ADDR_SPACE (type), GET_MODE (ref));
+    = find_mem_attrs (alias, expr, offset, size, align,
+		      TYPE_ADDR_SPACE (type), GET_MODE (ref));
 
   /* If this is already known to be a scalar or aggregate, we are done.  */
   if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
@@ -1862,9 +1861,9 @@  set_mem_alias_set (rtx mem, alias_set_ty
   /* 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) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
-				   MEM_SIZE (mem), MEM_ALIGN (mem),
-				   MEM_ADDR_SPACE (mem), GET_MODE (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));
 }
 
 /* Set the address space of MEM to ADDRSPACE (target-defined).  */
@@ -1872,9 +1871,9 @@  set_mem_alias_set (rtx mem, alias_set_ty
 void
 set_mem_addr_space (rtx mem, addr_space_t addrspace)
 {
-  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   MEM_OFFSET (mem), MEM_SIZE (mem),
-				   MEM_ALIGN (mem), addrspace, GET_MODE (mem));
+  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));
 }
 
 /* Set the alignment of MEM to ALIGN bits.  */
@@ -1882,9 +1881,9 @@  set_mem_addr_space (rtx mem, addr_space_
 void
 set_mem_align (rtx mem, unsigned int align)
 {
-  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   MEM_OFFSET (mem), MEM_SIZE (mem), align,
-				   MEM_ADDR_SPACE (mem), GET_MODE (mem));
+  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));
 }
 
 /* Set the expr for MEM to EXPR.  */
@@ -1893,9 +1892,9 @@  set_mem_align (rtx mem, unsigned int ali
 set_mem_expr (rtx mem, tree expr)
 {
   MEM_ATTRS (mem)
-    = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
-		     MEM_SIZE (mem), MEM_ALIGN (mem),
-		     MEM_ADDR_SPACE (mem), GET_MODE (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));
 }
 
 /* Set the offset of MEM to OFFSET.  */
@@ -1903,9 +1902,9 @@  set_mem_expr (rtx mem, tree expr)
 void
 set_mem_offset (rtx mem, rtx offset)
 {
-  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   offset, MEM_SIZE (mem), MEM_ALIGN (mem),
-				   MEM_ADDR_SPACE (mem), GET_MODE (mem));
+  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));
 }
 
 /* Set the size of MEM to SIZE.  */
@@ -1913,9 +1912,9 @@  set_mem_offset (rtx mem, rtx offset)
 void
 set_mem_size (rtx mem, rtx size)
 {
-  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));
+  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));
 }
 
 /* Return a memory reference like MEMREF, but with its mode changed to MODE
@@ -1984,8 +1983,8 @@  change_address (rtx memref, enum machine
     }
 
   MEM_ATTRS (new_rtx)
-    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
-		     MEM_ADDR_SPACE (memref), mmode);
+    = find_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align,
+		      MEM_ADDR_SPACE (memref), mmode);
 
   return new_rtx;
 }
@@ -2069,9 +2068,10 @@  adjust_address_1 (rtx memref, enum machi
   else if (MEM_SIZE (memref))
     size = plus_constant (MEM_SIZE (memref), -offset);
 
-  MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
-				       memoffset, size, memalign, as,
-				       GET_MODE (new_rtx));
+  MEM_ATTRS (new_rtx) = find_mem_attrs (MEM_ALIAS_SET (memref),
+					MEM_EXPR (memref),
+					memoffset, size, memalign, as,
+					GET_MODE (new_rtx));
 
   /* At some point, we should validate that this offset is within the object,
      if all the appropriate values are known.  */
@@ -2129,9 +2129,9 @@  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)
-    = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
-		     MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
-		     as, GET_MODE (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));
   return new_rtx;
 }
 
@@ -2234,9 +2234,9 @@  widen_memory_access (rtx memref, enum ma
   /* 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) = get_mem_attrs (0, expr, memoffset, GEN_INT (size),
-				       MEM_ALIGN (new_rtx),
-				       MEM_ADDR_SPACE (new_rtx), mode);
+  MEM_ATTRS (new_rtx) = find_mem_attrs (0, expr, memoffset, GEN_INT (size),
+					MEM_ALIGN (new_rtx),
+					MEM_ADDR_SPACE (new_rtx), mode);
 
   return new_rtx;
 }
@@ -2262,8 +2262,8 @@  get_spill_slot_decl (bool force_build_p)
 
   rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
   MEM_NOTRAP_P (rd) = 1;
-  MEM_ATTRS (rd) = get_mem_attrs (new_alias_set (), d, const0_rtx,
-				  NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode);
+  MEM_ATTRS (rd) = find_mem_attrs (new_alias_set (), d, const0_rtx,
+				   NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode);
   SET_DECL_RTL (d, rd);
 
   return d;
@@ -2294,9 +2294,9 @@  set_mem_attrs_for_spill (rtx mem)
       && CONST_INT_P (XEXP (addr, 1)))
     offset = XEXP (addr, 1);
 
-  MEM_ATTRS (mem) = get_mem_attrs (alias, expr, offset,
-				   MEM_SIZE (mem), MEM_ALIGN (mem),
-				   ADDR_SPACE_GENERIC, GET_MODE (mem));
+  MEM_ATTRS (mem) = find_mem_attrs (alias, expr, offset,
+				    MEM_SIZE (mem), MEM_ALIGN (mem),
+				    ADDR_SPACE_GENERIC, GET_MODE (mem));
   MEM_NOTRAP_P (mem) = 1;
 }
 
@@ -5442,6 +5442,8 @@  gen_rtx_CONST_VECTOR (enum machine_mode
 init_emit_regs (void)
 {
   int i;
+  enum machine_mode mode;
+  mem_attrs *attrs;
 
   /* Reset register attributes */
   htab_empty (reg_attrs_htab);
@@ -5483,6 +5485,21 @@  init_emit_regs (void)
     pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
   else
     pic_offset_table_rtx = NULL_RTX;
+
+  for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
+    {
+      mode = (enum machine_mode) i;
+      attrs = ggc_alloc_cleared_mem_attrs ();
+      attrs->align = BITS_PER_UNIT;
+      attrs->addrspace = ADDR_SPACE_GENERIC;
+      if (mode != BLKmode)
+	{
+	  attrs->size = GEN_INT (GET_MODE_SIZE (mode));
+	  if (STRICT_ALIGNMENT)
+	    attrs->align = GET_MODE_ALIGNMENT (mode);
+	}
+      mode_mem_attrs[i] = attrs;
+    }
 }
 
 /* Create some permanent unique rtl objects shared between all functions.  */