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]

[vta] handle auto-inc-dec in debug insns in combine


When combine substitutes an auto-inc-dec in a set into a use, and
there's a debug insn that references the set pseudo, we lose (*)
unless we adjust the addressing mode to lose the auto-inc-dec.  This
is what the patch below accomplishes, fixing problems in ia64.

(*) say, debug insns suddently become setters, oops

While at that, I realized that propagate_for_debug was too
conservative in moving or marking for rescan debug insns that it found
between the combined insns.  Marking insns for rescan without changes
is "just" wasteful, but needlessly moving debug insns around, that are
supposed to mark assignment points, is detrimental to the quality of
debug information, so we must only move them if there's absolutely no
way around it.

I'm installing this in the vta branch.

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

	* combine.c (cleanup_auto_inc_dec): New.
	(struct rtx_subst_pair): Add new fields to track changes and
	auto-inc-dec.
	(propagate_for_debug_subst): Handle auto-inc-dec.
	(propagate_for_debug): Initialize new fields.  Only move or
	mark for rescan debug insns that have actually changed.

Index: gcc/combine.c
===================================================================
--- gcc/combine.c.orig	2007-12-23 06:02:20.000000000 -0200
+++ gcc/combine.c	2007-12-23 06:02:37.000000000 -0200
@@ -2165,11 +2165,95 @@ reg_subword_p (rtx x, rtx reg)
 	 && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT;
 }
 
+#ifdef AUTO_INC_DEC
+/* Replace auto-increment addressing modes with explicit operations to
+   access the same addresses without modifying the corresponding
+   registers.  If AFTER holds, SRC is meant to be reused after the
+   side effect, otherwise it is to be reused before that.  */
+
+static rtx
+cleanup_auto_inc_dec (rtx src, bool after, enum machine_mode mem_mode)
+{
+  rtx x = src, new, old;
+  const RTX_CODE code = GET_CODE (x);
+  int i;
+  const char *fmt;
+
+  switch (code)
+    {
+    case MEM:
+      mem_mode = GET_MODE (x);
+      break;
+
+    case PRE_INC:
+    case PRE_DEC:
+    case POST_INC:
+    case POST_DEC:
+      gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
+      if (after == (code == PRE_INC || code == PRE_DEC))
+	x = XEXP (x, 0);
+      else
+	x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+			  GEN_INT ((code == PRE_INC || code == POST_INC)
+				   ? GET_MODE_SIZE (mem_mode)
+				   : -GET_MODE_SIZE (mem_mode)));
+      return cleanup_auto_inc_dec (x, after, mem_mode);
+
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      if (after == (code == PRE_INC))
+	x = XEXP (x, 0);
+      else
+	x = XEXP (x, 1);
+      return cleanup_auto_inc_dec (x, after, mem_mode);
+
+    default:
+      break;
+    }
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    if (fmt[i] == 'e')
+      {
+	old = XEXP (x, i);
+	new = cleanup_auto_inc_dec (old, after, mem_mode);
+	if (old != new)
+	  {
+	    if (x == src)
+	      x = shallow_copy_rtx (x);
+	    XEXP (x, i) = new;
+	  }
+      }
+    else if (fmt[i] == 'E')
+      {
+	int j;
+	for (j = 0; j < XVECLEN (x, i); j++)
+	  {
+	    old = XVECEXP (x, i, j);
+	    new = cleanup_auto_inc_dec (old, after, mem_mode);
+	    if (old != new)
+	      {
+		if (x == src)
+		  x = shallow_copy_rtx (x);
+		XVECEXP (x, i, j) = new;
+	      }
+	  }
+      }
+
+  return x;
+}
+#endif
+
 /* Auxiliary data structure for propagate_for_debug_stmt.  */
 
 struct rtx_subst_pair
 {
   rtx from, to;
+  bool changed;
+#ifdef AUTO_INC_DEC
+  bool adjusted;
+  bool after;
+#endif
 };
 
 /* If *LOC is the same as FROM in the struct rtx_subst_pair passed as
@@ -2184,7 +2268,20 @@ propagate_for_debug_subst (rtx *loc, voi
 
   if (rtx_equal_p (x, from))
     {
-      *loc = copy_rtx (to);
+#ifdef AUTO_INC_DEC
+      if (!pair->adjusted)
+	{
+	  to = cleanup_auto_inc_dec (to, pair->after, VOIDmode);
+	  pair->adjusted = true;
+	  if (pair->to != to)
+	    *loc = pair->to = to;
+	  else
+	    *loc = copy_rtx (to);
+	}
+      else
+#endif
+	*loc = copy_rtx (to);
+      pair->changed = true;
       return -1;
     }
 
@@ -2203,6 +2300,12 @@ propagate_for_debug (rtx insn, rtx last,
 
   p.from = dest;
   p.to = src;
+  p.changed = false;
+
+#ifdef AUTO_INC_DEC
+  p.adjusted = false;
+  p.after = move;
+#endif
 
   next = NEXT_INSN (insn);
   while (next != last)
@@ -2213,6 +2316,9 @@ propagate_for_debug (rtx insn, rtx last,
 	{
 	  for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
 			propagate_for_debug_subst, &p);
+	  if (!p.changed)
+	    continue;
+	  p.changed = false;
 	  if (move_pos)
 	    {
 	      remove_insn (insn);
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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