summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/combine.c43
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr62151.c41
4 files changed, 89 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c5e878b883a..e096b52da3f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-12-22 Bin Cheng <bin.cheng@arm.com>
+
+ 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 <mliska@suse.cz>
* cgraphunit.c (symbol_table::process_new_functions): New inline_summaries
diff --git a/gcc/combine.c b/gcc/combine.c
index 212da3320f3..61df870e9b3 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 f69fb33368d..7ede224342e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-12-22 Bin Cheng <bin.cheng@arm.com>
+
+ PR rtl-optimization/62151
+ * gcc.c-torture/execute/pr62151.c: New test.
+
2014-12-22 Eric Botcazou <ebotcazou@adacore.com>
* 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 00000000000..283d46f0a24
--- /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;
+}