aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp198
1 files changed, 120 insertions, 78 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c9baeda..a31f17b 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2424,10 +2424,10 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
// We're trying to construct a SCEV of type `Type' with `Ops' as operands and
// `OldFlags' as can't-wrap behavior. Infer a more aggressive set of
// can't-overflow flags for the operation if possible.
-static SCEV::NoWrapFlags
-StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
- const ArrayRef<const SCEV *> Ops,
- SCEV::NoWrapFlags Flags) {
+static SCEV::NoWrapFlags StrengthenNoWrapFlags(ScalarEvolution *SE,
+ SCEVTypes Type,
+ ArrayRef<const SCEV *> Ops,
+ SCEV::NoWrapFlags Flags) {
using namespace std::placeholders;
using OBO = OverflowingBinaryOperator;
@@ -2540,7 +2540,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
unsigned Idx = isa<SCEVConstant>(Ops[0]) ? 1 : 0;
// Delay expensive flag strengthening until necessary.
- auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
+ auto ComputeFlags = [this, OrigFlags](ArrayRef<const SCEV *> Ops) {
return StrengthenNoWrapFlags(this, scAddExpr, Ops, OrigFlags);
};
@@ -3125,7 +3125,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
return Folded;
// Delay expensive flag strengthening until necessary.
- auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
+ auto ComputeFlags = [this, OrigFlags](ArrayRef<const SCEV *> Ops) {
return StrengthenNoWrapFlags(this, scMulExpr, Ops, OrigFlags);
};
@@ -15510,6 +15510,78 @@ static const SCEV *getNextSCEVDivisibleByDivisor(const SCEV *Expr,
return SE.getConstant(*ExprVal + DivisorVal - Rem);
}
+static bool collectDivisibilityInformation(
+ ICmpInst::Predicate Predicate, const SCEV *LHS, const SCEV *RHS,
+ DenseMap<const SCEV *, const SCEV *> &DivInfo,
+ DenseMap<const SCEV *, APInt> &Multiples, ScalarEvolution &SE) {
+ // If we have LHS == 0, check if LHS is computing a property of some unknown
+ // SCEV %v which we can rewrite %v to express explicitly.
+ if (Predicate != CmpInst::ICMP_EQ || !match(RHS, m_scev_Zero()))
+ return false;
+ // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to
+ // explicitly express that.
+ const SCEVUnknown *URemLHS = nullptr;
+ const SCEV *URemRHS = nullptr;
+ if (!match(LHS, m_scev_URem(m_SCEVUnknown(URemLHS), m_SCEV(URemRHS), SE)))
+ return false;
+
+ const SCEV *Multiple =
+ SE.getMulExpr(SE.getUDivExpr(URemLHS, URemRHS), URemRHS);
+ DivInfo[URemLHS] = Multiple;
+ if (auto *C = dyn_cast<SCEVConstant>(URemRHS))
+ Multiples[URemLHS] = C->getAPInt();
+ return true;
+}
+
+// Check if the condition is a divisibility guard (A % B == 0).
+static bool isDivisibilityGuard(const SCEV *LHS, const SCEV *RHS,
+ ScalarEvolution &SE) {
+ const SCEV *X, *Y;
+ return match(LHS, m_scev_URem(m_SCEV(X), m_SCEV(Y), SE)) && RHS->isZero();
+}
+
+// Apply divisibility by \p Divisor on MinMaxExpr with constant values,
+// recursively. This is done by aligning up/down the constant value to the
+// Divisor.
+static const SCEV *applyDivisibilityOnMinMaxExpr(const SCEV *MinMaxExpr,
+ APInt Divisor,
+ ScalarEvolution &SE) {
+ // Return true if \p Expr is a MinMax SCEV expression with a non-negative
+ // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS
+ // the non-constant operand and in \p LHS the constant operand.
+ auto IsMinMaxSCEVWithNonNegativeConstant =
+ [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS,
+ const SCEV *&RHS) {
+ if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
+ if (MinMax->getNumOperands() != 2)
+ return false;
+ if (auto *C = dyn_cast<SCEVConstant>(MinMax->getOperand(0))) {
+ if (C->getAPInt().isNegative())
+ return false;
+ SCTy = MinMax->getSCEVType();
+ LHS = MinMax->getOperand(0);
+ RHS = MinMax->getOperand(1);
+ return true;
+ }
+ }
+ return false;
+ };
+
+ const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr;
+ SCEVTypes SCTy;
+ if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS,
+ MinMaxRHS))
+ return MinMaxExpr;
+ auto IsMin = isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr);
+ assert(SE.isKnownNonNegative(MinMaxLHS) && "Expected non-negative operand!");
+ auto *DivisibleExpr =
+ IsMin ? getPreviousSCEVDivisibleByDivisor(MinMaxLHS, Divisor, SE)
+ : getNextSCEVDivisibleByDivisor(MinMaxLHS, Divisor, SE);
+ SmallVector<const SCEV *> Ops = {
+ applyDivisibilityOnMinMaxExpr(MinMaxRHS, Divisor, SE), DivisibleExpr};
+ return SE.getMinMaxExpr(SCTy, Ops);
+}
+
void ScalarEvolution::LoopGuards::collectFromBlock(
ScalarEvolution &SE, ScalarEvolution::LoopGuards &Guards,
const BasicBlock *Block, const BasicBlock *Pred,
@@ -15520,19 +15592,13 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
SmallVector<const SCEV *> ExprsToRewrite;
auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS,
const SCEV *RHS,
- DenseMap<const SCEV *, const SCEV *>
- &RewriteMap) {
+ DenseMap<const SCEV *, const SCEV *> &RewriteMap,
+ const LoopGuards &DivGuards) {
// WARNING: It is generally unsound to apply any wrap flags to the proposed
// replacement SCEV which isn't directly implied by the structure of that
// SCEV. In particular, using contextual facts to imply flags is *NOT*
// legal. See the scoping rules for flags in the header to understand why.
- // If LHS is a constant, apply information to the other expression.
- if (isa<SCEVConstant>(LHS)) {
- std::swap(LHS, RHS);
- Predicate = CmpInst::getSwappedPredicate(Predicate);
- }
-
// Check for a condition of the form (-C1 + X < C2). InstCombine will
// create this form when combining two checks of the form (X u< C2 + C1) and
// (X >=u C1).
@@ -15565,67 +15631,6 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
if (MatchRangeCheckIdiom())
return;
- // Return true if \p Expr is a MinMax SCEV expression with a non-negative
- // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS
- // the non-constant operand and in \p LHS the constant operand.
- auto IsMinMaxSCEVWithNonNegativeConstant =
- [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS,
- const SCEV *&RHS) {
- const APInt *C;
- SCTy = Expr->getSCEVType();
- return match(Expr, m_scev_MinMax(m_SCEV(LHS), m_SCEV(RHS))) &&
- match(LHS, m_scev_APInt(C)) && C->isNonNegative();
- };
-
- // Apply divisibilty by \p Divisor on MinMaxExpr with constant values,
- // recursively. This is done by aligning up/down the constant value to the
- // Divisor.
- std::function<const SCEV *(const SCEV *, const SCEV *)>
- ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr,
- const SCEV *Divisor) {
- auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor);
- if (!ConstDivisor)
- return MinMaxExpr;
- const APInt &DivisorVal = ConstDivisor->getAPInt();
-
- const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr;
- SCEVTypes SCTy;
- if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS,
- MinMaxRHS))
- return MinMaxExpr;
- auto IsMin =
- isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr);
- assert(SE.isKnownNonNegative(MinMaxLHS) &&
- "Expected non-negative operand!");
- auto *DivisibleExpr =
- IsMin
- ? getPreviousSCEVDivisibleByDivisor(MinMaxLHS, DivisorVal, SE)
- : getNextSCEVDivisibleByDivisor(MinMaxLHS, DivisorVal, SE);
- SmallVector<const SCEV *> Ops = {
- ApplyDivisibiltyOnMinMaxExpr(MinMaxRHS, Divisor), DivisibleExpr};
- return SE.getMinMaxExpr(SCTy, Ops);
- };
-
- // If we have LHS == 0, check if LHS is computing a property of some unknown
- // SCEV %v which we can rewrite %v to express explicitly.
- if (Predicate == CmpInst::ICMP_EQ && match(RHS, m_scev_Zero())) {
- // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to
- // explicitly express that.
- const SCEVUnknown *URemLHS = nullptr;
- const SCEV *URemRHS = nullptr;
- if (match(LHS,
- m_scev_URem(m_SCEVUnknown(URemLHS), m_SCEV(URemRHS), SE))) {
- auto I = RewriteMap.find(URemLHS);
- const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : URemLHS;
- RewrittenLHS = ApplyDivisibiltyOnMinMaxExpr(RewrittenLHS, URemRHS);
- const auto *Multiple =
- SE.getMulExpr(SE.getUDivExpr(RewrittenLHS, URemRHS), URemRHS);
- RewriteMap[URemLHS] = Multiple;
- ExprsToRewrite.push_back(URemLHS);
- return;
- }
- }
-
// Do not apply information for constants or if RHS contains an AddRec.
if (isa<SCEVConstant>(LHS) || SE.containsAddRecurrence(RHS))
return;
@@ -15655,7 +15660,9 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
};
const SCEV *RewrittenLHS = GetMaybeRewritten(LHS);
- const APInt &DividesBy = SE.getConstantMultiple(RewrittenLHS);
+ // Apply divisibility information when computing the constant multiple.
+ const APInt &DividesBy =
+ SE.getConstantMultiple(DivGuards.rewrite(RewrittenLHS));
// Collect rewrites for LHS and its transitive operands based on the
// condition.
@@ -15840,8 +15847,11 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
// Now apply the information from the collected conditions to
// Guards.RewriteMap. Conditions are processed in reverse order, so the
- // earliest conditions is processed first. This ensures the SCEVs with the
+ // earliest conditions is processed first, except guards with divisibility
+ // information, which are moved to the back. This ensures the SCEVs with the
// shortest dependency chains are constructed first.
+ SmallVector<std::tuple<CmpInst::Predicate, const SCEV *, const SCEV *>>
+ GuardsToProcess;
for (auto [Term, EnterIfTrue] : reverse(Terms)) {
SmallVector<Value *, 8> Worklist;
SmallPtrSet<Value *, 8> Visited;
@@ -15856,7 +15866,14 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
EnterIfTrue ? Cmp->getPredicate() : Cmp->getInversePredicate();
const auto *LHS = SE.getSCEV(Cmp->getOperand(0));
const auto *RHS = SE.getSCEV(Cmp->getOperand(1));
- CollectCondition(Predicate, LHS, RHS, Guards.RewriteMap);
+ // If LHS is a constant, apply information to the other expression.
+ // TODO: If LHS is not a constant, check if using CompareSCEVComplexity
+ // can improve results.
+ if (isa<SCEVConstant>(LHS)) {
+ std::swap(LHS, RHS);
+ Predicate = CmpInst::getSwappedPredicate(Predicate);
+ }
+ GuardsToProcess.emplace_back(Predicate, LHS, RHS);
continue;
}
@@ -15869,6 +15886,31 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
}
}
+ // Process divisibility guards in reverse order to populate DivGuards early.
+ DenseMap<const SCEV *, APInt> Multiples;
+ LoopGuards DivGuards(SE);
+ for (const auto &[Predicate, LHS, RHS] : GuardsToProcess) {
+ if (!isDivisibilityGuard(LHS, RHS, SE))
+ continue;
+ collectDivisibilityInformation(Predicate, LHS, RHS, DivGuards.RewriteMap,
+ Multiples, SE);
+ }
+
+ for (const auto &[Predicate, LHS, RHS] : GuardsToProcess)
+ CollectCondition(Predicate, LHS, RHS, Guards.RewriteMap, DivGuards);
+
+ // Apply divisibility information last. This ensures it is applied to the
+ // outermost expression after other rewrites for the given value.
+ for (const auto &[K, Divisor] : Multiples) {
+ const SCEV *DivisorSCEV = SE.getConstant(Divisor);
+ Guards.RewriteMap[K] =
+ SE.getMulExpr(SE.getUDivExpr(applyDivisibilityOnMinMaxExpr(
+ Guards.rewrite(K), Divisor, SE),
+ DivisorSCEV),
+ DivisorSCEV);
+ ExprsToRewrite.push_back(K);
+ }
+
// Let the rewriter preserve NUW/NSW flags if the unsigned/signed ranges of
// the replacement expressions are contained in the ranges of the replaced
// expressions.