summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp60
1 files changed, 49 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index 9fa49fdf81f..f72a808eaef 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -450,10 +450,20 @@ struct LoopStructure {
// equivalent to:
//
// intN_ty inc = IndVarIncreasing ? 1 : -1;
- // pred_ty predicate = IndVarIncreasing ? ICMP_SLT : ICMP_SGT;
+ // pred_ty predicate = IndVarIncreasing
+ // ? IsSignedPredicate ? ICMP_SLT : ICMP_ULT
+ // : IsSignedPredicate ? ICMP_SGT : ICMP_UGT;
//
- // for (intN_ty iv = IndVarStart; predicate(iv, LoopExitAt); iv = IndVarBase)
+ //
+ // for (intN_ty iv = IndVarStart; predicate(IndVarBase, LoopExitAt);
+ // iv = IndVarNext)
// ... body ...
+ //
+ // Here IndVarBase is either current or next value of the induction variable.
+ // in the former case, IsIndVarNext = false and IndVarBase points to the
+ // Phi node of the induction variable. Otherwise, IsIndVarNext = true and
+ // IndVarBase points to IV increment instruction.
+ //
Value *IndVarBase;
Value *IndVarStart;
@@ -461,12 +471,13 @@ struct LoopStructure {
Value *LoopExitAt;
bool IndVarIncreasing;
bool IsSignedPredicate;
+ bool IsIndVarNext;
LoopStructure()
: Tag(""), Header(nullptr), Latch(nullptr), LatchBr(nullptr),
LatchExit(nullptr), LatchBrExitIdx(-1), IndVarBase(nullptr),
IndVarStart(nullptr), IndVarStep(nullptr), LoopExitAt(nullptr),
- IndVarIncreasing(false), IsSignedPredicate(true) {}
+ IndVarIncreasing(false), IsSignedPredicate(true), IsIndVarNext(false) {}
template <typename M> LoopStructure map(M Map) const {
LoopStructure Result;
@@ -482,6 +493,7 @@ struct LoopStructure {
Result.LoopExitAt = Map(LoopExitAt);
Result.IndVarIncreasing = IndVarIncreasing;
Result.IsSignedPredicate = IsSignedPredicate;
+ Result.IsIndVarNext = IsIndVarNext;
return Result;
}
@@ -829,21 +841,42 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
return false;
};
- // `ICI` is interpreted as taking the backedge if the *next* value of the
- // induction variable satisfies some constraint.
+ // `ICI` can either be a comparison against IV or a comparison of IV.next.
+ // Depending on the interpretation, we calculate the start value differently.
+ // Pair {IndVarBase; IsIndVarNext} semantically designates whether the latch
+ // comparisons happens against the IV before or after its value is
+ // incremented. Two valid combinations for them are:
+ //
+ // 1) { phi [ iv.start, preheader ], [ iv.next, latch ]; false },
+ // 2) { iv.next; true }.
+ //
+ // The latch comparison happens against IndVarBase which can be either current
+ // or next value of the induction variable.
const SCEVAddRecExpr *IndVarBase = cast<SCEVAddRecExpr>(LeftSCEV);
bool IsIncreasing = false;
bool IsSignedPredicate = true;
+ bool IsIndVarNext = false;
ConstantInt *StepCI;
if (!IsInductionVar(IndVarBase, IsIncreasing, StepCI)) {
FailureReason = "LHS in icmp not induction variable";
return None;
}
- const SCEV *StartNext = IndVarBase->getStart();
- const SCEV *Addend = SE.getNegativeSCEV(IndVarBase->getStepRecurrence(SE));
- const SCEV *IndVarStart = SE.getAddExpr(StartNext, Addend);
+ const SCEV *IndVarStart = nullptr;
+ // TODO: Currently we only handle comparison against IV, but we can extend
+ // this analysis to be able to deal with comparison against sext(iv) and such.
+ if (isa<PHINode>(LeftValue) &&
+ cast<PHINode>(LeftValue)->getParent() == Header)
+ // The comparison is made against current IV value.
+ IndVarStart = IndVarBase->getStart();
+ else {
+ // Assume that the comparison is made against next IV value.
+ const SCEV *StartNext = IndVarBase->getStart();
+ const SCEV *Addend = SE.getNegativeSCEV(IndVarBase->getStepRecurrence(SE));
+ IndVarStart = SE.getAddExpr(StartNext, Addend);
+ IsIndVarNext = true;
+ }
const SCEV *Step = SE.getSCEV(StepCI);
ConstantInt *One = ConstantInt::get(IndVarTy, 1);
@@ -1027,6 +1060,7 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
Result.IndVarIncreasing = IsIncreasing;
Result.LoopExitAt = RightValue;
Result.IsSignedPredicate = IsSignedPredicate;
+ Result.IsIndVarNext = IsIndVarNext;
FailureReason = nullptr;
@@ -1316,8 +1350,9 @@ LoopConstrainer::RewrittenRangeInfo LoopConstrainer::changeIterationSpaceEnd(
BranchToContinuation);
NewPHI->addIncoming(PN->getIncomingValueForBlock(Preheader), Preheader);
- NewPHI->addIncoming(PN->getIncomingValueForBlock(LS.Latch),
- RRI.ExitSelector);
+ auto *FixupValue =
+ LS.IsIndVarNext ? PN->getIncomingValueForBlock(LS.Latch) : PN;
+ NewPHI->addIncoming(FixupValue, RRI.ExitSelector);
RRI.PHIValuesAtPseudoExit.push_back(NewPHI);
}
@@ -1700,7 +1735,10 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
}
LoopStructure LS = MaybeLoopStructure.getValue();
const SCEVAddRecExpr *IndVar =
- cast<SCEVAddRecExpr>(SE.getMinusSCEV(SE.getSCEV(LS.IndVarBase), SE.getSCEV(LS.IndVarStep)));
+ cast<SCEVAddRecExpr>(SE.getSCEV(LS.IndVarBase));
+ if (LS.IsIndVarNext)
+ IndVar = cast<SCEVAddRecExpr>(SE.getMinusSCEV(IndVar,
+ SE.getSCEV(LS.IndVarStep)));
Optional<InductiveRangeCheck::Range> SafeIterRange;
Instruction *ExprInsertPt = Preheader->getTerminator();
OpenPOWER on IntegriCloud