Skip to content

Commit c7b5c98

Browse files
committed
move isKnownMultipleOf to ScalarEvolution
1 parent f81e32c commit c7b5c98

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
@@ -10983,6 +10983,110 @@ bool ScalarEvolution::isKnownToBeAPowerOfTwo(const SCEV *S, bool OrZero,
1098310983
return all_of(Mul->operands(), NonRecursive) && (OrZero || isKnownNonZero(S));
1098410984
}
1098510985

10986+
bool ScalarEvolution::isKnownMultipleOf(const SCEV *V, const SCEV *&Param,
10987+
uint64_t EltSize) {
10988+
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V))
10989+
return isKnownMultipleOf(AddRec->getStart(), Param, EltSize) &&
10990+
isKnownMultipleOf(AddRec->getStepRecurrence(*this), Param, EltSize);
10991+
10992+
if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
10993+
APInt C = Cst->getAPInt();
10994+
// For example, alias_with_different_offsets in
10995+
// test/Analysis/DependenceAnalysis/DifferentOffsets.ll accesses "%A + 2":
10996+
// %arrayidx = getelementptr inbounds i8, ptr %A, i64 2
10997+
// store i32 42, ptr %arrayidx, align 1
10998+
// which is writing an i32, i.e., EltSize = 4 bytes, with an offset C = 2.
10999+
// isKnownMultipleOf returns false, as C=2 is not a multiple of 4.
11000+
return C.urem(EltSize) == 0;
11001+
}
11002+
11003+
// Use a lambda helper function to check V for parametric expressions.
11004+
// Param records the first parametric expression. If the scalar evolution V
11005+
// contains two or more parameters, we check that the subsequent parametric
11006+
// expressions are multiples of the first parametric expression Param.
11007+
auto checkParamsMultipleOfSize = [&](const SCEV *V,
11008+
const SCEV *&Param) -> bool {
11009+
if (EltSize == 1)
11010+
return true;
11011+
if (!Param) {
11012+
Param = V;
11013+
return true;
11014+
}
11015+
if (Param == V)
11016+
return true;
11017+
11018+
// Check whether "(Param - V) % Size == 0".
11019+
const SCEV *Diff = getMinusSCEV(Param, V);
11020+
if (auto *Cst = dyn_cast<SCEVConstant>(Diff)) {
11021+
APInt Val = Cst->getAPInt();
11022+
if (Val.isZero())
11023+
return true;
11024+
APInt Rem = Val.urem(APInt(Val.getBitWidth(), EltSize, /*isSigned=*/true));
11025+
if (Rem.isZero())
11026+
// For example in test/Analysis/DependenceAnalysis/Preliminary.ll
11027+
// SrcSCEV = ((4 * (sext i8 %n to i64))<nsw> + %A)
11028+
// DstSCEV = (4 + (4 * (sext i8 %n to i64))<nsw> + %A)
11029+
// Param = (4 * (sext i8 %n to i64))<nsw>
11030+
// V = 4 + (4 * (sext i8 %n to i64))<nsw>
11031+
// Diff = -4, Rem = 0, and so all offsets are multiple of 4.
11032+
return true;
11033+
LLVM_DEBUG(dbgs() << "SCEV with different offsets: " << *Param << " - "
11034+
<< *V << " = " << *Diff << " % " << EltSize << " = "
11035+
<< Rem << " != 0\n");
11036+
return false;
11037+
}
11038+
// Check if the symbolic difference is a multiple of Size.
11039+
const SCEV *Val =
11040+
getConstant(APInt(Diff->getType()->getScalarSizeInBits(), EltSize));
11041+
11042+
// Check by using the remainder computation.
11043+
const SCEV *Remainder = getURemExpr(Diff, Val);
11044+
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
11045+
if (C->getValue()->isZero())
11046+
// For example test/Analysis/DependenceAnalysis/DADelin.ll
11047+
// SrcSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
11048+
// DstSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
11049+
// The strides '(4 * %m * %o)' and '(4 * %o)' are multiple of 4.
11050+
return true;
11051+
11052+
// Check by using the division computation.
11053+
const SCEV *Q = getUDivExpr(Diff, Val);
11054+
const SCEV *Product = getMulExpr(Q, Val);
11055+
if (Diff == Product)
11056+
return true;
11057+
LLVM_DEBUG(dbgs() << "SCEV with different offsets:\n"
11058+
<< *Param << " - " << *V << " = " << *Diff << "\n"
11059+
<< "Remainder = " << *Remainder << "\n"
11060+
<< "Q = " << *Q << " Product = " << *Product << "\n");
11061+
// For example in test/Analysis/DependenceAnalysis/MIVCheckConst.ll
11062+
// SrcSCEV = {(80640 + (4 * (1 + %n) * %v1) + %A),+,(8 * %v1)}<%bb13>
11063+
// DstSCEV = {(126720 + (128 * %m) + %A),+,256}<%bb13>
11064+
// We fail to prove that the offsets 80640 + (4 * (1 + %n) * %v1) and
11065+
// (8 * %v1) are multiples of 128.
11066+
// Param = 80640 + (4 * (1 + %n) * %v1)
11067+
// (80640 + (4 * (1 + %n) * %v1)) - (8 * %v1) =
11068+
// (80640 + ((-4 + (4 * %n)) * %v1))
11069+
// Remainder = (zext i7 ((trunc i32 %v1 to i7) *
11070+
// (-4 + (4 * (trunc i32 %n to i7)))) to i32)
11071+
// Q = ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128)
11072+
// Product = (128 * ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128))<nuw>
11073+
return false;
11074+
};
11075+
11076+
// Expressions like "n".
11077+
if (isa<SCEVUnknown>(V))
11078+
return checkParamsMultipleOfSize(V, Param);
11079+
11080+
// Expressions like "n + 1".
11081+
if (isa<SCEVAddExpr>(V) || isa<SCEVMulExpr>(V))
11082+
return !SCEVExprContains(V, [](const SCEV *S) {
11083+
return isa<SCEVUnknown>(S);
11084+
}) || checkParamsMultipleOfSize(V, Param);
11085+
11086+
LLVM_DEBUG(dbgs() << "SCEV node not handled yet: " << *V << "\n");
11087+
return false;
11088+
}
11089+
1098611090
std::pair<const SCEV *, const SCEV *>
1098711091
ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, const SCEV *S) {
1098811092
// Compute SCEV on entry of loop L.

0 commit comments

Comments
 (0)