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

Jeff Law law@redhat.com
Fri Feb 26 07:50:00 GMT 2016


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

-------------- next part --------------
	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();
+  }
+}


More information about the Gcc-patches mailing list