Hi,
As described both in the PR and patch comments, this patch fixes PR62151 by
setting right value to ELIM_I0/ELIM_I1 when distributing REG_DEAD notes from
i0/i1. It is said that distribute_notes had caused many bugs in the past.
I think it still has bug in it, as noted in the PR. This patch doesn't
touch distribute_notes because we are in stage3 and I want to have more
discussion on it.
Bootstrap and test on x86_64. aarch64 is ongoing. So is it ok?
2014-12-11 Bin Cheng <bin.ch...@arm.com>
PR rtl-optimization/62151
* combine.c (try_combine): Reset elim_i0 and elim_i1 when
distributing notes from i0notes or i1notes, this time don't
check whether newi2pat sets i1dest or i0dest.
gcc/testsuite/ChangeLog
2014-12-11 Bin Cheng <bin.ch...@arm.com>
PR rtl-optimization/62151
* gcc.c-torture/execute/pr62151.c: New test.
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;
+}