| //===------- LoopBoundSplit.cpp - Split Loop Bound --------------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Transforms/Scalar/LoopBoundSplit.h" | |
| #include "llvm/ADT/Sequence.h" | |
| #include "llvm/Analysis/LoopAnalysisManager.h" | |
| #include "llvm/Analysis/LoopInfo.h" | |
| #include "llvm/Analysis/ScalarEvolution.h" | |
| #include "llvm/Analysis/ScalarEvolutionExpressions.h" | |
| #include "llvm/IR/PatternMatch.h" | |
| #include "llvm/Transforms/Scalar/LoopPassManager.h" | |
| #include "llvm/Transforms/Utils/BasicBlockUtils.h" | |
| #include "llvm/Transforms/Utils/Cloning.h" | |
| #include "llvm/Transforms/Utils/LoopSimplify.h" | |
| #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" | |
| #define DEBUG_TYPE "loop-bound-split" | |
| namespace llvm { | |
| using namespace PatternMatch; | |
| namespace { | |
| struct ConditionInfo { | |
| /// Branch instruction with this condition | |
| BranchInst *BI = nullptr; | |
| /// ICmp instruction with this condition | |
| ICmpInst *ICmp = nullptr; | |
| /// Preciate info | |
| ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE; | |
| /// AddRec llvm value | |
| Value *AddRecValue = nullptr; | |
| /// Non PHI AddRec llvm value | |
| Value *NonPHIAddRecValue; | |
| /// Bound llvm value | |
| Value *BoundValue = nullptr; | |
| /// AddRec SCEV | |
| const SCEVAddRecExpr *AddRecSCEV = nullptr; | |
| /// Bound SCEV | |
| const SCEV *BoundSCEV = nullptr; | |
| ConditionInfo() = default; | |
| }; | |
| } // namespace | |
| static void analyzeICmp(ScalarEvolution &SE, ICmpInst *ICmp, | |
| ConditionInfo &Cond, const Loop &L) { | |
| Cond.ICmp = ICmp; | |
| if (match(ICmp, m_ICmp(Cond.Pred, m_Value(Cond.AddRecValue), | |
| m_Value(Cond.BoundValue)))) { | |
| const SCEV *AddRecSCEV = SE.getSCEV(Cond.AddRecValue); | |
| const SCEV *BoundSCEV = SE.getSCEV(Cond.BoundValue); | |
| const SCEVAddRecExpr *LHSAddRecSCEV = dyn_cast<SCEVAddRecExpr>(AddRecSCEV); | |
| const SCEVAddRecExpr *RHSAddRecSCEV = dyn_cast<SCEVAddRecExpr>(BoundSCEV); | |
| // Locate AddRec in LHSSCEV and Bound in RHSSCEV. | |
| if (!LHSAddRecSCEV && RHSAddRecSCEV) { | |
| std::swap(Cond.AddRecValue, Cond.BoundValue); | |
| std::swap(AddRecSCEV, BoundSCEV); | |
| Cond.Pred = ICmpInst::getSwappedPredicate(Cond.Pred); | |
| } | |
| Cond.AddRecSCEV = dyn_cast<SCEVAddRecExpr>(AddRecSCEV); | |
| Cond.BoundSCEV = BoundSCEV; | |
| Cond.NonPHIAddRecValue = Cond.AddRecValue; | |
| // If the Cond.AddRecValue is PHI node, update Cond.NonPHIAddRecValue with | |
| // value from backedge. | |
| if (Cond.AddRecSCEV && isa<PHINode>(Cond.AddRecValue)) { | |
| PHINode *PN = cast<PHINode>(Cond.AddRecValue); | |
| Cond.NonPHIAddRecValue = PN->getIncomingValueForBlock(L.getLoopLatch()); | |
| } | |
| } | |
| } | |
| static bool calculateUpperBound(const Loop &L, ScalarEvolution &SE, | |
| ConditionInfo &Cond, bool IsExitCond) { | |
| if (IsExitCond) { | |
| const SCEV *ExitCount = SE.getExitCount(&L, Cond.ICmp->getParent()); | |
| if (isa<SCEVCouldNotCompute>(ExitCount)) | |
| return false; | |
| Cond.BoundSCEV = ExitCount; | |
| return true; | |
| } | |
| // For non-exit condtion, if pred is LT, keep existing bound. | |
| if (Cond.Pred == ICmpInst::ICMP_SLT || Cond.Pred == ICmpInst::ICMP_ULT) | |
| return true; | |
| // For non-exit condition, if pre is LE, try to convert it to LT. | |
| // Range Range | |
| // AddRec <= Bound --> AddRec < Bound + 1 | |
| if (Cond.Pred != ICmpInst::ICMP_ULE && Cond.Pred != ICmpInst::ICMP_SLE) | |
| return false; | |
| if (IntegerType *BoundSCEVIntType = | |
| dyn_cast<IntegerType>(Cond.BoundSCEV->getType())) { | |
| unsigned BitWidth = BoundSCEVIntType->getBitWidth(); | |
| APInt Max = ICmpInst::isSigned(Cond.Pred) | |
| ? APInt::getSignedMaxValue(BitWidth) | |
| : APInt::getMaxValue(BitWidth); | |
| const SCEV *MaxSCEV = SE.getConstant(Max); | |
| // Check Bound < INT_MAX | |
| ICmpInst::Predicate Pred = | |
| ICmpInst::isSigned(Cond.Pred) ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; | |
| if (SE.isKnownPredicate(Pred, Cond.BoundSCEV, MaxSCEV)) { | |
| const SCEV *BoundPlusOneSCEV = | |
| SE.getAddExpr(Cond.BoundSCEV, SE.getOne(BoundSCEVIntType)); | |
| Cond.BoundSCEV = BoundPlusOneSCEV; | |
| Cond.Pred = Pred; | |
| return true; | |
| } | |
| } | |
| // ToDo: Support ICMP_NE/EQ. | |
| return false; | |
| } | |
| static bool hasProcessableCondition(const Loop &L, ScalarEvolution &SE, | |
| ICmpInst *ICmp, ConditionInfo &Cond, | |
| bool IsExitCond) { | |
| analyzeICmp(SE, ICmp, Cond, L); | |
| // The BoundSCEV should be evaluated at loop entry. | |
| if (!SE.isAvailableAtLoopEntry(Cond.BoundSCEV, &L)) | |
| return false; | |
| // Allowed AddRec as induction variable. | |
| if (!Cond.AddRecSCEV) | |
| return false; | |
| if (!Cond.AddRecSCEV->isAffine()) | |
| return false; | |
| const SCEV *StepRecSCEV = Cond.AddRecSCEV->getStepRecurrence(SE); | |
| // Allowed constant step. | |
| if (!isa<SCEVConstant>(StepRecSCEV)) | |
| return false; | |
| ConstantInt *StepCI = cast<SCEVConstant>(StepRecSCEV)->getValue(); | |
| // Allowed positive step for now. | |
| // TODO: Support negative step. | |
| if (StepCI->isNegative() || StepCI->isZero()) | |
| return false; | |
| // Calculate upper bound. | |
| if (!calculateUpperBound(L, SE, Cond, IsExitCond)) | |
| return false; | |
| return true; | |
| } | |
| static bool isProcessableCondBI(const ScalarEvolution &SE, | |
| const BranchInst *BI) { | |
| BasicBlock *TrueSucc = nullptr; | |
| BasicBlock *FalseSucc = nullptr; | |
| ICmpInst::Predicate Pred; | |
| Value *LHS, *RHS; | |
| if (!match(BI, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), | |
| m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) | |
| return false; | |
| if (!SE.isSCEVable(LHS->getType())) | |
| return false; | |
| assert(SE.isSCEVable(RHS->getType()) && "Expected RHS's type is SCEVable"); | |
| if (TrueSucc == FalseSucc) | |
| return false; | |
| return true; | |
| } | |
| static bool canSplitLoopBound(const Loop &L, const DominatorTree &DT, | |
| ScalarEvolution &SE, ConditionInfo &Cond) { | |
| // Skip function with optsize. | |
| if (L.getHeader()->getParent()->hasOptSize()) | |
| return false; | |
| // Split only innermost loop. | |
| if (!L.isInnermost()) | |
| return false; | |
| // Check loop is in simplified form. | |
| if (!L.isLoopSimplifyForm()) | |
| return false; | |
| // Check loop is in LCSSA form. | |
| if (!L.isLCSSAForm(DT)) | |
| return false; | |
| // Skip loop that cannot be cloned. | |
| if (!L.isSafeToClone()) | |
| return false; | |
| BasicBlock *ExitingBB = L.getExitingBlock(); | |
| // Assumed only one exiting block. | |
| if (!ExitingBB) | |
| return false; | |
| BranchInst *ExitingBI = dyn_cast<BranchInst>(ExitingBB->getTerminator()); | |
| if (!ExitingBI) | |
| return false; | |
| // Allowed only conditional branch with ICmp. | |
| if (!isProcessableCondBI(SE, ExitingBI)) | |
| return false; | |
| // Check the condition is processable. | |
| ICmpInst *ICmp = cast<ICmpInst>(ExitingBI->getCondition()); | |
| if (!hasProcessableCondition(L, SE, ICmp, Cond, /*IsExitCond*/ true)) | |
| return false; | |
| Cond.BI = ExitingBI; | |
| return true; | |
| } | |
| static bool isProfitableToTransform(const Loop &L, const BranchInst *BI) { | |
| // If the conditional branch splits a loop into two halves, we could | |
| // generally say it is profitable. | |
| // | |
| // ToDo: Add more profitable cases here. | |
| // Check this branch causes diamond CFG. | |
| BasicBlock *Succ0 = BI->getSuccessor(0); | |
| BasicBlock *Succ1 = BI->getSuccessor(1); | |
| BasicBlock *Succ0Succ = Succ0->getSingleSuccessor(); | |
| BasicBlock *Succ1Succ = Succ1->getSingleSuccessor(); | |
| if (!Succ0Succ || !Succ1Succ || Succ0Succ != Succ1Succ) | |
| return false; | |
| // ToDo: Calculate each successor's instruction cost. | |
| return true; | |
| } | |
| static BranchInst *findSplitCandidate(const Loop &L, ScalarEvolution &SE, | |
| ConditionInfo &ExitingCond, | |
| ConditionInfo &SplitCandidateCond) { | |
| for (auto *BB : L.blocks()) { | |
| // Skip condition of backedge. | |
| if (L.getLoopLatch() == BB) | |
| continue; | |
| auto *BI = dyn_cast<BranchInst>(BB->getTerminator()); | |
| if (!BI) | |
| continue; | |
| // Check conditional branch with ICmp. | |
| if (!isProcessableCondBI(SE, BI)) | |
| continue; | |
| // Skip loop invariant condition. | |
| if (L.isLoopInvariant(BI->getCondition())) | |
| continue; | |
| // Check the condition is processable. | |
| ICmpInst *ICmp = cast<ICmpInst>(BI->getCondition()); | |
| if (!hasProcessableCondition(L, SE, ICmp, SplitCandidateCond, | |
| /*IsExitCond*/ false)) | |
| continue; | |
| if (ExitingCond.BoundSCEV->getType() != | |
| SplitCandidateCond.BoundSCEV->getType()) | |
| continue; | |
| // After transformation, we assume the split condition of the pre-loop is | |
| // always true. In order to guarantee it, we need to check the start value | |
| // of the split cond AddRec satisfies the split condition. | |
| if (!SE.isLoopEntryGuardedByCond(&L, SplitCandidateCond.Pred, | |
| SplitCandidateCond.AddRecSCEV->getStart(), | |
| SplitCandidateCond.BoundSCEV)) | |
| continue; | |
| SplitCandidateCond.BI = BI; | |
| return BI; | |
| } | |
| return nullptr; | |
| } | |
| static bool splitLoopBound(Loop &L, DominatorTree &DT, LoopInfo &LI, | |
| ScalarEvolution &SE, LPMUpdater &U) { | |
| ConditionInfo SplitCandidateCond; | |
| ConditionInfo ExitingCond; | |
| // Check we can split this loop's bound. | |
| if (!canSplitLoopBound(L, DT, SE, ExitingCond)) | |
| return false; | |
| if (!findSplitCandidate(L, SE, ExitingCond, SplitCandidateCond)) | |
| return false; | |
| if (!isProfitableToTransform(L, SplitCandidateCond.BI)) | |
| return false; | |
| // Now, we have a split candidate. Let's build a form as below. | |
| // +--------------------+ | |
| // | preheader | | |
| // | set up newbound | | |
| // +--------------------+ | |
| // | /----------------\ | |
| // +--------v----v------+ | | |
| // | header |---\ | | |
| // | with true condition| | | | |
| // +--------------------+ | | | |
| // | | | | |
| // +--------v-----------+ | | | |
| // | if.then.BB | | | | |
| // +--------------------+ | | | |
| // | | | | |
| // +--------v-----------<---/ | | |
| // | latch >----------/ | |
| // | with newbound | | |
| // +--------------------+ | |
| // | | |
| // +--------v-----------+ | |
| // | preheader2 |--------------\ | |
| // | if (AddRec i != | | | |
| // | org bound) | | | |
| // +--------------------+ | | |
| // | /----------------\ | | |
| // +--------v----v------+ | | | |
| // | header2 |---\ | | | |
| // | conditional branch | | | | | |
| // |with false condition| | | | | |
| // +--------------------+ | | | | |
| // | | | | | |
| // +--------v-----------+ | | | | |
| // | if.then.BB2 | | | | | |
| // +--------------------+ | | | | |
| // | | | | | |
| // +--------v-----------<---/ | | | |
| // | latch2 >----------/ | | |
| // | with org bound | | | |
| // +--------v-----------+ | | |
| // | | | |
| // | +---------------+ | | |
| // +--> exit <-------/ | |
| // +---------------+ | |
| // Let's create post loop. | |
| SmallVector<BasicBlock *, 8> PostLoopBlocks; | |
| Loop *PostLoop; | |
| ValueToValueMapTy VMap; | |
| BasicBlock *PreHeader = L.getLoopPreheader(); | |
| BasicBlock *SplitLoopPH = SplitEdge(PreHeader, L.getHeader(), &DT, &LI); | |
| PostLoop = cloneLoopWithPreheader(L.getExitBlock(), SplitLoopPH, &L, VMap, | |
| ".split", &LI, &DT, PostLoopBlocks); | |
| remapInstructionsInBlocks(PostLoopBlocks, VMap); | |
| BasicBlock *PostLoopPreHeader = PostLoop->getLoopPreheader(); | |
| IRBuilder<> Builder(&PostLoopPreHeader->front()); | |
| // Update phi nodes in header of post-loop. | |
| bool isExitingLatch = | |
| (L.getExitingBlock() == L.getLoopLatch()) ? true : false; | |
| Value *ExitingCondLCSSAPhi = nullptr; | |
| for (PHINode &PN : L.getHeader()->phis()) { | |
| // Create LCSSA phi node in preheader of post-loop. | |
| PHINode *LCSSAPhi = | |
| Builder.CreatePHI(PN.getType(), 1, PN.getName() + ".lcssa"); | |
| LCSSAPhi->setDebugLoc(PN.getDebugLoc()); | |
| // If the exiting block is loop latch, the phi does not have the update at | |
| // last iteration. In this case, update lcssa phi with value from backedge. | |
| LCSSAPhi->addIncoming( | |
| isExitingLatch ? PN.getIncomingValueForBlock(L.getLoopLatch()) : &PN, | |
| L.getExitingBlock()); | |
| // Update the start value of phi node in post-loop with the LCSSA phi node. | |
| PHINode *PostLoopPN = cast<PHINode>(VMap[&PN]); | |
| PostLoopPN->setIncomingValueForBlock(PostLoopPreHeader, LCSSAPhi); | |
| // Find PHI with exiting condition from pre-loop. The PHI should be | |
| // SCEVAddRecExpr and have same incoming value from backedge with | |
| // ExitingCond. | |
| if (!SE.isSCEVable(PN.getType())) | |
| continue; | |
| const SCEVAddRecExpr *PhiSCEV = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(&PN)); | |
| if (PhiSCEV && ExitingCond.NonPHIAddRecValue == | |
| PN.getIncomingValueForBlock(L.getLoopLatch())) | |
| ExitingCondLCSSAPhi = LCSSAPhi; | |
| } | |
| // Add conditional branch to check we can skip post-loop in its preheader. | |
| Instruction *OrigBI = PostLoopPreHeader->getTerminator(); | |
| ICmpInst::Predicate Pred = ICmpInst::ICMP_NE; | |
| Value *Cond = | |
| Builder.CreateICmp(Pred, ExitingCondLCSSAPhi, ExitingCond.BoundValue); | |
| Builder.CreateCondBr(Cond, PostLoop->getHeader(), PostLoop->getExitBlock()); | |
| OrigBI->eraseFromParent(); | |
| // Create new loop bound and add it into preheader of pre-loop. | |
| const SCEV *NewBoundSCEV = ExitingCond.BoundSCEV; | |
| const SCEV *SplitBoundSCEV = SplitCandidateCond.BoundSCEV; | |
| NewBoundSCEV = ICmpInst::isSigned(ExitingCond.Pred) | |
| ? SE.getSMinExpr(NewBoundSCEV, SplitBoundSCEV) | |
| : SE.getUMinExpr(NewBoundSCEV, SplitBoundSCEV); | |
| SCEVExpander Expander( | |
| SE, L.getHeader()->getParent()->getParent()->getDataLayout(), "split"); | |
| Instruction *InsertPt = SplitLoopPH->getTerminator(); | |
| Value *NewBoundValue = | |
| Expander.expandCodeFor(NewBoundSCEV, NewBoundSCEV->getType(), InsertPt); | |
| NewBoundValue->setName("new.bound"); | |
| // Replace exiting bound value of pre-loop NewBound. | |
| ExitingCond.ICmp->setOperand(1, NewBoundValue); | |
| // Replace SplitCandidateCond.BI's condition of pre-loop by True. | |
| LLVMContext &Context = PreHeader->getContext(); | |
| SplitCandidateCond.BI->setCondition(ConstantInt::getTrue(Context)); | |
| // Replace cloned SplitCandidateCond.BI's condition in post-loop by False. | |
| BranchInst *ClonedSplitCandidateBI = | |
| cast<BranchInst>(VMap[SplitCandidateCond.BI]); | |
| ClonedSplitCandidateBI->setCondition(ConstantInt::getFalse(Context)); | |
| // Replace exit branch target of pre-loop by post-loop's preheader. | |
| if (L.getExitBlock() == ExitingCond.BI->getSuccessor(0)) | |
| ExitingCond.BI->setSuccessor(0, PostLoopPreHeader); | |
| else | |
| ExitingCond.BI->setSuccessor(1, PostLoopPreHeader); | |
| // Update phi node in exit block of post-loop. | |
| Builder.SetInsertPoint(&PostLoopPreHeader->front()); | |
| for (PHINode &PN : PostLoop->getExitBlock()->phis()) { | |
| for (auto i : seq<int>(0, PN.getNumOperands())) { | |
| // Check incoming block is pre-loop's exiting block. | |
| if (PN.getIncomingBlock(i) == L.getExitingBlock()) { | |
| Value *IncomingValue = PN.getIncomingValue(i); | |
| // Create LCSSA phi node for incoming value. | |
| PHINode *LCSSAPhi = | |
| Builder.CreatePHI(PN.getType(), 1, PN.getName() + ".lcssa"); | |
| LCSSAPhi->setDebugLoc(PN.getDebugLoc()); | |
| LCSSAPhi->addIncoming(IncomingValue, PN.getIncomingBlock(i)); | |
| // Replace pre-loop's exiting block by post-loop's preheader. | |
| PN.setIncomingBlock(i, PostLoopPreHeader); | |
| // Replace incoming value by LCSSAPhi. | |
| PN.setIncomingValue(i, LCSSAPhi); | |
| // Add a new incoming value with post-loop's exiting block. | |
| PN.addIncoming(VMap[IncomingValue], PostLoop->getExitingBlock()); | |
| } | |
| } | |
| } | |
| // Update dominator tree. | |
| DT.changeImmediateDominator(PostLoopPreHeader, L.getExitingBlock()); | |
| DT.changeImmediateDominator(PostLoop->getExitBlock(), PostLoopPreHeader); | |
| // Invalidate cached SE information. | |
| SE.forgetLoop(&L); | |
| // Canonicalize loops. | |
| simplifyLoop(&L, &DT, &LI, &SE, nullptr, nullptr, true); | |
| simplifyLoop(PostLoop, &DT, &LI, &SE, nullptr, nullptr, true); | |
| // Add new post-loop to loop pass manager. | |
| U.addSiblingLoops(PostLoop); | |
| return true; | |
| } | |
| PreservedAnalyses LoopBoundSplitPass::run(Loop &L, LoopAnalysisManager &AM, | |
| LoopStandardAnalysisResults &AR, | |
| LPMUpdater &U) { | |
| Function &F = *L.getHeader()->getParent(); | |
| (void)F; | |
| LLVM_DEBUG(dbgs() << "Spliting bound of loop in " << F.getName() << ": " << L | |
| << "\n"); | |
| if (!splitLoopBound(L, AR.DT, AR.LI, AR.SE, U)) | |
| return PreservedAnalyses::all(); | |
| assert(AR.DT.verify(DominatorTree::VerificationLevel::Fast)); | |
| AR.LI.verify(AR.DT); | |
| return getLoopPassPreservedAnalyses(); | |
| } | |
| } // end namespace llvm |