[RFA][PATCH][PR middle-end/59743] Fix ree improvement when defining insn is after use insn

Jeff Law law@redhat.com
Fri Jan 10 21:59:00 GMT 2014


As mentioned in the PR, we have a case where within a block the reaching 
def (defining insn) occurs after the use (extension insn).  This 
obviously can only happen in a loop and AFAICT should only happen for an 
uninitialized use.

Anyway, in this situation we'd segfault in reg_used_between_p during 
some of the correctness checks for the recent improvements to REE.

Thankfully, we have DF_INSN_LUIDs that we can rely on at this point, so 
we check those and if we find the reaching def follows the extension 
within the block, we don't try to apply the transformation.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu.

OK for the trunk?



-------------- next part --------------
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a125517..73d1217 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-10  Jeff Law  <law@redhat.com>
+
+	PR middle-end/59743
+	* ree.c (combine_reaching_defs): Ensure the defining statement
+	occurs before the extension when optimizing extensions with
+	different source and destination hard registers.
+
 2014-01-09  Rong Xu  <xur@google.com>
 
 	* libgcc/libgcov-driver.c (this_prg): make it local to save
diff --git a/gcc/ree.c b/gcc/ree.c
index 1c4f3ad..bd0fdc6 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -711,8 +711,10 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
 
       /* The defining statement and candidate insn must be in the same block.
 	 This is merely to keep the test for safety and updating the insn
-	 stream simple.  */
-      if (BLOCK_FOR_INSN (cand->insn) != BLOCK_FOR_INSN (def_insn))
+	 stream simple.  Also ensure that within the block the candidate
+	 follows the defining insn.  */
+      if (BLOCK_FOR_INSN (cand->insn) != BLOCK_FOR_INSN (def_insn)
+	  || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
 	return false;
 
       /* If there is an overlap between the destination of DEF_INSN and
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index acb1637..2ec5644 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-10  Jeff Law  <law@redhat.com>
+
+	PR middle-end/59743
+	* gcc.c-torture/compile/pr59743.c: New test.
+
 2014-10-09  Jakub Jelinek  <jakub@redhat.com>
 
 	PR sanitizer/59136
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59743.c b/gcc/testsuite/gcc.c-torture/compile/pr59743.c
new file mode 100644
index 0000000..f1b75b8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr59743.c
@@ -0,0 +1,22 @@
+
+typedef union {
+  long all;
+  struct {
+    int low;
+    int high;
+  } s;
+} udwords;
+int a, b, c, d;
+void __udivmoddi4() {
+  udwords r;
+  d = __builtin_clz(0);
+  r.s.low = 0;
+  for (; d; --d) {
+    r.s.high = r.s.high << 1 | r.s.low >> a;
+    r.s.low = r.s.low << b >> 1;
+    int s = -r.all;
+    c = s;
+    r.all--;
+  }
+}
+


More information about the Gcc-patches mailing list