aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
authorSebastian Pop <spop@nvidia.com>2025-05-19 09:08:59 -0500
committerGitHub <noreply@github.com>2025-05-19 09:08:59 -0500
commit2c6b239cc6102398701359dddda8023d26fcb95d (patch)
tree9a64789b9c79407eb88be3fac52cb7d6ebad236b /llvm/lib/Analysis/ScalarEvolution.cpp
parent91a7085faf268b595e597fa2a2b979ca7b8de0a8 (diff)
downloadllvm-2c6b239cc6102398701359dddda8023d26fcb95d.zip
llvm-2c6b239cc6102398701359dddda8023d26fcb95d.tar.gz
llvm-2c6b239cc6102398701359dddda8023d26fcb95d.tar.bz2
[DA] handle memory accesses with different offsets and strides (#123436)
This patch corrects the behavior of the Dependence Analysis for memory accesses that do not start at the same offset or do not have similar strides. When offsets or strides cannot be disambiguated at compile time, DA collects a set of runtime assumptions under which the dependence test becomes valid. The default remains the same as before the patch: DA rejects the dependence test as undecidable instead of collecting runtime assumptions. --------- Co-authored-by: Michael Kruse <github@meinersbur.de> Co-authored-by: Ryotaro Kasuga <kasuga.ryotaro@fujitsu.com>
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.