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.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 342c8e3..5e01c29 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -10963,6 +10963,56 @@ bool ScalarEvolution::isKnownToBeAPowerOfTwo(const SCEV *S, bool OrZero,
return all_of(Mul->operands(), NonRecursive) && (OrZero || isKnownNonZero(S));
}
+bool ScalarEvolution::isKnownMultipleOf(
+ const SCEV *S, uint64_t M,
+ SmallVectorImpl<const SCEVPredicate *> &Assumptions) {
+ if (M == 0)
+ return false;
+ if (M == 1)
+ return true;
+
+ // Recursively check AddRec operands. An AddRecExpr S is a multiple of M if S
+ // starts with a multiple of M and at every iteration step S only adds
+ // multiples of M.
+ if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
+ return isKnownMultipleOf(AddRec->getStart(), M, Assumptions) &&
+ isKnownMultipleOf(AddRec->getStepRecurrence(*this), M, Assumptions);
+
+ // For a constant, check that "S % M == 0".
+ if (auto *Cst = dyn_cast<SCEVConstant>(S)) {
+ APInt C = Cst->getAPInt();
+ return C.urem(M) == 0;
+ }
+
+ // TODO: Also check other SCEV expressions, i.e., SCEVAddRecExpr, etc.
+
+ // Basic tests have failed.
+ // Check "S % M == 0" at compile time and record runtime Assumptions.
+ auto *STy = dyn_cast<IntegerType>(S->getType());
+ const SCEV *SmodM =
+ getURemExpr(S, getConstant(ConstantInt::get(STy, M, false)));
+ const SCEV *Zero = getZero(STy);
+
+ // Check whether "S % M == 0" is known at compile time.
+ if (isKnownPredicate(ICmpInst::ICMP_EQ, SmodM, Zero))
+ return true;
+
+ // Check whether "S % M != 0" is known at compile time.
+ if (isKnownPredicate(ICmpInst::ICMP_NE, SmodM, Zero))
+ return false;
+
+ const SCEVPredicate *P = getComparePredicate(ICmpInst::ICMP_EQ, SmodM, Zero);
+
+ // Detect redundant predicates.
+ for (auto *A : Assumptions)
+ if (A->implies(P, *this))
+ return true;
+
+ // Only record non-redundant predicates.
+ Assumptions.push_back(P);
+ return true;
+}
+
std::pair<const SCEV *, const SCEV *>
ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, const SCEV *S) {
// Compute SCEV on entry of loop L.