[llvm] r230151 - IRCE: generalize InductiveRangeCheck::computeSafeIterationSpace to
Sanjoy Das
sanjoy at playingwithpointers.com
Sat Feb 21 14:20:22 PST 2015
Author: sanjoy
Date: Sat Feb 21 16:20:22 2015
New Revision: 230151
URL: http://llvm.org/viewvc/llvm-project?rev=230151&view=rev
Log:
IRCE: generalize InductiveRangeCheck::computeSafeIterationSpace to
work with a non-canonical induction variable.
This is currently a non-functional change because we only ever call
computeSafeIterationSpace on a canonical induction variable; but the
generalization will be useful in a later commit.
Modified:
llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp?rev=230151&r1=230150&r2=230151&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp Sat Feb 21 16:20:22 2015
@@ -162,9 +162,11 @@ public:
/// branch to take the hot successor (see (1) above).
bool getPassingDirection() { return true; }
- /// Computes a range for the induction variable in which the range check is
- /// redundant and can be constant-folded away.
+ /// Computes a range for the induction variable (IndVar) in which the range
+ /// check is redundant and can be constant-folded away. The induction
+ /// variable is not required to be the canonical {0,+,1} induction variable.
Optional<Range> computeSafeIterationSpace(ScalarEvolution &SE,
+ const SCEVAddRecExpr *IndVar,
IRBuilder<> &B) const;
/// Create an inductive range check out of BI if possible, else return
@@ -617,10 +619,7 @@ bool LoopConstrainer::recognizeLoop(Loop
}
PHINode *CIV = OriginalLoop.getCanonicalInductionVariable();
- if (!CIV) {
- FailureReason = "no CIV";
- return false;
- }
+ assert(CIV && "precondition");
BasicBlock *Header = OriginalLoop.getHeader();
BasicBlock *Preheader = OriginalLoop.getLoopPreheader();
@@ -1082,43 +1081,62 @@ bool LoopConstrainer::run() {
return true;
}
-/// Computes and returns a range of values for the induction variable in which
-/// the range check can be safely elided. If it cannot compute such a range,
-/// returns None.
+/// Computes and returns a range of values for the induction variable (IndVar)
+/// in which the range check can be safely elided. If it cannot compute such a
+/// range, returns None.
Optional<InductiveRangeCheck::Range>
InductiveRangeCheck::computeSafeIterationSpace(ScalarEvolution &SE,
- IRBuilder<> &B) const {
-
- // Currently we support inequalities of the form:
+ const SCEVAddRecExpr *IndVar,
+ IRBuilder<> &) const {
+ // IndVar is of the form "A + B * I" (where "I" is the canonical induction
+ // variable, that may or may not exist as a real llvm::Value in the loop) and
+ // this inductive range check is a range check on the "C + D * I" ("C" is
+ // getOffset() and "D" is getScale()). We rewrite the value being range
+ // checked to "M + N * IndVar" where "N" = "D * B^(-1)" and "M" = "C - NA".
+ // Currently we support this only for "B" = "D" = { 1 or -1 }, but the code
+ // can be generalized as needed.
+ //
+ // The actual inequalities we solve are of the form
//
- // 0 <= Offset + 1 * CIV < L given L >= 0
+ // 0 <= M + 1 * IndVar < L given L >= 0 (i.e. N == 1)
//
- // The inequality is satisfied by -Offset <= CIV < (L - Offset) [^1]. All
- // additions and subtractions are twos-complement wrapping and comparisons are
- // signed.
+ // The inequality is satisfied by -M <= IndVar < (L - M) [^1]. All additions
+ // and subtractions are twos-complement wrapping and comparisons are signed.
//
// Proof:
//
- // If there exists CIV such that -Offset <= CIV < (L - Offset) then it
- // follows that -Offset <= (-Offset + L) [== Eq. 1]. Since L >= 0, if
- // (-Offset + L) sign-overflows then (-Offset + L) < (-Offset). Hence by
- // [Eq. 1], (-Offset + L) could not have overflown.
- //
- // This means CIV = t + (-Offset) for t in [0, L). Hence (CIV + Offset) =
- // t. Hence 0 <= (CIV + Offset) < L
-
- // [^1]: Note that the solution does _not_ apply if L < 0; consider values
- // Offset = 127, CIV = 126 and L = -2 in an i8 world.
-
- const SCEVConstant *ScaleC = dyn_cast<SCEVConstant>(getScale());
- if (!(ScaleC && ScaleC->getValue()->getValue() == 1)) {
- DEBUG(dbgs() << "irce: could not compute safe iteration space for:\n";
- print(dbgs()));
+ // If there exists IndVar such that -M <= IndVar < (L - M) then it follows
+ // that -M <= (-M + L) [== Eq. 1]. Since L >= 0, if (-M + L) sign-overflows
+ // then (-M + L) < (-M). Hence by [Eq. 1], (-M + L) could not have
+ // overflown.
+ //
+ // This means IndVar = t + (-M) for t in [0, L). Hence (IndVar + M) = t.
+ // Hence 0 <= (IndVar + M) < L
+
+ // [^1]: Note that the solution does _not_ apply if L < 0; consider values M =
+ // 127, IndVar = 126 and L = -2 in an i8 world.
+
+ if (!IndVar->isAffine())
+ return None;
+
+ const SCEV *A = IndVar->getStart();
+ const SCEVConstant *B = dyn_cast<SCEVConstant>(IndVar->getStepRecurrence(SE));
+ if (!B)
+ return None;
+
+ const SCEV *C = getOffset();
+ const SCEVConstant *D = dyn_cast<SCEVConstant>(getScale());
+ if (D != B)
+ return None;
+
+ ConstantInt *ConstD = D->getValue();
+ if (!(ConstD->isMinusOne() || ConstD->isOne()))
return None;
- }
- const SCEV *Begin = SE.getNegativeSCEV(getOffset());
- const SCEV *End = SE.getMinusSCEV(SE.getSCEV(getLength()), getOffset());
+ const SCEV *M = SE.getMinusSCEV(C, A);
+
+ const SCEV *Begin = SE.getNegativeSCEV(M);
+ const SCEV *End = SE.getMinusSCEV(SE.getSCEV(getLength()), M);
return InductiveRangeCheck::Range(Begin, End);
}
@@ -1160,6 +1178,13 @@ bool InductiveRangeCheckElimination::run
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
+ PHINode *CIV = L->getCanonicalInductionVariable();
+ if (!CIV) {
+ DEBUG(dbgs() << "irce: loop has no canonical induction variable\n");
+ return false;
+ }
+ const SCEVAddRecExpr *IndVar = cast<SCEVAddRecExpr>(SE.getSCEV(CIV));
+
for (auto BBI : L->getBlocks())
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator()))
if (InductiveRangeCheck *IRC =
@@ -1183,7 +1208,7 @@ bool InductiveRangeCheckElimination::run
IRBuilder<> B(ExprInsertPt);
for (InductiveRangeCheck *IRC : RangeChecks) {
- auto Result = IRC->computeSafeIterationSpace(SE, B);
+ auto Result = IRC->computeSafeIterationSpace(SE, IndVar, B);
if (Result.hasValue()) {
auto MaybeSafeIterRange =
IntersectRange(SE, SafeIterRange, Result.getValue(), B);
More information about the llvm-commits
mailing list