Per Richi's suggestion in the PR, making an irreducible region
reducible is a good thing, so instead of preventing it just let loop
fixup discover the new loop: set LOOPS_NEED_FIXUP when we changed the
CFG, and drop preserves_loop_structure_p in favor of never duplicating
a loop header.

OK pending tests?

        PR tree-optimization/127085

gcc/ChangeLog:

        * tree-ssa-phiopt.cc (preserves_loop_structure_p): Remove.
        (replicate_cond_into_pred): Refuse only loop headers.
        (replicate_conds_over_phis): Do not mark back edges; set
        LOOPS_NEED_FIXUP when the CFG changed.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/pr127085.c: New test.
---
 gcc/testsuite/gcc.dg/torture/pr127085.c | 22 +++++++++++++++++
 gcc/tree-ssa-phiopt.cc                  | 33 ++++++-------------------
 2 files changed, 30 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr127085.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr127085.c 
b/gcc/testsuite/gcc.dg/torture/pr127085.c
new file mode 100644
index 00000000000..22f01159736
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127085.c
@@ -0,0 +1,22 @@
+/* PR tree-optimization/127085 */
+/* { dg-do compile } */
+
+typedef unsigned char uint8_t;
+typedef unsigned long long uint64_t;
+uint8_t g26;
+_Bool f19_c7, f19_c15;
+void f19(uint64_t a0)
+{
+    _Bool c4;
+lbl_sw3:
+    if (f19_c7) goto lbl_bf30;
+    goto lbl_cont19;
+lbl_sw14:
+    if (c4)
+    lbl_cont19:
+        if (f19_c15) goto lbl_sw14;
+    goto lbl_sw3;
+lbl_bf30:
+    c4 = g26;
+    if (a0 == 80504447930037642) goto lbl_sw14;
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index f8dbd26abc1..1540fe34b86 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -4872,29 +4872,6 @@ execute_over_cond_phis (func_type func)
 
    where left and right are typically adjacent pointers in a tree structure.  
*/
 
-/* Return TRUE if duplicating E's destination with E redirected to
-   the copy leaves the loop structure unchanged.  Requires
-   EDGE_DFS_BACK to be current.  */
-
-static bool
-preserves_loop_structure_p (edge e)
-{
-  basic_block bb = e->dest;
-
-  if ((e->flags & EDGE_DFS_BACK)
-      || e->src->loop_father != bb->loop_father)
-    return false;
-
-  edge s;
-  edge_iterator ei;
-  FOR_EACH_EDGE (s, ei, bb->succs)
-    if ((s->flags & EDGE_DFS_BACK)
-       || s->dest->loop_father != bb->loop_father)
-      return false;
-
-  return true;
-}
-
 /* Replicate the join block at E's destination into E's source.  The copy's
    PHIs degenerate to their argument on E, so the copied conditional tests the
    predecessor's own value.  The net effect after cleanups, for edge (3, 5)
@@ -4919,8 +4896,9 @@ replicate_cond_into_pred (edge e)
 {
   basic_block bb = e->dest;
 
+  /* Never duplicate loop headers.  */
   if (!can_duplicate_block_on_edge_p (e)
-      || !preserves_loop_structure_p (e))
+      || bb->loop_father->header == bb)
     return false;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4958,7 +4936,6 @@ replicate_conds_over_phis (void)
   bool cfgchanged = false;
   basic_block bb;
 
-  mark_dfs_back_edges ();
   initialize_original_copy_tables ();
   FOR_EACH_BB_FN (bb, cfun)
     {
@@ -4980,6 +4957,12 @@ replicate_conds_over_phis (void)
        }
     }
   free_original_copy_tables ();
+
+  /* Removing an entry of an irreducible region can make it reducible, creating
+     a new loop.  */
+  if (cfgchanged)
+    loops_state_set (LOOPS_NEED_FIXUP);
+
   return cfgchanged;
 }
 
-- 
2.47.3

Reply via email to