re PR rtl-optimization/44858 (likely integer wrong code bug)
authorJakub Jelinek <jakub@redhat.com>
Wed, 25 Aug 2010 17:50:59 +0000 (19:50 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 25 Aug 2010 17:50:59 +0000 (19:50 +0200)
PR rtl-optimization/44858
* combine.c (try_combine): If recog_for_combine added CLOBBERs to
newi2pat, make sure they don't affect newpat.

* gcc.c-torture/execute/pr44858.c: New test.

From-SVN: r163552

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

index 1123d07ce20839fd126934d41467477e998a7dde..0cdd6aaba95267656b3a87fc00da856f04ea7494 100644 (file)
@@ -1,5 +1,9 @@
 2010-08-25  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/44858
+       * combine.c (try_combine): If recog_for_combine added CLOBBERs to
+       newi2pat, make sure they don't affect newpat.
+
        PR rtl-optimization/45400
        * combine.c (simplify_shift_const_1) <case SUBREG>: Only use
        SUBREG_REG if both modes are of MODE_INT class.
index acff54198e54c3ec36bc22aab56dffbd7bb4ab07..273a9820df8abf6d06602a74b112028aa0799025 100644 (file)
@@ -3725,7 +3725,58 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
       i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
       if (i2_code_number >= 0)
-       insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+       {
+         /* recog_for_combine might have added CLOBBERs to newi2pat.
+            Make sure NEWPAT does not depend on the clobbered regs.  */
+         if (GET_CODE (newi2pat) == PARALLEL)
+           {
+             for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
+               if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
+                 {
+                   rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
+                   if (reg_overlap_mentioned_p (reg, newpat))
+                     break;
+                 }
+
+             if (i >= 0)
+               {
+                 /* CLOBBERs on newi2pat prevent it going first.
+                    Try the other order of the insns if possible.  */
+                 temp = newpat;
+                 newpat = XVECEXP (newi2pat, 0, 0);
+                 newi2pat = temp;
+#ifdef HAVE_cc0
+                 if (reg_referenced_p (cc0_rtx, newpat))
+                   {
+                     undo_all ();
+                     return 0;
+                   }
+#endif
+
+                 i2_code_number = recog_for_combine (&newi2pat, i2,
+                                                     &new_i2_notes);
+                 if (i2_code_number < 0)
+                   {
+                     undo_all ();
+                     return 0;
+                   }
+
+                 if (GET_CODE (newi2pat) == PARALLEL)
+                   for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
+                     if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
+                       {
+                         rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
+                         if (reg_overlap_mentioned_p (reg, newpat))
+                           {
+                             undo_all ();
+                             return 0;
+                           }
+                       }
+               }
+           }
+
+         insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+       }
     }
 
   /* If it still isn't recognized, fail and change things back the way they
index fd9f5ad3d0ae5ee2d01f55581f757d25ca296f52..15dad787affd8ffedc336d2f68ac054c751968b6 100644 (file)
@@ -1,5 +1,8 @@
 2010-08-25  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/44858
+       * gcc.c-torture/execute/pr44858.c: New test.
+
        PR rtl-optimization/45400
        * g++.dg/other/i386-8.C: New test.
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr44858.c b/gcc/testsuite/gcc.c-torture/execute/pr44858.c
new file mode 100644 (file)
index 0000000..45e1758
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR rtl-optimization/44858 */
+
+extern void abort (void);
+int a = 3;
+int b = 1;
+
+__attribute__((noinline)) long long
+foo (int x, int y)
+{
+  return x / y;
+}
+
+__attribute__((noinline)) int
+bar (void)
+{
+  int c = 2;
+  c &= foo (1, b) > b;
+  b = (a != 0) | c;
+  return c;
+}
+
+int
+main (void)
+{
+  if (bar () != 0 || b != 1)
+    abort ();
+  return 0;
+}