https://gcc.gnu.org/g:8ee6631540ca9d5c437ce4bf3236d6d6ae22c475

commit r13-9514-g8ee6631540ca9d5c437ce4bf3236d6d6ae22c475
Author: Richard Biener <rguent...@suse.de>
Date:   Mon Feb 3 15:12:52 2025 +0100

    tree-optimization/117113 - ICE with unroll-and-jam
    
    When there's an inner loop without virtual header PHI but the outer
    loop has one the fusion process cannot handle the need to create
    an inner loop virtual header PHI.  Punt in this case.
    
            PR tree-optimization/117113
            * gimple-loop-jam.cc (unroll_jam_possible_p): Detect when
            we cannot handle virtual SSA update.
    
            * gcc.dg/torture/pr117113.c: New testcase.
    
    (cherry picked from commit 0675eb17480bada678bf2769d39732027abcd6d0)

Diff:
---
 gcc/gimple-loop-jam.cc                  | 12 +++++++++++-
 gcc/testsuite/gcc.dg/torture/pr117113.c | 20 ++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/gcc/gimple-loop-jam.cc b/gcc/gimple-loop-jam.cc
index c6b2fc28d1c3..19aa4b68d073 100644
--- a/gcc/gimple-loop-jam.cc
+++ b/gcc/gimple-loop-jam.cc
@@ -279,13 +279,17 @@ unroll_jam_possible_p (class loop *outer, class loop 
*loop)
      body would be the after-iter value of the first body) if it's over
      an associative and commutative operation.  We wouldn't
      be able to handle unknown cycles.  */
+  bool inner_vdef = false;
   for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
     {
       affine_iv iv;
       tree op = gimple_phi_result (psi.phi ());
 
       if (virtual_operand_p (op))
-       continue;
+       {
+         inner_vdef = true;
+         continue;
+       }
       if (!simple_iv (loop, loop, op, &iv, true))
        return false;
       /* The inductions must be regular, loop invariant step and initial
@@ -301,6 +305,12 @@ unroll_jam_possible_p (class loop *outer, class loop *loop)
         copy, _not_ the next value of the second body.  */
     }
 
+  /* When there's no inner loop virtual PHI IV we cannot handle the update
+     required to the inner loop if that doesn't already have one.  See
+     PR117113.  */
+  if (!inner_vdef && get_virtual_phi (outer->header))
+    return false;
+
   return true;
 }
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr117113.c 
b/gcc/testsuite/gcc.dg/torture/pr117113.c
new file mode 100644
index 000000000000..e90ad034a4d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117113.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-dce -fno-inline" } */
+
+int a, b, c;
+volatile int d[1];
+void e() {}
+void f(int g) {}
+int main() {
+  int i;
+  for (; b; b--) {
+    for (i = 0; i < 3; i++) {
+      e();
+      f(d[0]);
+      d[0];
+    }
+    if (a)
+      c++;
+  }
+  return 0;
+}

Reply via email to