diff options
author | Sebastian Pop <spop@nvidia.com> | 2025-05-19 09:08:59 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-19 09:08:59 -0500 |
commit | 2c6b239cc6102398701359dddda8023d26fcb95d (patch) | |
tree | 9a64789b9c79407eb88be3fac52cb7d6ebad236b /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 91a7085faf268b595e597fa2a2b979ca7b8de0a8 (diff) | |
download | llvm-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.cpp | 50 |
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. |