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]

Re: [PATCH] [RFA] [PR tree-optmization/69740] Schedule loop fixups when needed


On 02/25/2016 03:00 AM, Richard Biener wrote:

So I fail to see how only successor edges are relevant.  Isn't the important
case to catch whether we remove an edge marked EDGE_IRREDUCIBLE_LOOP?
Even if the BB persists we might have exposed a new loop here.

Note that it is not safe to look at {BB,EDGE}_IRREDUCIBLE_LOOP if the loop
state does not have LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS set
(the flags may be stale or missing).  So it might be that we can't rely on
non-loop passes modifying the CFG to handle this optimistically.

Thus, how about (my main point) moving this to remove_edge instead, like
Yea. That works. The !loops_state_satisfies_p check will almost certainly cause us to trigger loop cleanups more often, but I think it's the right/safe thing to do to catch cases where we haven't go the IRREDUCIBLE_LOOP flags set.


Bootstrapped and regression tested on x86_64-linux-gnu.  OK for the trunk?

Thanks,
Jeff

	PR tree-optimization/69740
	* cfghooks.c (remove_edge): Request loop fixups if we delete
	an edge that might turn an irreducible loop into a natural
	loop.

	PR tree-optimization/69740
	* gcc.c-torture/compile/pr69740-1.c: New test.
	* gcc.c-torture/compile/pr69740-2.c: New test.

diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index bbb1017..f80e455 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -408,7 +408,14 @@ void
 remove_edge (edge e)
 {
   if (current_loops != NULL)
-    rescan_loop_exit (e, false, true);
+    {
+      rescan_loop_exit (e, false, true);
+
+      if (!loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+	  || (e->flags & EDGE_IRREDUCIBLE_LOOP)
+	  || (e->dest->flags & BB_IRREDUCIBLE_LOOP))
+	loops_state_set (LOOPS_NEED_FIXUP);
+    }
 
   /* This is probably not needed, but it doesn't hurt.  */
   /* FIXME: This should be called via a remove_edge hook.  */
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c
new file mode 100644
index 0000000..ac867d8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c
@@ -0,0 +1,12 @@
+char a;
+short b;
+void fn1() {
+  if (b)
+    ;
+  else {
+    int c[1] = {0};
+  l1:;
+  }
+  if (a)
+    goto l1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c
new file mode 100644
index 0000000..a89c9a0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c
@@ -0,0 +1,19 @@
+inline int foo(int *p1, int p2) {
+  int z = *p1;
+  while (z > p2)
+    p2 = 2;
+  return z;
+}
+int main() {
+  int i;
+  for (;;) {
+    int j, k;
+    i = foo(&k, 7);
+    if (k)
+      j = i;
+    else
+      k = j;
+    if (2 != j)
+      __builtin_abort();
+  }
+}

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