If we are combining insns like

        I1: (... r90)   REG_DEAD r90
        I2: (set r90 ...)
        I3: (...)

resulting in

        I2: (set r90 ...)
        I3: (...)

distribute_notes for that REG_DEAD r90 wil start searching (backwards)
for r90 starting from I3.  Then it will find I2, and because it thinks
it is a dead set, delete it.

This fixes it.  Tested on powerpc64-linux (c,c++,ada,fortran) with
--disable-libsanitizer --disable-libgomp, -m32,-m32/-mpowerpc,-m64,
-m64/-mlra; and on x86_64-linux (c,c++,fortran), no other options.
The new testcase fails on x86_64-linux without the patch (-O2 or
higher).

Is this okay for mainline?


Segher


2015-01-21  Segher Boessenkool  <seg...@kernel.crashing.org>

gcc/
        PR rtl-optimization/64682
        * combine.c (distribute_notes): When moving a death note for
        a register that is set in the new I2, make sure to put it
        before that new I2.

gcc/testsuite/
        PR rtl-optimization/64682
        * gcc.c-torture/execute/pr64682.c: New file.

---
 gcc/combine.c                                 |  5 +++++
 gcc/testsuite/gcc.c-torture/execute/pr64682.c | 26 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr64682.c

diff --git a/gcc/combine.c b/gcc/combine.c
index 597aa80..5c763b4 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -13684,6 +13684,11 @@ distribute_notes (rtx notes, rtx_insn *from_insn, 
rtx_insn *i3, rtx_insn *i2,
                       || rtx_equal_p (XEXP (note, 0), elim_i0))
                break;
              tem_insn = i3;
+             /* If the new I2 sets the same register that is marked dead
+                in the note, the note now should not be put on I2, as the
+                note refers to a previous incarnation of the reg.  */
+             if (i2 != 0 && reg_set_p (XEXP (note, 0), PATTERN (i2)))
+               tem_insn = i2;
            }
 
          if (place == 0)
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr64682.c 
b/gcc/testsuite/gcc.c-torture/execute/pr64682.c
new file mode 100644
index 0000000..58f610a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr64682.c
@@ -0,0 +1,26 @@
+/* PR rtl-optimization/64682 */
+
+int a, b = 1;
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+  if (x != 5)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 56; i++)
+    for (; a; a--)
+      ;
+  int *c = &b;
+  if (*c)
+    *c = 1 % (unsigned int) *c | 5;
+
+  foo (b);
+
+  return 0;
+}
-- 
1.8.1.4

Reply via email to