[llvm] Extending LoopVersioningLICM to handle cases where loopbound is invariant (PR #192902)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 02:14:50 PDT 2026
================
@@ -213,12 +232,124 @@ bool LoopVersioningLICM::legalLoopStructure() {
// to generate the bound checks.
const SCEV *ExitCount = SE->getBackedgeTakenCount(CurLoop);
if (isa<SCEVCouldNotCompute>(ExitCount)) {
+ IsDynamicBound = true;
LLVM_DEBUG(dbgs() << " loop does not have trip count\n");
+ LLVM_DEBUG(dbgs() << " checking the possibility of dynamic trip count\n");
+
+ HoistedDependencies.clear();
+
+ // Check if the loop trip count is dynamic
+ BasicBlock *ExitBlock = CurLoop->getExitingBlock();
+ assert(ExitBlock && "Exiting block guaranteed by earlier getExitingBlock() check");
+ CondBrInst *ExitBranch = dyn_cast<CondBrInst>(ExitBlock->getTerminator());
+ if (!ExitBranch) {
+ LLVM_DEBUG(dbgs() << " loop exit condition is not a conditional branch\n");
+ return false;
+ }
+ ICmpInst *ExitCmp = dyn_cast<ICmpInst>(ExitBranch->getCondition());
+ if (!ExitCmp) {
+ LLVM_DEBUG(dbgs() << " loop exit condition is not an icmp instruction\n");
+ return false;
+ }
+
+ PHINode *IndVar = CurLoop->getInductionVariable(*SE);
+ if (!IndVar) {
+ LLVM_DEBUG(dbgs() << " unable to find loop induction variable\n");
+ return false;
+ }
+ LLVM_DEBUG(dbgs() << " Induction variable: " << *IndVar << "\n");
+
+ Value *StepInst = IndVar->getIncomingValueForBlock(CurLoop->getLoopLatch());
+
+ auto IsIVOrStep = [&](Value *V) {
+ return V == IndVar || V == StepInst;
+ };
+
+ Value *DynamicUpperBound = nullptr;
+ if (IsIVOrStep(ExitCmp->getOperand(0))) {
+ DynamicUpperBound = ExitCmp->getOperand(1);
+ }
+ else if (IsIVOrStep(ExitCmp->getOperand(1))) {
+ DynamicUpperBound = ExitCmp->getOperand(0);
+ }
+ else {
+ LLVM_DEBUG(dbgs() << " unable to identify dynamic bound operand\n");
+ return false;
+ }
+ LLVM_DEBUG(dbgs() << " Dynamic upper bound: " << *DynamicUpperBound
+ << "\n");
+
+ SmallVector<Instruction *, 16> Worklist;
+
+ SmallPtrSet<Value *, 16> ModifiedPtrs;
+ for (BasicBlock *BB : CurLoop->getBlocks()) {
+ for (Instruction &I : *BB) {
+ if (StoreInst *SI = dyn_cast<StoreInst>(&I))
+ ModifiedPtrs.insert(SI->getPointerOperand());
+ }
+ }
+
+ if (Instruction *I = dyn_cast<Instruction>(DynamicUpperBound)) {
+ Worklist.push_back(I);
+ }
+
+ SmallPtrSet<Instruction *, 16> Visited;
+
+ while(!Worklist.empty()) {
+ Instruction *I = Worklist.pop_back_val();
+ if (!Visited.insert(I).second)
+ continue;
+
+ if (!CurLoop->contains(I->getParent()))
+ continue;
+
+ if (!isSafeToHoistBoundDep(I, ModifiedPtrs))
+ return false;
+
+ for (Use &U : I->operands()) {
+ if (Instruction *OpI = dyn_cast<Instruction>(U.get())) {
+ if (CurLoop->contains(OpI)) {
+ Worklist.push_back(OpI);
+ }
+ }
+ }
+
+ HoistedDependencies.push_back(I);
+ }
+ return true;
----------------
artagnon wrote:
```suggestion
```
There's already a `return true` at the end?
https://github.com/llvm/llvm-project/pull/192902
More information about the llvm-commits
mailing list