[llvm] [LoopInterchange] Reject inner-latch lcssa PHI feeding the exit condition (PR #202863)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 12 04:47:42 PDT 2026


================
@@ -1452,36 +1437,47 @@ static bool areOuterLoopExitPHIsSupported(Loop *OuterLoop, Loop *InnerLoop) {
   return true;
 }
 
-// In case of multi-level nested loops, it may occur that lcssa phis exist in
-// the latch of InnerLoop, i.e., when defs of the incoming values are further
-// inside the loopnest. Sometimes those incoming values are not available
-// after interchange, since the original inner latch will become the new outer
-// latch which may have predecessor paths that do not include those incoming
-// values.
+// In a multi-level nest the inner loop induction PHI lives in the header, so
+// any PHI in the inner latch is an lcssa phi whose incoming value is defined
+// further inside the nest. Interchange clones the latch's exit condition, so if
+// such a phi feeds that condition, a later interchange can leave the cloned phi
+// with a stale incoming block, producing invalid IR. Reject that case.
+//
+// For example, the inner latch is also the sub-loop's exit, %p is the lcssa phi
+// for the sub-loop value %v, and the inner loop's exit test reads %p, so %p
+// feeds the cloned condition:
+//
+//   inner.latch:
+//     %p  = phi i64 [ %v, %subloop.latch ]   ; lcssa: %v comes from sub-loop
+//     %ec = icmp eq i64 %iv, %p              ; inner exit test reads %p
+//     br i1 %ec, label %exit, label %inner.header
+//
 // TODO: Handle transformation of lcssa phis in the InnerLoop latch in case of
 // multi-level loop nests.
----------------
kasuga-fj wrote:

```suggestion
/// In a multi-level nest the inner loop induction PHI lives in the header, so
/// any PHI in the inner latch is an lcssa phi whose incoming value is defined
/// further inside the nest. Interchange clones the latch's exit condition, so if
/// such a phi feeds that condition, a later interchange can leave the cloned phi
/// with a stale incoming block, producing invalid IR. Reject that case.
///
/// For example, the inner latch is also the sub-loop's exit, %p is the lcssa phi
/// for the sub-loop value %v, and the inner loop's exit test reads %p, so %p
/// feeds the cloned condition:
///
///   inner.latch:
///     %p  = phi i64 [ %v, %subloop.latch ]   ; lcssa: %v comes from sub-loop
///     %ec = icmp eq i64 %iv, %p              ; inner exit test reads %p
///     br i1 %ec, label %exit, label %inner.header
///
/// TODO: Handle transformation of lcssa phis in the InnerLoop latch in case of
/// multi-level loop nests.
```

This has been around for a while, but I think this is a good opportunity to fix it.

---

By the way,

```cpp
/// In a multi-level nest the inner loop induction PHI lives in the header, so
/// any PHI in the inner latch is an lcssa phi whose incoming value is defined
/// further inside the nest.
```

I don't think this is correct. If I remember correctly, an inner loops like below should be allowed.

```llvm
inner.header:
  %iv = phi ...
  %cond = ...
  br i1 %cond, label %inner.inner.header, label %inner.latch
...
```

https://github.com/llvm/llvm-project/pull/202863


More information about the llvm-commits mailing list