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]

[Bug rtl-optimization/34302] [4.3 regression] Invalid code reordering


This patch fixes where the move insn is inserted on pre increments.  it
had been inserted before the auto inc but this is not correct.  it needs
to replace the existing add to properly handle the case where the
operands of the add change between the add and the load.

Tested on ppc-32.  The patch will only effect architectures with pre
increment.

Ok for commit?

Jakub, note that i changed the name of your testcase from 20071012-1.c
to 20071210-1.c.
I believe that this is the correct.

Kenny


2007-12-10  Kenneth Zadeck <zadeck@naturalbridge.com>

    PR rtl-optimization/34302
    * auto-inc-dec.c (attempt_change): Change place where move is
    inserted.

2007-12-10  Jakub Jelinek  <jakub@redhat.com>

    PR rtl-optimization/34302
    * gcc.c-torture/execute/20071210-1.c: New test.

Index: auto-inc-dec.c
===================================================================
--- auto-inc-dec.c	(revision 130748)
+++ auto-inc-dec.c	(working copy)
@@ -550,7 +550,10 @@ attempt_change (rtx new_addr, rtx inc_re
   switch (inc_insn.form)
     {
     case FORM_PRE_ADD:
-      mov_insn = insert_move_insn_before (mem_insn.insn, 
+      /* Replace the addition with a move.  Do it at the location of
+	 the addition since the operand of the addition may change
+	 before the memory reference.  */
+      mov_insn = insert_move_insn_before (inc_insn.insn, 
 					  inc_insn.reg_res, inc_insn.reg0);
       move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
 
@@ -673,7 +676,7 @@ try_merge (void)
     }
 
   /* Look to see if the inc register is dead after the memory
-     reference.  If it is do not do the combination.  */
+     reference.  If it is, do not do the combination.  */
   if (find_regno_note (last_insn, REG_DEAD, REGNO (inc_reg)))
     {
       if (dump_file)
Index: testsuite/gcc.c-torture/execute/20071210-1.c
===================================================================
--- testsuite/gcc.c-torture/execute/20071210-1.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/20071210-1.c	(revision 0)
@@ -0,0 +1,67 @@
+/* PR rtl-optimization/34302 */
+
+extern void abort (void);
+
+struct S
+{
+  int n1, n2, n3, n4;
+};
+
+__attribute__((noinline)) struct S
+foo (int x, int y, int z)
+{
+  if (x != 10 || y != 9 || z != 8)
+    abort ();
+  struct S s = { 1, 2, 3, 4 };
+  return s;
+}
+
+__attribute__((noinline)) void **
+bar (void **u, int *v)
+{
+  void **w = u;
+  int *s = v, x, y, z;
+  void **p, **q;
+  static void *l[] = { &&lab1, &&lab1, &&lab2, &&lab3, &&lab4 };
+
+  if (!u)
+    return l;
+
+  q = *w++;
+  goto *q;
+lab2:
+  p = q;
+  q = *w++;
+  x = s[2];
+  y = s[1];
+  z = s[0];
+  s -= 1;
+  struct S r = foo (x, y, z);
+  s[3] = r.n1;
+  s[2] = r.n2;
+  s[1] = r.n3;
+  s[0] = r.n4;
+  goto *q;
+lab3:
+  p = q;
+  q = *w++;
+  s += 1;
+  s[0] = 23;
+lab1:
+  goto *q;
+lab4:
+  return 0;
+}
+
+int
+main (void)
+{
+  void **u = bar ((void **) 0, (int *) 0);
+  void *t[] = { u[2], u[4] };
+  int s[] = { 7, 8, 9, 10, 11, 12 };
+  if (bar (t, &s[1]) != (void **) 0
+      || s[0] != 4 || s[1] != 3 || s[2] != 2 || s[3] != 1
+      || s[4] != 11 || s[5] != 12)
+    abort ();
+  return 0;
+}

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