Index: gcc/combine.c =================================================================== --- gcc/combine.c (revision 218200) +++ gcc/combine.c (working copy) @@ -4183,11 +4183,42 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL, elim_i2, elim_i1, elim_i0); if (i1notes) - distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL, - elim_i2, elim_i1, elim_i0); + { + /* When distributing REG_DEAD note from i1, it doesn't matter + if newi2pat sets i1dest/i0dest or not. Recompute and use + elim_i0/elim_i1 in temp variables. + + 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 this only affects cases in which I2 is after I0/I1, 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 + will not set i1dest or i0dest. */ + rtx tmp_elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src + || !i1dest_killed + ? 0 : i1dest); + rtx tmp_elim_i0 = (i0 == 0 || i0dest_in_i0src || !i0dest_killed + ? 0 : i0dest); + distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL, + elim_i2, tmp_elim_i1, tmp_elim_i0); + } if (i0notes) - distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL, - elim_i2, elim_i1, elim_i0); + { + /* Same with distribution of i1notes. */ + rtx tmp_elim_i0 = (i0 == 0 || i0dest_in_i0src || !i0dest_killed + ? 0 : i0dest); + distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL, + elim_i2, elim_i1, tmp_elim_i0); + } if (midnotes) distribute_notes (midnotes, NULL, i3, newi2pat ? i2 : NULL, elim_i2, elim_i1, elim_i0); Index: gcc/testsuite/gcc.c-torture/execute/pr62151.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/pr62151.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr62151.c (revision 0) @@ -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; +}