Skip to content

Commit 0eae7f0

Browse files
committed
move isKnownMultipleOf to ScalarEvolution
1 parent 92f6b4f commit 0eae7f0

File tree

3 files changed

+113
-112
lines changed

3 files changed

+113
-112
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,13 @@ class ScalarEvolution {
10441044
bool isKnownToBeAPowerOfTwo(const SCEV *S, bool OrZero = false,
10451045
bool OrNegative = false);
10461046

1047+
/// Check that memory access offsets in V are multiples of array element size
1048+
/// EltSize. Param records the first parametric expression. If the scalar
1049+
/// evolution V contains two or more parameters, we check that the subsequent
1050+
/// parametric expressions are multiples of the first parametric expression
1051+
/// Param.
1052+
bool isKnownMultipleOf(const SCEV *V, const SCEV *&Param, uint64_t EltSize);
1053+
10471054
/// Splits SCEV expression \p S into two SCEVs. One of them is obtained from
10481055
/// \p S by substitution of all AddRec sub-expression related to loop \p L
10491056
/// with initial value of that SCEV. The second is obtained from \p S by

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -3569,116 +3569,6 @@ bool DependenceInfo::invalidate(Function &F, const PreservedAnalyses &PA,
35693569
Inv.invalidate<LoopAnalysis>(F, PA);
35703570
}
35713571

3572-
/// Check that memory access offsets in V are multiples of array element size
3573-
/// EltSize. Param records the first parametric expression. If the scalar
3574-
/// evolution V contains two or more parameters, we check that the subsequent
3575-
/// parametric expressions are multiples of the first parametric expression
3576-
/// Param.
3577-
static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3578-
uint64_t EltSize) {
3579-
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
3580-
return checkOffsets(SE, AddRec->getStart(), Param, EltSize) &&
3581-
checkOffsets(SE, AddRec->getStepRecurrence(*SE), Param, EltSize);
3582-
}
3583-
if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
3584-
APInt C = Cst->getAPInt();
3585-
3586-
// For example, alias_with_different_offsets in
3587-
// test/Analysis/DependenceAnalysis/DifferentOffsets.ll accesses "%A + 2":
3588-
// %arrayidx = getelementptr inbounds i8, ptr %A, i64 2
3589-
// store i32 42, ptr %arrayidx, align 1
3590-
// which is writing an i32, i.e., EltSize = 4 bytes, with an offset C = 2.
3591-
// checkOffsets returns false, as the offset C=2 is not a multiple of 4.
3592-
return C.srem(EltSize) == 0;
3593-
}
3594-
3595-
// Use a lambda helper function to check V for parametric expressions.
3596-
// Param records the first parametric expression. If the scalar evolution V
3597-
// contains two or more parameters, we check that the subsequent parametric
3598-
// expressions are multiples of the first parametric expression Param.
3599-
auto checkParamsMultipleOfSize = [&](const SCEV *V,
3600-
const SCEV *&Param) -> bool {
3601-
if (EltSize == 1)
3602-
return true;
3603-
if (!Param) {
3604-
Param = V;
3605-
return true;
3606-
}
3607-
if (Param == V)
3608-
return true;
3609-
3610-
// Check whether "(Param - V) % Size == 0".
3611-
const SCEV *Diff = SE->getMinusSCEV(Param, V);
3612-
if (auto *Cst = dyn_cast<SCEVConstant>(Diff)) {
3613-
APInt Val = Cst->getAPInt();
3614-
if (Val.isZero())
3615-
return true;
3616-
auto Rem = Val.srem(APInt(Val.getBitWidth(), EltSize, /*isSigned=*/true));
3617-
if (Rem.isZero())
3618-
// For example in test/Analysis/DependenceAnalysis/Preliminary.ll
3619-
// SrcSCEV = ((4 * (sext i8 %n to i64))<nsw> + %A)
3620-
// DstSCEV = (4 + (4 * (sext i8 %n to i64))<nsw> + %A)
3621-
// Param = (4 * (sext i8 %n to i64))<nsw>
3622-
// V = 4 + (4 * (sext i8 %n to i64))<nsw>
3623-
// Diff = -4, Rem = 0, and so all offsets are multiple of 4.
3624-
return true;
3625-
LLVM_DEBUG(dbgs() << "SCEV with different offsets: " << *Param << " - "
3626-
<< *V << " = " << *Diff << " % " << EltSize << " = "
3627-
<< Rem << " != 0\n");
3628-
return false;
3629-
}
3630-
// Check if the symbolic difference is a multiple of Size.
3631-
const SCEV *Val =
3632-
SE->getConstant(APInt(Diff->getType()->getScalarSizeInBits(), EltSize));
3633-
3634-
// Check by using the remainder computation.
3635-
const SCEV *Remainder = SE->getURemExpr(Diff, Val);
3636-
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
3637-
if (C->getValue()->isZero())
3638-
// For example test/Analysis/DependenceAnalysis/DADelin.ll
3639-
// SrcSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
3640-
// DstSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
3641-
// The strides '(4 * %m * %o)' and '(4 * %o)' are multiple of 4.
3642-
return true;
3643-
3644-
// Check by using the division computation.
3645-
const SCEV *Q = SE->getUDivExpr(Diff, Val);
3646-
const SCEV *Product = SE->getMulExpr(Q, Val);
3647-
if (Diff == Product)
3648-
return true;
3649-
LLVM_DEBUG(dbgs() << "SCEV with different offsets:\n"
3650-
<< *Param << " - " << *V << " = " << *Diff << "\n"
3651-
<< "Remainder = " << *Remainder << "\n"
3652-
<< "Q = " << *Q << " Product = " << *Product << "\n");
3653-
// For example in test/Analysis/DependenceAnalysis/MIVCheckConst.ll
3654-
// SrcSCEV = {(80640 + (4 * (1 + %n) * %v1) + %A),+,(8 * %v1)}<%bb13>
3655-
// DstSCEV = {(126720 + (128 * %m) + %A),+,256}<%bb13>
3656-
// We fail to prove that the offsets 80640 + (4 * (1 + %n) * %v1) and
3657-
// (8 * %v1) are multiples of 128.
3658-
// Param = 80640 + (4 * (1 + %n) * %v1)
3659-
// (80640 + (4 * (1 + %n) * %v1)) - (8 * %v1) =
3660-
// (80640 + ((-4 + (4 * %n)) * %v1))
3661-
// Remainder = (zext i7 ((trunc i32 %v1 to i7) *
3662-
// (-4 + (4 * (trunc i32 %n to i7)))) to i32)
3663-
// Q = ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128)
3664-
// Product = (128 * ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128))<nuw>
3665-
return false;
3666-
};
3667-
3668-
// Expressions like "n".
3669-
if (isa<SCEVUnknown>(V))
3670-
return checkParamsMultipleOfSize(V, Param);
3671-
3672-
// Expressions like "n + 1".
3673-
if (isa<SCEVAddExpr>(V) || isa<SCEVMulExpr>(V))
3674-
return !SCEVExprContains(V, [](const SCEV *S) {
3675-
return isa<SCEVUnknown>(S);
3676-
}) || checkParamsMultipleOfSize(V, Param);
3677-
3678-
LLVM_DEBUG(dbgs() << "SCEV node not handled yet: " << *V << "\n");
3679-
return false;
3680-
}
3681-
36823572
// depends -
36833573
// Returns NULL if there is no dependence.
36843574
// Otherwise, return a Dependence with as many details as possible.
@@ -3758,8 +3648,8 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
37583648

37593649
if (Src != Dst) {
37603650
// Check that memory access offsets are multiples of element sizes.
3761-
if (!checkOffsets(SE, SrcEv, Param, EltSize) ||
3762-
!checkOffsets(SE, DstEv, Param, EltSize)) {
3651+
if (!SE->isKnownMultipleOf(SrcEv, Param, EltSize) ||
3652+
!SE->isKnownMultipleOf(DstEv, Param, EltSize)) {
37633653
LLVM_DEBUG(dbgs() << "can't analyze SCEV with different offsets\n");
37643654
return std::make_unique<Dependence>(Src, Dst);
37653655
}

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10971,6 +10971,110 @@ 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);
10979+
10980+
if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
10981+
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;
11005+
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;
11039+
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;
11062+
};
11063+
11064+
// Expressions like "n".
11065+
if (isa<SCEVUnknown>(V))
11066+
return checkParamsMultipleOfSize(V, Param);
11067+
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);
11073+
11074+
LLVM_DEBUG(dbgs() << "SCEV node not handled yet: " << *V << "\n");
11075+
return false;
11076+
}
11077+
1097411078
std::pair<const SCEV *, const SCEV *>
1097511079
ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, const SCEV *S) {
1097611080
// Compute SCEV on entry of loop L.

0 commit comments

Comments
 (0)