aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/LoopPeel.cpp
diff options
context:
space:
mode:
authorJoshua Cao <cao.joshua@yahoo.com>2023-05-21 13:30:26 -0700
committerJoshua Cao <cao.joshua@yahoo.com>2023-05-24 00:57:57 -0700
commit849d01bf3d97d05074a00d78903d782b2ac804f8 (patch)
tree9a1c05981ebab72ea1d58033f120188aef24c118 /llvm/lib/Transforms/Utils/LoopPeel.cpp
parentb76f0a0b153cb3d62e3e0d844deb3b6193922aaf (diff)
downloadllvm-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.cpp49
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;