From ae9f434509517d4c6671bc197d0d64ef7cf74cde Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Mon, 22 Dec 2014 10:25:10 +0000 Subject: [PATCH] re PR rtl-optimization/62151 (wrong code at -O2 and -O3 on x86_64-linux-gnu) PR rtl-optimization/62151 * combine.c (try_combine): New local variables local_elim_i1 and local_elim_i0. Set elim_i1 and elim_i0 using the local version variables. Distribute notes from i0notes or i1notes using the local variables. gcc/testsuite/ChangeLog PR rtl-optimization/62151 * gcc.c-torture/execute/pr62151.c: New test. From-SVN: r219008 --- gcc/ChangeLog | 8 +++++ gcc/combine.c | 43 ++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.c-torture/execute/pr62151.c | 41 +++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr62151.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c5e878b..e096b52 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-12-22 Bin Cheng + + PR rtl-optimization/62151 + * combine.c (try_combine): New local variables local_elim_i1 + and local_elim_i0. Set elim_i1 and elim_i0 using the local + version variables. Distribute notes from i0notes or i1notes + using the local variables. + 2014-12-22 Martin Liska * cgraphunit.c (symbol_table::process_new_functions): New inline_summaries diff --git a/gcc/combine.c b/gcc/combine.c index 212da33..61df870 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -4124,19 +4124,46 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, rtx midnotes = 0; int from_luid; /* Compute which registers we expect to eliminate. newi2pat may be setting - either i3dest or i2dest, so we must check it. Also, i1dest may be the - same as i3dest, in which case newi2pat may be setting i1dest. */ + either i3dest or i2dest, so we must check it. */ rtx elim_i2 = ((newi2pat && reg_set_p (i2dest, newi2pat)) || i2dest_in_i2src || i2dest_in_i1src || i2dest_in_i0src || !i2dest_killed ? 0 : i2dest); - rtx elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src + /* For i1, we need to compute both local elimination and global + elimination information with respect to newi2pat because i1dest + may be the same as i3dest, in which case newi2pat may be setting + i1dest. Global information is used when distributing REG_DEAD + note for i2 and i3, in which case it does matter if newi2pat sets + i1dest or not. + + Local information is used when distributing REG_DEAD note for i1, + in which case it doesn't matter if newi2pat sets i1dest or not. + 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 local information only affects cases in forms 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 won't set i1dest or + i0dest anyway. */ + rtx local_elim_i1 = (i1 == 0 || i1dest_in_i1src || i1dest_in_i0src + || !i1dest_killed + ? 0 : i1dest); + rtx elim_i1 = (local_elim_i1 == 0 || (newi2pat && reg_set_p (i1dest, newi2pat)) - || !i1dest_killed ? 0 : i1dest); - rtx elim_i0 = (i0 == 0 || i0dest_in_i0src + /* Same case as i1. */ + rtx local_elim_i0 = (i0 == 0 || i0dest_in_i0src || !i0dest_killed + ? 0 : i0dest); + rtx elim_i0 = (local_elim_i0 == 0 || (newi2pat && reg_set_p (i0dest, newi2pat)) - || !i0dest_killed ? 0 : i0dest); /* Get the old REG_NOTES and LOG_LINKS from all our insns and @@ -4305,10 +4332,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, elim_i2, elim_i1, elim_i0); if (i1notes) distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL, - elim_i2, elim_i1, elim_i0); + elim_i2, local_elim_i1, local_elim_i0); if (i0notes) distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL, - elim_i2, elim_i1, elim_i0); + elim_i2, elim_i1, local_elim_i0); if (midnotes) distribute_notes (midnotes, NULL, i3, newi2pat ? i2 : NULL, elim_i2, elim_i1, elim_i0); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f69fb33..7ede224 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-12-22 Bin Cheng + + PR rtl-optimization/62151 + * gcc.c-torture/execute/pr62151.c: New test. + 2014-12-22 Eric Botcazou * gnat.dg/specs/atomic2.ads: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr62151.c b/gcc/testsuite/gcc.c-torture/execute/pr62151.c new file mode 100644 index 0000000..283d46f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr62151.c @@ -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; +} -- 2.7.4