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
analyzeICmp(ScalarEvolution & SE,ICmpInst * ICmp,ConditionInfo & Cond,const Loop & L)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
calculateUpperBound(const Loop & L,ScalarEvolution & SE,ConditionInfo & Cond,bool IsExitCond)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
hasProcessableCondition(const Loop & L,ScalarEvolution & SE,ICmpInst * ICmp,ConditionInfo & Cond,bool IsExitCond)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
isProcessableCondBI(const ScalarEvolution & SE,const BranchInst * BI)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
canSplitLoopBound(const Loop & L,const DominatorTree & DT,ScalarEvolution & SE,ConditionInfo & Cond)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
isProfitableToTransform(const Loop & L,const BranchInst * BI)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
findSplitCandidate(const Loop & L,ScalarEvolution & SE,ConditionInfo & ExitingCond,ConditionInfo & SplitCandidateCond)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
splitLoopBound(Loop & L,DominatorTree & DT,LoopInfo & LI,ScalarEvolution & SE,LPMUpdater & U)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
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater & U)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