------- Comment #11 from zadeck at naturalbridge dot com  2007-12-10 20:46 
-------
Subject:  [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 <[EMAIL PROTECTED]>

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

2007-12-10  Jakub Jelinek  <[EMAIL PROTECTED]>

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


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34302

Reply via email to