]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/118552 - failed LC SSA update after unrolling
authorRichard Biener <rguenther@suse.de>
Mon, 20 Jan 2025 10:50:53 +0000 (11:50 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 20 Jan 2025 12:14:23 +0000 (13:14 +0100)
When unrolling changes nesting relationship of loops we fail to
mark blocks as in need to change for LC SSA update.  Specifically
the LC SSA PHI on a former inner loop exit might be misplaced
if that loop becomes a sibling of its outer loop.

PR tree-optimization/118552
* cfgloopmanip.cc (fix_loop_placement): Properly mark
exit source blocks as to be scanned for LC SSA update when
the loops nesting relationship changed.
(fix_loop_placements): Adjust.
(fix_bb_placements): Likewise.

* gcc.dg/torture/pr118552.c: New testcase.

gcc/cfgloopmanip.cc
gcc/testsuite/gcc.dg/torture/pr118552.c [new file with mode: 0644]

index 17bcf9f4acc4f592209a0909353495491bfd333c..573146b2e28497071757ca9c715c497eb7004d94 100644 (file)
@@ -123,7 +123,8 @@ fix_bb_placement (basic_block bb)
    invalidate the information about irreducible regions.  */
 
 static bool
-fix_loop_placement (class loop *loop, bool *irred_invalidated)
+fix_loop_placement (class loop *loop, bool *irred_invalidated,
+                   bitmap loop_closed_ssa_invalidated)
 {
   unsigned i;
   edge e;
@@ -153,6 +154,10 @@ fix_loop_placement (class loop *loop, bool *irred_invalidated)
          if (e->flags & EDGE_IRREDUCIBLE_LOOP)
            *irred_invalidated = true;
          rescan_loop_exit (e, false, false);
+         /* Any LC SSA PHIs on e->dest might now be on the wrong edge
+            if their defs were in a former outer loop.  */
+         if (loop_closed_ssa_invalidated)
+           bitmap_set_bit (loop_closed_ssa_invalidated, e->src->index);
        }
 
       ret = true;
@@ -224,7 +229,8 @@ fix_bb_placements (basic_block from,
       if (from->loop_father->header == from)
        {
          /* Subloop header, maybe move the loop upward.  */
-         if (!fix_loop_placement (from->loop_father, irred_invalidated))
+         if (!fix_loop_placement (from->loop_father, irred_invalidated,
+                                  loop_closed_ssa_invalidated))
            continue;
          target_loop = loop_outer (from->loop_father);
          if (loop_closed_ssa_invalidated)
@@ -1057,7 +1063,8 @@ fix_loop_placements (class loop *loop, bool *irred_invalidated,
   while (loop_outer (loop))
     {
       outer = loop_outer (loop);
-      if (!fix_loop_placement (loop, irred_invalidated))
+      if (!fix_loop_placement (loop, irred_invalidated,
+                              loop_closed_ssa_invalidated))
        break;
 
       /* Changing the placement of a loop in the loop tree may alter the
diff --git a/gcc/testsuite/gcc.dg/torture/pr118552.c b/gcc/testsuite/gcc.dg/torture/pr118552.c
new file mode 100644 (file)
index 0000000..03ee0d0
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-ch -fno-tree-ccp -fno-tree-fre" } */
+
+volatile int a;
+int b, c, d, e;
+int main() {
+  int f = 1, g = 1;
+h:
+  if (!d)
+    ;
+  else {
+    int i = 1;
+  j:
+    e = 0;
+    for (; e < 3; e++) {
+      if (e)
+        for (; g < 2; g++) {
+          if (c)
+            return 0;
+          if (f)
+            goto j;
+        }
+      a;
+      if (i)
+        continue;
+      f = i = 0;
+    }
+  }
+  f = 2;
+  b++;
+  if (c)
+    goto h;
+  return 0;
+}