This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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



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?



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--;
+  }
+}
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]