@@ -10971,107 +10971,64 @@ bool ScalarEvolution::isKnownToBeAPowerOfTwo(const SCEV *S, bool OrZero,
10971
10971
return all_of(Mul->operands(), NonRecursive) && (OrZero || isKnownNonZero(S));
10972
10972
}
10973
10973
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);
10979
10986
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)) {
10981
10989
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
+ }
11005
10992
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);
11039
11000
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;
11062
11015
};
11063
11016
11064
11017
// 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
+ }
11067
11022
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
+ }
11073
11029
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");
11075
11032
return false;
11076
11033
}
11077
11034
0 commit comments