[llvm] [LoopInterchange] Also look at lcssa phis in outer loop latch block (PR #160889)

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 2 05:26:42 PDT 2025


================
@@ -1837,6 +1838,38 @@ static void moveLCSSAPhis(BasicBlock *InnerExit, BasicBlock *InnerHeader,
   for (PHINode *P : LcssaInnerLatch)
     P->moveBefore(InnerExit->getFirstNonPHIIt());
 
+  // This deals with a corner case of LCSSA phi nodes in the outer loop latch
+  // block: the loop was in LCSSA form, some transformations can come along
+  // (e.g. unswitch) and create an empty block:
+  //
+  //   BB4:
+  //     br label %BB5
+  //   BB5:
+  //     %old.cond.lcssa = phi i16 [ %cond, %BB4 ]
+  //     br outer.header
+  //
+  // Interchange then brings it in LCSSA form again and we get:
+  //
+  //   BB4:
+  //     %new.cond.lcssa = phi i16 [ %cond, %BB3 ]
+  //     br label %BB5
+  //   BB5:
+  //     %old.cond.lcssa = phi i16 [ %new.cond.lcssa, %BB4 ]
+  //
+  // Which means that we have a chain of LCSSA phi nodes from %new.cond.lcssa
+  // to %old.cond.lcssa. The problem is that interchange can reoder blocks BB4
+  // and BB5 placing the use before the def if we don't check this. The
+  // observation is that %old.cond.lcssa is unused, so instead of moving and
+  // renaming these phi nodes, just delete it if it's trivially dead. If it
+  // isn't trivially dead, it is handled above. The loop should still be in
+  // LCSSA form, and if it isn't, formLCSSARecursively is called after the
+  // interchange rewrite.
+  SmallVector<PHINode *, 8> LcssaOuterLatch(
+      llvm::make_pointer_range(OuterLatch->phis()));
----------------
Meinersbur wrote:

Consider iterating over `OuterLatch->phis()`, and only adding those instructions to the list to be erased. That's the more established pattern. 

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


More information about the llvm-commits mailing list