public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes
@ 2011-07-17 14:34 Richard Sandiford
  2011-07-17 16:30 ` [1/5] Add a mode_mem_attrs array Richard Sandiford
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 14:34 UTC (permalink / raw)
  To: gcc-patches

Modeless const_ints have been a recurring source of problems.  The idea
behind keeping them modeless was presumably that we wanted to allow
const_ints to be shared between modes.  However, in practice, every
"real" const_int does have a conceptual mode, and the sign-extension
rules mean that something like 0x8000 can't be shared directly as an
HI and SI integer.

Others have referred to modeless const_ints as an historical mistake,
so I'd like to try to moving to const_ints with mode.  The first stage
of the plan is to replace calls to GEN_INT with calls to gen_int_mode.

Unfortunately, const_ints are sometimes used as a way of storing an
optional HOST_WIDE_INT (i.e. None | Some n).  These sorts of const_int
don't really represent rtl expressions, and so don't really have a
natural mode.

This patch deals with one such use of const_ints: MEM_SIZE and MEM_OFFSET.
Nothing might come of the wider grand plan -- and even if it does, it might
be rejected as a bad idea -- but I think MEM_SIZE and MEM_OFFSET are
worth changing regardless.

MEM_SIZE is defined as:

  /* 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)

But it seems like a bad idea to have GEN_INT embedded in such an
inocuous-looking macro.  The typical use case is to test whether
MEM_SIZE is null, then extract its INTVAL:

  sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
	   : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
	   : -1);

which in the attribute-less case means two pointless calls to GEN_INT.
Loops like:

	for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)

are not necessarily as cheap as they might seem.  The same applies
to the less-frequently-used MEM_OFFSET.

One fix might be to give every MEM a mem_attrs structure.  MEMs without
them are pretty rare these days anyway.  However, various parts of
the compiler change the mode in-place, so that would need a bit
more surgery.  I don't really want to do something so potentially
invasive.  (At the same time, I don't want to make it harder to
do that in future.)

Patch 1 instead adds a global mem_attrs for each mode.  It also adds
a function get_mem_attrs that always returns an attributes structure,
using the new array where necessary.

Patch 2 uses gen_mem_attrs to simplify the internals of emit-rtl.c,
and to make it easier to change mem_attrs in future.

As it happens, nothing really seems to want MEM_SIZE or MEM_OFFSET
as an rtx.  All users seem to go straight to the INTVAL. Patches 3 and 4
therefore change the interface so that:

   MEM_SIZE_KNOWN_P (x)
   MEM_OFFSET_KNOWN_P (x)

says whether the MEM_SIZE and MEM_OFFSET are known, while MEM_SIZE
and MEM_OFFSET give their values as HOST_WIDE_INTs.

Finally, patch 5 actually changes the mem_attrs representation.  This
might or might not be considered a Good Thing; I'll discuss it a bit
more in the patch's covering message.  I'd be happy for just patches
1-4 to go in at this stage if that seems better.

I wondered whether there should be special HOST_WIDE_INT values to mean
"no size known" or "no offset known".  One idea was to have an offset
of -1 mean "not known", but negative offsets are apparently acceptable
in some cases:

  /* If the base decl is a parameter we can have negative MEM_OFFSET in
     case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
     here.  */
  if (INTVAL (MEM_OFFSET (mem)) < 0
      && ((INTVAL (MEM_SIZE (mem)) + INTVAL (MEM_OFFSET (mem)))
	  * BITS_PER_UNIT) == ref->size)
    return true;

We could instead use the minimum HOST_WIDE_INT as the offset.  But that
comes back to Joseph's point (from other threads) that, while C doesn't
really cope properly with objects that are bigger than half the address
space, glibc does actually allow such objects.  The same concern applies
to MEM_SIZE.

The fact that most users treat the size as signed rather than unsigned
might mean we don't always cope properly with larger objects in GCC.
Even so, it seemed better to avoid any such assumptions in the
general case, hence the MEM_*_KNOWN_P stuff above.

Tested on x86_64-linux-gnu (all languages).  Also tested by compiling
gcc and g++ on:

	arm-linux-gnueabi
	h8300-elf
	x86_64-linux-gnu
	mips-linux-gnu
	powerpc-linux-gnu
	s390-linux-gnu
	sh-elf

and making sure that there were no changes in the assembly generated
for gcc.dg, g++.dg and gcc.c-torture.

Richard

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [1/5] Add a mode_mem_attrs array
  2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
@ 2011-07-17 16:30 ` Richard Sandiford
  2011-07-18 10:22   ` Richard Guenther
  2011-07-17 16:32 ` [2/5] Add a set_mem_attrs function Richard Sandiford
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 16:30 UTC (permalink / raw)
  To: gcc-patches

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.

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));
 }
 \f
 /* 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;
 }
 \f
@@ -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.  */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [2/5] Add a set_mem_attrs function
  2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
  2011-07-17 16:30 ` [1/5] Add a mode_mem_attrs array Richard Sandiford
@ 2011-07-17 16:32 ` Richard Sandiford
  2011-07-18 10:58   ` Richard Guenther
  2011-07-20 11:27   ` Named address spaces broken (Re: [2/5] Add a set_mem_attrs function) Ulrich Weigand
  2011-07-17 16:33 ` [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P Richard Sandiford
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 16:32 UTC (permalink / raw)
  To: gcc-patches

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.

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);
 }
 \f
 /* 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;
 }
 \f
@@ -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;
 }
 \f

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P
  2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
  2011-07-17 16:30 ` [1/5] Add a mode_mem_attrs array Richard Sandiford
  2011-07-17 16:32 ` [2/5] Add a set_mem_attrs function Richard Sandiford
@ 2011-07-17 16:33 ` Richard Sandiford
  2011-07-18 11:01   ` Richard Guenther
  2011-07-17 16:55 ` [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P Richard Sandiford
  2011-07-17 17:55 ` [5/5] Don't use rtxes in mem_attrs Richard Sandiford
  4 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 16:33 UTC (permalink / raw)
  To: gcc-patches

This patch does the mechanical MEM_SIZE interface change.  It also
makes set_mem_size take a HOST_WIDE_INT, and adds clear_mem_size
for resetting the size to "unknown".

The i386.c part includes an obvious pasto fix for:

  if (dst_size)
    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
  if (src_size)
    set_mem_size (dst, GEN_INT (INTVAL (src_size) - align_bytes));

(last "dst" should be "src") which I can split out into a separate
patch if desired.

Richard


gcc/
	* doc/rtl.texi (MEM_SIZE_KNOWN_P): Document.
	(MEM_SIZE): Change from returning an rtx to returning a HOST_WIDE_INT.
	* rtl.h (MEM_SIZE_KNOWN_P): New macro.
	(MEM_SIZE): Return a HOST_WIDE_INT rather than an rtx.
	* emit-rtl.h (set_mem_size): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_size): Declare.
	* emit-rtl.c (set_mem_size): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_size): New function.
	* alias.c (ao_ref_from_mem): Adjust uses of MEM_SIZE, using
	MEM_SIZE_KNOWN_P to test whether the size is known, and MEM_SIZE
	to get a HOST_WIDE_INT size.  Adjust calls to set_mem_size,
	passing a HOST_WIDE_INT rather than an rtx.  Use clear_mem_size
	to clear the size.
	(nonoverlapping_memrefs_p): Likewise.
	* builtins.c (get_memory_rtx, expand_builtin_memcmp): Likewise.
	(expand_builtin_init_trampoline): Likewise.
	* calls.c (compute_argument_addresses): Likewise.
	* cfgcleanup.c (merge_memattrs): Likewise.
	* dce.c (find_call_stack_args): Likewise.
	* dse.c (record_store, scan_insn): Likewise.
	* dwarf2out.c (dw_sra_loc_expr): Likewise.
	* expr.c (emit_block_move_hints): Likewise.
	* function.c (assign_parm_find_stack_rtl): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* reload.c (find_reloads_subreg_address): Likewise.
	* rtlanal.c (may_trap_p_1): Likewise.
	* var-tracking.c (track_expr_p): Likewise.
	* varasm.c (assemble_trampoline_template): Likewise.
	* config/arm/arm.c (arm_print_operand): Likewise.
	* config/h8300/h8300.c (h8sx_emit_movmd): Likewise.
	* config/i386/i386.c (expand_movmem_via_rep_mov): Likewise.
	(expand_setmem_via_rep_stos, expand_constant_movmem_prologue)
	(expand_constant_setmem_prologue): Likewise.
	* config/mips/mips.c (mips_get_unaligned_mem): Likewise.
	* config/rs6000/rs6000.c (expand_block_move): Likewise.
	(adjacent_mem_locations): Likewise.
	* config/s390/s390.c (s390_expand_setmem): Likewise.
	(s390_expand_insv): Likewise.
	* config/s390/s390.md (*extzv<mode>, *extv<mode>): Likewise.
	(*extendqi<mode>2_short_displ): Likewise.
	* config/sh/sh.c (expand_block_move): Likewise.
	* config/sh/sh.md (extv, extzv): Likewise.

Index: gcc/doc/rtl.texi
===================================================================
--- gcc/doc/rtl.texi	2011-07-17 11:30:32.000000000 +0100
+++ gcc/doc/rtl.texi	2011-07-17 13:19:35.000000000 +0100
@@ -413,11 +413,17 @@ object associated with the reference.
 @item MEM_OFFSET (@var{x})
 The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
 
+@findex MEM_SIZE_KNOWN_P
+@item MEM_SIZE_KNOWN_P (@var{x})
+True if the size of the memory reference is known.
+@samp{MEM_SIZE (@var{x})} provides its size if so.
+
 @findex MEM_SIZE
 @item MEM_SIZE (@var{x})
-The size in bytes of the memory reference as a @code{CONST_INT} rtx.
+The size in bytes of the memory reference.
 This is mostly relevant for @code{BLKmode} references as otherwise
-the size is implied by the mode.
+the size is implied by the mode.  The value is only valid if
+@samp{MEM_SIZE_KNOWN_P (@var{x})} is true.
 
 @findex MEM_ALIGN
 @item MEM_ALIGN (@var{x})
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2011-07-17 11:40:12.000000000 +0100
+++ gcc/rtl.h	2011-07-17 13:19:35.000000000 +0100
@@ -1309,9 +1309,11 @@ #define MEM_OFFSET(RTX) (get_mem_attrs (
 /* For a MEM rtx, the address space.  */
 #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) (get_mem_attrs (RTX)->size)
+/* For a MEM rtx, true if its MEM_SIZE is known.  */
+#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size != NULL_RTX)
+
+/* For a MEM rtx, the size in bytes of the MEM.  */
+#define MEM_SIZE(RTX) INTVAL (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.  */
Index: gcc/emit-rtl.h
===================================================================
--- gcc/emit-rtl.h	2011-07-17 11:30:32.000000000 +0100
+++ gcc/emit-rtl.h	2011-07-17 13:19:35.000000000 +0100
@@ -36,7 +36,10 @@ extern void set_mem_expr (rtx, tree);
 extern void set_mem_offset (rtx, rtx);
 
 /* Set the size for MEM to SIZE.  */
-extern void set_mem_size (rtx, rtx);
+extern void set_mem_size (rtx, HOST_WIDE_INT);
+
+/* Clear the size recorded for MEM.  */
+extern void clear_mem_size (rtx);
 
 /* Set the attributes for MEM appropriate for a spill slot.  */
 extern void set_mem_attrs_for_spill (rtx);
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2011-07-17 11:40:13.000000000 +0100
+++ gcc/emit-rtl.c	2011-07-17 13:19:35.000000000 +0100
@@ -1913,12 +1913,24 @@ set_mem_offset (rtx mem, rtx offset)
 /* Set the size of MEM to SIZE.  */
 
 void
-set_mem_size (rtx mem, rtx size)
+set_mem_size (rtx mem, HOST_WIDE_INT size)
 {
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.size = size;
+  attrs.size = GEN_INT (size);
+  set_mem_attrs (mem, &attrs);
+}
+
+/* Clear the size of MEM.  */
+
+void
+clear_mem_size (rtx mem)
+{
+  struct mem_attrs attrs;
+
+  attrs = *get_mem_attrs (mem);
+  attrs.size = NULL_RTX;
   set_mem_attrs (mem, &attrs);
 }
 \f
Index: gcc/alias.c
===================================================================
--- gcc/alias.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/alias.c	2011-07-17 13:19:35.000000000 +0100
@@ -313,10 +313,10 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
 
   ref->ref_alias_set = MEM_ALIAS_SET (mem);
 
-  /* If MEM_OFFSET or MEM_SIZE are NULL we have to punt.
+  /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
      Keep points-to related information though.  */
   if (!MEM_OFFSET (mem)
-      || !MEM_SIZE (mem))
+      || !MEM_SIZE_KNOWN_P (mem))
     {
       ref->ref = NULL_TREE;
       ref->offset = 0;
@@ -329,12 +329,12 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
      here.  */
   if (INTVAL (MEM_OFFSET (mem)) < 0
-      && ((INTVAL (MEM_SIZE (mem)) + INTVAL (MEM_OFFSET (mem)))
+      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
 	  * BITS_PER_UNIT) == ref->size)
     return true;
 
   ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
-  ref->size = INTVAL (MEM_SIZE (mem)) * BITS_PER_UNIT;
+  ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
 
   /* The MEM may extend into adjacent fields, so adjust max_size if
      necessary.  */
@@ -2338,11 +2338,11 @@ nonoverlapping_memrefs_p (const_rtx x, c
     return 0;              
 
   sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
-	   : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
+	   : MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx)
 	   : -1);
   sizey = (!MEM_P (rtly) ? (int) GET_MODE_SIZE (GET_MODE (rtly))
-	   : MEM_SIZE (rtly) ? INTVAL (MEM_SIZE (rtly)) :
-	   -1);
+	   : MEM_SIZE_KNOWN_P (rtly) ? MEM_SIZE (rtly)
+	   : -1);
 
   /* If we have an offset for either memref, it can update the values computed
      above.  */
@@ -2354,10 +2354,10 @@ nonoverlapping_memrefs_p (const_rtx x, c
   /* If a memref has both a size and an offset, we can use the smaller size.
      We can't do this if the offset isn't known because we must view this
      memref as being anywhere inside the DECL's MEM.  */
-  if (MEM_SIZE (x) && moffsetx)
-    sizex = INTVAL (MEM_SIZE (x));
-  if (MEM_SIZE (y) && moffsety)
-    sizey = INTVAL (MEM_SIZE (y));
+  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
+    sizex = MEM_SIZE (x);
+  if (MEM_SIZE_KNOWN_P (y) && moffsety)
+    sizey = MEM_SIZE (y);
 
   /* Put the values of the memref with the lower offset in X's values.  */
   if (offsetx > offsety)
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/builtins.c	2011-07-17 13:19:35.000000000 +0100
@@ -1299,7 +1299,7 @@ get_memory_rtx (tree exp, tree len)
 	    }
 	}
       set_mem_alias_set (mem, 0);
-      set_mem_size (mem, NULL_RTX);
+      clear_mem_size (mem);
     }
 
   return mem;
@@ -3691,8 +3691,8 @@ expand_builtin_memcmp (tree exp, ATTRIBU
     /* Set MEM_SIZE as appropriate.  */
     if (CONST_INT_P (arg3_rtx))
       {
-	set_mem_size (arg1_rtx, arg3_rtx);
-	set_mem_size (arg2_rtx, arg3_rtx);
+	set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
+	set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
       }
 
 #ifdef HAVE_cmpmemsi
@@ -4838,7 +4838,7 @@ expand_builtin_init_trampoline (tree exp
     {
       m_tramp = change_address (m_tramp, BLKmode, tmp);
       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
-      set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
+      set_mem_size (m_tramp, TRAMPOLINE_SIZE);
     }
 
   /* The FUNC argument should be the address of the nested function.
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/calls.c	2011-07-17 11:40:14.000000000 +0100
@@ -1481,7 +1481,7 @@ compute_argument_addresses (struct arg_d
 	      partial_mode = mode_for_size (units_on_stack * BITS_PER_UNIT,
 					    MODE_INT, 1);
 	      args[i].stack = gen_rtx_MEM (partial_mode, addr);
-	      set_mem_size (args[i].stack, GEN_INT (units_on_stack));
+	      set_mem_size (args[i].stack, units_on_stack);
 	    }
 	  else
 	    {
@@ -1513,7 +1513,7 @@ compute_argument_addresses (struct arg_d
 		 Generate a simple memory reference of the correct size.
 	       */
 	      args[i].stack_slot = gen_rtx_MEM (partial_mode, addr);
-	      set_mem_size (args[i].stack_slot, GEN_INT (units_on_stack));
+	      set_mem_size (args[i].stack_slot, units_on_stack);
 	    }
 	  else
 	    {
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/cfgcleanup.c	2011-07-17 13:19:35.000000000 +0100
@@ -883,7 +883,7 @@ merge_memattrs (rtx x, rtx y)
 	MEM_ATTRS (x) = 0;
       else
 	{
-	  rtx mem_size;
+	  HOST_WIDE_INT mem_size;
 
 	  if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
 	    {
@@ -904,15 +904,17 @@ merge_memattrs (rtx x, rtx y)
 	      set_mem_offset (y, 0);
 	    }
 
-	  if (!MEM_SIZE (x))
-	    mem_size = NULL_RTX;
-	  else if (!MEM_SIZE (y))
-	    mem_size = NULL_RTX;
+	  if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
+	    {
+	      mem_size = MAX (MEM_SIZE (x), MEM_SIZE (y));
+	      set_mem_size (x, mem_size);
+	      set_mem_size (y, mem_size);
+	    }
 	  else
-	    mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
-				     INTVAL (MEM_SIZE (y))));
-	  set_mem_size (x, mem_size);
-	  set_mem_size (y, mem_size);
+	    {
+	      clear_mem_size (x);
+	      clear_mem_size (y);
+	    }
 
 	  set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
 	  set_mem_align (y, MEM_ALIGN (x));
Index: gcc/dce.c
===================================================================
--- gcc/dce.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/dce.c	2011-07-17 11:40:14.000000000 +0100
@@ -275,11 +275,11 @@ find_call_stack_args (rtx call_insn, boo
     if (GET_CODE (XEXP (p, 0)) == USE
 	&& MEM_P (XEXP (XEXP (p, 0), 0)))
       {
-	rtx mem = XEXP (XEXP (p, 0), 0), addr, size;
-	HOST_WIDE_INT off = 0;
-	size = MEM_SIZE (mem);
-	if (size == NULL_RTX)
+	rtx mem = XEXP (XEXP (p, 0), 0), addr;
+	HOST_WIDE_INT off = 0, size;
+	if (!MEM_SIZE_KNOWN_P (mem))
 	  return false;
+	size = MEM_SIZE (mem);
 	addr = XEXP (mem, 0);
 	if (GET_CODE (addr) == PLUS
 	    && REG_P (XEXP (addr, 0))
@@ -329,7 +329,7 @@ find_call_stack_args (rtx call_insn, boo
 	      return false;
 	  }
 	min_sp_off = MIN (min_sp_off, off);
-	max_sp_off = MAX (max_sp_off, off + INTVAL (size));
+	max_sp_off = MAX (max_sp_off, off + size);
       }
 
   if (min_sp_off >= max_sp_off)
@@ -370,7 +370,7 @@ find_call_stack_args (rtx call_insn, boo
 	    set = single_set (DF_REF_INSN (defs->ref));
 	    off += INTVAL (XEXP (SET_SRC (set), 1));
 	  }
-	for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)
+	for (byte = off; byte < off + MEM_SIZE (mem); byte++)
 	  {
 	    if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
 	      gcc_unreachable ();
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/dse.c	2011-07-17 11:40:14.000000000 +0100
@@ -1355,11 +1355,10 @@ record_store (rtx body, bb_info_t bb_inf
 	}
       /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0))
 	 as memset (addr, 0, 36);  */
-      else if (!MEM_SIZE (mem)
-	       || !CONST_INT_P (MEM_SIZE (mem))
+      else if (!MEM_SIZE_KNOWN_P (mem)
+	       || MEM_SIZE (mem) <= 0
+	       || MEM_SIZE (mem) > MAX_OFFSET
 	       || GET_CODE (body) != SET
-	       || INTVAL (MEM_SIZE (mem)) <= 0
-	       || INTVAL (MEM_SIZE (mem)) > MAX_OFFSET
 	       || !CONST_INT_P (SET_SRC (body)))
 	{
 	  if (!store_is_unused)
@@ -1384,7 +1383,7 @@ record_store (rtx body, bb_info_t bb_inf
     }
 
   if (GET_MODE (mem) == BLKmode)
-    width = INTVAL (MEM_SIZE (mem));
+    width = MEM_SIZE (mem);
   else
     {
       width = GET_MODE_SIZE (GET_MODE (mem));
@@ -2517,7 +2516,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
 		  && INTVAL (args[2]) > 0)
 		{
 		  rtx mem = gen_rtx_MEM (BLKmode, args[0]);
-		  set_mem_size (mem, args[2]);
+		  set_mem_size (mem, INTVAL (args[2]));
 		  body = gen_rtx_SET (VOIDmode, mem, args[1]);
 		  mems_found += record_store (body, bb_info);
 		  if (dump_file)
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/dwarf2out.c	2011-07-17 13:19:35.000000000 +0100
@@ -12876,7 +12876,7 @@ dw_sra_loc_expr (tree decl, rtx loc)
 	  if (MEM_P (varloc))
 	    {
 	      unsigned HOST_WIDE_INT memsize
-		= INTVAL (MEM_SIZE (varloc)) * BITS_PER_UNIT;
+		= MEM_SIZE (varloc) * BITS_PER_UNIT;
 	      if (memsize != bitsize)
 		{
 		  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/expr.c	2011-07-17 11:40:14.000000000 +0100
@@ -1166,8 +1166,8 @@ emit_block_move_hints (rtx x, rtx y, rtx
     {
       x = shallow_copy_rtx (x);
       y = shallow_copy_rtx (y);
-      set_mem_size (x, size);
-      set_mem_size (y, size);
+      set_mem_size (x, INTVAL (size));
+      set_mem_size (y, INTVAL (size));
     }
 
   if (CONST_INT_P (size) && MOVE_BY_PIECES_P (INTVAL (size), align))
Index: gcc/function.c
===================================================================
--- gcc/function.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/function.c	2011-07-17 13:19:35.000000000 +0100
@@ -2576,8 +2576,7 @@ assign_parm_find_stack_rtl (tree parm, s
       if (data->promoted_mode != BLKmode
 	  && data->promoted_mode != DECL_MODE (parm))
 	{
-	  set_mem_size (stack_parm,
-			GEN_INT (GET_MODE_SIZE (data->promoted_mode)));
+	  set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
 	  if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
 	    {
 	      int offset = subreg_lowpart_offset (DECL_MODE (parm),
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/print-rtl.c	2011-07-17 13:19:35.000000000 +0100
@@ -601,9 +601,8 @@ print_rtx (const_rtx in_rtx)
 	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
 		 INTVAL (MEM_OFFSET (in_rtx)));
 
-      if (MEM_SIZE (in_rtx))
-	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC,
-		 INTVAL (MEM_SIZE (in_rtx)));
+      if (MEM_SIZE_KNOWN_P (in_rtx))
+	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
 
       if (MEM_ALIGN (in_rtx) != 1)
 	fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/reload.c	2011-07-17 13:19:35.000000000 +0100
@@ -6139,9 +6139,9 @@ find_reloads_subreg_address (rtx x, int
 	      PUT_MODE (tem, GET_MODE (x));
 	      if (MEM_OFFSET (tem))
 		set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
-	      if (MEM_SIZE (tem)
-		  && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size)
-		set_mem_size (tem, GEN_INT (outer_size));
+	      if (MEM_SIZE_KNOWN_P (tem)
+		  && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
+		set_mem_size (tem, outer_size);
 
 	      /* If this was a paradoxical subreg that we replaced, the
 		 resulting memory must be sufficiently aligned to allow
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/rtlanal.c	2011-07-17 11:40:14.000000000 +0100
@@ -2279,7 +2279,7 @@ may_trap_p_1 (const_rtx x, unsigned flag
 	  code_changed
 	  || !MEM_NOTRAP_P (x))
 	{
-	  HOST_WIDE_INT size = MEM_SIZE (x) ? INTVAL (MEM_SIZE (x)) : 0;
+	  HOST_WIDE_INT size = MEM_SIZE_KNOWN_P (x) ? MEM_SIZE (x) : 0;
 	  return rtx_addr_can_trap_p_1 (XEXP (x, 0), 0, size,
 					GET_MODE (x), code_changed);
 	}
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/var-tracking.c	2011-07-17 13:19:35.000000000 +0100
@@ -4674,8 +4674,8 @@ track_expr_p (tree expr, bool need_rtl)
       if (GET_MODE (decl_rtl) == BLKmode
 	  || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
 	return 0;
-      if (MEM_SIZE (decl_rtl)
-	  && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
+      if (MEM_SIZE_KNOWN_P (decl_rtl)
+	  && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS)
 	return 0;
     }
 
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/varasm.c	2011-07-17 11:40:14.000000000 +0100
@@ -2391,7 +2391,7 @@ assemble_trampoline_template (void)
 
   initial_trampoline = gen_const_mem (BLKmode, symbol);
   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
-  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
+  set_mem_size (initial_trampoline, TRAMPOLINE_SIZE);
 
   return initial_trampoline;
 }
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/arm/arm.c	2011-07-17 11:40:14.000000000 +0100
@@ -16713,7 +16713,7 @@ arm_print_operand (FILE *stream, rtx x,
 	   instruction (for some alignments) as an aid to the memory subsystem
 	   of the target.  */
 	align = MEM_ALIGN (x) >> 3;
-	memsize = INTVAL (MEM_SIZE (x));
+	memsize = MEM_SIZE (x);
 	
 	/* Only certain alignment specifiers are supported by the hardware.  */
 	if (memsize == 16 && (align % 32) == 0)
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/h8300/h8300.c	2011-07-17 11:40:14.000000000 +0100
@@ -2642,8 +2642,8 @@ h8sx_emit_movmd (rtx dest, rtx src, rtx
       first_dest = replace_equiv_address (dest, dest_reg);
       first_src = replace_equiv_address (src, src_reg);
 
-      set_mem_size (first_dest, GEN_INT (n & -factor));
-      set_mem_size (first_src, GEN_INT (n & -factor));
+      set_mem_size (first_dest, n & -factor);
+      set_mem_size (first_src, n & -factor);
 
       length = copy_to_mode_reg (HImode, gen_int_mode (n / factor, HImode));
       emit_insn (gen_movmd (first_dest, first_src, length, GEN_INT (factor)));
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/i386/i386.c	2011-07-17 11:40:14.000000000 +0100
@@ -19702,6 +19702,7 @@ expand_movmem_via_rep_mov (rtx destmem,
   rtx destexp;
   rtx srcexp;
   rtx countreg;
+  HOST_WIDE_INT rounded_count;
 
   /* If the size is known, it is shorter to use rep movs.  */
   if (mode == QImode && CONST_INT_P (count)
@@ -19729,19 +19730,19 @@ expand_movmem_via_rep_mov (rtx destmem,
     }
   if (CONST_INT_P (count))
     {
-      count = GEN_INT (INTVAL (count)
+      rounded_count = (INTVAL (count)
 		       & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
       destmem = shallow_copy_rtx (destmem);
       srcmem = shallow_copy_rtx (srcmem);
-      set_mem_size (destmem, count);
-      set_mem_size (srcmem, count);
+      set_mem_size (destmem, rounded_count);
+      set_mem_size (srcmem, rounded_count);
     }
   else
     {
-      if (MEM_SIZE (destmem))
-	set_mem_size (destmem, NULL_RTX);
-      if (MEM_SIZE (srcmem))
-	set_mem_size (srcmem, NULL_RTX);
+      if (MEM_SIZE_KNOWN_P (destmem))
+	clear_mem_size (destmem);
+      if (MEM_SIZE_KNOWN_P (srcmem))
+	clear_mem_size (srcmem);
     }
   emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
 			  destexp, srcexp));
@@ -19756,6 +19757,7 @@ expand_setmem_via_rep_stos (rtx destmem,
 {
   rtx destexp;
   rtx countreg;
+  HOST_WIDE_INT rounded_count;
 
   if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
     destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
@@ -19771,13 +19773,13 @@ expand_setmem_via_rep_stos (rtx destmem,
     destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
   if (orig_value == const0_rtx && CONST_INT_P (count))
     {
-      count = GEN_INT (INTVAL (count)
+      rounded_count = (INTVAL (count)
 		       & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
       destmem = shallow_copy_rtx (destmem);
-      set_mem_size (destmem, count);
+      set_mem_size (destmem, rounded_count);
     }
-  else if (MEM_SIZE (destmem))
-    set_mem_size (destmem, NULL_RTX);
+  else if (MEM_SIZE_KNOWN_P (destmem))
+    clear_mem_size (destmem);
   emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
 }
 
@@ -20118,13 +20120,12 @@ expand_constant_movmem_prologue (rtx dst
 				 int desired_align, int align_bytes)
 {
   rtx src = *srcp;
-  rtx src_size, dst_size;
+  rtx orig_dst = dst;
+  rtx orig_src = src;
   int off = 0;
   int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT);
   if (src_align_bytes >= 0)
     src_align_bytes = desired_align - src_align_bytes;
-  src_size = MEM_SIZE (src);
-  dst_size = MEM_SIZE (dst);
   if (align_bytes & 1)
     {
       dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
@@ -20182,10 +20183,10 @@ expand_constant_movmem_prologue (rtx dst
       if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
 	set_mem_align (src, src_align * BITS_PER_UNIT);
     }
-  if (dst_size)
-    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
-  if (src_size)
-    set_mem_size (dst, GEN_INT (INTVAL (src_size) - align_bytes));
+  if (MEM_SIZE_KNOWN_P (orig_dst))
+    set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
+  if (MEM_SIZE_KNOWN_P (orig_src))
+    set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
   *srcp = src;
   return dst;
 }
@@ -20233,7 +20234,7 @@ expand_constant_setmem_prologue (rtx dst
 				 int desired_align, int align_bytes)
 {
   int off = 0;
-  rtx dst_size = MEM_SIZE (dst);
+  rtx orig_dst = dst;
   if (align_bytes & 1)
     {
       dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
@@ -20262,8 +20263,8 @@ expand_constant_setmem_prologue (rtx dst
   dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
   if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
     set_mem_align (dst, desired_align * BITS_PER_UNIT);
-  if (dst_size)
-    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
+  if (MEM_SIZE_KNOWN_P (orig_dst))
+    set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
   return dst;
 }
 
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/mips/mips.c	2011-07-17 13:19:35.000000000 +0100
@@ -6862,7 +6862,7 @@ mips_get_unaligned_mem (rtx *op, HOST_WI
   /* Adjust *OP to refer to the whole field.  This also has the effect
      of legitimizing *OP's address for BLKmode, possibly simplifying it.  */
   *op = adjust_address (*op, BLKmode, 0);
-  set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT));
+  set_mem_size (*op, width / BITS_PER_UNIT);
 
   /* Get references to both ends of the field.  We deliberately don't
      use the original QImode *OP for FIRST since the new BLKmode one
@@ -6962,13 +6962,9 @@ mips_expand_ins_as_unaligned_store (rtx
 bool
 mips_mem_fits_mode_p (enum machine_mode mode, rtx x)
 {
-  rtx size;
-
-  if (!MEM_P (x))
-    return false;
-
-  size = MEM_SIZE (x);
-  return size && INTVAL (size) == GET_MODE_SIZE (mode);
+  return (MEM_P (x)
+	  && MEM_SIZE_KNOWN_P (x)
+	  && MEM_SIZE (x) == GET_MODE_SIZE (mode));
 }
 
 /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/rs6000/rs6000.c	2011-07-17 11:40:14.000000000 +0100
@@ -13685,14 +13685,14 @@ expand_block_move (rtx operands[])
 	      rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
 	      src = replace_equiv_address (src, src_reg);
 	    }
-	  set_mem_size (src, GEN_INT (move_bytes));
+	  set_mem_size (src, move_bytes);
 
 	  if (!REG_P (XEXP (dest, 0)))
 	    {
 	      rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
 	      dest = replace_equiv_address (dest, dest_reg);
 	    }
-	  set_mem_size (dest, GEN_INT (move_bytes));
+	  set_mem_size (dest, move_bytes);
 
 	  emit_insn ((*gen_func.movmemsi) (dest, src,
 					   GEN_INT (move_bytes & 31),
@@ -23063,8 +23063,8 @@ adjacent_mem_locations (rtx insn1, rtx i
       val_diff = val1 - val0;
 
       return ((REGNO (reg0) == REGNO (reg1))
-	      && ((MEM_SIZE (a) && val_diff == INTVAL (MEM_SIZE (a)))
-		  || (MEM_SIZE (b) && val_diff == -INTVAL (MEM_SIZE (b)))));
+	      && ((MEM_SIZE_KNOWN_P (a) && val_diff == MEM_SIZE (a))
+		  || (MEM_SIZE_KNOWN_P (b) && val_diff == -MEM_SIZE (b))));
     }
 
   return false;
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/s390/s390.c	2011-07-17 11:40:14.000000000 +0100
@@ -4099,7 +4099,7 @@ s390_expand_setmem (rtx dst, rtx len, rt
 		 DST is set to size 1 so the rest of the memory location
 		 does not count as source operand.  */
 	      rtx dstp1 = adjust_address (dst, VOIDmode, 1);
-	      set_mem_size (dst, const1_rtx);
+	      set_mem_size (dst, 1);
 
 	      emit_insn (gen_movmem_short (dstp1, dst,
 					   GEN_INT (INTVAL (len) - 2)));
@@ -4142,7 +4142,7 @@ s390_expand_setmem (rtx dst, rtx len, rt
       else
 	{
 	  dstp1 = adjust_address (dst, VOIDmode, 1);
-	  set_mem_size (dst, const1_rtx);
+	  set_mem_size (dst, 1);
 
 	  /* Initialize memory by storing the first byte.  */
 	  emit_move_insn (adjust_address (dst, QImode, 0), val);
@@ -4551,7 +4551,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx
 					GET_MODE_SIZE (word_mode) - size);
 
 	  dest = adjust_address (dest, BLKmode, 0);
-	  set_mem_size (dest, GEN_INT (size));
+	  set_mem_size (dest, size);
 	  s390_expand_movmem (dest, src_mem, GEN_INT (size));
 	}
 
@@ -4569,7 +4569,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx
 
 	      emit_move_insn (adjust_address (dest, SImode, size),
 			      gen_lowpart (SImode, src));
-	      set_mem_size (dest, GEN_INT (size));
+	      set_mem_size (dest, size);
 	      emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
 						    (stcmh_width), const0_rtx),
 			      gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
Index: gcc/config/s390/s390.md
===================================================================
--- gcc/config/s390/s390.md	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/s390/s390.md	2011-07-17 11:40:14.000000000 +0100
@@ -3295,7 +3295,7 @@ (define_insn_and_split "*extzv<mode>"
   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
 
   operands[1] = adjust_address (operands[1], BLKmode, 0);
-  set_mem_size (operands[1], GEN_INT (size));
+  set_mem_size (operands[1], size);
   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
   operands[3] = GEN_INT (mask);
 })
@@ -3322,7 +3322,7 @@ (define_insn_and_split "*extv<mode>"
   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
 
   operands[1] = adjust_address (operands[1], BLKmode, 0);
-  set_mem_size (operands[1], GEN_INT (size));
+  set_mem_size (operands[1], size);
   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
   operands[3] = GEN_INT (mask);
 })
@@ -3656,7 +3656,7 @@ (define_insn_and_split "*extendqi<mode>2
      (clobber (reg:CC CC_REGNUM))])]
 {
   operands[1] = adjust_address (operands[1], BLKmode, 0);
-  set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
+  set_mem_size (operands[1], GET_MODE_SIZE (QImode));
   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)
 			 - GET_MODE_BITSIZE (QImode));
 })
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/sh/sh.c	2011-07-17 11:40:14.000000000 +0100
@@ -1456,7 +1456,7 @@ expand_block_move (rtx *operands)
 	  rtx from = adjust_automodify_address (src, BLKmode,
 						src_addr, copied);
 
-	  set_mem_size (from, GEN_INT (4));
+	  set_mem_size (from, 4);
 	  emit_insn (gen_movua (temp, from));
 	  emit_move_insn (src_addr, plus_constant (src_addr, 4));
 	  emit_move_insn (to, temp);
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md	2011-07-17 11:30:32.000000000 +0100
+++ gcc/config/sh/sh.md	2011-07-17 11:40:14.000000000 +0100
@@ -11070,7 +11070,7 @@ (define_expand "extv"
       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
     {
       rtx src = adjust_address (operands[1], BLKmode, 0);
-      set_mem_size (src, GEN_INT (4));
+      set_mem_size (src, 4);
       emit_insn (gen_movua (operands[0], src));
       DONE;
     }
@@ -11102,7 +11102,7 @@ (define_expand "extzv"
       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
     {
       rtx src = adjust_address (operands[1], BLKmode, 0);
-      set_mem_size (src, GEN_INT (4));
+      set_mem_size (src, 4);
       emit_insn (gen_movua (operands[0], src));
       DONE;
     }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P
  2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
                   ` (2 preceding siblings ...)
  2011-07-17 16:33 ` [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P Richard Sandiford
@ 2011-07-17 16:55 ` Richard Sandiford
  2011-07-18 11:10   ` Richard Guenther
  2011-07-17 17:55 ` [5/5] Don't use rtxes in mem_attrs Richard Sandiford
  4 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 16:55 UTC (permalink / raw)
  To: gcc-patches

This patch makes the mechanical MEM_OFFSET interface change,
along the same lines as the MEM_SIZE one.

Richard


gcc/
	* doc/rtl.texi (MEM_OFFSET_KNOWN_P): Document.
	(MEM_OFFSET): Change from returning an rtx to returning a
	HOST_WIDE_INT.
	* rtl.h (MEM_OFFSET_KNOWN_P): New macro.
	(MEM_OFFSET): Return a HOST_WIDE_INT rather than an rtx.
	* emit-rtl.h (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_offset): Declare.
	* alias.c (ao_ref_from_mem): Adjust uses of MEM_OFFSET, using
	MEM_OFFSET_KNOWN_P to test whether the offset is known, and
	MEM_OFFSET to get a HOST_WIDE_INT offset.
	(nonoverlapping_memrefs_p): Likewise.  Adjust calls to...
	(adjust_offset_for_component_ref): Take a bool "known_p"
	parameter and a HOST_WIDE_INT "offset" parameter.
	* builtins.c (get_memory_rtx): As for ao_ref_from_mem.
	Adjust calls to set_mem_offset, passing a HOST_WIDE_INT rather
	than an rtx.  Use clear_mem_offset to clear the offset.
	* cfgcleanup.c (merge_memattrs): Likewise.
	* dwarf2out.c (tls_mem_loc_descriptor): Likewise.
	* function.c (assign_parm_find_stack_rtl): Likewise.
	(assign_parm_setup_stack): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* reload.c (find_reloads_subreg_address): Likewise.
	* simplify-rtx.c (delegitimize_mem_from_attrs): Likewise.
	* var-tracking.c (INT_MEM_OFFSET): Likewise.
	* emit-rtl.c (set_reg_attrs_from_value): Likewise.
	(get_mem_align_offset): Likewise.
	(set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_offset): New function.
	* config/mips/mips.c (r10k_safe_mem_expr_p): Take a HOST_WIDE_INT
	offset rather than an rtx.  Assume both the expressio and offset
	are available.
	(r10k_needs_protection_p_1): Update accordingly, checking the
	expression and offset availability here instead.

Index: gcc/doc/rtl.texi
===================================================================
--- gcc/doc/rtl.texi	2011-07-17 10:53:19.000000000 +0100
+++ gcc/doc/rtl.texi	2011-07-17 10:54:22.000000000 +0100
@@ -409,9 +409,15 @@ and @code{TREE_OPERAND (@var{x}, 0)} con
 or another @code{COMPONENT_REF}, or null if there is no compile-time
 object associated with the reference.
 
+@findex MEM_OFFSET_KNOWN_P
+@item MEM_OFFSET_KNOWN_P (@var{x})
+True if the offset of the memory reference from @code{MEM_EXPR} is known.
+@samp{MEM_OFFSET (@var{x})} provides the offset if so.
+
 @findex MEM_OFFSET
 @item MEM_OFFSET (@var{x})
-The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
+The offset from the start of @code{MEM_EXPR}.  The value is only valid if
+@samp{MEM_OFFSET_KNOWN_P (@var{x})} is true.
 
 @findex MEM_SIZE_KNOWN_P
 @item MEM_SIZE_KNOWN_P (@var{x})
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2011-07-17 10:18:59.000000000 +0100
+++ gcc/rtl.h	2011-07-17 10:38:53.000000000 +0100
@@ -1302,9 +1302,11 @@ #define MEM_ALIAS_SET(RTX) (get_mem_attr
    refer to part of a DECL.  It may also be a COMPONENT_REF.  */
 #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
 
-/* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
-   RTX that is always a CONST_INT.  */
-#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
+/* For a MEM rtx, true if its MEM_OFFSET is known.  */
+#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
+
+/* For a MEM rtx, the offset from the start of MEM_EXPR.  */
+#define MEM_OFFSET(RTX) INTVAL (get_mem_attrs (RTX)->offset)
 
 /* For a MEM rtx, the address space.  */
 #define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
Index: gcc/emit-rtl.h
===================================================================
--- gcc/emit-rtl.h	2011-07-17 10:18:59.000000000 +0100
+++ gcc/emit-rtl.h	2011-07-17 10:38:53.000000000 +0100
@@ -33,7 +33,10 @@ extern void set_mem_addr_space (rtx, add
 extern void set_mem_expr (rtx, tree);
 
 /* Set the offset for MEM to OFFSET.  */
-extern void set_mem_offset (rtx, rtx);
+extern void set_mem_offset (rtx, HOST_WIDE_INT);
+
+/* Clear the offset recorded for MEM.  */
+extern void clear_mem_offset (rtx);
 
 /* Set the size for MEM to SIZE.  */
 extern void set_mem_size (rtx, HOST_WIDE_INT);
Index: gcc/alias.c
===================================================================
--- gcc/alias.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/alias.c	2011-07-17 10:43:20.000000000 +0100
@@ -162,7 +162,6 @@ static const_rtx fixed_scalar_and_varyin
 static int aliases_everything_p (const_rtx);
 static bool nonoverlapping_component_refs_p (const_tree, const_tree);
 static tree decl_for_component_ref (tree);
-static rtx adjust_offset_for_component_ref (tree, rtx);
 static int write_dependence_p (const_rtx, const_rtx, int);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
@@ -315,7 +314,7 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
 
   /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
      Keep points-to related information though.  */
-  if (!MEM_OFFSET (mem)
+  if (!MEM_OFFSET_KNOWN_P (mem)
       || !MEM_SIZE_KNOWN_P (mem))
     {
       ref->ref = NULL_TREE;
@@ -328,12 +327,11 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
   /* If the base decl is a parameter we can have negative MEM_OFFSET in
      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
      here.  */
-  if (INTVAL (MEM_OFFSET (mem)) < 0
-      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
-	  * BITS_PER_UNIT) == ref->size)
+  if (MEM_OFFSET (mem) < 0
+      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
     return true;
 
-  ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
+  ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
 
   /* The MEM may extend into adjacent fields, so adjust max_size if
@@ -2201,34 +2199,33 @@ decl_for_component_ref (tree x)
   return x && DECL_P (x) ? x : NULL_TREE;
 }
 
-/* Walk up the COMPONENT_REF list and adjust OFFSET to compensate for the
-   offset of the field reference.  */
+/* Walk up the COMPONENT_REF list in X and adjust *OFFSET to compensate
+   for the offset of the field reference.  *KNOWN_P says whether the
+   offset is known.  */
 
-static rtx
-adjust_offset_for_component_ref (tree x, rtx offset)
+static void
+adjust_offset_for_component_ref (tree x, bool *known_p,
+				 HOST_WIDE_INT *offset)
 {
-  HOST_WIDE_INT ioffset;
-
-  if (! offset)
-    return NULL_RTX;
-
-  ioffset = INTVAL (offset);
+  if (!*known_p)
+    return;
   do
     {
-      tree offset = component_ref_field_offset (x);
+      tree xoffset = component_ref_field_offset (x);
       tree field = TREE_OPERAND (x, 1);
 
-      if (! host_integerp (offset, 1))
-	return NULL_RTX;
-      ioffset += (tree_low_cst (offset, 1)
+      if (! host_integerp (xoffset, 1))
+	{
+	  *known_p = false;
+	  return;
+	}
+      *offset += (tree_low_cst (xoffset, 1)
 		  + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 		     / BITS_PER_UNIT));
 
       x = TREE_OPERAND (x, 0);
     }
   while (x && TREE_CODE (x) == COMPONENT_REF);
-
-  return GEN_INT (ioffset);
 }
 
 /* Return nonzero if we can determine the exprs corresponding to memrefs
@@ -2241,7 +2238,8 @@ nonoverlapping_memrefs_p (const_rtx x, c
   tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
   rtx rtlx, rtly;
   rtx basex, basey;
-  rtx moffsetx, moffsety;
+  bool moffsetx_known_p, moffsety_known_p;
+  HOST_WIDE_INT moffsetx = 0, moffsety = 0;
   HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
 
   /* Unless both have exprs, we can't tell anything.  */
@@ -2250,9 +2248,9 @@ nonoverlapping_memrefs_p (const_rtx x, c
 
   /* For spill-slot accesses make sure we have valid offsets.  */
   if ((exprx == get_spill_slot_decl (false)
-       && ! MEM_OFFSET (x))
+       && ! MEM_OFFSET_KNOWN_P (x))
       || (expry == get_spill_slot_decl (false)
-	  && ! MEM_OFFSET (y)))
+	  && ! MEM_OFFSET_KNOWN_P (y)))
     return 0;
 
   /* If both are field references, we may be able to determine something.  */
@@ -2263,23 +2261,27 @@ nonoverlapping_memrefs_p (const_rtx x, c
 
 
   /* If the field reference test failed, look at the DECLs involved.  */
-  moffsetx = MEM_OFFSET (x);
+  moffsetx_known_p = MEM_OFFSET_KNOWN_P (x);
+  if (moffsetx_known_p)
+    moffsetx = MEM_OFFSET (x);
   if (TREE_CODE (exprx) == COMPONENT_REF)
     {
       tree t = decl_for_component_ref (exprx);
       if (! t)
 	return 0;
-      moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
+      adjust_offset_for_component_ref (exprx, &moffsetx_known_p, &moffsetx);
       exprx = t;
     }
 
-  moffsety = MEM_OFFSET (y);
+  moffsety_known_p = MEM_OFFSET_KNOWN_P (y);
+  if (moffsety_known_p)
+    moffsety = MEM_OFFSET (y);
   if (TREE_CODE (expry) == COMPONENT_REF)
     {
       tree t = decl_for_component_ref (expry);
       if (! t)
 	return 0;
-      moffsety = adjust_offset_for_component_ref (expry, moffsety);
+      adjust_offset_for_component_ref (expry, &moffsety_known_p, &moffsety);
       expry = t;
     }
 
@@ -2346,17 +2348,17 @@ nonoverlapping_memrefs_p (const_rtx x, c
 
   /* If we have an offset for either memref, it can update the values computed
      above.  */
-  if (moffsetx)
-    offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
-  if (moffsety)
-    offsety += INTVAL (moffsety), sizey -= INTVAL (moffsety);
+  if (moffsetx_known_p)
+    offsetx += moffsetx, sizex -= moffsetx;
+  if (moffsety_known_p)
+    offsety += moffsety, sizey -= moffsety;
 
   /* If a memref has both a size and an offset, we can use the smaller size.
      We can't do this if the offset isn't known because we must view this
      memref as being anywhere inside the DECL's MEM.  */
-  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
+  if (MEM_SIZE_KNOWN_P (x) && moffsetx_known_p)
     sizex = MEM_SIZE (x);
-  if (MEM_SIZE_KNOWN_P (y) && moffsety)
+  if (MEM_SIZE_KNOWN_P (y) && moffsety_known_p)
     sizey = MEM_SIZE (y);
 
   /* Put the values of the memref with the lower offset in X's values.  */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/builtins.c	2011-07-17 10:38:53.000000000 +0100
@@ -1238,9 +1238,8 @@ get_memory_rtx (tree exp, tree len)
 
 	  gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
 
-	  if (MEM_OFFSET (mem)
-	      && CONST_INT_P (MEM_OFFSET (mem)))
-	    offset = INTVAL (MEM_OFFSET (mem));
+	  if (MEM_OFFSET_KNOWN_P (mem))
+	    offset = MEM_OFFSET (mem);
 
 	  if (offset >= 0 && len && host_integerp (len, 0))
 	    length = tree_low_cst (len, 0);
@@ -1295,7 +1294,10 @@ get_memory_rtx (tree exp, tree len)
 	  if (mem_expr != MEM_EXPR (mem))
 	    {
 	      set_mem_expr (mem, mem_expr);
-	      set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
+	      if (offset >= 0)
+		set_mem_offset (mem, offset);
+	      else
+		clear_mem_offset (mem);
 	    }
 	}
       set_mem_alias_set (mem, 0);
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/cfgcleanup.c	2011-07-17 10:38:53.000000000 +0100
@@ -895,13 +895,15 @@ merge_memattrs (rtx x, rtx y)
 	    {
 	      set_mem_expr (x, 0);
 	      set_mem_expr (y, 0);
-	      set_mem_offset (x, 0);
-	      set_mem_offset (y, 0);
+	      clear_mem_offset (x);
+	      clear_mem_offset (y);
 	    }
-	  else if (MEM_OFFSET (x) != MEM_OFFSET (y))
+	  else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y)
+		   || (MEM_OFFSET_KNOWN_P (x)
+		       && MEM_OFFSET (x) != MEM_OFFSET (y)))
 	    {
-	      set_mem_offset (x, 0);
-	      set_mem_offset (y, 0);
+	      clear_mem_offset (x);
+	      clear_mem_offset (y);
 	    }
 
 	  if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/dwarf2out.c	2011-07-17 10:38:53.000000000 +0100
@@ -10453,7 +10453,7 @@ tls_mem_loc_descriptor (rtx mem)
   tree base;
   dw_loc_descr_ref loc_result;
 
-  if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
+  if (MEM_EXPR (mem) == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
     return NULL;
 
   base = get_base_address (MEM_EXPR (mem));
@@ -10466,8 +10466,8 @@ tls_mem_loc_descriptor (rtx mem)
   if (loc_result == NULL)
     return NULL;
 
-  if (INTVAL (MEM_OFFSET (mem)))
-    loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
+  if (MEM_OFFSET (mem))
+    loc_descr_plus_const (&loc_result, MEM_OFFSET (mem));
 
   return loc_result;
 }
Index: gcc/function.c
===================================================================
--- gcc/function.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/function.c	2011-07-17 10:38:53.000000000 +0100
@@ -2577,14 +2577,12 @@ assign_parm_find_stack_rtl (tree parm, s
 	  && data->promoted_mode != DECL_MODE (parm))
 	{
 	  set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
-	  if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
+	  if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
 	    {
 	      int offset = subreg_lowpart_offset (DECL_MODE (parm),
 						  data->promoted_mode);
 	      if (offset)
-		set_mem_offset (stack_parm,
-				plus_constant (MEM_OFFSET (stack_parm),
-					       -offset));
+		set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
 	    }
 	}
     }
@@ -3198,10 +3196,9 @@ assign_parm_setup_stack (struct assign_p
 	  /* ??? This may need a big-endian conversion on sparc64.  */
 	  data->stack_parm
 	    = adjust_address (data->stack_parm, data->nominal_mode, 0);
-	  if (offset && MEM_OFFSET (data->stack_parm))
+	  if (offset && MEM_OFFSET_KNOWN_P (data->stack_parm))
 	    set_mem_offset (data->stack_parm,
-			    plus_constant (MEM_OFFSET (data->stack_parm),
-					   offset));
+			    MEM_OFFSET (data->stack_parm) + offset);
 	}
     }
 
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/print-rtl.c	2011-07-17 10:38:53.000000000 +0100
@@ -597,9 +597,8 @@ print_rtx (const_rtx in_rtx)
       if (MEM_EXPR (in_rtx))
 	print_mem_expr (outfile, MEM_EXPR (in_rtx));
 
-      if (MEM_OFFSET (in_rtx))
-	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
-		 INTVAL (MEM_OFFSET (in_rtx)));
+      if (MEM_OFFSET_KNOWN_P (in_rtx))
+	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
 
       if (MEM_SIZE_KNOWN_P (in_rtx))
 	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/reload.c	2011-07-17 10:38:53.000000000 +0100
@@ -6137,8 +6137,8 @@ find_reloads_subreg_address (rtx x, int
 
 	      XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
 	      PUT_MODE (tem, GET_MODE (x));
-	      if (MEM_OFFSET (tem))
-		set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
+	      if (MEM_OFFSET_KNOWN_P (tem))
+		set_mem_offset (tem, MEM_OFFSET (tem) + offset);
 	      if (MEM_SIZE_KNOWN_P (tem)
 		  && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
 		set_mem_size (tem, outer_size);
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	2011-07-17 10:03:00.000000000 +0100
+++ gcc/simplify-rtx.c	2011-07-17 10:38:53.000000000 +0100
@@ -268,7 +268,7 @@ delegitimize_mem_from_attrs (rtx x)
      use their base addresses as equivalent.  */
   if (MEM_P (x)
       && MEM_EXPR (x)
-      && MEM_OFFSET (x))
+      && MEM_OFFSET_KNOWN_P (x))
     {
       tree decl = MEM_EXPR (x);
       enum machine_mode mode = GET_MODE (x);
@@ -321,7 +321,7 @@ delegitimize_mem_from_attrs (rtx x)
 	{
 	  rtx newx;
 
-	  offset += INTVAL (MEM_OFFSET (x));
+	  offset += MEM_OFFSET (x);
 
 	  newx = DECL_RTL (decl);
 
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/var-tracking.c	2011-07-17 10:38:53.000000000 +0100
@@ -365,7 +365,7 @@ typedef const struct value_chain_def *co
 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
 
 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
-#define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
+#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
 
 /* Alloc pool for struct attrs_def.  */
 static alloc_pool attrs_pool;
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/emit-rtl.c	2011-07-17 10:38:53.000000000 +0100
@@ -969,9 +969,9 @@ set_reg_attrs_from_value (rtx reg, rtx x
   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
   if (MEM_P (x))
     {
-      if (MEM_OFFSET (x) && CONST_INT_P (MEM_OFFSET (x)))
-	REG_ATTRS (reg)
-	  = get_reg_attrs (MEM_EXPR (x), INTVAL (MEM_OFFSET (x)) + offset);
+      if (MEM_OFFSET_KNOWN_P (x))
+	REG_ATTRS (reg) = get_reg_attrs (MEM_EXPR (x),
+					 MEM_OFFSET (x) + offset);
       if (MEM_POINTER (x))
 	mark_reg_pointer (reg, 0);
     }
@@ -1460,14 +1460,13 @@ get_mem_align_offset (rtx mem, unsigned
   unsigned HOST_WIDE_INT offset;
 
   /* This function can't use
-     if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
-	 || !CONST_INT_P (MEM_OFFSET (mem))
+     if (!MEM_EXPR (mem) || !MEM_OFFSET_KNOWN_P (mem)
 	 || (MAX (MEM_ALIGN (mem),
 	          get_object_alignment (MEM_EXPR (mem), align))
 	     < align))
        return -1;
      else
-       return (- INTVAL (MEM_OFFSET (mem))) & (align / BITS_PER_UNIT - 1);
+       return (- MEM_OFFSET (mem)) & (align / BITS_PER_UNIT - 1);
      for two reasons:
      - COMPONENT_REFs in MEM_EXPR can have NULL first operand,
        for <variable>.  get_inner_reference doesn't handle it and
@@ -1477,12 +1476,10 @@ get_mem_align_offset (rtx mem, unsigned
        isn't sufficiently aligned, the object it is in might be.  */
   gcc_assert (MEM_P (mem));
   expr = MEM_EXPR (mem);
-  if (expr == NULL_TREE
-      || MEM_OFFSET (mem) == NULL_RTX
-      || !CONST_INT_P (MEM_OFFSET (mem)))
+  if (expr == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
     return -1;
 
-  offset = INTVAL (MEM_OFFSET (mem));
+  offset = MEM_OFFSET (mem);
   if (DECL_P (expr))
     {
       if (DECL_ALIGN (expr) < align)
@@ -1901,12 +1898,24 @@ set_mem_expr (rtx mem, tree expr)
 /* Set the offset of MEM to OFFSET.  */
 
 void
-set_mem_offset (rtx mem, rtx offset)
+set_mem_offset (rtx mem, HOST_WIDE_INT offset)
 {
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.offset = offset;
+  attrs.offset = GEN_INT (offset);
+  set_mem_attrs (mem, &attrs);
+}
+
+/* Clear the offset of MEM.  */
+
+void
+clear_mem_offset (rtx mem)
+{
+  struct mem_attrs attrs;
+
+  attrs = *get_mem_attrs (mem);
+  attrs.offset = NULL_RTX;
   set_mem_attrs (mem, &attrs);
 }
 
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/config/mips/mips.c	2011-07-17 10:38:53.000000000 +0100
@@ -13777,13 +13777,9 @@ r10k_safe_address_p (rtx x, rtx insn)
    a link-time-constant address.  */
 
 static bool
-r10k_safe_mem_expr_p (tree expr, rtx offset)
+r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
 {
-  if (expr == NULL_TREE
-      || offset == NULL_RTX
-      || !CONST_INT_P (offset)
-      || INTVAL (offset) < 0
-      || INTVAL (offset) >= int_size_in_bytes (TREE_TYPE (expr)))
+  if (offset < 0 || offset >= int_size_in_bytes (TREE_TYPE (expr)))
     return false;
 
   while (TREE_CODE (expr) == COMPONENT_REF)
@@ -13809,7 +13805,9 @@ r10k_needs_protection_p_1 (rtx *loc, voi
   if (!MEM_P (mem))
     return 0;
 
-  if (r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
+  if (MEM_EXPR (mem)
+      && MEM_OFFSET_KNOWN_P (mem)
+      && r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
     return -1;
 
   if (r10k_safe_address_p (XEXP (mem, 0), (rtx) data))

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [5/5] Don't use rtxes in mem_attrs
  2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
                   ` (3 preceding siblings ...)
  2011-07-17 16:55 ` [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P Richard Sandiford
@ 2011-07-17 17:55 ` Richard Sandiford
  2011-07-18 11:15   ` Richard Guenther
  4 siblings, 1 reply; 14+ messages in thread
From: Richard Sandiford @ 2011-07-17 17:55 UTC (permalink / raw)
  To: gcc-patches

This patch replaces the rtxes in mem_attrs with (bool, HOST_WIDE_INT) pairs.
There's already room for the bools in the padding after "addrspace".
(There's room for one more bool after this patch; we could move to
bitfields if more are needed.)

The new structure is 8 bytes bigger when using a combination of a 32-bit
host and a need_64bit_hwint target.  In other cases it should be the same
as before, and will avoid some pointer chasing.  The question is whether
that's an acceptable trade-off or not.

Richard


gcc/
	* rtl.h (mem_attrs): Turn offset and size fields into HOST_WIDE_INTs.
	Add offset_known_p and size_known_p fields.
	(MEM_OFFSET_KNOWN_P): Update accordingly.
	(MEM_OFFSET, MEM_SIZE_KNOWN_P, MEM_SIZE): Likewise.
	* emit-rtl.c (mem_attrs_htab_hash): Update after mem_attrs changes.
	(mem_attrs_eq_p, set_mem_attributes_minus_bitpos, set_mem_offset)
	(clear_mem_offset, set_mem_size, clear_mem_size, change_address)
	(adjust_address_1, widen_memory_access, set_mem_attrs_for_spill)
	(init_emit_regs): Likewise.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2011-07-17 11:40:14.000000000 +0100
+++ gcc/rtl.h	2011-07-17 11:40:18.000000000 +0100
@@ -136,19 +136,38 @@ typedef struct
 
 /* Structure used to describe the attributes of a MEM.  These are hashed
    so MEMs that the same attributes share a data structure.  This means
-   they cannot be modified in place.  If any element is nonzero, it means
-   the value of the corresponding attribute is unknown.  */
-/* ALIGN and SIZE are the alignment and size of the MEM itself,
-   while EXPR can describe a larger underlying object, which might have a
-   stricter alignment; OFFSET is the offset of the MEM within that object.  */
+   they cannot be modified in place.  */
 typedef struct GTY(()) mem_attrs
 {
-  tree expr;			/* expr corresponding to MEM.  */
-  rtx offset;			/* Offset from start of DECL, as CONST_INT.  */
-  rtx size;			/* Size in bytes, as a CONST_INT.  */
-  alias_set_type alias;		/* Memory alias set.  */
-  unsigned int align;		/* Alignment of MEM in bits.  */
-  unsigned char addrspace;	/* Address space (0 for generic).  */
+  /* The expression that the MEM accesses, or null if not known.
+     This expression might be larger than the memory reference itself.
+     (In other words, the MEM might access only part of the object.)  */
+  tree expr;
+
+  /* The offset of the memory reference from the start of EXPR.
+     Only valid if OFFSET_KNOWN_P.  */
+  HOST_WIDE_INT offset;
+
+  /* The size of the memory reference in bytes.  Only valid if
+     SIZE_KNOWN_P.  */
+  HOST_WIDE_INT size;
+
+  /* The alias set of the memory reference.  */
+  alias_set_type alias;
+
+  /* The alignment of the reference in bits.  Always a multiple of
+     BITS_PER_UNIT.  Note that EXPR may have a stricter alignment
+     than the memory reference itself.  */
+  unsigned int align;
+
+  /* The address space that the memory reference uses.  */
+  unsigned char addrspace;
+
+  /* True if OFFSET is known.  */
+  bool offset_known_p;
+
+  /* True if SIZE is known.  */
+  bool size_known_p;
 } mem_attrs;
 
 /* Structure used to describe the attributes of a REG in similar way as
@@ -1303,19 +1322,19 @@ #define MEM_ALIAS_SET(RTX) (get_mem_attr
 #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
 
 /* For a MEM rtx, true if its MEM_OFFSET is known.  */
-#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
+#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)
 
 /* For a MEM rtx, the offset from the start of MEM_EXPR.  */
-#define MEM_OFFSET(RTX) INTVAL (get_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) (get_mem_attrs (RTX)->addrspace)
 
 /* For a MEM rtx, true if its MEM_SIZE is known.  */
-#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size != NULL_RTX)
+#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size_known_p)
 
 /* For a MEM rtx, the size in bytes of the MEM.  */
-#define MEM_SIZE(RTX) INTVAL (get_mem_attrs (RTX)->size)
+#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.  */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2011-07-17 11:40:14.000000000 +0100
+++ gcc/emit-rtl.c	2011-07-17 11:40:18.000000000 +0100
@@ -256,8 +256,8 @@ mem_attrs_htab_hash (const void *x)
 
   return (p->alias ^ (p->align * 1000)
 	  ^ (p->addrspace * 4000)
-	  ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
-	  ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
+	  ^ ((p->offset_known_p ? p->offset : 0) * 50000)
+	  ^ ((p->size_known_p ? p->size : 0) * 2500000)
 	  ^ (size_t) iterative_hash_expr (p->expr, 0));
 }
 
@@ -266,8 +266,12 @@ mem_attrs_htab_hash (const void *x)
 static bool
 mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
 {
-  return (p->alias == q->alias && p->offset == q->offset
-	  && p->size == q->size && p->align == q->align
+  return (p->alias == q->alias
+	  && p->offset_known_p == q->offset_known_p
+	  && (!p->offset_known_p || p->offset == q->offset)
+	  && p->size_known_p == q->size_known_p
+	  && (!p->size_known_p || p->size == q->size)
+	  && p->align == q->align
 	  && p->addrspace == q->addrspace
 	  && (p->expr == q->expr
 	      || (p->expr != NULL_TREE && q->expr != NULL_TREE
@@ -1585,7 +1589,9 @@ set_mem_attributes_minus_bitpos (rtx ref
       /* ??? Can this ever happen?  Calling this routine on a MEM that
 	 already carries memory attributes should probably be invalid.  */
       attrs.expr = refattrs->expr;
+      attrs.offset_known_p = refattrs->offset_known_p;
       attrs.offset = refattrs->offset;
+      attrs.size_known_p = refattrs->size_known_p;
       attrs.size = refattrs->size;
       attrs.align = refattrs->align;
     }
@@ -1595,9 +1601,10 @@ set_mem_attributes_minus_bitpos (rtx ref
     {
       defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
       gcc_assert (!defattrs->expr);
-      gcc_assert (!defattrs->offset);
+      gcc_assert (!defattrs->offset_known_p);
 
       /* Respect mode size.  */
+      attrs.size_known_p = defattrs->size_known_p;
       attrs.size = defattrs->size;
       /* ??? Is this really necessary?  We probably should always get
 	 the size from the type below.  */
@@ -1656,7 +1663,10 @@ set_mem_attributes_minus_bitpos (rtx ref
 
   /* If the size is known, we can set that.  */
   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
-    attrs.size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
+    {
+      attrs.size_known_p = true;
+      attrs.size = 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.  */
@@ -1694,11 +1704,16 @@ set_mem_attributes_minus_bitpos (rtx ref
       if (DECL_P (t))
 	{
 	  attrs.expr = t;
-	  attrs.offset = const0_rtx;
+	  attrs.offset_known_p = true;
+	  attrs.offset = 0;
 	  apply_bitpos = bitpos;
-	  attrs.size = (DECL_SIZE_UNIT (t)
-			&& host_integerp (DECL_SIZE_UNIT (t), 1)
-			? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
+	  if (DECL_SIZE_UNIT (t) && host_integerp (DECL_SIZE_UNIT (t), 1))
+	    {
+	      attrs.size_known_p = true;
+	      attrs.size = tree_low_cst (DECL_SIZE_UNIT (t), 1);
+	    }
+	  else
+	    attrs.size_known_p = false;
 	  attrs.align = DECL_ALIGN (t);
 	  align_computed = true;
 	}
@@ -1721,7 +1736,8 @@ set_mem_attributes_minus_bitpos (rtx ref
 	       && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
 	{
 	  attrs.expr = t;
-	  attrs.offset = const0_rtx;
+	  attrs.offset_known_p = true;
+	  attrs.offset = 0;
 	  apply_bitpos = bitpos;
 	  /* ??? Any reason the field size would be different than
 	     the size we got from the type?  */
@@ -1762,7 +1778,7 @@ set_mem_attributes_minus_bitpos (rtx ref
 	  if (DECL_P (t2))
 	    {
 	      attrs.expr = t2;
-	      attrs.offset = NULL;
+	      attrs.offset_known_p = false;
 	      if (host_integerp (off_tree, 1))
 		{
 		  HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1);
@@ -1771,17 +1787,19 @@ set_mem_attributes_minus_bitpos (rtx ref
 		  if (aoff && (unsigned HOST_WIDE_INT) aoff < attrs.align)
 	            attrs.align = aoff;
 		  align_computed = true;
-		  attrs.offset = GEN_INT (ioff);
+		  attrs.offset_known_p = true;
+		  attrs.offset = ioff;
 		  apply_bitpos = bitpos;
 		}
 	    }
 	  else if (TREE_CODE (t2) == COMPONENT_REF)
 	    {
 	      attrs.expr = t2;
-	      attrs.offset = NULL;
+	      attrs.offset_known_p = false;
 	      if (host_integerp (off_tree, 1))
 		{
-		  attrs.offset = GEN_INT (tree_low_cst (off_tree, 1));
+		  attrs.offset_known_p = true;
+		  attrs.offset = tree_low_cst (off_tree, 1);
 		  apply_bitpos = bitpos;
 		}
 	      /* ??? Any reason the field size would be different than
@@ -1792,7 +1810,8 @@ set_mem_attributes_minus_bitpos (rtx ref
 	  else if (TREE_CODE (t) == MEM_REF)
 	    {
 	      attrs.expr = t;
-	      attrs.offset = const0_rtx;
+	      attrs.offset_known_p = true;
+	      attrs.offset = 0;
 	      apply_bitpos = bitpos;
 	    }
 	}
@@ -1802,7 +1821,8 @@ set_mem_attributes_minus_bitpos (rtx ref
 	       || TREE_CODE (t) == TARGET_MEM_REF)
 	{
 	  attrs.expr = t;
-	  attrs.offset = const0_rtx;
+	  attrs.offset_known_p = true;
+	  attrs.offset = 0;
 	  apply_bitpos = bitpos;
 	}
 
@@ -1818,10 +1838,10 @@ set_mem_attributes_minus_bitpos (rtx ref
      object to contain the negative offset.  */
   if (apply_bitpos)
     {
-      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);
+      gcc_assert (attrs.offset_known_p);
+      attrs.offset -= apply_bitpos / BITS_PER_UNIT;
+      if (attrs.size_known_p)
+	attrs.size += apply_bitpos / BITS_PER_UNIT;
     }
 
   /* Now set the attributes we computed above.  */
@@ -1903,7 +1923,8 @@ set_mem_offset (rtx mem, HOST_WIDE_INT o
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.offset = GEN_INT (offset);
+  attrs.offset_known_p = true;
+  attrs.offset = offset;
   set_mem_attrs (mem, &attrs);
 }
 
@@ -1915,7 +1936,7 @@ clear_mem_offset (rtx mem)
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.offset = NULL_RTX;
+  attrs.offset_known_p = false;
   set_mem_attrs (mem, &attrs);
 }
 
@@ -1927,7 +1948,8 @@ set_mem_size (rtx mem, HOST_WIDE_INT siz
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.size = GEN_INT (size);
+  attrs.size_known_p = true;
+  attrs.size = size;
   set_mem_attrs (mem, &attrs);
 }
 
@@ -1939,7 +1961,7 @@ clear_mem_size (rtx mem)
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.size = NULL_RTX;
+  attrs.size_known_p = false;
   set_mem_attrs (mem, &attrs);
 }
 \f
@@ -1993,8 +2015,9 @@ change_address (rtx memref, enum machine
 
   attrs = *get_mem_attrs (memref);
   defattrs = mode_mem_attrs[(int) mmode];
-  attrs.expr = defattrs->expr;
-  attrs.offset = defattrs->offset;
+  attrs.expr = NULL_TREE;
+  attrs.offset_known_p = false;
+  attrs.size_known_p = defattrs->size_known_p;
   attrs.size = defattrs->size;
   attrs.align = defattrs->align;
 
@@ -2076,8 +2099,8 @@ 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 (attrs.offset)
-    attrs.offset = GEN_INT (offset + INTVAL (attrs.offset));
+  if (attrs.offset_known_p)
+    attrs.offset += 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
@@ -2090,10 +2113,13 @@ adjust_address_1 (rtx memref, enum machi
 
   /* We can compute the size in a number of ways.  */
   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);
+  if (defattrs->size_known_p)
+    {
+      attrs.size_known_p = true;
+      attrs.size = defattrs->size;
+    }
+  else if (attrs.size_known_p)
+    attrs.size -= offset;
 
   set_mem_attrs (new_rtx, &attrs);
 
@@ -2124,7 +2150,7 @@ offset_address (rtx memref, rtx offset,
 {
   rtx new_rtx, addr = XEXP (memref, 0);
   enum machine_mode address_mode;
-  struct mem_attrs attrs;
+  struct mem_attrs attrs, *defattrs;
 
   attrs = *get_mem_attrs (memref);
   address_mode = targetm.addr_space.address_mode (attrs.addrspace);
@@ -2155,8 +2181,10 @@ offset_address (rtx memref, rtx offset,
 
   /* Update the alignment to reflect the offset.  Reset the offset, which
      we don't know.  */
-  attrs.offset = 0;
-  attrs.size = mode_mem_attrs[(int) GET_MODE (new_rtx)]->size;
+  defattrs = mode_mem_attrs[(int) GET_MODE (new_rtx)];
+  attrs.offset_known_p = false;
+  attrs.size_known_p = defattrs->size_known_p;
+  attrs.size = defattrs->size;
   attrs.align = MIN (attrs.align, pow2 * BITS_PER_UNIT);
   set_mem_attrs (new_rtx, &attrs);
   return new_rtx;
@@ -2204,7 +2232,7 @@ widen_memory_access (rtx memref, enum ma
 
   /* If we don't know what offset we were at within the expression, then
      we can't know if we've overstepped the bounds.  */
-  if (! attrs.offset)
+  if (! attrs.offset_known_p)
     attrs.expr = NULL_TREE;
 
   while (attrs.expr)
@@ -2224,7 +2252,7 @@ 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 (attrs.offset) >= 0)
+	      && attrs.offset >= 0)
 	    break;
 
 	  if (! host_integerp (offset, 1))
@@ -2234,18 +2262,16 @@ widen_memory_access (rtx memref, enum ma
 	    }
 
 	  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)));
+	  attrs.offset += tree_low_cst (offset, 1);
+	  attrs.offset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+			   / BITS_PER_UNIT);
 	}
       /* Similarly for the decl.  */
       else if (DECL_P (attrs.expr)
 	       && DECL_SIZE_UNIT (attrs.expr)
 	       && TREE_CODE (DECL_SIZE_UNIT (attrs.expr)) == INTEGER_CST
 	       && compare_tree_int (DECL_SIZE_UNIT (attrs.expr), size) >= 0
-	       && (! attrs.offset || INTVAL (attrs.offset) >= 0))
+	       && (! attrs.offset_known_p || attrs.offset >= 0))
 	break;
       else
 	{
@@ -2257,12 +2283,13 @@ widen_memory_access (rtx memref, enum ma
     }
 
   if (! attrs.expr)
-    attrs.offset = NULL_RTX;
+    attrs.offset_known_p = false;
 
   /* The widened memory may alias other stuff, so zap the alias set.  */
   /* ??? Maybe use get_alias_set on any remaining expression.  */
   attrs.alias = 0;
-  attrs.size = GEN_INT (size);
+  attrs.size_known_p = true;
+  attrs.size = size;
   set_mem_attrs (new_rtx, &attrs);
   return new_rtx;
 }
@@ -2319,10 +2346,11 @@ set_mem_attrs_for_spill (rtx mem)
 	(mem:MODE (plus (reg sfp) (const_int offset)))
      with perhaps the plus missing for offset = 0.  */
   addr = XEXP (mem, 0);
-  attrs.offset = const0_rtx;
+  attrs.offset_known_p = true;
+  attrs.offset = 0;
   if (GET_CODE (addr) == PLUS
       && CONST_INT_P (XEXP (addr, 1)))
-    attrs.offset = XEXP (addr, 1);
+    attrs.offset = INTVAL (XEXP (addr, 1));
 
   set_mem_attrs (mem, &attrs);
   MEM_NOTRAP_P (mem) = 1;
@@ -5522,7 +5550,8 @@ init_emit_regs (void)
       attrs->addrspace = ADDR_SPACE_GENERIC;
       if (mode != BLKmode)
 	{
-	  attrs->size = GEN_INT (GET_MODE_SIZE (mode));
+	  attrs->size_known_p = true;
+	  attrs->size = GET_MODE_SIZE (mode);
 	  if (STRICT_ALIGNMENT)
 	    attrs->align = GET_MODE_ALIGNMENT (mode);
 	}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [1/5] Add a mode_mem_attrs array
  2011-07-17 16:30 ` [1/5] Add a mode_mem_attrs array Richard Sandiford
@ 2011-07-18 10:22   ` Richard Guenther
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2011-07-18 10:22 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

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.  */
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [2/5] Add a set_mem_attrs function
  2011-07-17 16:32 ` [2/5] Add a set_mem_attrs function Richard Sandiford
@ 2011-07-18 10:58   ` Richard Guenther
  2011-07-20 11:27   ` Named address spaces broken (Re: [2/5] Add a set_mem_attrs function) Ulrich Weigand
  1 sibling, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2011-07-18 10:58 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P
  2011-07-17 16:33 ` [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P Richard Sandiford
@ 2011-07-18 11:01   ` Richard Guenther
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2011-07-18 11:01 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

On Sun, Jul 17, 2011 at 4:31 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch does the mechanical MEM_SIZE interface change.  It also
> makes set_mem_size take a HOST_WIDE_INT, and adds clear_mem_size
> for resetting the size to "unknown".
>
> The i386.c part includes an obvious pasto fix for:
>
>  if (dst_size)
>    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
>  if (src_size)
>    set_mem_size (dst, GEN_INT (INTVAL (src_size) - align_bytes));
>
> (last "dst" should be "src") which I can split out into a separate
> patch if desired.

Ok if there are no objections from target maintainers.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * doc/rtl.texi (MEM_SIZE_KNOWN_P): Document.
>        (MEM_SIZE): Change from returning an rtx to returning a HOST_WIDE_INT.
>        * rtl.h (MEM_SIZE_KNOWN_P): New macro.
>        (MEM_SIZE): Return a HOST_WIDE_INT rather than an rtx.
>        * emit-rtl.h (set_mem_size): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_size): Declare.
>        * emit-rtl.c (set_mem_size): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_size): New function.
>        * alias.c (ao_ref_from_mem): Adjust uses of MEM_SIZE, using
>        MEM_SIZE_KNOWN_P to test whether the size is known, and MEM_SIZE
>        to get a HOST_WIDE_INT size.  Adjust calls to set_mem_size,
>        passing a HOST_WIDE_INT rather than an rtx.  Use clear_mem_size
>        to clear the size.
>        (nonoverlapping_memrefs_p): Likewise.
>        * builtins.c (get_memory_rtx, expand_builtin_memcmp): Likewise.
>        (expand_builtin_init_trampoline): Likewise.
>        * calls.c (compute_argument_addresses): Likewise.
>        * cfgcleanup.c (merge_memattrs): Likewise.
>        * dce.c (find_call_stack_args): Likewise.
>        * dse.c (record_store, scan_insn): Likewise.
>        * dwarf2out.c (dw_sra_loc_expr): Likewise.
>        * expr.c (emit_block_move_hints): Likewise.
>        * function.c (assign_parm_find_stack_rtl): Likewise.
>        * print-rtl.c (print_rtx): Likewise.
>        * reload.c (find_reloads_subreg_address): Likewise.
>        * rtlanal.c (may_trap_p_1): Likewise.
>        * var-tracking.c (track_expr_p): Likewise.
>        * varasm.c (assemble_trampoline_template): Likewise.
>        * config/arm/arm.c (arm_print_operand): Likewise.
>        * config/h8300/h8300.c (h8sx_emit_movmd): Likewise.
>        * config/i386/i386.c (expand_movmem_via_rep_mov): Likewise.
>        (expand_setmem_via_rep_stos, expand_constant_movmem_prologue)
>        (expand_constant_setmem_prologue): Likewise.
>        * config/mips/mips.c (mips_get_unaligned_mem): Likewise.
>        * config/rs6000/rs6000.c (expand_block_move): Likewise.
>        (adjacent_mem_locations): Likewise.
>        * config/s390/s390.c (s390_expand_setmem): Likewise.
>        (s390_expand_insv): Likewise.
>        * config/s390/s390.md (*extzv<mode>, *extv<mode>): Likewise.
>        (*extendqi<mode>2_short_displ): Likewise.
>        * config/sh/sh.c (expand_block_move): Likewise.
>        * config/sh/sh.md (extv, extzv): Likewise.
>
> Index: gcc/doc/rtl.texi
> ===================================================================
> --- gcc/doc/rtl.texi    2011-07-17 11:30:32.000000000 +0100
> +++ gcc/doc/rtl.texi    2011-07-17 13:19:35.000000000 +0100
> @@ -413,11 +413,17 @@ object associated with the reference.
>  @item MEM_OFFSET (@var{x})
>  The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
>
> +@findex MEM_SIZE_KNOWN_P
> +@item MEM_SIZE_KNOWN_P (@var{x})
> +True if the size of the memory reference is known.
> +@samp{MEM_SIZE (@var{x})} provides its size if so.
> +
>  @findex MEM_SIZE
>  @item MEM_SIZE (@var{x})
> -The size in bytes of the memory reference as a @code{CONST_INT} rtx.
> +The size in bytes of the memory reference.
>  This is mostly relevant for @code{BLKmode} references as otherwise
> -the size is implied by the mode.
> +the size is implied by the mode.  The value is only valid if
> +@samp{MEM_SIZE_KNOWN_P (@var{x})} is true.
>
>  @findex MEM_ALIGN
>  @item MEM_ALIGN (@var{x})
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h   2011-07-17 11:40:12.000000000 +0100
> +++ gcc/rtl.h   2011-07-17 13:19:35.000000000 +0100
> @@ -1309,9 +1309,11 @@ #define MEM_OFFSET(RTX) (get_mem_attrs (
>  /* For a MEM rtx, the address space.  */
>  #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) (get_mem_attrs (RTX)->size)
> +/* For a MEM rtx, true if its MEM_SIZE is known.  */
> +#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size != NULL_RTX)
> +
> +/* For a MEM rtx, the size in bytes of the MEM.  */
> +#define MEM_SIZE(RTX) INTVAL (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.  */
> Index: gcc/emit-rtl.h
> ===================================================================
> --- gcc/emit-rtl.h      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/emit-rtl.h      2011-07-17 13:19:35.000000000 +0100
> @@ -36,7 +36,10 @@ extern void set_mem_expr (rtx, tree);
>  extern void set_mem_offset (rtx, rtx);
>
>  /* Set the size for MEM to SIZE.  */
> -extern void set_mem_size (rtx, rtx);
> +extern void set_mem_size (rtx, HOST_WIDE_INT);
> +
> +/* Clear the size recorded for MEM.  */
> +extern void clear_mem_size (rtx);
>
>  /* Set the attributes for MEM appropriate for a spill slot.  */
>  extern void set_mem_attrs_for_spill (rtx);
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 11:40:13.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 13:19:35.000000000 +0100
> @@ -1913,12 +1913,24 @@ set_mem_offset (rtx mem, rtx offset)
>  /* Set the size of MEM to SIZE.  */
>
>  void
> -set_mem_size (rtx mem, rtx size)
> +set_mem_size (rtx mem, HOST_WIDE_INT size)
>  {
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.size = size;
> +  attrs.size = GEN_INT (size);
> +  set_mem_attrs (mem, &attrs);
> +}
> +
> +/* Clear the size of MEM.  */
> +
> +void
> +clear_mem_size (rtx mem)
> +{
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.size = NULL_RTX;
>   set_mem_attrs (mem, &attrs);
>  }
>
> Index: gcc/alias.c
> ===================================================================
> --- gcc/alias.c 2011-07-17 11:30:32.000000000 +0100
> +++ gcc/alias.c 2011-07-17 13:19:35.000000000 +0100
> @@ -313,10 +313,10 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>
>   ref->ref_alias_set = MEM_ALIAS_SET (mem);
>
> -  /* If MEM_OFFSET or MEM_SIZE are NULL we have to punt.
> +  /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
>      Keep points-to related information though.  */
>   if (!MEM_OFFSET (mem)
> -      || !MEM_SIZE (mem))
> +      || !MEM_SIZE_KNOWN_P (mem))
>     {
>       ref->ref = NULL_TREE;
>       ref->offset = 0;
> @@ -329,12 +329,12 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
>      here.  */
>   if (INTVAL (MEM_OFFSET (mem)) < 0
> -      && ((INTVAL (MEM_SIZE (mem)) + INTVAL (MEM_OFFSET (mem)))
> +      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
>          * BITS_PER_UNIT) == ref->size)
>     return true;
>
>   ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
> -  ref->size = INTVAL (MEM_SIZE (mem)) * BITS_PER_UNIT;
> +  ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
>
>   /* The MEM may extend into adjacent fields, so adjust max_size if
>      necessary.  */
> @@ -2338,11 +2338,11 @@ nonoverlapping_memrefs_p (const_rtx x, c
>     return 0;
>
>   sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
> -          : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
> +          : MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx)
>           : -1);
>   sizey = (!MEM_P (rtly) ? (int) GET_MODE_SIZE (GET_MODE (rtly))
> -          : MEM_SIZE (rtly) ? INTVAL (MEM_SIZE (rtly)) :
> -          -1);
> +          : MEM_SIZE_KNOWN_P (rtly) ? MEM_SIZE (rtly)
> +          : -1);
>
>   /* If we have an offset for either memref, it can update the values computed
>      above.  */
> @@ -2354,10 +2354,10 @@ nonoverlapping_memrefs_p (const_rtx x, c
>   /* If a memref has both a size and an offset, we can use the smaller size.
>      We can't do this if the offset isn't known because we must view this
>      memref as being anywhere inside the DECL's MEM.  */
> -  if (MEM_SIZE (x) && moffsetx)
> -    sizex = INTVAL (MEM_SIZE (x));
> -  if (MEM_SIZE (y) && moffsety)
> -    sizey = INTVAL (MEM_SIZE (y));
> +  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
> +    sizex = MEM_SIZE (x);
> +  if (MEM_SIZE_KNOWN_P (y) && moffsety)
> +    sizey = MEM_SIZE (y);
>
>   /* Put the values of the memref with the lower offset in X's values.  */
>   if (offsetx > offsety)
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/builtins.c      2011-07-17 13:19:35.000000000 +0100
> @@ -1299,7 +1299,7 @@ get_memory_rtx (tree exp, tree len)
>            }
>        }
>       set_mem_alias_set (mem, 0);
> -      set_mem_size (mem, NULL_RTX);
> +      clear_mem_size (mem);
>     }
>
>   return mem;
> @@ -3691,8 +3691,8 @@ expand_builtin_memcmp (tree exp, ATTRIBU
>     /* Set MEM_SIZE as appropriate.  */
>     if (CONST_INT_P (arg3_rtx))
>       {
> -       set_mem_size (arg1_rtx, arg3_rtx);
> -       set_mem_size (arg2_rtx, arg3_rtx);
> +       set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
> +       set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
>       }
>
>  #ifdef HAVE_cmpmemsi
> @@ -4838,7 +4838,7 @@ expand_builtin_init_trampoline (tree exp
>     {
>       m_tramp = change_address (m_tramp, BLKmode, tmp);
>       set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
> -      set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
> +      set_mem_size (m_tramp, TRAMPOLINE_SIZE);
>     }
>
>   /* The FUNC argument should be the address of the nested function.
> Index: gcc/calls.c
> ===================================================================
> --- gcc/calls.c 2011-07-17 11:30:32.000000000 +0100
> +++ gcc/calls.c 2011-07-17 11:40:14.000000000 +0100
> @@ -1481,7 +1481,7 @@ compute_argument_addresses (struct arg_d
>              partial_mode = mode_for_size (units_on_stack * BITS_PER_UNIT,
>                                            MODE_INT, 1);
>              args[i].stack = gen_rtx_MEM (partial_mode, addr);
> -             set_mem_size (args[i].stack, GEN_INT (units_on_stack));
> +             set_mem_size (args[i].stack, units_on_stack);
>            }
>          else
>            {
> @@ -1513,7 +1513,7 @@ compute_argument_addresses (struct arg_d
>                 Generate a simple memory reference of the correct size.
>               */
>              args[i].stack_slot = gen_rtx_MEM (partial_mode, addr);
> -             set_mem_size (args[i].stack_slot, GEN_INT (units_on_stack));
> +             set_mem_size (args[i].stack_slot, units_on_stack);
>            }
>          else
>            {
> Index: gcc/cfgcleanup.c
> ===================================================================
> --- gcc/cfgcleanup.c    2011-07-17 11:30:32.000000000 +0100
> +++ gcc/cfgcleanup.c    2011-07-17 13:19:35.000000000 +0100
> @@ -883,7 +883,7 @@ merge_memattrs (rtx x, rtx y)
>        MEM_ATTRS (x) = 0;
>       else
>        {
> -         rtx mem_size;
> +         HOST_WIDE_INT mem_size;
>
>          if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
>            {
> @@ -904,15 +904,17 @@ merge_memattrs (rtx x, rtx y)
>              set_mem_offset (y, 0);
>            }
>
> -         if (!MEM_SIZE (x))
> -           mem_size = NULL_RTX;
> -         else if (!MEM_SIZE (y))
> -           mem_size = NULL_RTX;
> +         if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
> +           {
> +             mem_size = MAX (MEM_SIZE (x), MEM_SIZE (y));
> +             set_mem_size (x, mem_size);
> +             set_mem_size (y, mem_size);
> +           }
>          else
> -           mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
> -                                    INTVAL (MEM_SIZE (y))));
> -         set_mem_size (x, mem_size);
> -         set_mem_size (y, mem_size);
> +           {
> +             clear_mem_size (x);
> +             clear_mem_size (y);
> +           }
>
>          set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
>          set_mem_align (y, MEM_ALIGN (x));
> Index: gcc/dce.c
> ===================================================================
> --- gcc/dce.c   2011-07-17 11:30:32.000000000 +0100
> +++ gcc/dce.c   2011-07-17 11:40:14.000000000 +0100
> @@ -275,11 +275,11 @@ find_call_stack_args (rtx call_insn, boo
>     if (GET_CODE (XEXP (p, 0)) == USE
>        && MEM_P (XEXP (XEXP (p, 0), 0)))
>       {
> -       rtx mem = XEXP (XEXP (p, 0), 0), addr, size;
> -       HOST_WIDE_INT off = 0;
> -       size = MEM_SIZE (mem);
> -       if (size == NULL_RTX)
> +       rtx mem = XEXP (XEXP (p, 0), 0), addr;
> +       HOST_WIDE_INT off = 0, size;
> +       if (!MEM_SIZE_KNOWN_P (mem))
>          return false;
> +       size = MEM_SIZE (mem);
>        addr = XEXP (mem, 0);
>        if (GET_CODE (addr) == PLUS
>            && REG_P (XEXP (addr, 0))
> @@ -329,7 +329,7 @@ find_call_stack_args (rtx call_insn, boo
>              return false;
>          }
>        min_sp_off = MIN (min_sp_off, off);
> -       max_sp_off = MAX (max_sp_off, off + INTVAL (size));
> +       max_sp_off = MAX (max_sp_off, off + size);
>       }
>
>   if (min_sp_off >= max_sp_off)
> @@ -370,7 +370,7 @@ find_call_stack_args (rtx call_insn, boo
>            set = single_set (DF_REF_INSN (defs->ref));
>            off += INTVAL (XEXP (SET_SRC (set), 1));
>          }
> -       for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)
> +       for (byte = off; byte < off + MEM_SIZE (mem); byte++)
>          {
>            if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
>              gcc_unreachable ();
> Index: gcc/dse.c
> ===================================================================
> --- gcc/dse.c   2011-07-17 11:30:32.000000000 +0100
> +++ gcc/dse.c   2011-07-17 11:40:14.000000000 +0100
> @@ -1355,11 +1355,10 @@ record_store (rtx body, bb_info_t bb_inf
>        }
>       /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0))
>         as memset (addr, 0, 36);  */
> -      else if (!MEM_SIZE (mem)
> -              || !CONST_INT_P (MEM_SIZE (mem))
> +      else if (!MEM_SIZE_KNOWN_P (mem)
> +              || MEM_SIZE (mem) <= 0
> +              || MEM_SIZE (mem) > MAX_OFFSET
>               || GET_CODE (body) != SET
> -              || INTVAL (MEM_SIZE (mem)) <= 0
> -              || INTVAL (MEM_SIZE (mem)) > MAX_OFFSET
>               || !CONST_INT_P (SET_SRC (body)))
>        {
>          if (!store_is_unused)
> @@ -1384,7 +1383,7 @@ record_store (rtx body, bb_info_t bb_inf
>     }
>
>   if (GET_MODE (mem) == BLKmode)
> -    width = INTVAL (MEM_SIZE (mem));
> +    width = MEM_SIZE (mem);
>   else
>     {
>       width = GET_MODE_SIZE (GET_MODE (mem));
> @@ -2517,7 +2516,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
>                  && INTVAL (args[2]) > 0)
>                {
>                  rtx mem = gen_rtx_MEM (BLKmode, args[0]);
> -                 set_mem_size (mem, args[2]);
> +                 set_mem_size (mem, INTVAL (args[2]));
>                  body = gen_rtx_SET (VOIDmode, mem, args[1]);
>                  mems_found += record_store (body, bb_info);
>                  if (dump_file)
> Index: gcc/dwarf2out.c
> ===================================================================
> --- gcc/dwarf2out.c     2011-07-17 11:30:32.000000000 +0100
> +++ gcc/dwarf2out.c     2011-07-17 13:19:35.000000000 +0100
> @@ -12876,7 +12876,7 @@ dw_sra_loc_expr (tree decl, rtx loc)
>          if (MEM_P (varloc))
>            {
>              unsigned HOST_WIDE_INT memsize
> -               = INTVAL (MEM_SIZE (varloc)) * BITS_PER_UNIT;
> +               = MEM_SIZE (varloc) * BITS_PER_UNIT;
>              if (memsize != bitsize)
>                {
>                  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  2011-07-17 11:30:32.000000000 +0100
> +++ gcc/expr.c  2011-07-17 11:40:14.000000000 +0100
> @@ -1166,8 +1166,8 @@ emit_block_move_hints (rtx x, rtx y, rtx
>     {
>       x = shallow_copy_rtx (x);
>       y = shallow_copy_rtx (y);
> -      set_mem_size (x, size);
> -      set_mem_size (y, size);
> +      set_mem_size (x, INTVAL (size));
> +      set_mem_size (y, INTVAL (size));
>     }
>
>   if (CONST_INT_P (size) && MOVE_BY_PIECES_P (INTVAL (size), align))
> Index: gcc/function.c
> ===================================================================
> --- gcc/function.c      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/function.c      2011-07-17 13:19:35.000000000 +0100
> @@ -2576,8 +2576,7 @@ assign_parm_find_stack_rtl (tree parm, s
>       if (data->promoted_mode != BLKmode
>          && data->promoted_mode != DECL_MODE (parm))
>        {
> -         set_mem_size (stack_parm,
> -                       GEN_INT (GET_MODE_SIZE (data->promoted_mode)));
> +         set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
>          if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
>            {
>              int offset = subreg_lowpart_offset (DECL_MODE (parm),
> Index: gcc/print-rtl.c
> ===================================================================
> --- gcc/print-rtl.c     2011-07-17 11:30:32.000000000 +0100
> +++ gcc/print-rtl.c     2011-07-17 13:19:35.000000000 +0100
> @@ -601,9 +601,8 @@ print_rtx (const_rtx in_rtx)
>        fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
>                 INTVAL (MEM_OFFSET (in_rtx)));
>
> -      if (MEM_SIZE (in_rtx))
> -       fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC,
> -                INTVAL (MEM_SIZE (in_rtx)));
> +      if (MEM_SIZE_KNOWN_P (in_rtx))
> +       fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
>
>       if (MEM_ALIGN (in_rtx) != 1)
>        fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
> Index: gcc/reload.c
> ===================================================================
> --- gcc/reload.c        2011-07-17 11:30:32.000000000 +0100
> +++ gcc/reload.c        2011-07-17 13:19:35.000000000 +0100
> @@ -6139,9 +6139,9 @@ find_reloads_subreg_address (rtx x, int
>              PUT_MODE (tem, GET_MODE (x));
>              if (MEM_OFFSET (tem))
>                set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
> -             if (MEM_SIZE (tem)
> -                 && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size)
> -               set_mem_size (tem, GEN_INT (outer_size));
> +             if (MEM_SIZE_KNOWN_P (tem)
> +                 && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
> +               set_mem_size (tem, outer_size);
>
>              /* If this was a paradoxical subreg that we replaced, the
>                 resulting memory must be sufficiently aligned to allow
> Index: gcc/rtlanal.c
> ===================================================================
> --- gcc/rtlanal.c       2011-07-17 11:30:32.000000000 +0100
> +++ gcc/rtlanal.c       2011-07-17 11:40:14.000000000 +0100
> @@ -2279,7 +2279,7 @@ may_trap_p_1 (const_rtx x, unsigned flag
>          code_changed
>          || !MEM_NOTRAP_P (x))
>        {
> -         HOST_WIDE_INT size = MEM_SIZE (x) ? INTVAL (MEM_SIZE (x)) : 0;
> +         HOST_WIDE_INT size = MEM_SIZE_KNOWN_P (x) ? MEM_SIZE (x) : 0;
>          return rtx_addr_can_trap_p_1 (XEXP (x, 0), 0, size,
>                                        GET_MODE (x), code_changed);
>        }
> Index: gcc/var-tracking.c
> ===================================================================
> --- gcc/var-tracking.c  2011-07-17 11:30:32.000000000 +0100
> +++ gcc/var-tracking.c  2011-07-17 13:19:35.000000000 +0100
> @@ -4674,8 +4674,8 @@ track_expr_p (tree expr, bool need_rtl)
>       if (GET_MODE (decl_rtl) == BLKmode
>          || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
>        return 0;
> -      if (MEM_SIZE (decl_rtl)
> -         && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
> +      if (MEM_SIZE_KNOWN_P (decl_rtl)
> +         && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS)
>        return 0;
>     }
>
> Index: gcc/varasm.c
> ===================================================================
> --- gcc/varasm.c        2011-07-17 11:30:32.000000000 +0100
> +++ gcc/varasm.c        2011-07-17 11:40:14.000000000 +0100
> @@ -2391,7 +2391,7 @@ assemble_trampoline_template (void)
>
>   initial_trampoline = gen_const_mem (BLKmode, symbol);
>   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
> -  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
> +  set_mem_size (initial_trampoline, TRAMPOLINE_SIZE);
>
>   return initial_trampoline;
>  }
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c        2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/arm/arm.c        2011-07-17 11:40:14.000000000 +0100
> @@ -16713,7 +16713,7 @@ arm_print_operand (FILE *stream, rtx x,
>           instruction (for some alignments) as an aid to the memory subsystem
>           of the target.  */
>        align = MEM_ALIGN (x) >> 3;
> -       memsize = INTVAL (MEM_SIZE (x));
> +       memsize = MEM_SIZE (x);
>
>        /* Only certain alignment specifiers are supported by the hardware.  */
>        if (memsize == 16 && (align % 32) == 0)
> Index: gcc/config/h8300/h8300.c
> ===================================================================
> --- gcc/config/h8300/h8300.c    2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/h8300/h8300.c    2011-07-17 11:40:14.000000000 +0100
> @@ -2642,8 +2642,8 @@ h8sx_emit_movmd (rtx dest, rtx src, rtx
>       first_dest = replace_equiv_address (dest, dest_reg);
>       first_src = replace_equiv_address (src, src_reg);
>
> -      set_mem_size (first_dest, GEN_INT (n & -factor));
> -      set_mem_size (first_src, GEN_INT (n & -factor));
> +      set_mem_size (first_dest, n & -factor);
> +      set_mem_size (first_src, n & -factor);
>
>       length = copy_to_mode_reg (HImode, gen_int_mode (n / factor, HImode));
>       emit_insn (gen_movmd (first_dest, first_src, length, GEN_INT (factor)));
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/i386/i386.c      2011-07-17 11:40:14.000000000 +0100
> @@ -19702,6 +19702,7 @@ expand_movmem_via_rep_mov (rtx destmem,
>   rtx destexp;
>   rtx srcexp;
>   rtx countreg;
> +  HOST_WIDE_INT rounded_count;
>
>   /* If the size is known, it is shorter to use rep movs.  */
>   if (mode == QImode && CONST_INT_P (count)
> @@ -19729,19 +19730,19 @@ expand_movmem_via_rep_mov (rtx destmem,
>     }
>   if (CONST_INT_P (count))
>     {
> -      count = GEN_INT (INTVAL (count)
> +      rounded_count = (INTVAL (count)
>                       & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
>       destmem = shallow_copy_rtx (destmem);
>       srcmem = shallow_copy_rtx (srcmem);
> -      set_mem_size (destmem, count);
> -      set_mem_size (srcmem, count);
> +      set_mem_size (destmem, rounded_count);
> +      set_mem_size (srcmem, rounded_count);
>     }
>   else
>     {
> -      if (MEM_SIZE (destmem))
> -       set_mem_size (destmem, NULL_RTX);
> -      if (MEM_SIZE (srcmem))
> -       set_mem_size (srcmem, NULL_RTX);
> +      if (MEM_SIZE_KNOWN_P (destmem))
> +       clear_mem_size (destmem);
> +      if (MEM_SIZE_KNOWN_P (srcmem))
> +       clear_mem_size (srcmem);
>     }
>   emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
>                          destexp, srcexp));
> @@ -19756,6 +19757,7 @@ expand_setmem_via_rep_stos (rtx destmem,
>  {
>   rtx destexp;
>   rtx countreg;
> +  HOST_WIDE_INT rounded_count;
>
>   if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
>     destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
> @@ -19771,13 +19773,13 @@ expand_setmem_via_rep_stos (rtx destmem,
>     destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
>   if (orig_value == const0_rtx && CONST_INT_P (count))
>     {
> -      count = GEN_INT (INTVAL (count)
> +      rounded_count = (INTVAL (count)
>                       & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
>       destmem = shallow_copy_rtx (destmem);
> -      set_mem_size (destmem, count);
> +      set_mem_size (destmem, rounded_count);
>     }
> -  else if (MEM_SIZE (destmem))
> -    set_mem_size (destmem, NULL_RTX);
> +  else if (MEM_SIZE_KNOWN_P (destmem))
> +    clear_mem_size (destmem);
>   emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
>  }
>
> @@ -20118,13 +20120,12 @@ expand_constant_movmem_prologue (rtx dst
>                                 int desired_align, int align_bytes)
>  {
>   rtx src = *srcp;
> -  rtx src_size, dst_size;
> +  rtx orig_dst = dst;
> +  rtx orig_src = src;
>   int off = 0;
>   int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT);
>   if (src_align_bytes >= 0)
>     src_align_bytes = desired_align - src_align_bytes;
> -  src_size = MEM_SIZE (src);
> -  dst_size = MEM_SIZE (dst);
>   if (align_bytes & 1)
>     {
>       dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
> @@ -20182,10 +20183,10 @@ expand_constant_movmem_prologue (rtx dst
>       if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
>        set_mem_align (src, src_align * BITS_PER_UNIT);
>     }
> -  if (dst_size)
> -    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
> -  if (src_size)
> -    set_mem_size (dst, GEN_INT (INTVAL (src_size) - align_bytes));
> +  if (MEM_SIZE_KNOWN_P (orig_dst))
> +    set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
> +  if (MEM_SIZE_KNOWN_P (orig_src))
> +    set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
>   *srcp = src;
>   return dst;
>  }
> @@ -20233,7 +20234,7 @@ expand_constant_setmem_prologue (rtx dst
>                                 int desired_align, int align_bytes)
>  {
>   int off = 0;
> -  rtx dst_size = MEM_SIZE (dst);
> +  rtx orig_dst = dst;
>   if (align_bytes & 1)
>     {
>       dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
> @@ -20262,8 +20263,8 @@ expand_constant_setmem_prologue (rtx dst
>   dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
>   if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
>     set_mem_align (dst, desired_align * BITS_PER_UNIT);
> -  if (dst_size)
> -    set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes));
> +  if (MEM_SIZE_KNOWN_P (orig_dst))
> +    set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
>   return dst;
>  }
>
> Index: gcc/config/mips/mips.c
> ===================================================================
> --- gcc/config/mips/mips.c      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/mips/mips.c      2011-07-17 13:19:35.000000000 +0100
> @@ -6862,7 +6862,7 @@ mips_get_unaligned_mem (rtx *op, HOST_WI
>   /* Adjust *OP to refer to the whole field.  This also has the effect
>      of legitimizing *OP's address for BLKmode, possibly simplifying it.  */
>   *op = adjust_address (*op, BLKmode, 0);
> -  set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT));
> +  set_mem_size (*op, width / BITS_PER_UNIT);
>
>   /* Get references to both ends of the field.  We deliberately don't
>      use the original QImode *OP for FIRST since the new BLKmode one
> @@ -6962,13 +6962,9 @@ mips_expand_ins_as_unaligned_store (rtx
>  bool
>  mips_mem_fits_mode_p (enum machine_mode mode, rtx x)
>  {
> -  rtx size;
> -
> -  if (!MEM_P (x))
> -    return false;
> -
> -  size = MEM_SIZE (x);
> -  return size && INTVAL (size) == GET_MODE_SIZE (mode);
> +  return (MEM_P (x)
> +         && MEM_SIZE_KNOWN_P (x)
> +         && MEM_SIZE (x) == GET_MODE_SIZE (mode));
>  }
>
>  /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/rs6000/rs6000.c  2011-07-17 11:40:14.000000000 +0100
> @@ -13685,14 +13685,14 @@ expand_block_move (rtx operands[])
>              rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
>              src = replace_equiv_address (src, src_reg);
>            }
> -         set_mem_size (src, GEN_INT (move_bytes));
> +         set_mem_size (src, move_bytes);
>
>          if (!REG_P (XEXP (dest, 0)))
>            {
>              rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
>              dest = replace_equiv_address (dest, dest_reg);
>            }
> -         set_mem_size (dest, GEN_INT (move_bytes));
> +         set_mem_size (dest, move_bytes);
>
>          emit_insn ((*gen_func.movmemsi) (dest, src,
>                                           GEN_INT (move_bytes & 31),
> @@ -23063,8 +23063,8 @@ adjacent_mem_locations (rtx insn1, rtx i
>       val_diff = val1 - val0;
>
>       return ((REGNO (reg0) == REGNO (reg1))
> -             && ((MEM_SIZE (a) && val_diff == INTVAL (MEM_SIZE (a)))
> -                 || (MEM_SIZE (b) && val_diff == -INTVAL (MEM_SIZE (b)))));
> +             && ((MEM_SIZE_KNOWN_P (a) && val_diff == MEM_SIZE (a))
> +                 || (MEM_SIZE_KNOWN_P (b) && val_diff == -MEM_SIZE (b))));
>     }
>
>   return false;
> Index: gcc/config/s390/s390.c
> ===================================================================
> --- gcc/config/s390/s390.c      2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/s390/s390.c      2011-07-17 11:40:14.000000000 +0100
> @@ -4099,7 +4099,7 @@ s390_expand_setmem (rtx dst, rtx len, rt
>                 DST is set to size 1 so the rest of the memory location
>                 does not count as source operand.  */
>              rtx dstp1 = adjust_address (dst, VOIDmode, 1);
> -             set_mem_size (dst, const1_rtx);
> +             set_mem_size (dst, 1);
>
>              emit_insn (gen_movmem_short (dstp1, dst,
>                                           GEN_INT (INTVAL (len) - 2)));
> @@ -4142,7 +4142,7 @@ s390_expand_setmem (rtx dst, rtx len, rt
>       else
>        {
>          dstp1 = adjust_address (dst, VOIDmode, 1);
> -         set_mem_size (dst, const1_rtx);
> +         set_mem_size (dst, 1);
>
>          /* Initialize memory by storing the first byte.  */
>          emit_move_insn (adjust_address (dst, QImode, 0), val);
> @@ -4551,7 +4551,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx
>                                        GET_MODE_SIZE (word_mode) - size);
>
>          dest = adjust_address (dest, BLKmode, 0);
> -         set_mem_size (dest, GEN_INT (size));
> +         set_mem_size (dest, size);
>          s390_expand_movmem (dest, src_mem, GEN_INT (size));
>        }
>
> @@ -4569,7 +4569,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx
>
>              emit_move_insn (adjust_address (dest, SImode, size),
>                              gen_lowpart (SImode, src));
> -             set_mem_size (dest, GEN_INT (size));
> +             set_mem_size (dest, size);
>              emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
>                                                    (stcmh_width), const0_rtx),
>                              gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
> Index: gcc/config/s390/s390.md
> ===================================================================
> --- gcc/config/s390/s390.md     2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/s390/s390.md     2011-07-17 11:40:14.000000000 +0100
> @@ -3295,7 +3295,7 @@ (define_insn_and_split "*extzv<mode>"
>   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
>
>   operands[1] = adjust_address (operands[1], BLKmode, 0);
> -  set_mem_size (operands[1], GEN_INT (size));
> +  set_mem_size (operands[1], size);
>   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
>   operands[3] = GEN_INT (mask);
>  })
> @@ -3322,7 +3322,7 @@ (define_insn_and_split "*extv<mode>"
>   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
>
>   operands[1] = adjust_address (operands[1], BLKmode, 0);
> -  set_mem_size (operands[1], GEN_INT (size));
> +  set_mem_size (operands[1], size);
>   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
>   operands[3] = GEN_INT (mask);
>  })
> @@ -3656,7 +3656,7 @@ (define_insn_and_split "*extendqi<mode>2
>      (clobber (reg:CC CC_REGNUM))])]
>  {
>   operands[1] = adjust_address (operands[1], BLKmode, 0);
> -  set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
> +  set_mem_size (operands[1], GET_MODE_SIZE (QImode));
>   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)
>                         - GET_MODE_BITSIZE (QImode));
>  })
> Index: gcc/config/sh/sh.c
> ===================================================================
> --- gcc/config/sh/sh.c  2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/sh/sh.c  2011-07-17 11:40:14.000000000 +0100
> @@ -1456,7 +1456,7 @@ expand_block_move (rtx *operands)
>          rtx from = adjust_automodify_address (src, BLKmode,
>                                                src_addr, copied);
>
> -         set_mem_size (from, GEN_INT (4));
> +         set_mem_size (from, 4);
>          emit_insn (gen_movua (temp, from));
>          emit_move_insn (src_addr, plus_constant (src_addr, 4));
>          emit_move_insn (to, temp);
> Index: gcc/config/sh/sh.md
> ===================================================================
> --- gcc/config/sh/sh.md 2011-07-17 11:30:32.000000000 +0100
> +++ gcc/config/sh/sh.md 2011-07-17 11:40:14.000000000 +0100
> @@ -11070,7 +11070,7 @@ (define_expand "extv"
>       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
>     {
>       rtx src = adjust_address (operands[1], BLKmode, 0);
> -      set_mem_size (src, GEN_INT (4));
> +      set_mem_size (src, 4);
>       emit_insn (gen_movua (operands[0], src));
>       DONE;
>     }
> @@ -11102,7 +11102,7 @@ (define_expand "extzv"
>       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
>     {
>       rtx src = adjust_address (operands[1], BLKmode, 0);
> -      set_mem_size (src, GEN_INT (4));
> +      set_mem_size (src, 4);
>       emit_insn (gen_movua (operands[0], src));
>       DONE;
>     }
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P
  2011-07-17 16:55 ` [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P Richard Sandiford
@ 2011-07-18 11:10   ` Richard Guenther
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2011-07-18 11:10 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

On Sun, Jul 17, 2011 at 4:32 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch makes the mechanical MEM_OFFSET interface change,
> along the same lines as the MEM_SIZE one.

Ok if there are no objections from target maintainers.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * doc/rtl.texi (MEM_OFFSET_KNOWN_P): Document.
>        (MEM_OFFSET): Change from returning an rtx to returning a
>        HOST_WIDE_INT.
>        * rtl.h (MEM_OFFSET_KNOWN_P): New macro.
>        (MEM_OFFSET): Return a HOST_WIDE_INT rather than an rtx.
>        * emit-rtl.h (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_offset): Declare.
>        * alias.c (ao_ref_from_mem): Adjust uses of MEM_OFFSET, using
>        MEM_OFFSET_KNOWN_P to test whether the offset is known, and
>        MEM_OFFSET to get a HOST_WIDE_INT offset.
>        (nonoverlapping_memrefs_p): Likewise.  Adjust calls to...
>        (adjust_offset_for_component_ref): Take a bool "known_p"
>        parameter and a HOST_WIDE_INT "offset" parameter.
>        * builtins.c (get_memory_rtx): As for ao_ref_from_mem.
>        Adjust calls to set_mem_offset, passing a HOST_WIDE_INT rather
>        than an rtx.  Use clear_mem_offset to clear the offset.
>        * cfgcleanup.c (merge_memattrs): Likewise.
>        * dwarf2out.c (tls_mem_loc_descriptor): Likewise.
>        * function.c (assign_parm_find_stack_rtl): Likewise.
>        (assign_parm_setup_stack): Likewise.
>        * print-rtl.c (print_rtx): Likewise.
>        * reload.c (find_reloads_subreg_address): Likewise.
>        * simplify-rtx.c (delegitimize_mem_from_attrs): Likewise.
>        * var-tracking.c (INT_MEM_OFFSET): Likewise.
>        * emit-rtl.c (set_reg_attrs_from_value): Likewise.
>        (get_mem_align_offset): Likewise.
>        (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_offset): New function.
>        * config/mips/mips.c (r10k_safe_mem_expr_p): Take a HOST_WIDE_INT
>        offset rather than an rtx.  Assume both the expressio and offset
>        are available.
>        (r10k_needs_protection_p_1): Update accordingly, checking the
>        expression and offset availability here instead.
>
> Index: gcc/doc/rtl.texi
> ===================================================================
> --- gcc/doc/rtl.texi    2011-07-17 10:53:19.000000000 +0100
> +++ gcc/doc/rtl.texi    2011-07-17 10:54:22.000000000 +0100
> @@ -409,9 +409,15 @@ and @code{TREE_OPERAND (@var{x}, 0)} con
>  or another @code{COMPONENT_REF}, or null if there is no compile-time
>  object associated with the reference.
>
> +@findex MEM_OFFSET_KNOWN_P
> +@item MEM_OFFSET_KNOWN_P (@var{x})
> +True if the offset of the memory reference from @code{MEM_EXPR} is known.
> +@samp{MEM_OFFSET (@var{x})} provides the offset if so.
> +
>  @findex MEM_OFFSET
>  @item MEM_OFFSET (@var{x})
> -The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
> +The offset from the start of @code{MEM_EXPR}.  The value is only valid if
> +@samp{MEM_OFFSET_KNOWN_P (@var{x})} is true.
>
>  @findex MEM_SIZE_KNOWN_P
>  @item MEM_SIZE_KNOWN_P (@var{x})
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h   2011-07-17 10:18:59.000000000 +0100
> +++ gcc/rtl.h   2011-07-17 10:38:53.000000000 +0100
> @@ -1302,9 +1302,11 @@ #define MEM_ALIAS_SET(RTX) (get_mem_attr
>    refer to part of a DECL.  It may also be a COMPONENT_REF.  */
>  #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
>
> -/* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
> -   RTX that is always a CONST_INT.  */
> -#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
> +/* For a MEM rtx, true if its MEM_OFFSET is known.  */
> +#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
> +
> +/* For a MEM rtx, the offset from the start of MEM_EXPR.  */
> +#define MEM_OFFSET(RTX) INTVAL (get_mem_attrs (RTX)->offset)
>
>  /* For a MEM rtx, the address space.  */
>  #define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
> Index: gcc/emit-rtl.h
> ===================================================================
> --- gcc/emit-rtl.h      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/emit-rtl.h      2011-07-17 10:38:53.000000000 +0100
> @@ -33,7 +33,10 @@ extern void set_mem_addr_space (rtx, add
>  extern void set_mem_expr (rtx, tree);
>
>  /* Set the offset for MEM to OFFSET.  */
> -extern void set_mem_offset (rtx, rtx);
> +extern void set_mem_offset (rtx, HOST_WIDE_INT);
> +
> +/* Clear the offset recorded for MEM.  */
> +extern void clear_mem_offset (rtx);
>
>  /* Set the size for MEM to SIZE.  */
>  extern void set_mem_size (rtx, HOST_WIDE_INT);
> Index: gcc/alias.c
> ===================================================================
> --- gcc/alias.c 2011-07-17 10:18:59.000000000 +0100
> +++ gcc/alias.c 2011-07-17 10:43:20.000000000 +0100
> @@ -162,7 +162,6 @@ static const_rtx fixed_scalar_and_varyin
>  static int aliases_everything_p (const_rtx);
>  static bool nonoverlapping_component_refs_p (const_tree, const_tree);
>  static tree decl_for_component_ref (tree);
> -static rtx adjust_offset_for_component_ref (tree, rtx);
>  static int write_dependence_p (const_rtx, const_rtx, int);
>
>  static void memory_modified_1 (rtx, const_rtx, void *);
> @@ -315,7 +314,7 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>
>   /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
>      Keep points-to related information though.  */
> -  if (!MEM_OFFSET (mem)
> +  if (!MEM_OFFSET_KNOWN_P (mem)
>       || !MEM_SIZE_KNOWN_P (mem))
>     {
>       ref->ref = NULL_TREE;
> @@ -328,12 +327,11 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>   /* If the base decl is a parameter we can have negative MEM_OFFSET in
>      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
>      here.  */
> -  if (INTVAL (MEM_OFFSET (mem)) < 0
> -      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
> -         * BITS_PER_UNIT) == ref->size)
> +  if (MEM_OFFSET (mem) < 0
> +      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
>     return true;
>
> -  ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
> +  ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
>   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
>
>   /* The MEM may extend into adjacent fields, so adjust max_size if
> @@ -2201,34 +2199,33 @@ decl_for_component_ref (tree x)
>   return x && DECL_P (x) ? x : NULL_TREE;
>  }
>
> -/* Walk up the COMPONENT_REF list and adjust OFFSET to compensate for the
> -   offset of the field reference.  */
> +/* Walk up the COMPONENT_REF list in X and adjust *OFFSET to compensate
> +   for the offset of the field reference.  *KNOWN_P says whether the
> +   offset is known.  */
>
> -static rtx
> -adjust_offset_for_component_ref (tree x, rtx offset)
> +static void
> +adjust_offset_for_component_ref (tree x, bool *known_p,
> +                                HOST_WIDE_INT *offset)
>  {
> -  HOST_WIDE_INT ioffset;
> -
> -  if (! offset)
> -    return NULL_RTX;
> -
> -  ioffset = INTVAL (offset);
> +  if (!*known_p)
> +    return;
>   do
>     {
> -      tree offset = component_ref_field_offset (x);
> +      tree xoffset = component_ref_field_offset (x);
>       tree field = TREE_OPERAND (x, 1);
>
> -      if (! host_integerp (offset, 1))
> -       return NULL_RTX;
> -      ioffset += (tree_low_cst (offset, 1)
> +      if (! host_integerp (xoffset, 1))
> +       {
> +         *known_p = false;
> +         return;
> +       }
> +      *offset += (tree_low_cst (xoffset, 1)
>                  + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
>                     / BITS_PER_UNIT));
>
>       x = TREE_OPERAND (x, 0);
>     }
>   while (x && TREE_CODE (x) == COMPONENT_REF);
> -
> -  return GEN_INT (ioffset);
>  }
>
>  /* Return nonzero if we can determine the exprs corresponding to memrefs
> @@ -2241,7 +2238,8 @@ nonoverlapping_memrefs_p (const_rtx x, c
>   tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
>   rtx rtlx, rtly;
>   rtx basex, basey;
> -  rtx moffsetx, moffsety;
> +  bool moffsetx_known_p, moffsety_known_p;
> +  HOST_WIDE_INT moffsetx = 0, moffsety = 0;
>   HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
>
>   /* Unless both have exprs, we can't tell anything.  */
> @@ -2250,9 +2248,9 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>   /* For spill-slot accesses make sure we have valid offsets.  */
>   if ((exprx == get_spill_slot_decl (false)
> -       && ! MEM_OFFSET (x))
> +       && ! MEM_OFFSET_KNOWN_P (x))
>       || (expry == get_spill_slot_decl (false)
> -         && ! MEM_OFFSET (y)))
> +         && ! MEM_OFFSET_KNOWN_P (y)))
>     return 0;
>
>   /* If both are field references, we may be able to determine something.  */
> @@ -2263,23 +2261,27 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>
>   /* If the field reference test failed, look at the DECLs involved.  */
> -  moffsetx = MEM_OFFSET (x);
> +  moffsetx_known_p = MEM_OFFSET_KNOWN_P (x);
> +  if (moffsetx_known_p)
> +    moffsetx = MEM_OFFSET (x);
>   if (TREE_CODE (exprx) == COMPONENT_REF)
>     {
>       tree t = decl_for_component_ref (exprx);
>       if (! t)
>        return 0;
> -      moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
> +      adjust_offset_for_component_ref (exprx, &moffsetx_known_p, &moffsetx);
>       exprx = t;
>     }
>
> -  moffsety = MEM_OFFSET (y);
> +  moffsety_known_p = MEM_OFFSET_KNOWN_P (y);
> +  if (moffsety_known_p)
> +    moffsety = MEM_OFFSET (y);
>   if (TREE_CODE (expry) == COMPONENT_REF)
>     {
>       tree t = decl_for_component_ref (expry);
>       if (! t)
>        return 0;
> -      moffsety = adjust_offset_for_component_ref (expry, moffsety);
> +      adjust_offset_for_component_ref (expry, &moffsety_known_p, &moffsety);
>       expry = t;
>     }
>
> @@ -2346,17 +2348,17 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>   /* If we have an offset for either memref, it can update the values computed
>      above.  */
> -  if (moffsetx)
> -    offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
> -  if (moffsety)
> -    offsety += INTVAL (moffsety), sizey -= INTVAL (moffsety);
> +  if (moffsetx_known_p)
> +    offsetx += moffsetx, sizex -= moffsetx;
> +  if (moffsety_known_p)
> +    offsety += moffsety, sizey -= moffsety;
>
>   /* If a memref has both a size and an offset, we can use the smaller size.
>      We can't do this if the offset isn't known because we must view this
>      memref as being anywhere inside the DECL's MEM.  */
> -  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
> +  if (MEM_SIZE_KNOWN_P (x) && moffsetx_known_p)
>     sizex = MEM_SIZE (x);
> -  if (MEM_SIZE_KNOWN_P (y) && moffsety)
> +  if (MEM_SIZE_KNOWN_P (y) && moffsety_known_p)
>     sizey = MEM_SIZE (y);
>
>   /* Put the values of the memref with the lower offset in X's values.  */
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/builtins.c      2011-07-17 10:38:53.000000000 +0100
> @@ -1238,9 +1238,8 @@ get_memory_rtx (tree exp, tree len)
>
>          gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
>
> -         if (MEM_OFFSET (mem)
> -             && CONST_INT_P (MEM_OFFSET (mem)))
> -           offset = INTVAL (MEM_OFFSET (mem));
> +         if (MEM_OFFSET_KNOWN_P (mem))
> +           offset = MEM_OFFSET (mem);
>
>          if (offset >= 0 && len && host_integerp (len, 0))
>            length = tree_low_cst (len, 0);
> @@ -1295,7 +1294,10 @@ get_memory_rtx (tree exp, tree len)
>          if (mem_expr != MEM_EXPR (mem))
>            {
>              set_mem_expr (mem, mem_expr);
> -             set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
> +             if (offset >= 0)
> +               set_mem_offset (mem, offset);
> +             else
> +               clear_mem_offset (mem);
>            }
>        }
>       set_mem_alias_set (mem, 0);
> Index: gcc/cfgcleanup.c
> ===================================================================
> --- gcc/cfgcleanup.c    2011-07-17 10:18:59.000000000 +0100
> +++ gcc/cfgcleanup.c    2011-07-17 10:38:53.000000000 +0100
> @@ -895,13 +895,15 @@ merge_memattrs (rtx x, rtx y)
>            {
>              set_mem_expr (x, 0);
>              set_mem_expr (y, 0);
> -             set_mem_offset (x, 0);
> -             set_mem_offset (y, 0);
> +             clear_mem_offset (x);
> +             clear_mem_offset (y);
>            }
> -         else if (MEM_OFFSET (x) != MEM_OFFSET (y))
> +         else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y)
> +                  || (MEM_OFFSET_KNOWN_P (x)
> +                      && MEM_OFFSET (x) != MEM_OFFSET (y)))
>            {
> -             set_mem_offset (x, 0);
> -             set_mem_offset (y, 0);
> +             clear_mem_offset (x);
> +             clear_mem_offset (y);
>            }
>
>          if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
> Index: gcc/dwarf2out.c
> ===================================================================
> --- gcc/dwarf2out.c     2011-07-17 10:18:59.000000000 +0100
> +++ gcc/dwarf2out.c     2011-07-17 10:38:53.000000000 +0100
> @@ -10453,7 +10453,7 @@ tls_mem_loc_descriptor (rtx mem)
>   tree base;
>   dw_loc_descr_ref loc_result;
>
> -  if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
> +  if (MEM_EXPR (mem) == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
>     return NULL;
>
>   base = get_base_address (MEM_EXPR (mem));
> @@ -10466,8 +10466,8 @@ tls_mem_loc_descriptor (rtx mem)
>   if (loc_result == NULL)
>     return NULL;
>
> -  if (INTVAL (MEM_OFFSET (mem)))
> -    loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
> +  if (MEM_OFFSET (mem))
> +    loc_descr_plus_const (&loc_result, MEM_OFFSET (mem));
>
>   return loc_result;
>  }
> Index: gcc/function.c
> ===================================================================
> --- gcc/function.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/function.c      2011-07-17 10:38:53.000000000 +0100
> @@ -2577,14 +2577,12 @@ assign_parm_find_stack_rtl (tree parm, s
>          && data->promoted_mode != DECL_MODE (parm))
>        {
>          set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
> -         if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
> +         if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
>            {
>              int offset = subreg_lowpart_offset (DECL_MODE (parm),
>                                                  data->promoted_mode);
>              if (offset)
> -               set_mem_offset (stack_parm,
> -                               plus_constant (MEM_OFFSET (stack_parm),
> -                                              -offset));
> +               set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
>            }
>        }
>     }
> @@ -3198,10 +3196,9 @@ assign_parm_setup_stack (struct assign_p
>          /* ??? This may need a big-endian conversion on sparc64.  */
>          data->stack_parm
>            = adjust_address (data->stack_parm, data->nominal_mode, 0);
> -         if (offset && MEM_OFFSET (data->stack_parm))
> +         if (offset && MEM_OFFSET_KNOWN_P (data->stack_parm))
>            set_mem_offset (data->stack_parm,
> -                           plus_constant (MEM_OFFSET (data->stack_parm),
> -                                          offset));
> +                           MEM_OFFSET (data->stack_parm) + offset);
>        }
>     }
>
> Index: gcc/print-rtl.c
> ===================================================================
> --- gcc/print-rtl.c     2011-07-17 10:18:59.000000000 +0100
> +++ gcc/print-rtl.c     2011-07-17 10:38:53.000000000 +0100
> @@ -597,9 +597,8 @@ print_rtx (const_rtx in_rtx)
>       if (MEM_EXPR (in_rtx))
>        print_mem_expr (outfile, MEM_EXPR (in_rtx));
>
> -      if (MEM_OFFSET (in_rtx))
> -       fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
> -                INTVAL (MEM_OFFSET (in_rtx)));
> +      if (MEM_OFFSET_KNOWN_P (in_rtx))
> +       fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
>
>       if (MEM_SIZE_KNOWN_P (in_rtx))
>        fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
> Index: gcc/reload.c
> ===================================================================
> --- gcc/reload.c        2011-07-17 10:18:59.000000000 +0100
> +++ gcc/reload.c        2011-07-17 10:38:53.000000000 +0100
> @@ -6137,8 +6137,8 @@ find_reloads_subreg_address (rtx x, int
>
>              XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
>              PUT_MODE (tem, GET_MODE (x));
> -             if (MEM_OFFSET (tem))
> -               set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
> +             if (MEM_OFFSET_KNOWN_P (tem))
> +               set_mem_offset (tem, MEM_OFFSET (tem) + offset);
>              if (MEM_SIZE_KNOWN_P (tem)
>                  && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
>                set_mem_size (tem, outer_size);
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c  2011-07-17 10:03:00.000000000 +0100
> +++ gcc/simplify-rtx.c  2011-07-17 10:38:53.000000000 +0100
> @@ -268,7 +268,7 @@ delegitimize_mem_from_attrs (rtx x)
>      use their base addresses as equivalent.  */
>   if (MEM_P (x)
>       && MEM_EXPR (x)
> -      && MEM_OFFSET (x))
> +      && MEM_OFFSET_KNOWN_P (x))
>     {
>       tree decl = MEM_EXPR (x);
>       enum machine_mode mode = GET_MODE (x);
> @@ -321,7 +321,7 @@ delegitimize_mem_from_attrs (rtx x)
>        {
>          rtx newx;
>
> -         offset += INTVAL (MEM_OFFSET (x));
> +         offset += MEM_OFFSET (x);
>
>          newx = DECL_RTL (decl);
>
> Index: gcc/var-tracking.c
> ===================================================================
> --- gcc/var-tracking.c  2011-07-17 10:18:59.000000000 +0100
> +++ gcc/var-tracking.c  2011-07-17 10:38:53.000000000 +0100
> @@ -365,7 +365,7 @@ typedef const struct value_chain_def *co
>  #define VTI(BB) ((variable_tracking_info) (BB)->aux)
>
>  /* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
> -#define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
> +#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
>
>  /* Alloc pool for struct attrs_def.  */
>  static alloc_pool attrs_pool;
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 10:38:53.000000000 +0100
> @@ -969,9 +969,9 @@ set_reg_attrs_from_value (rtx reg, rtx x
>   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
>   if (MEM_P (x))
>     {
> -      if (MEM_OFFSET (x) && CONST_INT_P (MEM_OFFSET (x)))
> -       REG_ATTRS (reg)
> -         = get_reg_attrs (MEM_EXPR (x), INTVAL (MEM_OFFSET (x)) + offset);
> +      if (MEM_OFFSET_KNOWN_P (x))
> +       REG_ATTRS (reg) = get_reg_attrs (MEM_EXPR (x),
> +                                        MEM_OFFSET (x) + offset);
>       if (MEM_POINTER (x))
>        mark_reg_pointer (reg, 0);
>     }
> @@ -1460,14 +1460,13 @@ get_mem_align_offset (rtx mem, unsigned
>   unsigned HOST_WIDE_INT offset;
>
>   /* This function can't use
> -     if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
> -        || !CONST_INT_P (MEM_OFFSET (mem))
> +     if (!MEM_EXPR (mem) || !MEM_OFFSET_KNOWN_P (mem)
>         || (MAX (MEM_ALIGN (mem),
>                  get_object_alignment (MEM_EXPR (mem), align))
>             < align))
>        return -1;
>      else
> -       return (- INTVAL (MEM_OFFSET (mem))) & (align / BITS_PER_UNIT - 1);
> +       return (- MEM_OFFSET (mem)) & (align / BITS_PER_UNIT - 1);
>      for two reasons:
>      - COMPONENT_REFs in MEM_EXPR can have NULL first operand,
>        for <variable>.  get_inner_reference doesn't handle it and
> @@ -1477,12 +1476,10 @@ get_mem_align_offset (rtx mem, unsigned
>        isn't sufficiently aligned, the object it is in might be.  */
>   gcc_assert (MEM_P (mem));
>   expr = MEM_EXPR (mem);
> -  if (expr == NULL_TREE
> -      || MEM_OFFSET (mem) == NULL_RTX
> -      || !CONST_INT_P (MEM_OFFSET (mem)))
> +  if (expr == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
>     return -1;
>
> -  offset = INTVAL (MEM_OFFSET (mem));
> +  offset = MEM_OFFSET (mem);
>   if (DECL_P (expr))
>     {
>       if (DECL_ALIGN (expr) < align)
> @@ -1901,12 +1898,24 @@ set_mem_expr (rtx mem, tree expr)
>  /* Set the offset of MEM to OFFSET.  */
>
>  void
> -set_mem_offset (rtx mem, rtx offset)
> +set_mem_offset (rtx mem, HOST_WIDE_INT offset)
>  {
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.offset = offset;
> +  attrs.offset = GEN_INT (offset);
> +  set_mem_attrs (mem, &attrs);
> +}
> +
> +/* Clear the offset of MEM.  */
> +
> +void
> +clear_mem_offset (rtx mem)
> +{
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.offset = NULL_RTX;
>   set_mem_attrs (mem, &attrs);
>  }
>
> Index: gcc/config/mips/mips.c
> ===================================================================
> --- gcc/config/mips/mips.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/config/mips/mips.c      2011-07-17 10:38:53.000000000 +0100
> @@ -13777,13 +13777,9 @@ r10k_safe_address_p (rtx x, rtx insn)
>    a link-time-constant address.  */
>
>  static bool
> -r10k_safe_mem_expr_p (tree expr, rtx offset)
> +r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
>  {
> -  if (expr == NULL_TREE
> -      || offset == NULL_RTX
> -      || !CONST_INT_P (offset)
> -      || INTVAL (offset) < 0
> -      || INTVAL (offset) >= int_size_in_bytes (TREE_TYPE (expr)))
> +  if (offset < 0 || offset >= int_size_in_bytes (TREE_TYPE (expr)))
>     return false;
>
>   while (TREE_CODE (expr) == COMPONENT_REF)
> @@ -13809,7 +13805,9 @@ r10k_needs_protection_p_1 (rtx *loc, voi
>   if (!MEM_P (mem))
>     return 0;
>
> -  if (r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
> +  if (MEM_EXPR (mem)
> +      && MEM_OFFSET_KNOWN_P (mem)
> +      && r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
>     return -1;
>
>   if (r10k_safe_address_p (XEXP (mem, 0), (rtx) data))
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [5/5] Don't use rtxes in mem_attrs
  2011-07-17 17:55 ` [5/5] Don't use rtxes in mem_attrs Richard Sandiford
@ 2011-07-18 11:15   ` Richard Guenther
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2011-07-18 11:15 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

On Sun, Jul 17, 2011 at 4:34 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch replaces the rtxes in mem_attrs with (bool, HOST_WIDE_INT) pairs.
> There's already room for the bools in the padding after "addrspace".
> (There's room for one more bool after this patch; we could move to
> bitfields if more are needed.)
>
> The new structure is 8 bytes bigger when using a combination of a 32-bit
> host and a need_64bit_hwint target.  In other cases it should be the same
> as before, and will avoid some pointer chasing.  The question is whether
> that's an acceptable trade-off or not.

It sure is.

Ok.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * rtl.h (mem_attrs): Turn offset and size fields into HOST_WIDE_INTs.
>        Add offset_known_p and size_known_p fields.
>        (MEM_OFFSET_KNOWN_P): Update accordingly.
>        (MEM_OFFSET, MEM_SIZE_KNOWN_P, MEM_SIZE): Likewise.
>        * emit-rtl.c (mem_attrs_htab_hash): Update after mem_attrs changes.
>        (mem_attrs_eq_p, set_mem_attributes_minus_bitpos, set_mem_offset)
>        (clear_mem_offset, set_mem_size, clear_mem_size, change_address)
>        (adjust_address_1, widen_memory_access, set_mem_attrs_for_spill)
>        (init_emit_regs): Likewise.
>
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h   2011-07-17 11:40:14.000000000 +0100
> +++ gcc/rtl.h   2011-07-17 11:40:18.000000000 +0100
> @@ -136,19 +136,38 @@ typedef struct
>
>  /* Structure used to describe the attributes of a MEM.  These are hashed
>    so MEMs that the same attributes share a data structure.  This means
> -   they cannot be modified in place.  If any element is nonzero, it means
> -   the value of the corresponding attribute is unknown.  */
> -/* ALIGN and SIZE are the alignment and size of the MEM itself,
> -   while EXPR can describe a larger underlying object, which might have a
> -   stricter alignment; OFFSET is the offset of the MEM within that object.  */
> +   they cannot be modified in place.  */
>  typedef struct GTY(()) mem_attrs
>  {
> -  tree expr;                   /* expr corresponding to MEM.  */
> -  rtx offset;                  /* Offset from start of DECL, as CONST_INT.  */
> -  rtx size;                    /* Size in bytes, as a CONST_INT.  */
> -  alias_set_type alias;                /* Memory alias set.  */
> -  unsigned int align;          /* Alignment of MEM in bits.  */
> -  unsigned char addrspace;     /* Address space (0 for generic).  */
> +  /* The expression that the MEM accesses, or null if not known.
> +     This expression might be larger than the memory reference itself.
> +     (In other words, the MEM might access only part of the object.)  */
> +  tree expr;
> +
> +  /* The offset of the memory reference from the start of EXPR.
> +     Only valid if OFFSET_KNOWN_P.  */
> +  HOST_WIDE_INT offset;
> +
> +  /* The size of the memory reference in bytes.  Only valid if
> +     SIZE_KNOWN_P.  */
> +  HOST_WIDE_INT size;
> +
> +  /* The alias set of the memory reference.  */
> +  alias_set_type alias;
> +
> +  /* The alignment of the reference in bits.  Always a multiple of
> +     BITS_PER_UNIT.  Note that EXPR may have a stricter alignment
> +     than the memory reference itself.  */
> +  unsigned int align;
> +
> +  /* The address space that the memory reference uses.  */
> +  unsigned char addrspace;
> +
> +  /* True if OFFSET is known.  */
> +  bool offset_known_p;
> +
> +  /* True if SIZE is known.  */
> +  bool size_known_p;
>  } mem_attrs;
>
>  /* Structure used to describe the attributes of a REG in similar way as
> @@ -1303,19 +1322,19 @@ #define MEM_ALIAS_SET(RTX) (get_mem_attr
>  #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
>
>  /* For a MEM rtx, true if its MEM_OFFSET is known.  */
> -#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
> +#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)
>
>  /* For a MEM rtx, the offset from the start of MEM_EXPR.  */
> -#define MEM_OFFSET(RTX) INTVAL (get_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) (get_mem_attrs (RTX)->addrspace)
>
>  /* For a MEM rtx, true if its MEM_SIZE is known.  */
> -#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size != NULL_RTX)
> +#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size_known_p)
>
>  /* For a MEM rtx, the size in bytes of the MEM.  */
> -#define MEM_SIZE(RTX) INTVAL (get_mem_attrs (RTX)->size)
> +#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.  */
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 11:40:14.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 11:40:18.000000000 +0100
> @@ -256,8 +256,8 @@ mem_attrs_htab_hash (const void *x)
>
>   return (p->alias ^ (p->align * 1000)
>          ^ (p->addrspace * 4000)
> -         ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
> -         ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
> +         ^ ((p->offset_known_p ? p->offset : 0) * 50000)
> +         ^ ((p->size_known_p ? p->size : 0) * 2500000)
>          ^ (size_t) iterative_hash_expr (p->expr, 0));
>  }
>
> @@ -266,8 +266,12 @@ mem_attrs_htab_hash (const void *x)
>  static bool
>  mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
>  {
> -  return (p->alias == q->alias && p->offset == q->offset
> -         && p->size == q->size && p->align == q->align
> +  return (p->alias == q->alias
> +         && p->offset_known_p == q->offset_known_p
> +         && (!p->offset_known_p || p->offset == q->offset)
> +         && p->size_known_p == q->size_known_p
> +         && (!p->size_known_p || p->size == q->size)
> +         && p->align == q->align
>          && p->addrspace == q->addrspace
>          && (p->expr == q->expr
>              || (p->expr != NULL_TREE && q->expr != NULL_TREE
> @@ -1585,7 +1589,9 @@ set_mem_attributes_minus_bitpos (rtx ref
>       /* ??? Can this ever happen?  Calling this routine on a MEM that
>         already carries memory attributes should probably be invalid.  */
>       attrs.expr = refattrs->expr;
> +      attrs.offset_known_p = refattrs->offset_known_p;
>       attrs.offset = refattrs->offset;
> +      attrs.size_known_p = refattrs->size_known_p;
>       attrs.size = refattrs->size;
>       attrs.align = refattrs->align;
>     }
> @@ -1595,9 +1601,10 @@ set_mem_attributes_minus_bitpos (rtx ref
>     {
>       defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
>       gcc_assert (!defattrs->expr);
> -      gcc_assert (!defattrs->offset);
> +      gcc_assert (!defattrs->offset_known_p);
>
>       /* Respect mode size.  */
> +      attrs.size_known_p = defattrs->size_known_p;
>       attrs.size = defattrs->size;
>       /* ??? Is this really necessary?  We probably should always get
>         the size from the type below.  */
> @@ -1656,7 +1663,10 @@ set_mem_attributes_minus_bitpos (rtx ref
>
>   /* If the size is known, we can set that.  */
>   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
> -    attrs.size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
> +    {
> +      attrs.size_known_p = true;
> +      attrs.size = 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.  */
> @@ -1694,11 +1704,16 @@ set_mem_attributes_minus_bitpos (rtx ref
>       if (DECL_P (t))
>        {
>          attrs.expr = t;
> -         attrs.offset = const0_rtx;
> +         attrs.offset_known_p = true;
> +         attrs.offset = 0;
>          apply_bitpos = bitpos;
> -         attrs.size = (DECL_SIZE_UNIT (t)
> -                       && host_integerp (DECL_SIZE_UNIT (t), 1)
> -                       ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
> +         if (DECL_SIZE_UNIT (t) && host_integerp (DECL_SIZE_UNIT (t), 1))
> +           {
> +             attrs.size_known_p = true;
> +             attrs.size = tree_low_cst (DECL_SIZE_UNIT (t), 1);
> +           }
> +         else
> +           attrs.size_known_p = false;
>          attrs.align = DECL_ALIGN (t);
>          align_computed = true;
>        }
> @@ -1721,7 +1736,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>               && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
>        {
>          attrs.expr = t;
> -         attrs.offset = const0_rtx;
> +         attrs.offset_known_p = true;
> +         attrs.offset = 0;
>          apply_bitpos = bitpos;
>          /* ??? Any reason the field size would be different than
>             the size we got from the type?  */
> @@ -1762,7 +1778,7 @@ set_mem_attributes_minus_bitpos (rtx ref
>          if (DECL_P (t2))
>            {
>              attrs.expr = t2;
> -             attrs.offset = NULL;
> +             attrs.offset_known_p = false;
>              if (host_integerp (off_tree, 1))
>                {
>                  HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1);
> @@ -1771,17 +1787,19 @@ set_mem_attributes_minus_bitpos (rtx ref
>                  if (aoff && (unsigned HOST_WIDE_INT) aoff < attrs.align)
>                    attrs.align = aoff;
>                  align_computed = true;
> -                 attrs.offset = GEN_INT (ioff);
> +                 attrs.offset_known_p = true;
> +                 attrs.offset = ioff;
>                  apply_bitpos = bitpos;
>                }
>            }
>          else if (TREE_CODE (t2) == COMPONENT_REF)
>            {
>              attrs.expr = t2;
> -             attrs.offset = NULL;
> +             attrs.offset_known_p = false;
>              if (host_integerp (off_tree, 1))
>                {
> -                 attrs.offset = GEN_INT (tree_low_cst (off_tree, 1));
> +                 attrs.offset_known_p = true;
> +                 attrs.offset = tree_low_cst (off_tree, 1);
>                  apply_bitpos = bitpos;
>                }
>              /* ??? Any reason the field size would be different than
> @@ -1792,7 +1810,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>          else if (TREE_CODE (t) == MEM_REF)
>            {
>              attrs.expr = t;
> -             attrs.offset = const0_rtx;
> +             attrs.offset_known_p = true;
> +             attrs.offset = 0;
>              apply_bitpos = bitpos;
>            }
>        }
> @@ -1802,7 +1821,8 @@ set_mem_attributes_minus_bitpos (rtx ref
>               || TREE_CODE (t) == TARGET_MEM_REF)
>        {
>          attrs.expr = t;
> -         attrs.offset = const0_rtx;
> +         attrs.offset_known_p = true;
> +         attrs.offset = 0;
>          apply_bitpos = bitpos;
>        }
>
> @@ -1818,10 +1838,10 @@ set_mem_attributes_minus_bitpos (rtx ref
>      object to contain the negative offset.  */
>   if (apply_bitpos)
>     {
> -      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);
> +      gcc_assert (attrs.offset_known_p);
> +      attrs.offset -= apply_bitpos / BITS_PER_UNIT;
> +      if (attrs.size_known_p)
> +       attrs.size += apply_bitpos / BITS_PER_UNIT;
>     }
>
>   /* Now set the attributes we computed above.  */
> @@ -1903,7 +1923,8 @@ set_mem_offset (rtx mem, HOST_WIDE_INT o
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.offset = GEN_INT (offset);
> +  attrs.offset_known_p = true;
> +  attrs.offset = offset;
>   set_mem_attrs (mem, &attrs);
>  }
>
> @@ -1915,7 +1936,7 @@ clear_mem_offset (rtx mem)
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.offset = NULL_RTX;
> +  attrs.offset_known_p = false;
>   set_mem_attrs (mem, &attrs);
>  }
>
> @@ -1927,7 +1948,8 @@ set_mem_size (rtx mem, HOST_WIDE_INT siz
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.size = GEN_INT (size);
> +  attrs.size_known_p = true;
> +  attrs.size = size;
>   set_mem_attrs (mem, &attrs);
>  }
>
> @@ -1939,7 +1961,7 @@ clear_mem_size (rtx mem)
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.size = NULL_RTX;
> +  attrs.size_known_p = false;
>   set_mem_attrs (mem, &attrs);
>  }
>
> @@ -1993,8 +2015,9 @@ change_address (rtx memref, enum machine
>
>   attrs = *get_mem_attrs (memref);
>   defattrs = mode_mem_attrs[(int) mmode];
> -  attrs.expr = defattrs->expr;
> -  attrs.offset = defattrs->offset;
> +  attrs.expr = NULL_TREE;
> +  attrs.offset_known_p = false;
> +  attrs.size_known_p = defattrs->size_known_p;
>   attrs.size = defattrs->size;
>   attrs.align = defattrs->align;
>
> @@ -2076,8 +2099,8 @@ 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 (attrs.offset)
> -    attrs.offset = GEN_INT (offset + INTVAL (attrs.offset));
> +  if (attrs.offset_known_p)
> +    attrs.offset += 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
> @@ -2090,10 +2113,13 @@ adjust_address_1 (rtx memref, enum machi
>
>   /* We can compute the size in a number of ways.  */
>   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);
> +  if (defattrs->size_known_p)
> +    {
> +      attrs.size_known_p = true;
> +      attrs.size = defattrs->size;
> +    }
> +  else if (attrs.size_known_p)
> +    attrs.size -= offset;
>
>   set_mem_attrs (new_rtx, &attrs);
>
> @@ -2124,7 +2150,7 @@ offset_address (rtx memref, rtx offset,
>  {
>   rtx new_rtx, addr = XEXP (memref, 0);
>   enum machine_mode address_mode;
> -  struct mem_attrs attrs;
> +  struct mem_attrs attrs, *defattrs;
>
>   attrs = *get_mem_attrs (memref);
>   address_mode = targetm.addr_space.address_mode (attrs.addrspace);
> @@ -2155,8 +2181,10 @@ offset_address (rtx memref, rtx offset,
>
>   /* Update the alignment to reflect the offset.  Reset the offset, which
>      we don't know.  */
> -  attrs.offset = 0;
> -  attrs.size = mode_mem_attrs[(int) GET_MODE (new_rtx)]->size;
> +  defattrs = mode_mem_attrs[(int) GET_MODE (new_rtx)];
> +  attrs.offset_known_p = false;
> +  attrs.size_known_p = defattrs->size_known_p;
> +  attrs.size = defattrs->size;
>   attrs.align = MIN (attrs.align, pow2 * BITS_PER_UNIT);
>   set_mem_attrs (new_rtx, &attrs);
>   return new_rtx;
> @@ -2204,7 +2232,7 @@ widen_memory_access (rtx memref, enum ma
>
>   /* If we don't know what offset we were at within the expression, then
>      we can't know if we've overstepped the bounds.  */
> -  if (! attrs.offset)
> +  if (! attrs.offset_known_p)
>     attrs.expr = NULL_TREE;
>
>   while (attrs.expr)
> @@ -2224,7 +2252,7 @@ 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 (attrs.offset) >= 0)
> +             && attrs.offset >= 0)
>            break;
>
>          if (! host_integerp (offset, 1))
> @@ -2234,18 +2262,16 @@ widen_memory_access (rtx memref, enum ma
>            }
>
>          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)));
> +         attrs.offset += tree_low_cst (offset, 1);
> +         attrs.offset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
> +                          / BITS_PER_UNIT);
>        }
>       /* Similarly for the decl.  */
>       else if (DECL_P (attrs.expr)
>               && DECL_SIZE_UNIT (attrs.expr)
>               && TREE_CODE (DECL_SIZE_UNIT (attrs.expr)) == INTEGER_CST
>               && compare_tree_int (DECL_SIZE_UNIT (attrs.expr), size) >= 0
> -              && (! attrs.offset || INTVAL (attrs.offset) >= 0))
> +              && (! attrs.offset_known_p || attrs.offset >= 0))
>        break;
>       else
>        {
> @@ -2257,12 +2283,13 @@ widen_memory_access (rtx memref, enum ma
>     }
>
>   if (! attrs.expr)
> -    attrs.offset = NULL_RTX;
> +    attrs.offset_known_p = false;
>
>   /* The widened memory may alias other stuff, so zap the alias set.  */
>   /* ??? Maybe use get_alias_set on any remaining expression.  */
>   attrs.alias = 0;
> -  attrs.size = GEN_INT (size);
> +  attrs.size_known_p = true;
> +  attrs.size = size;
>   set_mem_attrs (new_rtx, &attrs);
>   return new_rtx;
>  }
> @@ -2319,10 +2346,11 @@ set_mem_attrs_for_spill (rtx mem)
>        (mem:MODE (plus (reg sfp) (const_int offset)))
>      with perhaps the plus missing for offset = 0.  */
>   addr = XEXP (mem, 0);
> -  attrs.offset = const0_rtx;
> +  attrs.offset_known_p = true;
> +  attrs.offset = 0;
>   if (GET_CODE (addr) == PLUS
>       && CONST_INT_P (XEXP (addr, 1)))
> -    attrs.offset = XEXP (addr, 1);
> +    attrs.offset = INTVAL (XEXP (addr, 1));
>
>   set_mem_attrs (mem, &attrs);
>   MEM_NOTRAP_P (mem) = 1;
> @@ -5522,7 +5550,8 @@ init_emit_regs (void)
>       attrs->addrspace = ADDR_SPACE_GENERIC;
>       if (mode != BLKmode)
>        {
> -         attrs->size = GEN_INT (GET_MODE_SIZE (mode));
> +         attrs->size_known_p = true;
> +         attrs->size = GET_MODE_SIZE (mode);
>          if (STRICT_ALIGNMENT)
>            attrs->align = GET_MODE_ALIGNMENT (mode);
>        }
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Named address spaces broken (Re: [2/5] Add a set_mem_attrs function)
  2011-07-17 16:32 ` [2/5] Add a set_mem_attrs function Richard Sandiford
  2011-07-18 10:58   ` Richard Guenther
@ 2011-07-20 11:27   ` Ulrich Weigand
  2011-07-20 11:29     ` Richard Guenther
  1 sibling, 1 reply; 14+ messages in thread
From: Ulrich Weigand @ 2011-07-20 11:27 UTC (permalink / raw)
  To: Richard Sandiford, rguenther; +Cc: gcc-patches

Richard Sandiford wrote:

>    /* 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);

This removes the bit where the MEM's address space is initialized
to the type's address space, which fundamentally breaks named
address space suppport ...

I guess we need something like the patch below to restore the
old behaviour.

OK for mainline?

Bye,
Ulrich

ChangeLog:

	* emit-rtl.c (set_mem_attributes_minus_bitpos): Restore setting
	memory address space to the type's address space.

Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c	(revision 176499)
--- gcc/emit-rtl.c	(working copy)
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1845,1850 ****
--- 1845,1851 ----
      }
  
    /* Now set the attributes we computed above.  */
+   attrs.addrspace = TYPE_ADDR_SPACE (type);
    set_mem_attrs (ref, &attrs);
  
    /* If this is already known to be a scalar or aggregate, we are done.  */


-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Named address spaces broken (Re: [2/5] Add a set_mem_attrs function)
  2011-07-20 11:27   ` Named address spaces broken (Re: [2/5] Add a set_mem_attrs function) Ulrich Weigand
@ 2011-07-20 11:29     ` Richard Guenther
  2011-07-20 18:13       ` Ulrich Weigand
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Guenther @ 2011-07-20 11:29 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Sandiford, gcc-patches

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1560 bytes --]

On Wed, 20 Jul 2011, Ulrich Weigand wrote:

> Richard Sandiford wrote:
> 
> >    /* 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);
> 
> This removes the bit where the MEM's address space is initialized
> to the type's address space, which fundamentally breaks named
> address space suppport ...
> 
> I guess we need something like the patch below to restore the
> old behaviour.
> 
> OK for mainline?

Ok.

Do we have any chance of adding generic testcases for named-address-space
support that would show these issues?

Thanks,
Richard.

> Bye,
> Ulrich
> 
> ChangeLog:
> 
> 	* emit-rtl.c (set_mem_attributes_minus_bitpos): Restore setting
> 	memory address space to the type's address space.
> 
> Index: gcc/emit-rtl.c
> ===================================================================
> *** gcc/emit-rtl.c	(revision 176499)
> --- gcc/emit-rtl.c	(working copy)
> *************** set_mem_attributes_minus_bitpos (rtx ref
> *** 1845,1850 ****
> --- 1845,1851 ----
>       }
>   
>     /* Now set the attributes we computed above.  */
> +   attrs.addrspace = TYPE_ADDR_SPACE (type);
>     set_mem_attrs (ref, &attrs);
>   
>     /* If this is already known to be a scalar or aggregate, we are done.  */
> 
> 
> 

-- 
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Named address spaces broken (Re: [2/5] Add a set_mem_attrs function)
  2011-07-20 11:29     ` Richard Guenther
@ 2011-07-20 18:13       ` Ulrich Weigand
  0 siblings, 0 replies; 14+ messages in thread
From: Ulrich Weigand @ 2011-07-20 18:13 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Richard Sandiford, gcc-patches

Richard Guenther wrote:

> Ok.

Checked in, thanks.

> Do we have any chance of adding generic testcases for named-address-space
> support that would show these issues?

Not really; named address space are fundamentally target-specific.

It certainly would help if a more common target provided some
address spaces; on i386 you could e.g. implement "far" segmented
pointers as an address space; or you could at least implement
the %gs: segment as an address space and use it to implement
TLS accesses ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-07-20 18:06 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-17 14:34 [0/5] Don't treat MEM_OFFSET and MEM_SIZE as rtxes Richard Sandiford
2011-07-17 16:30 ` [1/5] Add a mode_mem_attrs array Richard Sandiford
2011-07-18 10:22   ` Richard Guenther
2011-07-17 16:32 ` [2/5] Add a set_mem_attrs function Richard Sandiford
2011-07-18 10:58   ` Richard Guenther
2011-07-20 11:27   ` Named address spaces broken (Re: [2/5] Add a set_mem_attrs function) Ulrich Weigand
2011-07-20 11:29     ` Richard Guenther
2011-07-20 18:13       ` Ulrich Weigand
2011-07-17 16:33 ` [3/5] MEM_SIZE and MEM_SIZE_KNOWN_P Richard Sandiford
2011-07-18 11:01   ` Richard Guenther
2011-07-17 16:55 ` [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P Richard Sandiford
2011-07-18 11:10   ` Richard Guenther
2011-07-17 17:55 ` [5/5] Don't use rtxes in mem_attrs Richard Sandiford
2011-07-18 11:15   ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).