1fe6060f1SDimitry Andric //===------- LoopBoundSplit.cpp - Split Loop Bound --------------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "llvm/Transforms/Scalar/LoopBoundSplit.h" 10349cc55cSDimitry Andric #include "llvm/ADT/Sequence.h" 11fe6060f1SDimitry Andric #include "llvm/Analysis/LoopAnalysisManager.h" 12fe6060f1SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 13fe6060f1SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 14fe6060f1SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 15fe6060f1SDimitry Andric #include "llvm/IR/PatternMatch.h" 1681ad6265SDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h" 17fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 18fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 19fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/LoopSimplify.h" 20fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #define DEBUG_TYPE "loop-bound-split" 23fe6060f1SDimitry Andric 24fe6060f1SDimitry Andric namespace llvm { 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric using namespace PatternMatch; 27fe6060f1SDimitry Andric 28fe6060f1SDimitry Andric namespace { 29fe6060f1SDimitry Andric struct ConditionInfo { 30fe6060f1SDimitry Andric /// Branch instruction with this condition 3181ad6265SDimitry Andric BranchInst *BI = nullptr; 32fe6060f1SDimitry Andric /// ICmp instruction with this condition 3381ad6265SDimitry Andric ICmpInst *ICmp = nullptr; 34fe6060f1SDimitry Andric /// Preciate info 3581ad6265SDimitry Andric ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE; 36fe6060f1SDimitry Andric /// AddRec llvm value 3781ad6265SDimitry Andric Value *AddRecValue = nullptr; 38349cc55cSDimitry Andric /// Non PHI AddRec llvm value 39349cc55cSDimitry Andric Value *NonPHIAddRecValue; 40fe6060f1SDimitry Andric /// Bound llvm value 4181ad6265SDimitry Andric Value *BoundValue = nullptr; 42fe6060f1SDimitry Andric /// AddRec SCEV 4381ad6265SDimitry Andric const SCEVAddRecExpr *AddRecSCEV = nullptr; 44fe6060f1SDimitry Andric /// Bound SCEV 4581ad6265SDimitry Andric const SCEV *BoundSCEV = nullptr; 46fe6060f1SDimitry Andric 4781ad6265SDimitry Andric ConditionInfo() = default; 48fe6060f1SDimitry Andric }; 49fe6060f1SDimitry Andric } // namespace 50fe6060f1SDimitry Andric 51fe6060f1SDimitry Andric static void analyzeICmp(ScalarEvolution &SE, ICmpInst *ICmp, 52349cc55cSDimitry Andric ConditionInfo &Cond, const Loop &L) { 53fe6060f1SDimitry Andric Cond.ICmp = ICmp; 54fe6060f1SDimitry Andric if (match(ICmp, m_ICmp(Cond.Pred, m_Value(Cond.AddRecValue), 55fe6060f1SDimitry Andric m_Value(Cond.BoundValue)))) { 56349cc55cSDimitry Andric const SCEV *AddRecSCEV = SE.getSCEV(Cond.AddRecValue); 57349cc55cSDimitry Andric const SCEV *BoundSCEV = SE.getSCEV(Cond.BoundValue); 58349cc55cSDimitry Andric const SCEVAddRecExpr *LHSAddRecSCEV = dyn_cast<SCEVAddRecExpr>(AddRecSCEV); 59349cc55cSDimitry Andric const SCEVAddRecExpr *RHSAddRecSCEV = dyn_cast<SCEVAddRecExpr>(BoundSCEV); 60fe6060f1SDimitry Andric // Locate AddRec in LHSSCEV and Bound in RHSSCEV. 61349cc55cSDimitry Andric if (!LHSAddRecSCEV && RHSAddRecSCEV) { 62fe6060f1SDimitry Andric std::swap(Cond.AddRecValue, Cond.BoundValue); 63349cc55cSDimitry Andric std::swap(AddRecSCEV, BoundSCEV); 64fe6060f1SDimitry Andric Cond.Pred = ICmpInst::getSwappedPredicate(Cond.Pred); 65fe6060f1SDimitry Andric } 66349cc55cSDimitry Andric 67349cc55cSDimitry Andric Cond.AddRecSCEV = dyn_cast<SCEVAddRecExpr>(AddRecSCEV); 68349cc55cSDimitry Andric Cond.BoundSCEV = BoundSCEV; 69349cc55cSDimitry Andric Cond.NonPHIAddRecValue = Cond.AddRecValue; 70349cc55cSDimitry Andric 71349cc55cSDimitry Andric // If the Cond.AddRecValue is PHI node, update Cond.NonPHIAddRecValue with 72349cc55cSDimitry Andric // value from backedge. 73349cc55cSDimitry Andric if (Cond.AddRecSCEV && isa<PHINode>(Cond.AddRecValue)) { 74349cc55cSDimitry Andric PHINode *PN = cast<PHINode>(Cond.AddRecValue); 75349cc55cSDimitry Andric Cond.NonPHIAddRecValue = PN->getIncomingValueForBlock(L.getLoopLatch()); 76349cc55cSDimitry Andric } 77fe6060f1SDimitry Andric } 78fe6060f1SDimitry Andric } 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric static bool calculateUpperBound(const Loop &L, ScalarEvolution &SE, 81fe6060f1SDimitry Andric ConditionInfo &Cond, bool IsExitCond) { 82fe6060f1SDimitry Andric if (IsExitCond) { 83fe6060f1SDimitry Andric const SCEV *ExitCount = SE.getExitCount(&L, Cond.ICmp->getParent()); 84fe6060f1SDimitry Andric if (isa<SCEVCouldNotCompute>(ExitCount)) 85fe6060f1SDimitry Andric return false; 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric Cond.BoundSCEV = ExitCount; 88fe6060f1SDimitry Andric return true; 89fe6060f1SDimitry Andric } 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric // For non-exit condtion, if pred is LT, keep existing bound. 92fe6060f1SDimitry Andric if (Cond.Pred == ICmpInst::ICMP_SLT || Cond.Pred == ICmpInst::ICMP_ULT) 93fe6060f1SDimitry Andric return true; 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric // For non-exit condition, if pre is LE, try to convert it to LT. 96fe6060f1SDimitry Andric // Range Range 97fe6060f1SDimitry Andric // AddRec <= Bound --> AddRec < Bound + 1 98fe6060f1SDimitry Andric if (Cond.Pred != ICmpInst::ICMP_ULE && Cond.Pred != ICmpInst::ICMP_SLE) 99fe6060f1SDimitry Andric return false; 100fe6060f1SDimitry Andric 101fe6060f1SDimitry Andric if (IntegerType *BoundSCEVIntType = 102fe6060f1SDimitry Andric dyn_cast<IntegerType>(Cond.BoundSCEV->getType())) { 103fe6060f1SDimitry Andric unsigned BitWidth = BoundSCEVIntType->getBitWidth(); 104fe6060f1SDimitry Andric APInt Max = ICmpInst::isSigned(Cond.Pred) 105fe6060f1SDimitry Andric ? APInt::getSignedMaxValue(BitWidth) 106fe6060f1SDimitry Andric : APInt::getMaxValue(BitWidth); 107fe6060f1SDimitry Andric const SCEV *MaxSCEV = SE.getConstant(Max); 108fe6060f1SDimitry Andric // Check Bound < INT_MAX 109fe6060f1SDimitry Andric ICmpInst::Predicate Pred = 110fe6060f1SDimitry Andric ICmpInst::isSigned(Cond.Pred) ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; 111fe6060f1SDimitry Andric if (SE.isKnownPredicate(Pred, Cond.BoundSCEV, MaxSCEV)) { 112fe6060f1SDimitry Andric const SCEV *BoundPlusOneSCEV = 113fe6060f1SDimitry Andric SE.getAddExpr(Cond.BoundSCEV, SE.getOne(BoundSCEVIntType)); 114fe6060f1SDimitry Andric Cond.BoundSCEV = BoundPlusOneSCEV; 115fe6060f1SDimitry Andric Cond.Pred = Pred; 116fe6060f1SDimitry Andric return true; 117fe6060f1SDimitry Andric } 118fe6060f1SDimitry Andric } 119fe6060f1SDimitry Andric 120fe6060f1SDimitry Andric // ToDo: Support ICMP_NE/EQ. 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric return false; 123fe6060f1SDimitry Andric } 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric static bool hasProcessableCondition(const Loop &L, ScalarEvolution &SE, 126fe6060f1SDimitry Andric ICmpInst *ICmp, ConditionInfo &Cond, 127fe6060f1SDimitry Andric bool IsExitCond) { 128349cc55cSDimitry Andric analyzeICmp(SE, ICmp, Cond, L); 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric // The BoundSCEV should be evaluated at loop entry. 131fe6060f1SDimitry Andric if (!SE.isAvailableAtLoopEntry(Cond.BoundSCEV, &L)) 132fe6060f1SDimitry Andric return false; 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric // Allowed AddRec as induction variable. 135349cc55cSDimitry Andric if (!Cond.AddRecSCEV) 136fe6060f1SDimitry Andric return false; 137fe6060f1SDimitry Andric 138349cc55cSDimitry Andric if (!Cond.AddRecSCEV->isAffine()) 139fe6060f1SDimitry Andric return false; 140fe6060f1SDimitry Andric 141349cc55cSDimitry Andric const SCEV *StepRecSCEV = Cond.AddRecSCEV->getStepRecurrence(SE); 142fe6060f1SDimitry Andric // Allowed constant step. 143fe6060f1SDimitry Andric if (!isa<SCEVConstant>(StepRecSCEV)) 144fe6060f1SDimitry Andric return false; 145fe6060f1SDimitry Andric 146fe6060f1SDimitry Andric ConstantInt *StepCI = cast<SCEVConstant>(StepRecSCEV)->getValue(); 147fe6060f1SDimitry Andric // Allowed positive step for now. 148fe6060f1SDimitry Andric // TODO: Support negative step. 149fe6060f1SDimitry Andric if (StepCI->isNegative() || StepCI->isZero()) 150fe6060f1SDimitry Andric return false; 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric // Calculate upper bound. 153fe6060f1SDimitry Andric if (!calculateUpperBound(L, SE, Cond, IsExitCond)) 154fe6060f1SDimitry Andric return false; 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric return true; 157fe6060f1SDimitry Andric } 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric static bool isProcessableCondBI(const ScalarEvolution &SE, 160fe6060f1SDimitry Andric const BranchInst *BI) { 161fe6060f1SDimitry Andric BasicBlock *TrueSucc = nullptr; 162fe6060f1SDimitry Andric BasicBlock *FalseSucc = nullptr; 163fe6060f1SDimitry Andric ICmpInst::Predicate Pred; 164fe6060f1SDimitry Andric Value *LHS, *RHS; 165fe6060f1SDimitry Andric if (!match(BI, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), 166fe6060f1SDimitry Andric m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) 167fe6060f1SDimitry Andric return false; 168fe6060f1SDimitry Andric 169fe6060f1SDimitry Andric if (!SE.isSCEVable(LHS->getType())) 170fe6060f1SDimitry Andric return false; 171fe6060f1SDimitry Andric assert(SE.isSCEVable(RHS->getType()) && "Expected RHS's type is SCEVable"); 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric if (TrueSucc == FalseSucc) 174fe6060f1SDimitry Andric return false; 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric return true; 177fe6060f1SDimitry Andric } 178fe6060f1SDimitry Andric 179fe6060f1SDimitry Andric static bool canSplitLoopBound(const Loop &L, const DominatorTree &DT, 180fe6060f1SDimitry Andric ScalarEvolution &SE, ConditionInfo &Cond) { 181fe6060f1SDimitry Andric // Skip function with optsize. 182fe6060f1SDimitry Andric if (L.getHeader()->getParent()->hasOptSize()) 183fe6060f1SDimitry Andric return false; 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric // Split only innermost loop. 186fe6060f1SDimitry Andric if (!L.isInnermost()) 187fe6060f1SDimitry Andric return false; 188fe6060f1SDimitry Andric 189fe6060f1SDimitry Andric // Check loop is in simplified form. 190fe6060f1SDimitry Andric if (!L.isLoopSimplifyForm()) 191fe6060f1SDimitry Andric return false; 192fe6060f1SDimitry Andric 193fe6060f1SDimitry Andric // Check loop is in LCSSA form. 194fe6060f1SDimitry Andric if (!L.isLCSSAForm(DT)) 195fe6060f1SDimitry Andric return false; 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric // Skip loop that cannot be cloned. 198fe6060f1SDimitry Andric if (!L.isSafeToClone()) 199fe6060f1SDimitry Andric return false; 200fe6060f1SDimitry Andric 201fe6060f1SDimitry Andric BasicBlock *ExitingBB = L.getExitingBlock(); 202fe6060f1SDimitry Andric // Assumed only one exiting block. 203fe6060f1SDimitry Andric if (!ExitingBB) 204fe6060f1SDimitry Andric return false; 205fe6060f1SDimitry Andric 206fe6060f1SDimitry Andric BranchInst *ExitingBI = dyn_cast<BranchInst>(ExitingBB->getTerminator()); 207fe6060f1SDimitry Andric if (!ExitingBI) 208fe6060f1SDimitry Andric return false; 209fe6060f1SDimitry Andric 210fe6060f1SDimitry Andric // Allowed only conditional branch with ICmp. 211fe6060f1SDimitry Andric if (!isProcessableCondBI(SE, ExitingBI)) 212fe6060f1SDimitry Andric return false; 213fe6060f1SDimitry Andric 214fe6060f1SDimitry Andric // Check the condition is processable. 215fe6060f1SDimitry Andric ICmpInst *ICmp = cast<ICmpInst>(ExitingBI->getCondition()); 216fe6060f1SDimitry Andric if (!hasProcessableCondition(L, SE, ICmp, Cond, /*IsExitCond*/ true)) 217fe6060f1SDimitry Andric return false; 218fe6060f1SDimitry Andric 219fe6060f1SDimitry Andric Cond.BI = ExitingBI; 220fe6060f1SDimitry Andric return true; 221fe6060f1SDimitry Andric } 222fe6060f1SDimitry Andric 223fe6060f1SDimitry Andric static bool isProfitableToTransform(const Loop &L, const BranchInst *BI) { 224fe6060f1SDimitry Andric // If the conditional branch splits a loop into two halves, we could 225fe6060f1SDimitry Andric // generally say it is profitable. 226fe6060f1SDimitry Andric // 227fe6060f1SDimitry Andric // ToDo: Add more profitable cases here. 228fe6060f1SDimitry Andric 229fe6060f1SDimitry Andric // Check this branch causes diamond CFG. 230fe6060f1SDimitry Andric BasicBlock *Succ0 = BI->getSuccessor(0); 231fe6060f1SDimitry Andric BasicBlock *Succ1 = BI->getSuccessor(1); 232fe6060f1SDimitry Andric 233fe6060f1SDimitry Andric BasicBlock *Succ0Succ = Succ0->getSingleSuccessor(); 234fe6060f1SDimitry Andric BasicBlock *Succ1Succ = Succ1->getSingleSuccessor(); 235fe6060f1SDimitry Andric if (!Succ0Succ || !Succ1Succ || Succ0Succ != Succ1Succ) 236fe6060f1SDimitry Andric return false; 237fe6060f1SDimitry Andric 238fe6060f1SDimitry Andric // ToDo: Calculate each successor's instruction cost. 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric return true; 241fe6060f1SDimitry Andric } 242fe6060f1SDimitry Andric 243fe6060f1SDimitry Andric static BranchInst *findSplitCandidate(const Loop &L, ScalarEvolution &SE, 244fe6060f1SDimitry Andric ConditionInfo &ExitingCond, 245fe6060f1SDimitry Andric ConditionInfo &SplitCandidateCond) { 246fe6060f1SDimitry Andric for (auto *BB : L.blocks()) { 247fe6060f1SDimitry Andric // Skip condition of backedge. 248fe6060f1SDimitry Andric if (L.getLoopLatch() == BB) 249fe6060f1SDimitry Andric continue; 250fe6060f1SDimitry Andric 251fe6060f1SDimitry Andric auto *BI = dyn_cast<BranchInst>(BB->getTerminator()); 252fe6060f1SDimitry Andric if (!BI) 253fe6060f1SDimitry Andric continue; 254fe6060f1SDimitry Andric 255fe6060f1SDimitry Andric // Check conditional branch with ICmp. 256fe6060f1SDimitry Andric if (!isProcessableCondBI(SE, BI)) 257fe6060f1SDimitry Andric continue; 258fe6060f1SDimitry Andric 259fe6060f1SDimitry Andric // Skip loop invariant condition. 260fe6060f1SDimitry Andric if (L.isLoopInvariant(BI->getCondition())) 261fe6060f1SDimitry Andric continue; 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric // Check the condition is processable. 264fe6060f1SDimitry Andric ICmpInst *ICmp = cast<ICmpInst>(BI->getCondition()); 265fe6060f1SDimitry Andric if (!hasProcessableCondition(L, SE, ICmp, SplitCandidateCond, 266fe6060f1SDimitry Andric /*IsExitCond*/ false)) 267fe6060f1SDimitry Andric continue; 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric if (ExitingCond.BoundSCEV->getType() != 270fe6060f1SDimitry Andric SplitCandidateCond.BoundSCEV->getType()) 271fe6060f1SDimitry Andric continue; 272fe6060f1SDimitry Andric 273349cc55cSDimitry Andric // After transformation, we assume the split condition of the pre-loop is 274349cc55cSDimitry Andric // always true. In order to guarantee it, we need to check the start value 275349cc55cSDimitry Andric // of the split cond AddRec satisfies the split condition. 276349cc55cSDimitry Andric if (!SE.isLoopEntryGuardedByCond(&L, SplitCandidateCond.Pred, 277349cc55cSDimitry Andric SplitCandidateCond.AddRecSCEV->getStart(), 278349cc55cSDimitry Andric SplitCandidateCond.BoundSCEV)) 279349cc55cSDimitry Andric continue; 280349cc55cSDimitry Andric 281fe6060f1SDimitry Andric SplitCandidateCond.BI = BI; 282fe6060f1SDimitry Andric return BI; 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric 285fe6060f1SDimitry Andric return nullptr; 286fe6060f1SDimitry Andric } 287fe6060f1SDimitry Andric 288fe6060f1SDimitry Andric static bool splitLoopBound(Loop &L, DominatorTree &DT, LoopInfo &LI, 289fe6060f1SDimitry Andric ScalarEvolution &SE, LPMUpdater &U) { 290fe6060f1SDimitry Andric ConditionInfo SplitCandidateCond; 291fe6060f1SDimitry Andric ConditionInfo ExitingCond; 292fe6060f1SDimitry Andric 293fe6060f1SDimitry Andric // Check we can split this loop's bound. 294fe6060f1SDimitry Andric if (!canSplitLoopBound(L, DT, SE, ExitingCond)) 295fe6060f1SDimitry Andric return false; 296fe6060f1SDimitry Andric 297fe6060f1SDimitry Andric if (!findSplitCandidate(L, SE, ExitingCond, SplitCandidateCond)) 298fe6060f1SDimitry Andric return false; 299fe6060f1SDimitry Andric 300fe6060f1SDimitry Andric if (!isProfitableToTransform(L, SplitCandidateCond.BI)) 301fe6060f1SDimitry Andric return false; 302fe6060f1SDimitry Andric 303fe6060f1SDimitry Andric // Now, we have a split candidate. Let's build a form as below. 304fe6060f1SDimitry Andric // +--------------------+ 305fe6060f1SDimitry Andric // | preheader | 306fe6060f1SDimitry Andric // | set up newbound | 307fe6060f1SDimitry Andric // +--------------------+ 308fe6060f1SDimitry Andric // | /----------------\ 309fe6060f1SDimitry Andric // +--------v----v------+ | 310fe6060f1SDimitry Andric // | header |---\ | 311fe6060f1SDimitry Andric // | with true condition| | | 312fe6060f1SDimitry Andric // +--------------------+ | | 313fe6060f1SDimitry Andric // | | | 314fe6060f1SDimitry Andric // +--------v-----------+ | | 315fe6060f1SDimitry Andric // | if.then.BB | | | 316fe6060f1SDimitry Andric // +--------------------+ | | 317fe6060f1SDimitry Andric // | | | 318fe6060f1SDimitry Andric // +--------v-----------<---/ | 319fe6060f1SDimitry Andric // | latch >----------/ 320fe6060f1SDimitry Andric // | with newbound | 321fe6060f1SDimitry Andric // +--------------------+ 322fe6060f1SDimitry Andric // | 323fe6060f1SDimitry Andric // +--------v-----------+ 324fe6060f1SDimitry Andric // | preheader2 |--------------\ 325fe6060f1SDimitry Andric // | if (AddRec i != | | 326fe6060f1SDimitry Andric // | org bound) | | 327fe6060f1SDimitry Andric // +--------------------+ | 328fe6060f1SDimitry Andric // | /----------------\ | 329fe6060f1SDimitry Andric // +--------v----v------+ | | 330fe6060f1SDimitry Andric // | header2 |---\ | | 331fe6060f1SDimitry Andric // | conditional branch | | | | 332fe6060f1SDimitry Andric // |with false condition| | | | 333fe6060f1SDimitry Andric // +--------------------+ | | | 334fe6060f1SDimitry Andric // | | | | 335fe6060f1SDimitry Andric // +--------v-----------+ | | | 336fe6060f1SDimitry Andric // | if.then.BB2 | | | | 337fe6060f1SDimitry Andric // +--------------------+ | | | 338fe6060f1SDimitry Andric // | | | | 339fe6060f1SDimitry Andric // +--------v-----------<---/ | | 340fe6060f1SDimitry Andric // | latch2 >----------/ | 341fe6060f1SDimitry Andric // | with org bound | | 342fe6060f1SDimitry Andric // +--------v-----------+ | 343fe6060f1SDimitry Andric // | | 344fe6060f1SDimitry Andric // | +---------------+ | 345fe6060f1SDimitry Andric // +--> exit <-------/ 346fe6060f1SDimitry Andric // +---------------+ 347fe6060f1SDimitry Andric 348fe6060f1SDimitry Andric // Let's create post loop. 349fe6060f1SDimitry Andric SmallVector<BasicBlock *, 8> PostLoopBlocks; 350fe6060f1SDimitry Andric Loop *PostLoop; 351fe6060f1SDimitry Andric ValueToValueMapTy VMap; 352fe6060f1SDimitry Andric BasicBlock *PreHeader = L.getLoopPreheader(); 353fe6060f1SDimitry Andric BasicBlock *SplitLoopPH = SplitEdge(PreHeader, L.getHeader(), &DT, &LI); 354fe6060f1SDimitry Andric PostLoop = cloneLoopWithPreheader(L.getExitBlock(), SplitLoopPH, &L, VMap, 355fe6060f1SDimitry Andric ".split", &LI, &DT, PostLoopBlocks); 356fe6060f1SDimitry Andric remapInstructionsInBlocks(PostLoopBlocks, VMap); 357fe6060f1SDimitry Andric 358fe6060f1SDimitry Andric BasicBlock *PostLoopPreHeader = PostLoop->getLoopPreheader(); 359349cc55cSDimitry Andric IRBuilder<> Builder(&PostLoopPreHeader->front()); 360349cc55cSDimitry Andric 361349cc55cSDimitry Andric // Update phi nodes in header of post-loop. 362349cc55cSDimitry Andric bool isExitingLatch = 363349cc55cSDimitry Andric (L.getExitingBlock() == L.getLoopLatch()) ? true : false; 364349cc55cSDimitry Andric Value *ExitingCondLCSSAPhi = nullptr; 365349cc55cSDimitry Andric for (PHINode &PN : L.getHeader()->phis()) { 366349cc55cSDimitry Andric // Create LCSSA phi node in preheader of post-loop. 367349cc55cSDimitry Andric PHINode *LCSSAPhi = 368349cc55cSDimitry Andric Builder.CreatePHI(PN.getType(), 1, PN.getName() + ".lcssa"); 369349cc55cSDimitry Andric LCSSAPhi->setDebugLoc(PN.getDebugLoc()); 370349cc55cSDimitry Andric // If the exiting block is loop latch, the phi does not have the update at 371349cc55cSDimitry Andric // last iteration. In this case, update lcssa phi with value from backedge. 372349cc55cSDimitry Andric LCSSAPhi->addIncoming( 373349cc55cSDimitry Andric isExitingLatch ? PN.getIncomingValueForBlock(L.getLoopLatch()) : &PN, 374349cc55cSDimitry Andric L.getExitingBlock()); 375349cc55cSDimitry Andric 376349cc55cSDimitry Andric // Update the start value of phi node in post-loop with the LCSSA phi node. 377349cc55cSDimitry Andric PHINode *PostLoopPN = cast<PHINode>(VMap[&PN]); 378349cc55cSDimitry Andric PostLoopPN->setIncomingValueForBlock(PostLoopPreHeader, LCSSAPhi); 379349cc55cSDimitry Andric 380349cc55cSDimitry Andric // Find PHI with exiting condition from pre-loop. The PHI should be 381349cc55cSDimitry Andric // SCEVAddRecExpr and have same incoming value from backedge with 382349cc55cSDimitry Andric // ExitingCond. 383349cc55cSDimitry Andric if (!SE.isSCEVable(PN.getType())) 384349cc55cSDimitry Andric continue; 385349cc55cSDimitry Andric 386349cc55cSDimitry Andric const SCEVAddRecExpr *PhiSCEV = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(&PN)); 387349cc55cSDimitry Andric if (PhiSCEV && ExitingCond.NonPHIAddRecValue == 388349cc55cSDimitry Andric PN.getIncomingValueForBlock(L.getLoopLatch())) 389349cc55cSDimitry Andric ExitingCondLCSSAPhi = LCSSAPhi; 390349cc55cSDimitry Andric } 391349cc55cSDimitry Andric 392349cc55cSDimitry Andric // Add conditional branch to check we can skip post-loop in its preheader. 393fe6060f1SDimitry Andric Instruction *OrigBI = PostLoopPreHeader->getTerminator(); 394fe6060f1SDimitry Andric ICmpInst::Predicate Pred = ICmpInst::ICMP_NE; 395fe6060f1SDimitry Andric Value *Cond = 396349cc55cSDimitry Andric Builder.CreateICmp(Pred, ExitingCondLCSSAPhi, ExitingCond.BoundValue); 397fe6060f1SDimitry Andric Builder.CreateCondBr(Cond, PostLoop->getHeader(), PostLoop->getExitBlock()); 398fe6060f1SDimitry Andric OrigBI->eraseFromParent(); 399fe6060f1SDimitry Andric 400fe6060f1SDimitry Andric // Create new loop bound and add it into preheader of pre-loop. 401fe6060f1SDimitry Andric const SCEV *NewBoundSCEV = ExitingCond.BoundSCEV; 402fe6060f1SDimitry Andric const SCEV *SplitBoundSCEV = SplitCandidateCond.BoundSCEV; 403fe6060f1SDimitry Andric NewBoundSCEV = ICmpInst::isSigned(ExitingCond.Pred) 404fe6060f1SDimitry Andric ? SE.getSMinExpr(NewBoundSCEV, SplitBoundSCEV) 405fe6060f1SDimitry Andric : SE.getUMinExpr(NewBoundSCEV, SplitBoundSCEV); 406fe6060f1SDimitry Andric 407fe6060f1SDimitry Andric SCEVExpander Expander( 408*0fca6ea1SDimitry Andric SE, L.getHeader()->getDataLayout(), "split"); 409fe6060f1SDimitry Andric Instruction *InsertPt = SplitLoopPH->getTerminator(); 410fe6060f1SDimitry Andric Value *NewBoundValue = 411fe6060f1SDimitry Andric Expander.expandCodeFor(NewBoundSCEV, NewBoundSCEV->getType(), InsertPt); 412fe6060f1SDimitry Andric NewBoundValue->setName("new.bound"); 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric // Replace exiting bound value of pre-loop NewBound. 415fe6060f1SDimitry Andric ExitingCond.ICmp->setOperand(1, NewBoundValue); 416fe6060f1SDimitry Andric 417fe6060f1SDimitry Andric // Replace SplitCandidateCond.BI's condition of pre-loop by True. 418fe6060f1SDimitry Andric LLVMContext &Context = PreHeader->getContext(); 419fe6060f1SDimitry Andric SplitCandidateCond.BI->setCondition(ConstantInt::getTrue(Context)); 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric // Replace cloned SplitCandidateCond.BI's condition in post-loop by False. 422fe6060f1SDimitry Andric BranchInst *ClonedSplitCandidateBI = 423fe6060f1SDimitry Andric cast<BranchInst>(VMap[SplitCandidateCond.BI]); 424fe6060f1SDimitry Andric ClonedSplitCandidateBI->setCondition(ConstantInt::getFalse(Context)); 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric // Replace exit branch target of pre-loop by post-loop's preheader. 427fe6060f1SDimitry Andric if (L.getExitBlock() == ExitingCond.BI->getSuccessor(0)) 428fe6060f1SDimitry Andric ExitingCond.BI->setSuccessor(0, PostLoopPreHeader); 429fe6060f1SDimitry Andric else 430fe6060f1SDimitry Andric ExitingCond.BI->setSuccessor(1, PostLoopPreHeader); 431fe6060f1SDimitry Andric 432349cc55cSDimitry Andric // Update phi node in exit block of post-loop. 4335f757f3fSDimitry Andric Builder.SetInsertPoint(PostLoopPreHeader, PostLoopPreHeader->begin()); 434349cc55cSDimitry Andric for (PHINode &PN : PostLoop->getExitBlock()->phis()) { 435349cc55cSDimitry Andric for (auto i : seq<int>(0, PN.getNumOperands())) { 436349cc55cSDimitry Andric // Check incoming block is pre-loop's exiting block. 437349cc55cSDimitry Andric if (PN.getIncomingBlock(i) == L.getExitingBlock()) { 438349cc55cSDimitry Andric Value *IncomingValue = PN.getIncomingValue(i); 439349cc55cSDimitry Andric 440349cc55cSDimitry Andric // Create LCSSA phi node for incoming value. 441349cc55cSDimitry Andric PHINode *LCSSAPhi = 442349cc55cSDimitry Andric Builder.CreatePHI(PN.getType(), 1, PN.getName() + ".lcssa"); 443349cc55cSDimitry Andric LCSSAPhi->setDebugLoc(PN.getDebugLoc()); 444349cc55cSDimitry Andric LCSSAPhi->addIncoming(IncomingValue, PN.getIncomingBlock(i)); 445349cc55cSDimitry Andric 446349cc55cSDimitry Andric // Replace pre-loop's exiting block by post-loop's preheader. 447349cc55cSDimitry Andric PN.setIncomingBlock(i, PostLoopPreHeader); 448349cc55cSDimitry Andric // Replace incoming value by LCSSAPhi. 449349cc55cSDimitry Andric PN.setIncomingValue(i, LCSSAPhi); 450349cc55cSDimitry Andric // Add a new incoming value with post-loop's exiting block. 451349cc55cSDimitry Andric PN.addIncoming(VMap[IncomingValue], PostLoop->getExitingBlock()); 452349cc55cSDimitry Andric } 453349cc55cSDimitry Andric } 454349cc55cSDimitry Andric } 455349cc55cSDimitry Andric 456fe6060f1SDimitry Andric // Update dominator tree. 457fe6060f1SDimitry Andric DT.changeImmediateDominator(PostLoopPreHeader, L.getExitingBlock()); 458fe6060f1SDimitry Andric DT.changeImmediateDominator(PostLoop->getExitBlock(), PostLoopPreHeader); 459fe6060f1SDimitry Andric 460fe6060f1SDimitry Andric // Invalidate cached SE information. 461fe6060f1SDimitry Andric SE.forgetLoop(&L); 462fe6060f1SDimitry Andric 463fe6060f1SDimitry Andric // Canonicalize loops. 464fe6060f1SDimitry Andric simplifyLoop(&L, &DT, &LI, &SE, nullptr, nullptr, true); 465fe6060f1SDimitry Andric simplifyLoop(PostLoop, &DT, &LI, &SE, nullptr, nullptr, true); 466fe6060f1SDimitry Andric 467fe6060f1SDimitry Andric // Add new post-loop to loop pass manager. 468fe6060f1SDimitry Andric U.addSiblingLoops(PostLoop); 469fe6060f1SDimitry Andric 470fe6060f1SDimitry Andric return true; 471fe6060f1SDimitry Andric } 472fe6060f1SDimitry Andric 473fe6060f1SDimitry Andric PreservedAnalyses LoopBoundSplitPass::run(Loop &L, LoopAnalysisManager &AM, 474fe6060f1SDimitry Andric LoopStandardAnalysisResults &AR, 475fe6060f1SDimitry Andric LPMUpdater &U) { 476fe6060f1SDimitry Andric Function &F = *L.getHeader()->getParent(); 477fe6060f1SDimitry Andric (void)F; 478fe6060f1SDimitry Andric 479fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Spliting bound of loop in " << F.getName() << ": " << L 480fe6060f1SDimitry Andric << "\n"); 481fe6060f1SDimitry Andric 482fe6060f1SDimitry Andric if (!splitLoopBound(L, AR.DT, AR.LI, AR.SE, U)) 483fe6060f1SDimitry Andric return PreservedAnalyses::all(); 484fe6060f1SDimitry Andric 485fe6060f1SDimitry Andric assert(AR.DT.verify(DominatorTree::VerificationLevel::Fast)); 486fe6060f1SDimitry Andric AR.LI.verify(AR.DT); 487fe6060f1SDimitry Andric 488fe6060f1SDimitry Andric return getLoopPassPreservedAnalyses(); 489fe6060f1SDimitry Andric } 490fe6060f1SDimitry Andric 491fe6060f1SDimitry Andric } // end namespace llvm 492