re PR rtl-optimization/87468 (ice "wrong amount of branch edges after conditional...
authorJeff Law <law@redhat.com>
Sat, 24 Nov 2018 06:51:26 +0000 (23:51 -0700)
committerJeff Law <law@gcc.gnu.org>
Sat, 24 Nov 2018 06:51:26 +0000 (23:51 -0700)
PR rtl-optimization/87468
* tree-ssa-threadupdate.c (create_block_for_threading): Clear
EDGE_IGNORE on all outgoing edges of the duplicate block.

From-SVN: r266426

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr87468.c [new file with mode: 0644]
gcc/tree-ssa-threadupdate.c

index b0b85bac352e6e41f02f45a2795d4a5dd3ad9185..f9a12f88a609617e09b668ae816eed98b09e7dbd 100644 (file)
@@ -1,3 +1,9 @@
+2018-11-23  Jeff Law  <law@redhat.com>
+
+       PR rtl-optimization/87468
+       * tree-ssa-threadupdate.c (create_block_for_threading): Clear
+       EDGE_IGNORE on all outgoing edges of the duplicate block.
+
 2018-11-23  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR bootstrap/88157
index e31d40d7924fcecd62a24a22519033f472ab97ff..587526e7443bff9002661773767aba7ae1e4874a 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-23  Jeff Law  <law@redhat.com>
+
+       PR rtl-optimization/84768
+       * gcc.c-torture/compile/pr84768.c: New test.
+
 2018-11-23  Vladimir Makarov  <vmakarov@redhat.com>
 
        * gcc.target/powerpc/pr70669.c: Use unary minus instead of
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr87468.c b/gcc/testsuite/gcc.c-torture/compile/pr87468.c
new file mode 100644 (file)
index 0000000..2f5cf80
--- /dev/null
@@ -0,0 +1,15 @@
+a;
+b() {
+  int c = 1;
+  for (; c <= 3;) {
+    int d = e() && !0;
+    switch (c)
+    case 1:
+      if (d)
+      case 2:
+      case 3:
+        f();
+    if (a)
+      c++;
+  }
+}
index 6630516b99a10f0a087958f33c9b12278c0632b2..e7c7ca6fb1591527f9561157a8592297a700bcc1 100644 (file)
@@ -336,7 +336,17 @@ create_block_for_threading (basic_block bb,
   rd->dup_blocks[count] = duplicate_block (bb, NULL, NULL);
 
   FOR_EACH_EDGE (e, ei, rd->dup_blocks[count]->succs)
-    e->aux = NULL;
+    {
+      e->aux = NULL;
+
+      /* If we duplicate a block with an outgoing edge marked as
+        EDGE_IGNORE, we must clear EDGE_IGNORE so that it doesn't
+        leak out of the current pass.
+
+        It would be better to simplify switch statements and remove
+        the edges before we get here, but the sequencing is nontrivial.  */
+      e->flags &= ~EDGE_IGNORE;
+    }
 
   /* Zero out the profile, since the block is unreachable for now.  */
   rd->dup_blocks[count]->count = profile_count::uninitialized ();