@@ -10971,107 +10971,64 @@ bool ScalarEvolution::isKnownToBeAPowerOfTwo(const SCEV *S, bool OrZero,
1097110971 return all_of(Mul->operands(), NonRecursive) && (OrZero || isKnownNonZero(S));
1097210972}
1097310973
10974- bool ScalarEvolution::isKnownMultipleOf(const SCEV *V, const SCEV *&Param,
10975- uint64_t EltSize) {
10976- if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V))
10977- return isKnownMultipleOf(AddRec->getStart(), Param, EltSize) &&
10978- isKnownMultipleOf(AddRec->getStepRecurrence(*this), Param, EltSize);
10974+ bool ScalarEvolution::isKnownMultipleOf(
10975+ const SCEV *S, uint64_t M,
10976+ SmallVectorImpl<const SCEVPredicate *> &Assumptions) {
10977+ if (M == 0)
10978+ return false;
10979+ if (M == 1)
10980+ return true;
10981+
10982+ // Recursively check AddRec operands.
10983+ if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
10984+ return isKnownMultipleOf(AddRec->getStart(), M, Assumptions) &&
10985+ isKnownMultipleOf(AddRec->getStepRecurrence(*this), M, Assumptions);
1097910986
10980- if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
10987+ // For a constant, check that "S % M == 0".
10988+ if (auto *Cst = dyn_cast<SCEVConstant>(S)) {
1098110989 APInt C = Cst->getAPInt();
10982- // For example, alias_with_different_offsets in
10983- // test/Analysis/DependenceAnalysis/DifferentOffsets.ll accesses "%A + 2":
10984- // %arrayidx = getelementptr inbounds i8, ptr %A, i64 2
10985- // store i32 42, ptr %arrayidx, align 1
10986- // which is writing an i32, i.e., EltSize = 4 bytes, with an offset C = 2.
10987- // isKnownMultipleOf returns false, as C=2 is not a multiple of 4.
10988- return C.urem(EltSize) == 0;
10989- }
10990-
10991- // Use a lambda helper function to check V for parametric expressions.
10992- // Param records the first parametric expression. If the scalar evolution V
10993- // contains two or more parameters, we check that the subsequent parametric
10994- // expressions are multiples of the first parametric expression Param.
10995- auto checkParamsMultipleOfSize = [&](const SCEV *V,
10996- const SCEV *&Param) -> bool {
10997- if (EltSize == 1)
10998- return true;
10999- if (!Param) {
11000- Param = V;
11001- return true;
11002- }
11003- if (Param == V)
11004- return true;
10990+ return C.urem(M) == 0;
10991+ }
1100510992
11006- // Check whether "(Param - V) % Size == 0".
11007- const SCEV *Diff = getMinusSCEV(Param, V);
11008- if (auto *Cst = dyn_cast<SCEVConstant>(Diff)) {
11009- APInt Val = Cst->getAPInt();
11010- if (Val.isZero())
11011- return true;
11012- APInt Rem = Val.urem(APInt(Val.getBitWidth(), EltSize, /*isSigned=*/true));
11013- if (Rem.isZero())
11014- // For example in test/Analysis/DependenceAnalysis/Preliminary.ll
11015- // SrcSCEV = ((4 * (sext i8 %n to i64))<nsw> + %A)
11016- // DstSCEV = (4 + (4 * (sext i8 %n to i64))<nsw> + %A)
11017- // Param = (4 * (sext i8 %n to i64))<nsw>
11018- // V = 4 + (4 * (sext i8 %n to i64))<nsw>
11019- // Diff = -4, Rem = 0, and so all offsets are multiple of 4.
11020- return true;
11021- LLVM_DEBUG(dbgs() << "SCEV with different offsets: " << *Param << " - "
11022- << *V << " = " << *Diff << " % " << EltSize << " = "
11023- << Rem << " != 0\n");
11024- return false;
11025- }
11026- // Check if the symbolic difference is a multiple of Size.
11027- const SCEV *Val =
11028- getConstant(APInt(Diff->getType()->getScalarSizeInBits(), EltSize));
11029-
11030- // Check by using the remainder computation.
11031- const SCEV *Remainder = getURemExpr(Diff, Val);
11032- if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
11033- if (C->getValue()->isZero())
11034- // For example test/Analysis/DependenceAnalysis/DADelin.ll
11035- // SrcSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
11036- // DstSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
11037- // The strides '(4 * %m * %o)' and '(4 * %o)' are multiple of 4.
11038- return true;
10993+ // Basic tests have failed.
10994+ // Record "S % M == 0" in the runtime Assumptions.
10995+ auto recordRuntimePredicate = [&](const SCEV *S) -> void {
10996+ auto *STy = dyn_cast<IntegerType>(S->getType());
10997+ const SCEV *SmodM =
10998+ getURemExpr(S, getConstant(ConstantInt::get(STy, M, false)));
10999+ const SCEV *Zero = getZero(STy);
1103911000
11040- // Check by using the division computation.
11041- const SCEV *Q = getUDivExpr(Diff, Val);
11042- const SCEV *Product = getMulExpr(Q, Val);
11043- if (Diff == Product)
11044- return true;
11045- LLVM_DEBUG(dbgs() << "SCEV with different offsets:\n"
11046- << *Param << " - " << *V << " = " << *Diff << "\n"
11047- << "Remainder = " << *Remainder << "\n"
11048- << "Q = " << *Q << " Product = " << *Product << "\n");
11049- // For example in test/Analysis/DependenceAnalysis/MIVCheckConst.ll
11050- // SrcSCEV = {(80640 + (4 * (1 + %n) * %v1) + %A),+,(8 * %v1)}<%bb13>
11051- // DstSCEV = {(126720 + (128 * %m) + %A),+,256}<%bb13>
11052- // We fail to prove that the offsets 80640 + (4 * (1 + %n) * %v1) and
11053- // (8 * %v1) are multiples of 128.
11054- // Param = 80640 + (4 * (1 + %n) * %v1)
11055- // (80640 + (4 * (1 + %n) * %v1)) - (8 * %v1) =
11056- // (80640 + ((-4 + (4 * %n)) * %v1))
11057- // Remainder = (zext i7 ((trunc i32 %v1 to i7) *
11058- // (-4 + (4 * (trunc i32 %n to i7)))) to i32)
11059- // Q = ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128)
11060- // Product = (128 * ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128))<nuw>
11061- return false;
11001+ // Check whether "S % M == 0" is known at compile time.
11002+ if (isKnownPredicate(ICmpInst::ICMP_EQ, SmodM, Zero))
11003+ return;
11004+
11005+ const SCEVPredicate *P =
11006+ getComparePredicate(ICmpInst::ICMP_EQ, SmodM, Zero);
11007+
11008+ // Detect redundant predicates.
11009+ for (auto *A : Assumptions)
11010+ if (A->implies(P, *this))
11011+ return;
11012+
11013+ Assumptions.push_back(P);
11014+ return;
1106211015 };
1106311016
1106411017 // Expressions like "n".
11065- if (isa<SCEVUnknown>(V))
11066- return checkParamsMultipleOfSize(V, Param);
11018+ if (isa<SCEVUnknown>(S)) {
11019+ recordRuntimePredicate(S);
11020+ return true;
11021+ }
1106711022
11068- // Expressions like "n + 1".
11069- if (isa<SCEVAddExpr>(V) || isa<SCEVMulExpr>(V))
11070- return !SCEVExprContains(V, [](const SCEV *S) {
11071- return isa<SCEVUnknown>(S);
11072- }) || checkParamsMultipleOfSize(V, Param);
11023+ // Expressions like "n + 1" and "n * 3".
11024+ if (isa<SCEVAddExpr>(S) || isa<SCEVMulExpr>(S)) {
11025+ if (SCEVExprContains(S, [](const SCEV *X) { return isa<SCEVUnknown>(X); }))
11026+ recordRuntimePredicate(S);
11027+ return true;
11028+ }
1107311029
11074- LLVM_DEBUG(dbgs() << "SCEV node not handled yet: " << *V << "\n");
11030+ LLVM_DEBUG(dbgs() << "SCEV node not handled yet in isKnownMultipleOf: " << *S
11031+ << "\n");
1107511032 return false;
1107611033}
1107711034
0 commit comments