diff options
author | Joshua Cao <cao.joshua@yahoo.com> | 2023-05-21 13:30:26 -0700 |
---|---|---|
committer | Joshua Cao <cao.joshua@yahoo.com> | 2023-05-24 00:57:57 -0700 |
commit | 849d01bf3d97d05074a00d78903d782b2ac804f8 (patch) | |
tree | 9a1c05981ebab72ea1d58033f120188aef24c118 /llvm/lib/Transforms/Utils/LoopPeel.cpp | |
parent | b76f0a0b153cb3d62e3e0d844deb3b6193922aaf (diff) | |
download | llvm-849d01bf3d97d05074a00d78903d782b2ac804f8.zip llvm-849d01bf3d97d05074a00d78903d782b2ac804f8.tar.gz llvm-849d01bf3d97d05074a00d78903d782b2ac804f8.tar.bz2 |
[LoopUnroll] Peel iterations based on select conditions
This also allows us to peel loops with a `select`:
```
for (int i = 0; i <= N; ++i);
f3(i == 0 ? a : b); // select instruction
```
into:
```
f3(a); // peel one iteration
for (int i = 1; i <= N; ++i)
f3(b);
```
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D151052
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopPeel.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LoopPeel.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp index 2acbe90..1ec46e0 100644 --- a/llvm/lib/Transforms/Utils/LoopPeel.cpp +++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp @@ -345,20 +345,20 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, assert(L.isLoopSimplifyForm() && "Loop needs to be in loop simplify form"); unsigned DesiredPeelCount = 0; - for (auto *BB : L.blocks()) { - auto *BI = dyn_cast<BranchInst>(BB->getTerminator()); - if (!BI || BI->isUnconditional()) - continue; - - // Ignore loop exit condition. - if (L.getLoopLatch() == BB) - continue; + // Do not peel the entire loop. + const SCEV *BE = SE.getConstantMaxBackedgeTakenCount(&L); + if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(BE)) + MaxPeelCount = + std::min((unsigned)SC->getAPInt().getLimitedValue() - 1, MaxPeelCount); + + auto ComputePeelCount = [&](Value *Condition) -> void { + if (!Condition->getType()->isIntegerTy()) + return; - Value *Condition = BI->getCondition(); Value *LeftVal, *RightVal; CmpInst::Predicate Pred; if (!match(Condition, m_ICmp(Pred, m_Value(LeftVal), m_Value(RightVal)))) - continue; + return; const SCEV *LeftSCEV = SE.getSCEV(LeftVal); const SCEV *RightSCEV = SE.getSCEV(RightVal); @@ -366,7 +366,7 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, // Do not consider predicates that are known to be true or false // independently of the loop iteration. if (SE.evaluatePredicate(Pred, LeftSCEV, RightSCEV)) - continue; + return; // Check if we have a condition with one AddRec and one non AddRec // expression. Normalize LeftSCEV to be the AddRec. @@ -375,7 +375,7 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, std::swap(LeftSCEV, RightSCEV); Pred = ICmpInst::getSwappedPredicate(Pred); } else - continue; + return; } const SCEVAddRecExpr *LeftAR = cast<SCEVAddRecExpr>(LeftSCEV); @@ -383,10 +383,10 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, // Avoid huge SCEV computations in the loop below, make sure we only // consider AddRecs of the loop we are trying to peel. if (!LeftAR->isAffine() || LeftAR->getLoop() != &L) - continue; + return; if (!(ICmpInst::isEquality(Pred) && LeftAR->hasNoSelfWrap()) && !SE.getMonotonicPredicateType(LeftAR, Pred)) - continue; + return; // Check if extending the current DesiredPeelCount lets us evaluate Pred // or !Pred in the loop body statically. @@ -422,7 +422,7 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, // first iteration of the loop body after peeling? if (!SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), IterVal, RightSCEV)) - continue; // If not, give up. + return; // If not, give up. // However, for equality comparisons, that isn't always sufficient to // eliminate the comparsion in loop body, we may need to peel one more @@ -433,11 +433,28 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount, !SE.isKnownPredicate(Pred, IterVal, RightSCEV) && SE.isKnownPredicate(Pred, NextIterVal, RightSCEV)) { if (!CanPeelOneMoreIteration()) - continue; // Need to peel one more iteration, but can't. Give up. + return; // Need to peel one more iteration, but can't. Give up. PeelOneMoreIteration(); // Great! } DesiredPeelCount = std::max(DesiredPeelCount, NewPeelCount); + }; + + for (BasicBlock *BB : L.blocks()) { + for (Instruction &I : *BB) { + if (SelectInst *SI = dyn_cast<SelectInst>(&I)) + ComputePeelCount(SI->getCondition()); + } + + auto *BI = dyn_cast<BranchInst>(BB->getTerminator()); + if (!BI || BI->isUnconditional()) + continue; + + // Ignore loop exit condition. + if (L.getLoopLatch() == BB) + continue; + + ComputePeelCount(BI->getCondition()); } return DesiredPeelCount; |