The testcase shows that when cleaning up the CFG we can end up
with broken LC SSA (for virtual operands with the testcase).  The
case here involves deleting a loop after which it is not enough
to scan the blocks with changed loop depth for SSA uses that need
to be rewritten.  So make fix_loop_sturcture return the sum of
the number of new loops and the number of deleted loops.

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

        PR tree-optimization/106182
        * loop-init.cc (fix_loop_structure): Return the number
        of newly discovered plus the number of deleted loops.
        * tree-cfgcleanup.cc (repair_loop_structures): Adjust
        variable name.

        * gcc.dg/torture/pr106182.c: New testcase.
---
 gcc/loop-init.cc                        | 10 +++++-----
 gcc/testsuite/gcc.dg/torture/pr106182.c | 18 ++++++++++++++++++
 gcc/tree-cfgcleanup.cc                  |  6 +++---
 3 files changed, 26 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr106182.c

diff --git a/gcc/loop-init.cc b/gcc/loop-init.cc
index 648aa290916..b9e07973dd6 100644
--- a/gcc/loop-init.cc
+++ b/gcc/loop-init.cc
@@ -194,7 +194,7 @@ loop_fini_done:
    If CHANGED_BBS is not NULL, basic blocks whose loop depth has changed are
    marked in it.
 
-   Returns the number of new discovered loops.  */
+   Returns the number of new discovered plus the number of removed loops.  */
 
 unsigned
 fix_loop_structure (bitmap changed_bbs)
@@ -277,7 +277,7 @@ fix_loop_structure (bitmap changed_bbs)
     }
 
   /* Finally free deleted loops.  */
-  bool any_deleted = false;
+  unsigned n_deleted = 0;
   class loop *loop;
   FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop)
     if (loop && loop->header == NULL)
@@ -311,12 +311,12 @@ fix_loop_structure (bitmap changed_bbs)
          }
        (*get_loops (cfun))[i] = NULL;
        flow_loop_free (loop);
-       any_deleted = true;
+       n_deleted++;
       }
 
   /* If we deleted loops then the cached scalar evolutions refering to
      those loops become invalid.  */
-  if (any_deleted && scev_initialized_p ())
+  if (n_deleted > 0 && scev_initialized_p ())
     scev_reset_htab ();
 
   loops_state_clear (LOOPS_NEED_FIXUP);
@@ -328,7 +328,7 @@ fix_loop_structure (bitmap changed_bbs)
 
   timevar_pop (TV_LOOP_INIT);
 
-  return number_of_loops (cfun) - old_nloops;
+  return number_of_loops (cfun) - old_nloops + n_deleted;
 }
 
 /* The RTL loop superpass.  The actual passes are subpasses.  See passes.cc for
diff --git a/gcc/testsuite/gcc.dg/torture/pr106182.c 
b/gcc/testsuite/gcc.dg/torture/pr106182.c
new file mode 100644
index 00000000000..6b5c2493fd6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr106182.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-funswitch-loops" } */
+
+short var_32;
+int test_var_0;
+unsigned char test_var_6;
+char test_var_13;
+void test(int var_2)
+{
+  for (;;)
+    for (short i_7; i_7 < test_var_13; i_7 += 1)
+      for (; test_var_0;) {
+        for (; var_2;)
+          var_32 = 0;
+        for (char i_19; i_19 < test_var_6 + 135; i_19 += 200)
+          ;
+      }
+}
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index a6d0bf2c40a..3b24e021b6b 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -1170,13 +1170,13 @@ static void
 repair_loop_structures (void)
 {
   bitmap changed_bbs;
-  unsigned n_new_loops;
+  unsigned n_new_or_deleted_loops;
 
   calculate_dominance_info (CDI_DOMINATORS);
 
   timevar_push (TV_REPAIR_LOOPS);
   changed_bbs = BITMAP_ALLOC (NULL);
-  n_new_loops = fix_loop_structure (changed_bbs);
+  n_new_or_deleted_loops = fix_loop_structure (changed_bbs);
 
   /* This usually does nothing.  But sometimes parts of cfg that originally
      were inside a loop get out of it due to edge removal (since they
@@ -1184,7 +1184,7 @@ repair_loop_structures (void)
      irreducible loop can become reducible - in this case force a full
      rewrite into loop-closed SSA form.  */
   if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
-    rewrite_into_loop_closed_ssa (n_new_loops ? NULL : changed_bbs,
+    rewrite_into_loop_closed_ssa (n_new_or_deleted_loops ? NULL : changed_bbs,
                                  TODO_update_ssa);
 
   BITMAP_FREE (changed_bbs);
-- 
2.35.3

Reply via email to