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]

[PATCH] Fix -fcompare-debug failures caused by combine-stack-adj pass


Hi!

On the attached testcase on i586 csa pass fails to merge two stack
adjustments if there is a DEBUG_INSN with (mem (mem (sp + cst)) in it.
While that testcase can be fixed just by the first record_stack_memrefs
hunk, I'm pretty sure it is possible to have a sp reference in DEBUG_INSN
that CSA doesn't handle ATM, which would still lead to -fcompare-debug
failure, as with -g adjustments wouldn't be merged because of it, while
with -g0 when there is no such DEBUG_INSN they would.
Fortunately in DEBUG_INSN we can just replace SP with SP + CST as a
fallback.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2009-09-04  Jakub Jelinek  <jakub@redhat.com>

	PR bootstrap/41241
	* combine-stack-adj.c (record_one_stack_memref): Handle REG_P.
	(try_apply_stack_adjustment): Likewise.
	(record_stack_memrefs): For DEBUG_INSNs keep traversing subexpressions
	instead of failing when a MEM contains SP references.  For SP itself
	in DEBUG_INSNs queue it also onto memlist chain.

	* gcc.dg/pr41241.c: New test.

--- gcc/combine-stack-adj.c.jj	2009-06-30 13:10:30.000000000 +0200
+++ gcc/combine-stack-adj.c	2009-09-04 21:13:05.000000000 +0200
@@ -180,7 +180,7 @@ record_one_stack_memref (rtx insn, rtx *
 
   ml = XNEW (struct csa_memlist);
 
-  if (XEXP (*mem, 0) == stack_pointer_rtx)
+  if (REG_P (*mem) || XEXP (*mem, 0) == stack_pointer_rtx)
     ml->sp_offset = 0;
   else
     ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1));
@@ -206,11 +206,19 @@ try_apply_stack_adjustment (rtx insn, st
   validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
 
   for (ml = memlist; ml ; ml = ml->next)
-    validate_change
-      (ml->insn, ml->mem,
-       replace_equiv_address_nv (*ml->mem,
-				 plus_constant (stack_pointer_rtx,
-						ml->sp_offset - delta)), 1);
+    {
+      rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta);
+      rtx new_val;
+
+      if (MEM_P (*ml->mem))
+	new_val = replace_equiv_address_nv (*ml->mem, new_addr);
+      else if (GET_MODE (*ml->mem) == GET_MODE (stack_pointer_rtx))
+	new_val = new_addr;
+      else
+	new_val = lowpart_subreg (GET_MODE (*ml->mem), new_addr,
+				  GET_MODE (new_addr));
+      validate_change (ml->insn, ml->mem, new_val, 1);
+    }
 
   if (apply_change_group ())
     {
@@ -252,7 +260,8 @@ record_stack_memrefs (rtx *xp, void *dat
 	  d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
 	  return -1;
 	}
-      return 1;
+      /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4).  */
+      return !DEBUG_INSN_P (d->insn);
     case REG:
       /* ??? We want be able to handle non-memory stack pointer
 	 references later.  For now just discard all insns referring to
@@ -262,9 +271,17 @@ record_stack_memrefs (rtx *xp, void *dat
 	 We can't just compare with STACK_POINTER_RTX because the
 	 reference to the stack pointer might be in some other mode.
 	 In particular, an explicit clobber in an asm statement will
-	 result in a QImode clobber.  */
+	 result in a QImode clobber.
+
+	 In DEBUG_INSNs, we want to replace all occurrences, otherwise
+	 they will cause -fcompare-debug failures.  */
       if (REGNO (x) == STACK_POINTER_REGNUM)
-	return 1;
+	{
+	  if (!DEBUG_INSN_P (d->insn))
+	    return 1;
+	  d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
+	  return -1;
+	}
       break;
     default:
       break;
--- gcc/testsuite/gcc.dg/pr41241.c.jj	2009-09-04 21:03:46.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr41241.c	2009-09-04 21:03:40.000000000 +0200
@@ -0,0 +1,34 @@
+/* PR bootstrap/41241 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcompare-debug -g" } */
+/* { dg-options "-O2 -fcompare-debug -g -march=i586 -mtune=i586 -fomit-frame-pointer" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+typedef struct { int t1; int t2; int t3; } *T;
+typedef struct { int s; } S;
+
+int fn1 (int);
+int fn2 (int, int, int);
+int fn3 (void);
+
+static S
+bar ()
+{
+  S s = { 0 };
+  return s;
+}
+
+void
+foo (T x)
+{
+  int a, b, c, d, e;
+  T f, g;
+  S h;
+  a = x->t2;
+  fn1 (x->t1);
+  h = bar (b);
+  c = fn1 (e);
+  d = fn3 ();
+  f->t3 &= g->t3 |= fn2 (0, b, x->t1);
+  fn2 (0, c, d);
+  fn2 (0, e, 0);
+}

	Jakub


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