65#define DEBUG_TYPE "da"
71STATISTIC(NonlinearSubscriptPairs,
"Nonlinear subscript pairs");
74STATISTIC(StrongSIVapplications,
"Strong SIV applications");
75STATISTIC(StrongSIVsuccesses,
"Strong SIV successes");
76STATISTIC(StrongSIVindependence,
"Strong SIV independence");
77STATISTIC(WeakCrossingSIVapplications,
"Weak-Crossing SIV applications");
78STATISTIC(WeakCrossingSIVsuccesses,
"Weak-Crossing SIV successes");
79STATISTIC(WeakCrossingSIVindependence,
"Weak-Crossing SIV independence");
80STATISTIC(ExactSIVapplications,
"Exact SIV applications");
82STATISTIC(ExactSIVindependence,
"Exact SIV independence");
83STATISTIC(WeakZeroSIVapplications,
"Weak-Zero SIV applications");
84STATISTIC(WeakZeroSIVsuccesses,
"Weak-Zero SIV successes");
85STATISTIC(WeakZeroSIVindependence,
"Weak-Zero SIV independence");
86STATISTIC(ExactRDIVapplications,
"Exact RDIV applications");
87STATISTIC(ExactRDIVindependence,
"Exact RDIV independence");
91STATISTIC(BanerjeeApplications,
"Banerjee applications");
92STATISTIC(BanerjeeIndependence,
"Banerjee independence");
94STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
98 cl::desc(
"Try to delinearize array references."));
100 "da-disable-delinearization-checks",
cl::Hidden,
102 "Disable checks that try to statically verify validity of "
103 "delinearized subscripts. Enabling this option may result in incorrect "
104 "dependence vectors for languages that allow the subscript of one "
105 "dimension to underflow or overflow into another dimension."));
109 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
110 "explore MIV direction vectors."));
115enum class DependenceTestType {
129 "da-enable-dependence-test",
cl::init(DependenceTestType::All),
131 cl::desc(
"Run only specified dependence test routine and disable others. "
132 "The purpose is mainly to exclude the influence of other "
133 "dependence test routines in regression tests. If set to All, all "
134 "dependence test routines are enabled."),
136 "Enable all dependence test routines."),
137 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
138 "Enable only Strong SIV test."),
139 clEnumValN(DependenceTestType::WeakCrossingSIV,
141 "Enable only Weak-Crossing SIV test."),
142 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
143 "Enable only Exact SIV test."),
144 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
145 "Enable only Weak-Zero SIV test."),
146 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
147 "Enable only Exact RDIV test."),
148 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
149 "Enable only GCD MIV test."),
150 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
151 "Enable only Banerjee MIV test.")));
167 "Dependence Analysis",
true,
true)
212struct OverflowSafeSignedAPInt {
213 OverflowSafeSignedAPInt() :
Value(
std::nullopt) {}
214 OverflowSafeSignedAPInt(
const APInt &V) :
Value(V) {}
215 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
217 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
219 return OverflowSafeSignedAPInt();
223 return OverflowSafeSignedAPInt();
224 return OverflowSafeSignedAPInt(Result);
229 return OverflowSafeSignedAPInt();
230 return *
this + fromInt(
RHS);
233 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
235 return OverflowSafeSignedAPInt();
239 return OverflowSafeSignedAPInt();
240 return OverflowSafeSignedAPInt(Result);
245 return OverflowSafeSignedAPInt();
246 return *
this - fromInt(
RHS);
249 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
251 return OverflowSafeSignedAPInt();
255 return OverflowSafeSignedAPInt();
256 return OverflowSafeSignedAPInt(Result);
259 OverflowSafeSignedAPInt
operator-()
const {
261 return OverflowSafeSignedAPInt();
262 if (
Value->isMinSignedValue())
263 return OverflowSafeSignedAPInt();
264 return OverflowSafeSignedAPInt(-*
Value);
267 operator bool()
const {
return Value.has_value(); }
276 const APInt *operator->()
const {
284 std::optional<APInt>
Value;
286 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
288 return OverflowSafeSignedAPInt(
289 APInt(
Value->getBitWidth(), V,
true));
301 bool NormalizeResults) {
302 auto *
F = DA->getFunction();
306 if (SrcI->mayReadOrWriteMemory()) {
309 if (DstI->mayReadOrWriteMemory()) {
310 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
311 OS <<
" da analyze - ";
312 if (
auto D = DA->depends(&*SrcI, &*DstI,
318 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
319 const SCEV *Distance =
D->getDistance(Level);
320 bool IsDistanceZero = Distance && Distance->
isZero();
323 assert(IsDistanceZero == IsDirectionEQ &&
324 "Inconsistent distance and direction.");
329 if (NormalizeResults &&
D->normalize(&SE))
330 OS <<
"normalized - ";
349 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
362 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
367 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
372 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
377 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
391 bool PossiblyLoopIndependent,
392 unsigned CommonLevels)
393 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
394 LoopIndependent(PossiblyLoopIndependent) {
397 DV = std::make_unique<
DVEntry[]>(CommonLevels);
416 for (
unsigned Level = 1; Level <= Levels; ++Level) {
417 unsigned char Direction = DV[Level - 1].Direction;
430 for (
unsigned Level = 1; Level <= Levels; ++Level) {
431 unsigned char Direction = DV[Level - 1].Direction;
439 DV[Level - 1].Direction = RevDirection;
441 if (DV[Level - 1].Distance !=
nullptr)
450 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
453 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
483 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
484 "Level out of range");
485 return Level > Levels;
506 if (SameSDLevels > 0) {
507 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
514 if (!Assumptions.isAlwaysTrue()) {
515 OS <<
" Runtime Assumptions:\n";
516 Assumptions.print(OS, 2);
525 bool OnSameSD =
false;
526 unsigned LevelNum = Levels;
528 LevelNum += SameSDLevels;
530 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
601 return LI->isUnordered();
603 return SI->isUnordered();
611bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
612 const Loop *DstLoop)
const {
613 if (SrcLoop == DstLoop)
623 const SCEV *SrcUB = SE->getBackedgeTakenCount(SrcLoop);
624 const SCEV *DstUB = SE->getBackedgeTakenCount(DstLoop);
629 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
630 DstUB = SE->getNoopOrZeroExtend(DstUB, WiderType);
702void DependenceInfo::establishNestingLevels(
const Instruction *Src,
704 const BasicBlock *SrcBlock = Src->getParent();
705 const BasicBlock *DstBlock = Dst->getParent();
706 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
707 unsigned DstLevel = LI->getLoopDepth(DstBlock);
708 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
709 const Loop *DstLoop = LI->getLoopFor(DstBlock);
710 SrcLevels = SrcLevel;
711 MaxLevels = SrcLevel + DstLevel;
713 while (SrcLevel > DstLevel) {
717 while (DstLevel > SrcLevel) {
722 const Loop *SrcUncommonFrontier =
nullptr, *DstUncommonFrontier =
nullptr;
725 while (SrcLoop != DstLoop) {
726 SrcUncommonFrontier = SrcLoop;
727 DstUncommonFrontier = DstLoop;
732 if (SrcUncommonFrontier && DstUncommonFrontier &&
733 haveSameSD(SrcUncommonFrontier, DstUncommonFrontier))
735 CommonLevels = SrcLevel;
736 MaxLevels -= CommonLevels;
741unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
747unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
749 if (
D > CommonLevels)
752 return D - CommonLevels + SrcLevels;
779 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
791 return isLoopInvariant(Expr, LoopNest);
798 const Loop *
L = LoopNest;
799 while (L && AddRec->
getLoop() != L)
800 L =
L->getParentLoop();
809 if (!isLoopInvariant(Step, LoopNest))
815 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
820bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
822 return checkSubscript(Src, LoopNest,
Loops,
true);
827bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
829 return checkSubscript(Dst, LoopNest,
Loops,
false);
835DependenceInfo::Subscript::ClassificationKind
836DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
837 const SCEV *Dst,
const Loop *DstLoopNest,
839 SmallBitVector SrcLoops(MaxLevels + 1);
840 SmallBitVector DstLoops(MaxLevels + 1);
841 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
842 return Subscript::NonLinear;
843 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
844 return Subscript::NonLinear;
847 unsigned N =
Loops.count();
849 return Subscript::ZIV;
851 return Subscript::SIV;
852 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
853 return Subscript::RDIV;
854 return Subscript::MIV;
864const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
865 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
866 const SCEV *UB = SE->getBackedgeTakenCount(L);
867 return SE->getTruncateOrZeroExtend(UB,
T);
875DependenceInfo::collectNonNegativeConstantUpperBound(
const Loop *L,
877 if (
const SCEV *UB = collectUpperBound(L,
T))
879 APInt Res =
C->getAPInt();
912bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
960 bool UnderRuntimeAssumptions) {
964 const SCEV *Coeff = Src->getStepRecurrence(*SE);
965 assert(Coeff == Dst->getStepRecurrence(*SE) &&
966 "Expecting same coefficient in Strong SIV test");
967 const SCEV *SrcConst = Src->getStart();
968 const SCEV *DstConst = Dst->getStart();
976 ++StrongSIVapplications;
977 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
990 APInt Distance = ConstDelta;
991 APInt Remainder = ConstDelta;
996 if (Remainder != 0) {
998 ++StrongSIVindependence;
999 ++StrongSIVsuccesses;
1002 Result.DV[
Level].Distance = SE->getConstant(Distance);
1003 if (Distance.
sgt(0))
1005 else if (Distance.
slt(0))
1009 ++StrongSIVsuccesses;
1010 }
else if (Delta->
isZero()) {
1014 if (SE->isKnownNonZero(Coeff)) {
1016 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1019 if (UnderRuntimeAssumptions) {
1020 const SCEVPredicate *Pred = SE->getComparePredicate(
1022 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1028 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1029 <<
" != 0, but not allowed. Failing this test.\n");
1036 ++StrongSIVsuccesses;
1038 if (Coeff->
isOne()) {
1044 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1045 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1046 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1047 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1048 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1053 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1054 (DeltaMaybeNegative && CoeffMaybeNegative))
1058 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1059 (DeltaMaybePositive && CoeffMaybeNegative))
1061 if (NewDirection <
Result.DV[Level].Direction)
1062 ++StrongSIVsuccesses;
1096bool DependenceInfo::weakCrossingSIVtest(
const SCEVAddRecExpr *Src,
1103 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1104 const SCEV *SrcConst = Src->getStart();
1105 const SCEV *DstConst = Dst->getStart();
1107 assert(Coeff == SE->getNegativeSCEV(Dst->getStepRecurrence(*SE)) &&
1108 "Unexpected input for weakCrossingSIVtest");
1114 ++WeakCrossingSIVapplications;
1115 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1130 ConstantRange SrcRange = SE->getSignedRange(Src);
1131 ConstantRange DstRange = SE->getSignedRange(Dst);
1136 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1137 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1138 ++WeakCrossingSIVsuccesses;
1139 if (!
Result.DV[Level].Direction) {
1140 ++WeakCrossingSIVindependence;
1148 APInt APDelta = ConstDelta->
getAPInt();
1149 APInt APCoeff = ConstCoeff->
getAPInt();
1150 APInt Distance = APDelta;
1151 APInt Remainder = APDelta;
1154 if (Remainder != 0) {
1156 ++WeakCrossingSIVindependence;
1157 ++WeakCrossingSIVsuccesses;
1165 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1166 ++WeakCrossingSIVsuccesses;
1189 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1190 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1198 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1199 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1206 X = AM.
slt(0) ? -A1 : A1;
1207 Y = BM.
slt(0) ? B1 : -B1;
1217static OverflowSafeSignedAPInt
1219 const OverflowSafeSignedAPInt &OB) {
1221 return OverflowSafeSignedAPInt();
1230 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1232 return OverflowSafeSignedAPInt(Q) - 1;
1235static OverflowSafeSignedAPInt
1237 const OverflowSafeSignedAPInt &OB) {
1239 return OverflowSafeSignedAPInt();
1248 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1249 return OverflowSafeSignedAPInt(Q) + 1;
1283static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1285 OverflowSafeSignedAPInt UB) {
1286 assert(
A &&
B &&
"A and B must be available");
1287 assert(*
A != 0 &&
"A must be non-zero");
1288 assert((!UB || UB->isNonNegative()) &&
"UB must be non-negative");
1289 OverflowSafeSignedAPInt TL, TU;
1292 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1296 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1299 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1303 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1305 return std::make_pair(TL, TU);
1334 ++ExactSIVapplications;
1335 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1337 bool Res = exactTestImpl(Src, Dst, Result, Level);
1339 ++ExactSIVsuccesses;
1340 ++ExactSIVindependence;
1350 return ConstDividend.
srem(ConstDivisor) == 0;
1353bool DependenceInfo::weakZeroSIVtestImpl(
const SCEVAddRecExpr *AR,
1354 const SCEV *Const,
unsigned Level,
1357 const SCEV *ARConst = AR->
getStart();
1359 if (Const == ARConst && SE->isKnownNonZero(ARCoeff)) {
1360 if (Level < CommonLevels) {
1362 ++WeakZeroSIVsuccesses;
1374 if (
const SCEV *UpperBound =
1377 bool OverlapAtLast = [&] {
1378 if (!SE->isKnownNonZero(ConstCoeff))
1383 if (OverlapAtLast) {
1385 if (Level < CommonLevels) {
1387 ++WeakZeroSIVsuccesses;
1396 ++WeakZeroSIVindependence;
1397 ++WeakZeroSIVsuccesses;
1432bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *SrcConst,
1442 [[maybe_unused]]
const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1443 [[maybe_unused]]
const SCEV *DstConst = Dst->getStart();
1448 ++WeakZeroSIVapplications;
1449 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1458 bool Res = weakZeroSIVtestImpl(Dst, SrcConst, Level, Result);
1492bool DependenceInfo::weakZeroDstSIVtest(
const SCEVAddRecExpr *Src,
1493 const SCEV *DstConst,
unsigned Level,
1500 [[maybe_unused]]
const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1501 [[maybe_unused]]
const SCEV *SrcConst = Src->getStart();
1506 ++WeakZeroSIVapplications;
1507 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1510 return weakZeroSIVtestImpl(Src, DstConst, Level, Result);
1526 ++ExactRDIVapplications;
1527 bool Res = exactTestImpl(Src, Dst, Result, std::nullopt);
1529 ++ExactRDIVindependence;
1536 std::optional<unsigned> Level)
const {
1537 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1538 const SCEV *SrcConst = Src->getStart();
1539 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1540 const SCEV *DstConst = Dst->getStart();
1553 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1558 APInt AM = ConstSrcCoeff->
getAPInt();
1559 APInt BM = ConstDstCoeff->
getAPInt();
1570 std::optional<APInt> SrcUM =
1571 collectNonNegativeConstantUpperBound(Src->getLoop(), Delta->
getType());
1575 std::optional<APInt> DstUM =
1576 collectNonNegativeConstantUpperBound(Dst->getLoop(), Delta->
getType());
1582 APInt TC = CM.
sdiv(
G);
1607 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1608 const OverflowSafeSignedAPInt &V1,
1609 bool IsMin) -> std::optional<APInt> {
1616 return std::nullopt;
1619 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1620 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1621 if (!OptTL || !OptTU)
1624 TL = std::move(*OptTL);
1625 TU = std::move(*OptTU);
1634 assert(SrcUM == DstUM &&
"Expecting same upper bound for Src and Dst");
1638 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1639 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1643 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1644 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1646 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1647 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1650 if (!LowerDistance || !UpperDistance)
1653 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1654 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1656 if (LowerDistance->sle(0) && UpperDistance->sge(0))
1658 if (LowerDistance->slt(0))
1660 if (UpperDistance->sgt(0))
1678bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
1680 bool UnderRuntimeAssumptions) {
1685 if (SrcAddRec && DstAddRec) {
1688 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1689 [[maybe_unused]]
const Loop *CurDstLoop = DstAddRec->
getLoop();
1690 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
1691 "Loops in the SIV test should have the same iteration space and "
1693 Level = mapSrcLoop(CurSrcLoop);
1694 bool disproven =
false;
1695 if (SrcCoeff == DstCoeff)
1696 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
1697 UnderRuntimeAssumptions);
1698 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
1699 disproven = weakCrossingSIVtest(SrcAddRec, DstAddRec, Level, Result);
1700 return disproven || exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
1703 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1704 Level = mapSrcLoop(CurSrcLoop);
1705 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result);
1708 const Loop *CurDstLoop = DstAddRec->
getLoop();
1709 Level = mapDstLoop(CurDstLoop);
1710 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result);
1726bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
1732 assert(SrcAddRec && DstAddRec &&
"Unexpected non-addrec input");
1733 return exactRDIVtest(SrcAddRec, DstAddRec, Result) ||
1734 gcdMIVtest(Src, Dst, Result);
1740bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
1745 return gcdMIVtest(Src, Dst, Result) ||
1746 banerjeeMIVtest(Src, Dst,
Loops, Result);
1759 if (Product->hasNoSignedWrap())
1761 return std::nullopt;
1764bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
1765 const Loop *CurLoop,
1766 const SCEV *&CurLoopCoeff,
1767 APInt &RunningGCD)
const {
1770 if (RunningGCD == 1)
1775 assert(isLoopInvariant(Expr, CurLoop) &&
1776 "Expected loop invariant expression");
1783 if (AddRec->
getLoop() == CurLoop) {
1784 CurLoopCoeff = Step;
1798 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
1818 return Coefficients;
1838bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
1845 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
1865 if (ConstDelta == 0)
1868 APInt Remainder = ConstDelta.
srem(RunningGCD);
1869 if (Remainder != 0) {
1883 bool Improved =
false;
1884 const SCEV *Coefficients = Src;
1885 while (
const SCEVAddRecExpr *AddRec =
1888 const Loop *CurLoop = AddRec->
getLoop();
1891 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
1893 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
1894 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
1909 if (RunningGCD != 0) {
1910 Remainder = ConstDelta.
srem(RunningGCD);
1912 if (Remainder != 0) {
1913 unsigned Level = mapSrcLoop(CurLoop);
1914 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
1958bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
1965 ++BanerjeeApplications;
1969 collectCoeffInfo(Src,
true, A0,
A);
1973 collectCoeffInfo(Dst,
false, B0,
B);
1982 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
1983 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
1986 findBoundsALL(
A,
B, Bound, K);
2001 bool Disproved =
false;
2004 unsigned DepthExpanded = 0;
2006 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2008 bool Improved =
false;
2009 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2011 unsigned Old =
Result.DV[
K - 1].Direction;
2012 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2013 Improved |= Old !=
Result.DV[
K - 1].Direction;
2014 if (!
Result.DV[K - 1].Direction) {
2022 ++BanerjeeSuccesses;
2024 ++BanerjeeIndependence;
2028 ++BanerjeeIndependence;
2039unsigned DependenceInfo::exploreDirections(
2042 unsigned &DepthExpanded,
const SCEV *Delta)
const {
2048 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2049 "direction exploration is terminated.\n");
2050 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2056 if (Level > CommonLevels) {
2059 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2061 Bound[
K].DirSet |= Bound[
K].Direction;
2086 if (Level > DepthExpanded) {
2087 DepthExpanded =
Level;
2089 findBoundsLT(
A,
B, Bound, Level);
2090 findBoundsGT(
A,
B, Bound, Level);
2091 findBoundsEQ(
A,
B, Bound, Level);
2130 unsigned NewDeps = 0;
2134 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2139 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2144 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2150 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2155bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2157 const SCEV *Delta)
const {
2158 Bound[
Level].Direction = DirKind;
2159 if (
const SCEV *LowerBound = getLowerBound(Bound))
2162 if (
const SCEV *UpperBound = getUpperBound(Bound))
2191 if (Bound[K].Iterations) {
2193 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2195 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2200 SE->getZero(
A[K].Coeff->
getType());
2203 SE->getZero(
A[K].Coeff->
getType());
2230 if (Bound[K].Iterations) {
2231 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2232 const SCEV *NegativePart = getNegativePart(Delta);
2234 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2235 const SCEV *PositivePart = getPositivePart(Delta);
2237 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2241 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2242 const SCEV *NegativePart = getNegativePart(Delta);
2243 if (NegativePart->
isZero())
2245 const SCEV *PositivePart = getPositivePart(Delta);
2246 if (PositivePart->
isZero())
2272 if (Bound[K].Iterations) {
2273 const SCEV *Iter_1 = SE->getMinusSCEV(
2274 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2275 const SCEV *NegPart =
2276 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2278 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2279 const SCEV *PosPart =
2280 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2282 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2286 const SCEV *NegPart =
2287 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2290 const SCEV *PosPart =
2291 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2318 if (Bound[K].Iterations) {
2319 const SCEV *Iter_1 = SE->getMinusSCEV(
2320 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2321 const SCEV *NegPart =
2322 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2324 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2325 const SCEV *PosPart =
2326 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2328 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2332 const SCEV *NegPart =
2333 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2336 const SCEV *PosPart =
2337 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2344const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2345 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2349const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2350 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2356void DependenceInfo::collectCoeffInfo(
2359 const SCEV *
Zero = SE->getZero(Subscript->getType());
2360 CI.
resize(MaxLevels + 1);
2361 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2363 CI[
K].PosPart =
Zero;
2364 CI[
K].NegPart =
Zero;
2365 CI[
K].Iterations =
nullptr;
2369 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2371 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2372 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2373 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2379 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2386 if (CI[K].Iterations)
2401 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2402 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2416 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2417 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2436 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2437 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2438 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2439 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2440 const SCEVUnknown *SrcBase =
2442 const SCEVUnknown *DstBase =
2445 if (!SrcBase || !DstBase || SrcBase != DstBase)
2450 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2451 SrcSubscripts, DstSubscripts) &&
2452 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2453 SrcSubscripts, DstSubscripts))
2456 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2457 isLoopInvariant(DstBase, DstLoop) &&
2458 "Expected SrcBase and DstBase to be loop invariant");
2462 dbgs() <<
"\nSrcSubscripts: ";
2463 for (
int I = 0;
I <
Size;
I++)
2464 dbgs() << *SrcSubscripts[
I];
2465 dbgs() <<
"\nDstSubscripts: ";
2466 for (
int I = 0;
I <
Size;
I++)
2467 dbgs() << *DstSubscripts[
I];
2476 for (
int I = 0;
I <
Size; ++
I) {
2477 Pair[
I].Src = SrcSubscripts[
I];
2478 Pair[
I].Dst = DstSubscripts[
I];
2480 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2481 "Unexpected different types for the subscripts");
2490bool DependenceInfo::tryDelinearizeFixedSize(
2495 const SCEVUnknown *SrcBase =
2497 const SCEVUnknown *DstBase =
2499 assert(SrcBase && DstBase && SrcBase == DstBase &&
2500 "expected src and dst scev unknowns to be equal");
2503 const SCEV *ElemSize = SE->getElementSize(Src);
2504 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2507 SrcSubscripts, SrcSizes, ElemSize) ||
2509 DstSubscripts, DstSizes, ElemSize))
2514 if (SrcSizes.
size() != DstSizes.
size() ||
2515 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2516 SrcSubscripts.
clear();
2517 DstSubscripts.
clear();
2522 "Expected equal number of entries in the list of SrcSubscripts and "
2534 SrcSubscripts.
clear();
2535 DstSubscripts.
clear();
2540 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2547bool DependenceInfo::tryDelinearizeParametricSize(
2552 const SCEVUnknown *SrcBase =
2554 const SCEVUnknown *DstBase =
2556 assert(SrcBase && DstBase && SrcBase == DstBase &&
2557 "expected src and dst scev unknowns to be equal");
2559 const SCEV *ElementSize = SE->getElementSize(Src);
2560 if (ElementSize != SE->getElementSize(Dst))
2563 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2564 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2585 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2586 SrcSubscripts.
size() != DstSubscripts.
size())
2609 for (
unsigned VI : BV.
set_bits()) {
2619 FunctionAnalysisManager::Invalidator &Inv) {
2626 return Inv.invalidate<
AAManager>(F, PA) ||
2640std::unique_ptr<Dependence>
2642 bool UnderRuntimeAssumptions) {
2644 bool PossiblyLoopIndependent =
true;
2646 PossiblyLoopIndependent =
false;
2648 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2654 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2655 return std::make_unique<Dependence>(Src, Dst,
2667 return std::make_unique<Dependence>(Src, Dst,
2681 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2682 return std::make_unique<Dependence>(Src, Dst,
2688 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2689 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2692 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2693 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2694 if (SrcBase != DstBase) {
2701 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2702 return std::make_unique<Dependence>(Src, Dst,
2710 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2711 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2712 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2713 !isLoopInvariant(DstBase, DstLoop)) {
2714 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2715 return std::make_unique<Dependence>(Src, Dst,
2720 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2721 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2724 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2725 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2726 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2727 return std::make_unique<Dependence>(Src, Dst,
2732 if (!Assume.empty() && !UnderRuntimeAssumptions)
2733 return std::make_unique<Dependence>(Src, Dst,
2738 Pair[0].Src = SrcEv;
2739 Pair[0].Dst = DstEv;
2741 if (tryDelinearize(Src, Dst, Pair)) {
2743 Pairs = Pair.
size();
2748 establishNestingLevels(Src, Dst);
2750 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2751 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2752 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2755 CommonLevels += SameSDLevels;
2756 MaxLevels -= SameSDLevels;
2757 if (SameSDLevels > 0) {
2760 for (
unsigned P = 0;
P < Pairs; ++
P) {
2762 Subscript::ClassificationKind TestClass =
2763 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2764 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2766 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2767 TestClass != Subscript::RDIV) {
2769 CommonLevels -= SameSDLevels;
2770 MaxLevels += SameSDLevels;
2777 if (SameSDLevels > 0)
2781 PossiblyLoopIndependent, CommonLevels);
2784 for (
unsigned P = 0;
P < Pairs; ++
P) {
2785 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2786 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2787 Pair[
P].Loops.
resize(MaxLevels + 1);
2788 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2790 Pair[
P].Classification =
2791 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2792 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2793 Pair[
P].GroupLoops = Pair[
P].Loops;
2794 Pair[
P].Group.set(
P);
2804 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2813 switch (Pair[
SI].Classification) {
2814 case Subscript::NonLinear:
2816 ++NonlinearSubscriptPairs;
2817 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2819 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2822 case Subscript::ZIV:
2824 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2827 case Subscript::SIV: {
2830 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2831 UnderRuntimeAssumptions))
2835 case Subscript::RDIV:
2837 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2840 case Subscript::MIV:
2842 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2850 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2851 CompleteLoops |= Pair[
SI].
Loops;
2852 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2853 if (CompleteLoops[
II])
2854 Result.DV[
II - 1].Scalar =
false;
2859 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2861 if (Result.DV[
II - 1].Distance ==
nullptr)
2862 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2864 assert(Result.DV[
II - 1].Distance->isZero() &&
2865 "Inconsistency between distance and direction");
2871 const SCEV *Distance = Result.getDistance(
II);
2872 if (Distance && Distance->
isZero())
2874 "Distance is zero, but direction is not EQ");
2878 if (SameSDLevels > 0) {
2881 assert(CommonLevels >= SameSDLevels);
2882 CommonLevels -= SameSDLevels;
2883 MaxLevels += SameSDLevels;
2884 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2885 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2886 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2887 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2888 DV[Level] = Result.DV[Level];
2889 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2890 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2891 Result.DV = std::move(DV);
2892 Result.DVSameSD = std::move(DVSameSD);
2893 Result.Levels = CommonLevels;
2894 Result.SameSDLevels = SameSDLevels;
2897 if (PossiblyLoopIndependent) {
2901 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2903 Result.LoopIndependent =
false;
2911 bool AllEqual =
true;
2912 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2918 if (AllEqual && Result.Assumptions.getPredicates().empty())
2922 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isLoadOrStore(const Instruction *I)
static OverflowSafeSignedAPInt floorOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
static OverflowSafeSignedAPInt ceilingOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static bool isDependenceTestEnabled(DependenceTestType Test)
Returns true iff Test is enabled.
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static std::pair< OverflowSafeSignedAPInt, OverflowSafeSignedAPInt > inferDomainOfAffine(OverflowSafeSignedAPInt A, OverflowSafeSignedAPInt B, OverflowSafeSignedAPInt UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::All), cl::ReallyHidden, cl::desc("Run only specified dependence test routine and disable others. " "The purpose is mainly to exclude the influence of other " "dependence test routines in regression tests. If set to All, all " "dependence test routines are enabled."), cl::values(clEnumValN(DependenceTestType::All, "all", "Enable all dependence test routines."), clEnumValN(DependenceTestType::StrongSIV, "strong-siv", "Enable only Strong SIV test."), clEnumValN(DependenceTestType::WeakCrossingSIV, "weak-crossing-siv", "Enable only Weak-Crossing SIV test."), clEnumValN(DependenceTestType::ExactSIV, "exact-siv", "Enable only Exact SIV test."), clEnumValN(DependenceTestType::WeakZeroSIV, "weak-zero-siv", "Enable only Weak-Zero SIV test."), clEnumValN(DependenceTestType::ExactRDIV, "exact-rdiv", "Enable only Exact RDIV test."), clEnumValN(DependenceTestType::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
static const SCEV * analyzeCoefficientsForGCD(const SCEV *Coefficients, APInt &RunningGCD, ScalarEvolution *SE)
Compute RunningGCD and return the start value of the innermost SCEVAddRecExpr.
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< unsigned > MIVMaxLevelThreshold("da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors."))
static cl::opt< bool > DisableDelinearizationChecks("da-disable-delinearization-checks", cl::Hidden, cl::desc("Disable checks that try to statically verify validity of " "delinearized subscripts. Enabling this option may result in incorrect " "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension."))
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
static LLVM_ABI void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
APInt abs() const
Get the absolute value.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
@ ICMP_SGT
signed greater than
This class represents a range of values.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns the runtime assumptions under which this Dependence relation is valid...
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
virtual unsigned getDirection(unsigned Level, bool SameSD=false) const
getDirection - Returns the direction associated with a particular common or SameSD level.
virtual bool isScalar(unsigned Level, bool SameSD=false) const
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
virtual bool inSameSDLoops(unsigned Level) const
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
unsigned getDirection(unsigned Level, bool SameSD=false) const override
getDirection - Returns the direction associated with a particular common or SameSD level.
bool isScalar(unsigned Level, bool SameSD=false) const override
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isDirectionNegative() const override
Check if the direction vector is negative.
void negate(ScalarEvolution &SE) override
Negate the dependence by swapping the source and destination, and reversing the direction and distanc...
const SCEV * getDistance(unsigned Level, bool SameSD=false) const override
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
DVEntry getDVEntry(unsigned Level, bool IsSameSD) const
getDVEntry - Returns the DV entry associated with a regular or a SameSD level.
bool inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
This class represents a constant integer value.
const APInt & getAPInt() const
bool hasNoSignedWrap() const
This class represents a composition of other SCEV predicates, and is the class that most clients will...
This class represents an analyzed expression in the program.
LLVM_ABI bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
constexpr bool operator!(E Val)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
APInt operator+(APInt a, const APInt &b)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...