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