re PR rtl-optimization/62151 (wrong code at -O2 and -O3 on x86_64-linux-gnu)
authorBin Cheng <bin.cheng@arm.com>
Mon, 22 Dec 2014 10:25:10 +0000 (10:25 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Mon, 22 Dec 2014 10:25:10 +0000 (10:25 +0000)
PR rtl-optimization/62151
* combine.c (try_combine): New local variables local_elim_i1
and local_elim_i0.  Set elim_i1 and elim_i0 using the local
version variables.  Distribute notes from i0notes or i1notes
using the local variables.

gcc/testsuite/ChangeLog
PR rtl-optimization/62151
* gcc.c-torture/execute/pr62151.c: New test.

From-SVN: r219008

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr62151.c [new file with mode: 0644]

index c5e878b883a412510f6f6a505664645d2f654713..e096b52da3fe8d224c6643856cb390a5c851710c 100644 (file)
@@ -1,3 +1,11 @@
+2014-12-22  Bin Cheng  <bin.cheng@arm.com>
+
+       PR rtl-optimization/62151
+       * combine.c (try_combine): New local variables local_elim_i1
+       and local_elim_i0.  Set elim_i1 and elim_i0 using the local
+       version variables.  Distribute notes from i0notes or i1notes
+       using the local variables.
+
 2014-12-22  Martin Liska  <mliska@suse.cz>
 
        * cgraphunit.c (symbol_table::process_new_functions): New inline_summaries
index 212da3320f3fcc05c569e6352215379f758d64a8..61df870e9b3983e0eca182b2e711cf50393630af 100644 (file)
@@ -4124,19 +4124,46 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
     rtx midnotes = 0;
     int from_luid;
     /* Compute which registers we expect to eliminate.  newi2pat may be setting
-       either i3dest or i2dest, so we must check it.  Also, i1dest may be the
-       same as i3dest, in which case newi2pat may be setting i1dest.  */
+       either i3dest or i2dest, so we must check it.  */
     rtx elim_i2 = ((newi2pat && reg_set_p (i2dest, newi2pat))
                   || i2dest_in_i2src || i2dest_in_i1src || i2dest_in_i0src
                   || !i2dest_killed
                   ? 0 : i2dest);
-    rtx elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src
+    /* For i1, we need to compute both local elimination and global
+       elimination information with respect to newi2pat because i1dest
+       may be the same as i3dest, in which case newi2pat may be setting
+       i1dest.  Global information is used when distributing REG_DEAD
+       note for i2 and i3, in which case it does matter if newi2pat sets
+       i1dest or not.
+
+       Local information is used when distributing REG_DEAD note for i1,
+       in which case it doesn't matter if newi2pat sets i1dest or not.
+       See PR62151, if we have four insns combination:
+          i0: r0 <- i0src
+          i1: r1 <- i1src (using r0)
+                    REG_DEAD (r0)
+          i2: r0 <- i2src (using r1)
+          i3: r3 <- i3src (using r0)
+          ix: using r0
+       From i1's point of view, r0 is eliminated, no matter if it is set
+       by newi2pat or not.  In other words, REG_DEAD info for r0 in i1
+       should be discarded.
+
+       Note local information only affects cases in forms like "I1->I2->I3",
+       "I0->I1->I2->I3" or "I0&I1->I2, I2->I3".  For other cases like
+       "I0->I1, I1&I2->I3" or "I1&I2->I3", newi2pat won't set i1dest or
+       i0dest anyway.  */
+    rtx local_elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src
+                        || !i1dest_killed
+                        ? 0 : i1dest);
+    rtx elim_i1 = (local_elim_i1 == 0
                   || (newi2pat && reg_set_p (i1dest, newi2pat))
-                  || !i1dest_killed
                   ? 0 : i1dest);
-    rtx elim_i0 = (i0 == 0 || i0dest_in_i0src
+    /* Same case as i1.  */
+    rtx local_elim_i0 = (i0 == 0 || i0dest_in_i0src || !i0dest_killed
+                        ? 0 : i0dest);
+    rtx elim_i0 = (local_elim_i0 == 0
                   || (newi2pat && reg_set_p (i0dest, newi2pat))
-                  || !i0dest_killed
                   ? 0 : i0dest);
 
     /* Get the old REG_NOTES and LOG_LINKS from all our insns and
@@ -4305,10 +4332,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
                        elim_i2, elim_i1, elim_i0);
     if (i1notes)
       distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL,
-                       elim_i2, elim_i1, elim_i0);
+                       elim_i2, local_elim_i1, local_elim_i0);
     if (i0notes)
       distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL,
-                       elim_i2, elim_i1, elim_i0);
+                       elim_i2, elim_i1, local_elim_i0);
     if (midnotes)
       distribute_notes (midnotes, NULL, i3, newi2pat ? i2 : NULL,
                        elim_i2, elim_i1, elim_i0);
index f69fb33368dedc2bd1064f9193bcb40b4573a174..7ede224342e194747bcff439ae049c63deb3ef51 100644 (file)
@@ -1,3 +1,8 @@
+2014-12-22  Bin Cheng  <bin.cheng@arm.com>
+
+       PR rtl-optimization/62151
+       * gcc.c-torture/execute/pr62151.c: New test.
+
 2014-12-22  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/atomic2.ads: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr62151.c b/gcc/testsuite/gcc.c-torture/execute/pr62151.c
new file mode 100644 (file)
index 0000000..283d46f
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR rtl-optimization/62151 */
+
+int a, c, d, e, f, g, h, i;
+short b;
+
+int
+fn1 ()
+{
+  b = 0;
+  for (;;)
+    {
+      int j[2];
+      j[f] = 0;
+      if (h)
+       d = 0;
+      else
+       {
+         for (; f; f++)
+           ;
+         for (a = 0; a < 1; a++)
+           for (;;)
+             {
+               i = b & ((b ^ 1) & 83647) ? b : b - 1;
+               g = 1 ? i : 0;
+               e = j[0];
+               if (c)
+                 break;
+               return 0;
+             }
+       }
+    }
+}
+
+int
+main ()
+{
+  fn1 ();
+  if (g != -1)
+    __builtin_abort ();
+  return 0;
+}