This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix VTA sp (and fp) based MEM handling (PR debug/43051, PR debug/43092)


On Mar 15, 2010, Jakub Jelinek <jakub@redhat.com> wrote:

> One is that cselib doesn't handle autoinc rtls well
> (Alex has a follow-up patch in which it teaches cselib about these; this
> final version of the patch doesn't need it for var-tracking though).

Here it is.  Regstraped on x86_64-linux-gnu, i686-linux-gnu and
ia64-linux-gnu.  Ok to install?

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* rtl.h (for_each_inc_dec_fn): New type.
	(for_each_inc_dec): Declare.
	* rtlanal.c (struct for_each_inc_dec_ops): New type.
	(for_each_inc_dec_find_inc_dec): New fn.
	(for_each_inc_dec_find_mem): New fn.
	(for_each_inc_dec): New fn.
	* dse.c (struct insn_size): Remove.
	(replace_inc_dec, replace_inc_dec_mem): Remove.
	(emit_inc_dec_insn_before): New fn.
	(check_for_inc_dec): Use it, along with for_each_inc_dec.
	* cselib.h (CSELIB_RECORD_AUTOINC): New enumerator.
	(cselib_lookup_addr): Declare.
	(cselib_lookup): Replace with macro.
	(cselib_subst_to_values_addr): Declare.
	(cselib_subst_to_values): Replace with macro.
	* cselib.c (cselib_record_autoinc): New var.
	(find_slot_memmode): New var.
	(cselib_find_slot): New fn.  Use it instead of
	htab_find_slot_with_hash everywhere.
	(entry_and_rtx_equal_p): Use find_slot_memmode.
	(autoinc_split): New fn.
	(rtx_equal_for_cselib_p): Rename and implement in terms of...
	(rtx_equal_for_cselib_1): ... this.  Take memmode, pass it on.
	Deal with autoinc.
	(cselib_hash_rtx): Likewise.
	(cselib_lookup_mem): Infer pmode from address mode.  Distinguish
	address and MEM modes.
	(cselib_subst_to_values): Rename to...
	(cselib_subst_to_values_addr): ... this.  Add memmode, pass it on.
	Deal with autoinc.
	(cselib_lookup): Rename to...
	(cselib_lookup_addr): ... this.  Likewise.
	(struct cselib_record_autoinc_data): New.
	(cselib_record_autoinc_cb): New fn.
	(cselib_record_sets): Use it, along with for_each_inc_dec.  Pass MEM
	mode to cselib_lookup_addr.
	(cselib_init): Initialize cselib_record_autoinc.
	* var-tracking.c (replace_expr_with_values, use_type): Pass MEM mode
	to cselib_lookup_addr.
	(add_uses): Likewise, also to cselib_subst_to_values_addr.
	(add_stores): Likewise.
	(vt_initialize): Pass CSELIB_RECORD_AUTOINC to cselib_init.

Index: gcc/dse.c
===================================================================
--- gcc/dse.c.orig	2010-03-17 01:05:25.000000000 -0300
+++ gcc/dse.c	2010-03-17 22:14:46.000000000 -0300
@@ -806,81 +806,22 @@ free_store_info (insn_info_t insn_info)
 }
 
 
-struct insn_size {
-  int size;
-  rtx insn;
-};
-
-
-/* Add an insn to do the add inside a x if it is a
-   PRE/POST-INC/DEC/MODIFY.  D is an structure containing the insn and
-   the size of the mode of the MEM that this is inside of.  */
-
 static int
-replace_inc_dec (rtx *r, void *d)
+emit_inc_dec_insn_before (rtx mem ATTRIBUTE_UNUSED,
+			  rtx op ATTRIBUTE_UNUSED,
+			  rtx dest, rtx src, rtx srcoff, void *arg)
 {
-  rtx x = *r;
-  struct insn_size *data = (struct insn_size *)d;
-  switch (GET_CODE (x))
-    {
-    case PRE_INC:
-    case POST_INC:
-      {
-	rtx r1 = XEXP (x, 0);
-	rtx c = gen_int_mode (data->size, GET_MODE (r1));
-	emit_insn_before (gen_rtx_SET (VOIDmode, r1,
-				       gen_rtx_PLUS (GET_MODE (r1), r1, c)),
-			  data->insn);
-	return -1;
-      }
-
-    case PRE_DEC:
-    case POST_DEC:
-      {
-	rtx r1 = XEXP (x, 0);
-	rtx c = gen_int_mode (-data->size, GET_MODE (r1));
-	emit_insn_before (gen_rtx_SET (VOIDmode, r1,
-				       gen_rtx_PLUS (GET_MODE (r1), r1, c)),
-			  data->insn);
-	return -1;
-      }
-
-    case PRE_MODIFY:
-    case POST_MODIFY:
-      {
-	/* We can reuse the add because we are about to delete the
-	   insn that contained it.  */
-	rtx add = XEXP (x, 0);
-	rtx r1 = XEXP (add, 0);
-	emit_insn_before (gen_rtx_SET (VOIDmode, r1, add), data->insn);
-	return -1;
-      }
+  rtx insn = (rtx)arg;
 
-    default:
-      return 0;
-    }
-}
+  if (srcoff)
+    src = gen_rtx_PLUS (GET_MODE (src), src, srcoff);
 
+  /* We can reuse all operands without copying, because we are about
+     to delete the insn that contained it.  */
 
-/* If X is a MEM, check the address to see if it is PRE/POST-INC/DEC/MODIFY
-   and generate an add to replace that.  */
+  emit_insn_before (gen_rtx_SET (VOIDmode, dest, src), insn);
 
-static int
-replace_inc_dec_mem (rtx *r, void *d)
-{
-  rtx x = *r;
-  if (x != NULL_RTX && MEM_P (x))
-    {
-      struct insn_size data;
-
-      data.size = GET_MODE_SIZE (GET_MODE (x));
-      data.insn = (rtx) d;
-
-      for_each_rtx (&XEXP (x, 0), replace_inc_dec, &data);
-
-      return -1;
-    }
-  return 0;
+  return -1;
 }
 
 /* Before we delete INSN, make sure that the auto inc/dec, if it is
@@ -891,7 +832,7 @@ check_for_inc_dec (rtx insn)
 {
   rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
   if (note)
-    for_each_rtx (&insn, replace_inc_dec_mem, insn);
+    for_each_inc_dec (&insn, emit_inc_dec_insn_before, insn);
 }
 
 
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h.orig	2010-03-17 01:05:25.000000000 -0300
+++ gcc/rtl.h	2010-03-17 22:14:46.000000000 -0300
@@ -1875,6 +1875,9 @@ extern int computed_jump_p (const_rtx);
 typedef int (*rtx_function) (rtx *, void *);
 extern int for_each_rtx (rtx *, rtx_function, void *);
 
+typedef int (*for_each_inc_dec_fn) (rtx, rtx, rtx, rtx, rtx, void *);
+extern int for_each_inc_dec (rtx *, for_each_inc_dec_fn, void *);
+
 typedef int (*rtx_equal_p_callback_function) (const_rtx *, const_rtx *,
                                               rtx *, rtx *);
 extern int rtx_equal_p_cb (const_rtx, const_rtx,
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2010-03-17 01:05:25.000000000 -0300
+++ gcc/cselib.c	2010-03-22 03:41:57.000000000 -0300
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  
 
 static bool cselib_record_memory;
 static bool cselib_preserve_constants;
+static bool cselib_record_autoinc;
 static int entry_and_rtx_equal_p (const void *, const void *);
 static hashval_t get_value_hash (const void *);
 static struct elt_list *new_elt_list (struct elt_list *, cselib_val *);
@@ -56,7 +57,8 @@ static void unchain_one_elt_loc_list (st
 static int discard_useless_locs (void **, void *);
 static int discard_useless_values (void **, void *);
 static void remove_useless_values (void);
-static unsigned int cselib_hash_rtx (rtx, int);
+static int rtx_equal_for_cselib_1 (rtx, rtx, enum machine_mode);
+static unsigned int cselib_hash_rtx (rtx, int, enum machine_mode);
 static cselib_val *new_cselib_val (unsigned int, enum machine_mode, rtx);
 static void add_mem_for_addr (cselib_val *, cselib_val *, rtx);
 static cselib_val *cselib_lookup_mem (rtx, int);
@@ -319,6 +321,26 @@ cselib_get_next_uid (void)
   return next_uid;
 }
 
+/* See the documentation of cselib_find_slot below.  */
+static enum machine_mode find_slot_memmode;
+
+/* Search for X, whose hashcode is HASH, in CSELIB_HASH_TABLE,
+   INSERTing if requested.  When X is part of the address of a MEM,
+   MEMMODE should specify the mode of the MEM.  While searching the
+   table, MEMMODE is held in FIND_SLOT_MEMMODE, so that autoinc RTXs
+   in X can be resolved.  */
+
+static void **
+cselib_find_slot (rtx x, hashval_t hash, enum insert_option insert,
+		  enum machine_mode memmode)
+{
+  void **slot;
+  find_slot_memmode = memmode;
+  slot = htab_find_slot_with_hash (cselib_hash_table, x, hash, insert);
+  find_slot_memmode = VOIDmode;
+  return slot;
+}
+
 /* The equality test for our hash table.  The first argument ENTRY is a table
    element (i.e. a cselib_val), while the second arg X is an rtx.  We know
    that all callers of htab_find_slot_with_hash will wrap CONST_INTs into a
@@ -348,7 +370,7 @@ entry_and_rtx_equal_p (const void *entry
   /* We don't guarantee that distinct rtx's have different hash values,
      so we need to do a comparison.  */
   for (l = v->locs; l; l = l->next)
-    if (rtx_equal_for_cselib_p (l->loc, x))
+    if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode))
       return 1;
 
   return 0;
@@ -545,13 +567,59 @@ cselib_reg_set_mode (const_rtx x)
 int
 rtx_equal_for_cselib_p (rtx x, rtx y)
 {
+  return rtx_equal_for_cselib_1 (x, y, VOIDmode);
+}
+
+/* If x is a PLUS or an autoinc operation, expand the operation,
+   storing the offset, if any, in *OFF.  */
+
+static rtx
+autoinc_split (rtx x, rtx *off, enum machine_mode memmode)
+{
+  switch (GET_CODE (x))
+    {
+    case PLUS:
+      *off = XEXP (x, 1);
+      return XEXP (x, 0);
+
+    case PRE_DEC:
+      if (memmode == VOIDmode)
+	return x;
+
+      *off = GEN_INT (-GET_MODE_SIZE (memmode));
+      return XEXP (x, 0);
+      break;
+
+    case PRE_INC:
+      if (memmode == VOIDmode)
+	return x;
+
+      *off = GEN_INT (GET_MODE_SIZE (memmode));
+      return XEXP (x, 0);
+
+    case PRE_MODIFY:
+      return XEXP (x, 1);
+
+    case POST_DEC:
+    case POST_INC:
+    case POST_MODIFY:
+      return XEXP (x, 0);
+
+    default:
+      return x;
+    }
+}
+
+static int
+rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode)
+{
   enum rtx_code code;
   const char *fmt;
   int i;
 
   if (REG_P (x) || MEM_P (x))
     {
-      cselib_val *e = cselib_lookup (x, GET_MODE (x), 0);
+      cselib_val *e = cselib_lookup_addr (x, GET_MODE (x), 0, memmode);
 
       if (e)
 	x = e->val_rtx;
@@ -559,7 +627,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
 
   if (REG_P (y) || MEM_P (y))
     {
-      cselib_val *e = cselib_lookup (y, GET_MODE (y), 0);
+      cselib_val *e = cselib_lookup_addr (y, GET_MODE (y), 0, memmode);
 
       if (e)
 	y = e->val_rtx;
@@ -583,7 +651,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
 	  /* Avoid infinite recursion.  */
 	  if (REG_P (t) || MEM_P (t))
 	    continue;
-	  else if (rtx_equal_for_cselib_p (t, y))
+	  else if (rtx_equal_for_cselib_1 (t, y, memmode))
 	    return 1;
 	}
 
@@ -601,16 +669,40 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
 
 	  if (REG_P (t) || MEM_P (t))
 	    continue;
-	  else if (rtx_equal_for_cselib_p (x, t))
+	  else if (rtx_equal_for_cselib_1 (x, t, memmode))
 	    return 1;
 	}
 
       return 0;
     }
 
-  if (GET_CODE (x) != GET_CODE (y) || GET_MODE (x) != GET_MODE (y))
+  if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
+  if (GET_CODE (x) != GET_CODE (y))
+    {
+      if (cselib_record_autoinc)
+	{
+	  rtx xorig = x, yorig = y;
+	  rtx xoff = NULL, yoff = NULL;
+
+	  x = autoinc_split (x, &xoff, memmode);
+	  y = autoinc_split (y, &yoff, memmode);
+
+	  if (!xoff != !yoff)
+	    return 0;
+
+	  if (xoff && !rtx_equal_for_cselib_1 (xoff, yoff, memmode))
+	    return 0;
+
+	  /* Don't recurse if nothing changed.  */
+	  if (x != xorig || y != yorig)
+	    return rtx_equal_for_cselib_1 (x, y, memmode);
+	}
+
+      return 0;
+    }
+
   /* These won't be handled correctly by the code below.  */
   switch (GET_CODE (x))
     {
@@ -654,18 +746,18 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
 
 	  /* And the corresponding elements must match.  */
 	  for (j = 0; j < XVECLEN (x, i); j++)
-	    if (! rtx_equal_for_cselib_p (XVECEXP (x, i, j),
-					  XVECEXP (y, i, j)))
+	    if (! rtx_equal_for_cselib_1 (XVECEXP (x, i, j),
+					  XVECEXP (y, i, j), memmode))
 	      return 0;
 	  break;
 
 	case 'e':
 	  if (i == 1
 	      && targetm.commutative_p (x, UNKNOWN)
-	      && rtx_equal_for_cselib_p (XEXP (x, 1), XEXP (y, 0))
-	      && rtx_equal_for_cselib_p (XEXP (x, 0), XEXP (y, 1)))
+	      && rtx_equal_for_cselib_1 (XEXP (x, 1), XEXP (y, 0), memmode)
+	      && rtx_equal_for_cselib_1 (XEXP (x, 0), XEXP (y, 1), memmode))
 	    return 1;
-	  if (! rtx_equal_for_cselib_p (XEXP (x, i), XEXP (y, i)))
+	  if (! rtx_equal_for_cselib_1 (XEXP (x, i), XEXP (y, i), memmode))
 	    return 0;
 	  break;
 
@@ -717,6 +809,8 @@ wrap_constant (enum machine_mode mode, r
    that take commutativity into account.
    If we wanted to also support associative rules, we'd have to use a different
    strategy to avoid returning spurious 0, e.g. return ~(~0U >> 1) .
+   MEMMODE indicates the mode of an enclosing MEM, and it's only
+   used to compute auto-inc values.
    We used to have a MODE argument for hashing for CONST_INTs, but that
    didn't make sense, since it caused spurious hash differences between
     (set (reg:SI 1) (const_int))
@@ -727,7 +821,7 @@ wrap_constant (enum machine_mode mode, r
    in a comparison anyway, since relying on hash differences is unsafe.  */
 
 static unsigned int
-cselib_hash_rtx (rtx x, int create)
+cselib_hash_rtx (rtx x, int create, enum machine_mode memmode)
 {
   cselib_val *e;
   int i, j;
@@ -742,7 +836,7 @@ cselib_hash_rtx (rtx x, int create)
     {
     case MEM:
     case REG:
-      e = cselib_lookup (x, GET_MODE (x), create);
+      e = cselib_lookup_addr (x, GET_MODE (x), create, memmode);
       if (! e)
 	return 0;
 
@@ -783,7 +877,7 @@ cselib_hash_rtx (rtx x, int create)
 	for (i = 0; i < units; ++i)
 	  {
 	    elt = CONST_VECTOR_ELT (x, i);
-	    hash += cselib_hash_rtx (elt, 0);
+	    hash += cselib_hash_rtx (elt, 0, memmode);
 	  }
 
 	return hash;
@@ -816,10 +910,32 @@ cselib_hash_rtx (rtx x, int create)
 
     case PRE_DEC:
     case PRE_INC:
+      /* We can't compute these without knowing the MEM mode.  */
+      if (!cselib_record_autoinc)
+	return 0;
+      gcc_assert (memmode != VOIDmode);
+      i = GET_MODE_SIZE (memmode);
+      if (code == PRE_DEC)
+	i = -i;
+      hash += (unsigned) PLUS - (unsigned)code
+	+ cselib_hash_rtx (XEXP (x, 0), create, memmode)
+	+ cselib_hash_rtx (GEN_INT (i), create, memmode);
+      return hash ? hash : 1 + (unsigned) PLUS;
+
+    case PRE_MODIFY:
+      if (!cselib_record_autoinc)
+	return 0;
+      gcc_assert (memmode != VOIDmode);
+      return cselib_hash_rtx (XEXP (x, 1), create, memmode);
+
     case POST_DEC:
     case POST_INC:
     case POST_MODIFY:
-    case PRE_MODIFY:
+      if (!cselib_record_autoinc)
+	return 0;
+      gcc_assert (memmode != VOIDmode);
+      return cselib_hash_rtx (XEXP (x, 0), create, memmode);
+
     case PC:
     case CC0:
     case CALL:
@@ -845,7 +961,7 @@ cselib_hash_rtx (rtx x, int create)
 	case 'e':
 	  {
 	    rtx tem = XEXP (x, i);
-	    unsigned int tem_hash = cselib_hash_rtx (tem, create);
+	    unsigned int tem_hash = cselib_hash_rtx (tem, create, memmode);
 
 	    if (tem_hash == 0)
 	      return 0;
@@ -857,7 +973,7 @@ cselib_hash_rtx (rtx x, int create)
 	  for (j = 0; j < XVECLEN (x, i); j++)
 	    {
 	      unsigned int tem_hash
-		= cselib_hash_rtx (XVECEXP (x, i, j), create);
+		= cselib_hash_rtx (XVECEXP (x, i, j), create, memmode);
 
 	      if (tem_hash == 0)
 		return 0;
@@ -966,7 +1082,7 @@ add_mem_for_addr (cselib_val *addr_elt, 
 static cselib_val *
 cselib_lookup_mem (rtx x, int create)
 {
-  enum machine_mode mode = GET_MODE (x);
+  enum machine_mode mode = GET_MODE (x), pmode = Pmode;
   void **slot;
   cselib_val *addr;
   cselib_val *mem_elt;
@@ -977,8 +1093,11 @@ cselib_lookup_mem (rtx x, int create)
       || (FLOAT_MODE_P (mode) && flag_float_store))
     return 0;
 
+  if (GET_MODE (XEXP (x, 0)) != VOIDmode)
+    pmode = GET_MODE (XEXP (x, 0));
+
   /* Look up the value for the address.  */
-  addr = cselib_lookup (XEXP (x, 0), mode, create);
+  addr = cselib_lookup_addr (XEXP (x, 0), pmode, create, mode);
   if (! addr)
     return 0;
 
@@ -992,8 +1111,8 @@ cselib_lookup_mem (rtx x, int create)
 
   mem_elt = new_cselib_val (next_uid, mode, x);
   add_mem_for_addr (addr, mem_elt, x);
-  slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
-				   mem_elt->hash, INSERT);
+  slot = cselib_find_slot (wrap_constant (mode, x), mem_elt->hash,
+			   INSERT, mode);
   *slot = mem_elt;
   return mem_elt;
 }
@@ -1425,10 +1544,12 @@ cselib_expand_value_rtx_1 (rtx orig, str
    with VALUE expressions.  This way, it becomes independent of changes
    to registers and memory.
    X isn't actually modified; if modifications are needed, new rtl is
-   allocated.  However, the return value can share rtl with X.  */
+   allocated.  However, the return value can share rtl with X.
+   If X is within a MEM, MEMMODE must be the mode of the MEM if
+   cselib_record_autoinc holds.  */
 
 rtx
-cselib_subst_to_values (rtx x)
+cselib_subst_to_values_addr (rtx x, enum machine_mode memmode)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt = GET_RTX_FORMAT (code);
@@ -1465,14 +1586,34 @@ cselib_subst_to_values (rtx x)
     case CONST_FIXED:
       return x;
 
-    case POST_INC:
+    case PRE_DEC:
     case PRE_INC:
+      if (!cselib_record_autoinc)
+	{
+	no_autoinc:
+	  e = new_cselib_val (next_uid, GET_MODE (x), x);
+	  return e->val_rtx;
+	}
+      gcc_assert (memmode != VOIDmode);
+      i = GET_MODE_SIZE (memmode);
+      if (code == PRE_DEC)
+	i = -i;
+      return cselib_subst_to_values_addr (plus_constant (XEXP (x, 0), i),
+					  memmode);
+
+    case PRE_MODIFY:
+      if (!cselib_record_autoinc)
+	goto no_autoinc;
+      gcc_assert (memmode != VOIDmode);
+      return cselib_subst_to_values_addr (XEXP (x, 1), memmode);
+
     case POST_DEC:
-    case PRE_DEC:
+    case POST_INC:
     case POST_MODIFY:
-    case PRE_MODIFY:
-      e = new_cselib_val (next_uid, GET_MODE (x), x);
-      return e->val_rtx;
+      if (!cselib_record_autoinc)
+	goto no_autoinc;
+      gcc_assert (memmode != VOIDmode);
+      return cselib_subst_to_values_addr (XEXP (x, 0), memmode);
 
     default:
       break;
@@ -1482,7 +1623,7 @@ cselib_subst_to_values (rtx x)
     {
       if (fmt[i] == 'e')
 	{
-	  rtx t = cselib_subst_to_values (XEXP (x, i));
+	  rtx t = cselib_subst_to_values_addr (XEXP (x, i), memmode);
 
 	  if (t != XEXP (x, i))
 	    {
@@ -1497,7 +1638,7 @@ cselib_subst_to_values (rtx x)
 
 	  for (j = 0; j < XVECLEN (x, i); j++)
 	    {
-	      rtx t = cselib_subst_to_values (XVECEXP (x, i, j));
+	      rtx t = cselib_subst_to_values_addr (XVECEXP (x, i, j), memmode);
 
 	      if (t != XVECEXP (x, i, j))
 		{
@@ -1533,13 +1674,16 @@ cselib_log_lookup (rtx x, cselib_val *re
   return ret;
 }
 
-/* Look up the rtl expression X in our tables and return the value it has.
-   If CREATE is zero, we return NULL if we don't know the value.  Otherwise,
-   we create a new one if possible, using mode MODE if X doesn't have a mode
-   (i.e. because it's a constant).  */
+/* Look up the rtl expression X in our tables and return the value it
+   has.  If CREATE is zero, we return NULL if we don't know the value.
+   Otherwise, we create a new one if possible, using mode MODE if X
+   doesn't have a mode (i.e. because it's a constant).  When X is part
+   of an address, MEMMODE should be the mode of the enclosing MEM if
+   we're tracking autoinc expressions.  */
 
 cselib_val *
-cselib_lookup (rtx x, enum machine_mode mode, int create)
+cselib_lookup_addr (rtx x, enum machine_mode mode,
+		    int create, enum machine_mode memmode)
 {
   void **slot;
   cselib_val *e;
@@ -1585,7 +1729,7 @@ cselib_lookup (rtx x, enum machine_mode 
 	  REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL);
 	}
       REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e);
-      slot = htab_find_slot_with_hash (cselib_hash_table, x, e->hash, INSERT);
+      slot = cselib_find_slot (x, e->hash, INSERT, memmode);
       *slot = e;
       return cselib_log_lookup (x, e);
     }
@@ -1593,13 +1737,13 @@ cselib_lookup (rtx x, enum machine_mode 
   if (MEM_P (x))
     return cselib_log_lookup (x, cselib_lookup_mem (x, create));
 
-  hashval = cselib_hash_rtx (x, create);
+  hashval = cselib_hash_rtx (x, create, memmode);
   /* Can't even create if hashing is not possible.  */
   if (! hashval)
     return cselib_log_lookup (x, 0);
 
-  slot = htab_find_slot_with_hash (cselib_hash_table, wrap_constant (mode, x),
-				   hashval, create ? INSERT : NO_INSERT);
+  slot = cselib_find_slot (wrap_constant (mode, x), hashval,
+			   create ? INSERT : NO_INSERT, memmode);
   if (slot == 0)
     return cselib_log_lookup (x, 0);
 
@@ -1613,7 +1757,8 @@ cselib_lookup (rtx x, enum machine_mode 
      the hash table is inconsistent until we do so, and
      cselib_subst_to_values will need to do lookups.  */
   *slot = (void *) e;
-  e->locs = new_elt_loc_list (e->locs, cselib_subst_to_values (x));
+  e->locs = new_elt_loc_list (e->locs,
+			      cselib_subst_to_values_addr (x, memmode));
   return cselib_log_lookup (x, e);
 }
 
@@ -1768,7 +1913,7 @@ cselib_invalidate_mem (rtx mem_rtx)
 	  /* This one overlaps.  */
 	  /* We must have a mapping from this MEM's address to the
 	     value (E).  Remove that, too.  */
-	  addr = cselib_lookup (XEXP (x, 0), VOIDmode, 0);
+	  addr = cselib_lookup_addr (XEXP (x, 0), VOIDmode, 0, GET_MODE (x));
 	  mem_chain = &addr->addr_list;
 	  for (;;)
 	    {
@@ -1882,6 +2027,36 @@ cselib_record_set (rtx dest, cselib_val 
    in a PARALLEL.  Since it's fairly cheap, use a really large number.  */
 #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2)
 
+struct cselib_record_autoinc_data
+{
+  struct cselib_set *sets;
+  int n_sets;
+};
+
+/* Callback for for_each_inc_dec.  Records in ARG the SETs implied by
+   autoinc RTXs: SRCBASE plus SRCOFF if non-NULL is stored in
+   DEST.  */
+
+static int
+cselib_record_autoinc_cb (rtx mem ATTRIBUTE_UNUSED, rtx op ATTRIBUTE_UNUSED,
+			  rtx dest, rtx srcbase, rtx srcoff, void *arg)
+{
+  struct cselib_record_autoinc_data *data;
+  data = (struct cselib_record_autoinc_data *)arg;
+
+  data->sets[data->n_sets].dest = dest;
+
+  if (srcoff)
+    data->sets[data->n_sets].src = gen_rtx_PLUS (GET_MODE (srcbase),
+						 srcbase, srcoff);
+  else
+    data->sets[data->n_sets].src = srcbase;
+
+  data->n_sets++;
+
+  return -1;
+}
+
 /* Record the effects of any sets in INSN.  */
 static void
 cselib_record_sets (rtx insn)
@@ -1934,6 +2109,15 @@ cselib_record_sets (rtx insn)
 	sets[0].src = XEXP (note, 0);
     }
 
+  if (cselib_record_autoinc)
+    {
+      struct cselib_record_autoinc_data data;
+      data.sets = sets;
+      data.n_sets = n_sets;
+      for_each_inc_dec (&insn, cselib_record_autoinc_cb, &data);
+      n_sets = data.n_sets;
+    }
+
   /* Look up the values that are read.  Do this before invalidating the
      locations that are written.  */
   for (i = 0; i < n_sets; i++)
@@ -1958,8 +2142,9 @@ cselib_record_sets (rtx insn)
 	      enum machine_mode address_mode
 		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
 
-	      sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0),
-						     address_mode, 1);
+	      sets[i].dest_addr_elt = cselib_lookup_addr (XEXP (dest, 0),
+							  address_mode, 1,
+							  GET_MODE (dest));
 	    }
 	  else
 	    sets[i].dest_addr_elt = 0;
@@ -2098,6 +2283,7 @@ cselib_init (int record_what)
   value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100);
   cselib_record_memory = record_what & CSELIB_RECORD_MEMORY;
   cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS;
+  cselib_record_autoinc = record_what & CSELIB_RECORD_AUTOINC;
 
   /* (mem:BLK (scratch)) is a special mechanism to conflict with everything,
      see canon_true_dependence.  This is only created once.  */
Index: gcc/cselib.h
===================================================================
--- gcc/cselib.h.orig	2010-03-17 01:05:25.000000000 -0300
+++ gcc/cselib.h	2010-03-22 03:14:10.000000000 -0300
@@ -69,14 +69,18 @@ struct cselib_set
 enum cselib_record_what
 {
   CSELIB_RECORD_MEMORY = 1,
-  CSELIB_PRESERVE_CONSTANTS = 2
+  CSELIB_PRESERVE_CONSTANTS = 2,
+  CSELIB_RECORD_AUTOINC = 4
 };
 
 extern void (*cselib_discard_hook) (cselib_val *);
 extern void (*cselib_record_sets_hook) (rtx insn, struct cselib_set *sets,
 					int n_sets);
 
-extern cselib_val *cselib_lookup (rtx, enum machine_mode, int);
+extern cselib_val *cselib_lookup_addr (rtx, enum machine_mode,
+				       int, enum machine_mode);
+#define cselib_lookup(x, mode, create) \
+  (cselib_lookup_addr (x, mode, create, VOIDmode))
 extern void cselib_init (int);
 extern void cselib_clear_table (void);
 extern void cselib_finish (void);
@@ -90,7 +94,8 @@ extern rtx cselib_expand_value_rtx_cb (r
 				       cselib_expand_callback, void *);
 extern bool cselib_dummy_expand_value_rtx_cb (rtx, bitmap, int,
 					      cselib_expand_callback, void *);
-extern rtx cselib_subst_to_values (rtx);
+extern rtx cselib_subst_to_values_addr (rtx, enum machine_mode);
+#define cselib_subst_to_values(x) (cselib_subst_to_values_addr (x, VOIDmode))
 extern void cselib_invalidate_rtx (rtx);
 
 extern void cselib_reset_table (unsigned int);
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2010-03-17 19:08:53.000000000 -0300
+++ gcc/var-tracking.c	2010-03-22 03:15:45.000000000 -0300
@@ -4653,8 +4653,9 @@ replace_expr_with_values (rtx loc)
     return NULL;
   else if (MEM_P (loc))
     {
-      cselib_val *addr = cselib_lookup (XEXP (loc, 0),
-					get_address_mode (loc), 0);
+      cselib_val *addr = cselib_lookup_addr (XEXP (loc, 0),
+					     get_address_mode (loc), 0,
+					     GET_MODE (loc));
       if (addr)
 	return replace_equiv_address_nv (loc, addr->val_rtx);
       else
@@ -4702,8 +4703,9 @@ use_type (rtx loc, struct count_use_info
 	    {
 	      if (REG_P (loc)
 		  || (find_use_val (loc, GET_MODE (loc), cui)
-		      && cselib_lookup (XEXP (loc, 0),
-					get_address_mode (loc), 0)))
+		      && cselib_lookup_addr (XEXP (loc, 0),
+					     get_address_mode (loc), 0,
+					     GET_MODE (loc))))
 		return MO_VAL_SET;
 	    }
 	  else
@@ -4838,13 +4840,15 @@ add_uses (rtx *ploc, void *data)
 	      rtx mloc = vloc;
 	      enum machine_mode address_mode = get_address_mode (mloc);
 	      cselib_val *val
-		= cselib_lookup (XEXP (mloc, 0), address_mode, 0);
+		= cselib_lookup_addr (XEXP (mloc, 0), address_mode, 0,
+				      GET_MODE (mloc));
 
 	      if (val && !cselib_preserved_value_p (val))
 		{
 		  micro_operation moa;
 		  preserve_value (val);
-		  mloc = cselib_subst_to_values (XEXP (mloc, 0));
+		  mloc = cselib_subst_to_values_addr (XEXP (mloc, 0),
+						      GET_MODE (mloc));
 		  moa.type = MO_VAL_USE;
 		  moa.insn = cui->insn;
 		  moa.u.loc = gen_rtx_CONCAT (address_mode,
@@ -4910,13 +4914,15 @@ add_uses (rtx *ploc, void *data)
 	      rtx mloc = oloc;
 	      enum machine_mode address_mode = get_address_mode (mloc);
 	      cselib_val *val
-		= cselib_lookup (XEXP (mloc, 0), address_mode, 0);
+		= cselib_lookup_addr (XEXP (mloc, 0), address_mode, 0,
+				      GET_MODE (mloc));
 
 	      if (val && !cselib_preserved_value_p (val))
 		{
 		  micro_operation moa;
 		  preserve_value (val);
-		  mloc = cselib_subst_to_values (XEXP (mloc, 0));
+		  mloc = cselib_subst_to_values_addr (XEXP (mloc, 0),
+						      GET_MODE (mloc));
 		  moa.type = MO_VAL_USE;
 		  moa.insn = cui->insn;
 		  moa.u.loc = gen_rtx_CONCAT (address_mode,
@@ -5141,14 +5147,16 @@ add_stores (rtx loc, const_rtx expr, voi
 	{
 	  rtx mloc = loc;
 	  enum machine_mode address_mode = get_address_mode (mloc);
-	  cselib_val *val = cselib_lookup (XEXP (mloc, 0),
-					   address_mode, 0);
+	  cselib_val *val = cselib_lookup_addr (XEXP (mloc, 0),
+						address_mode, 0,
+						GET_MODE (mloc));
 
 	  if (val && !cselib_preserved_value_p (val))
 	    {
 	      preserve_value (val);
 	      mo.type = MO_VAL_USE;
-	      mloc = cselib_subst_to_values (XEXP (mloc, 0));
+	      mloc = cselib_subst_to_values_addr (XEXP (mloc, 0),
+						  GET_MODE (mloc));
 	      mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
 	      mo.insn = cui->insn;
 	      if (dump_file && (dump_flags & TDF_DETAILS))
@@ -8023,7 +8031,8 @@ vt_initialize (void)
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
-      cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
+      cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS
+		   | CSELIB_RECORD_AUTOINC);
       scratch_regs = BITMAP_ALLOC (NULL);
       valvar_pool = create_alloc_pool ("small variable_def pool",
 				       sizeof (struct variable_def), 256);
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c.orig	2010-03-12 04:33:41.000000000 -0300
+++ gcc/rtlanal.c	2010-03-17 22:14:47.000000000 -0300
@@ -2870,7 +2870,105 @@ for_each_rtx (rtx *x, rtx_function f, vo
   return for_each_rtx_1 (*x, i, f, data);
 }
 
+
+
+struct for_each_inc_dec_ops {
+  for_each_inc_dec_fn fn;
+  void *arg;
+  rtx mem;
+};
+
+static int for_each_inc_dec_find_mem (rtx *r, void *d);
+
+/* Add an insn to do the add inside a x if it is a
+   PRE/POST-INC/DEC/MODIFY.  D is an structure containing the insn and
+   the size of the mode of the MEM that this is inside of.  */
+
+static int
+for_each_inc_dec_find_inc_dec (rtx *r, void *d)
+{
+  rtx x = *r;
+  struct for_each_inc_dec_ops *data = (struct for_each_inc_dec_ops *)d;
+  int size = GET_MODE_SIZE (GET_MODE (data->mem));
+
+  switch (GET_CODE (x))
+    {
+    case PRE_INC:
+    case POST_INC:
+      {
+	rtx r1 = XEXP (x, 0);
+	rtx c = gen_int_mode (size, GET_MODE (r1));
+	return data->fn (data->mem, x, r1, r1, c, data->arg);
+      }
+
+    case PRE_DEC:
+    case POST_DEC:
+      {
+	rtx r1 = XEXP (x, 0);
+	rtx c = gen_int_mode (-size, GET_MODE (r1));
+	return data->fn (data->mem, x, r1, r1, c, data->arg);
+      }
+
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      {
+	rtx r1 = XEXP (x, 0);
+	rtx add = XEXP (x, 1);
+	return data->fn (data->mem, x, r1, add, NULL, data->arg);
+      }
+
+    case MEM:
+      {
+	rtx save = data->mem;
+	int ret = for_each_inc_dec_find_mem (r, d);
+	data->mem = save;
+	return ret;
+      }
+
+    default:
+      return 0;
+    }
+}
+
+/* If X is a MEM, check the address to see if it is PRE/POST-INC/DEC/MODIFY
+   and generate an add to replace that.  */
+
+static int
+for_each_inc_dec_find_mem (rtx *r, void *d)
+{
+  rtx x = *r;
+  if (x != NULL_RTX && MEM_P (x))
+    {
+      struct for_each_inc_dec_ops *data = (struct for_each_inc_dec_ops *) d;
+      int result;
+
+      data->mem = x;
 
+      result = for_each_rtx (&XEXP (x, 0), for_each_inc_dec_find_inc_dec,
+			     data);
+      if (result)
+	return result;
+
+      return -1;
+    }
+  return 0;
+}
+
+int
+for_each_inc_dec (rtx *insn,
+		  for_each_inc_dec_fn fn,
+		  void *arg)
+{
+  struct for_each_inc_dec_ops data;
+
+  data.fn = fn;
+  data.arg = arg;
+  data.mem = NULL;
+
+  return for_each_rtx (insn, for_each_inc_dec_find_mem, &data);
+}
+
+
 /* Searches X for any reference to REGNO, returning the rtx of the
    reference found if any.  Otherwise, returns NULL_RTX.  */
 
-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]