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 {
130 "da-enable-dependence-test",
cl::init(DependenceTestType::Default),
132 cl::desc(
"Run only specified dependence test routine and disable others. "
133 "The purpose is mainly to exclude the influence of other "
134 "dependence test routines in regression tests. If set to All, all "
135 "dependence test routines are enabled."),
137 "Enable all dependence test routines except "
138 "Banerjee MIV (default)."),
140 "Enable all dependence test routines."),
141 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
142 "Enable only Strong SIV test."),
143 clEnumValN(DependenceTestType::WeakCrossingSIV,
145 "Enable only Weak-Crossing SIV test."),
146 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
147 "Enable only Exact SIV test."),
148 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
149 "Enable only Weak-Zero SIV test."),
150 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
151 "Enable only Exact RDIV test."),
152 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
153 "Enable only GCD MIV test."),
154 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
155 "Enable only Banerjee MIV test.")));
171 "Dependence Analysis",
true,
true)
216struct OverflowSafeSignedAPInt {
217 OverflowSafeSignedAPInt() :
Value(
std::nullopt) {}
218 OverflowSafeSignedAPInt(
const APInt &V) :
Value(V) {}
219 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
221 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
223 return OverflowSafeSignedAPInt();
227 return OverflowSafeSignedAPInt();
228 return OverflowSafeSignedAPInt(Result);
233 return OverflowSafeSignedAPInt();
234 return *
this + fromInt(
RHS);
237 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
239 return OverflowSafeSignedAPInt();
243 return OverflowSafeSignedAPInt();
244 return OverflowSafeSignedAPInt(Result);
249 return OverflowSafeSignedAPInt();
250 return *
this - fromInt(
RHS);
253 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
255 return OverflowSafeSignedAPInt();
259 return OverflowSafeSignedAPInt();
260 return OverflowSafeSignedAPInt(Result);
263 OverflowSafeSignedAPInt
operator-()
const {
265 return OverflowSafeSignedAPInt();
266 if (
Value->isMinSignedValue())
267 return OverflowSafeSignedAPInt();
268 return OverflowSafeSignedAPInt(-*
Value);
271 operator bool()
const {
return Value.has_value(); }
280 const APInt *operator->()
const {
288 std::optional<APInt>
Value;
290 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
292 return OverflowSafeSignedAPInt(
293 APInt(
Value->getBitWidth(), V,
true));
305 bool NormalizeResults) {
306 auto *
F = DA->getFunction();
310 if (SrcI->mayReadOrWriteMemory()) {
313 if (DstI->mayReadOrWriteMemory()) {
314 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
315 OS <<
" da analyze - ";
316 if (
auto D = DA->depends(&*SrcI, &*DstI,
322 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
323 const SCEV *Distance =
D->getDistance(Level);
324 bool IsDistanceZero = Distance && Distance->
isZero();
327 assert(IsDistanceZero == IsDirectionEQ &&
328 "Inconsistent distance and direction.");
333 if (NormalizeResults &&
D->normalize(&SE))
334 OS <<
"normalized - ";
353 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
366 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
371 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
376 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
381 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
395 bool PossiblyLoopIndependent,
396 unsigned CommonLevels)
397 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
398 LoopIndependent(PossiblyLoopIndependent) {
401 DV = std::make_unique<
DVEntry[]>(CommonLevels);
420 for (
unsigned Level = 1; Level <= Levels; ++Level) {
421 unsigned char Direction = DV[Level - 1].Direction;
434 for (
unsigned Level = 1; Level <= Levels; ++Level) {
435 unsigned char Direction = DV[Level - 1].Direction;
443 DV[Level - 1].Direction = RevDirection;
445 if (DV[Level - 1].Distance !=
nullptr)
454 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
457 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
487 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
488 "Level out of range");
489 return Level > Levels;
510 if (SameSDLevels > 0) {
511 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
518 if (!Assumptions.isAlwaysTrue()) {
519 OS <<
" Runtime Assumptions:\n";
520 Assumptions.print(OS, 2);
529 bool OnSameSD =
false;
530 unsigned LevelNum = Levels;
532 LevelNum += SameSDLevels;
534 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
605 return LI->isUnordered();
607 return SI->isUnordered();
615bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
616 const Loop *DstLoop)
const {
617 if (SrcLoop == DstLoop)
627 const SCEV *SrcUB = SE->getBackedgeTakenCount(SrcLoop);
628 const SCEV *DstUB = SE->getBackedgeTakenCount(DstLoop);
633 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
634 DstUB = SE->getNoopOrZeroExtend(DstUB, WiderType);
706void DependenceInfo::establishNestingLevels(
const Instruction *Src,
708 const BasicBlock *SrcBlock = Src->getParent();
709 const BasicBlock *DstBlock = Dst->getParent();
710 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
711 unsigned DstLevel = LI->getLoopDepth(DstBlock);
712 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
713 const Loop *DstLoop = LI->getLoopFor(DstBlock);
714 SrcLevels = SrcLevel;
715 MaxLevels = SrcLevel + DstLevel;
717 while (SrcLevel > DstLevel) {
721 while (DstLevel > SrcLevel) {
726 const Loop *SrcUncommonFrontier =
nullptr, *DstUncommonFrontier =
nullptr;
729 while (SrcLoop != DstLoop) {
730 SrcUncommonFrontier = SrcLoop;
731 DstUncommonFrontier = DstLoop;
736 if (SrcUncommonFrontier && DstUncommonFrontier &&
737 haveSameSD(SrcUncommonFrontier, DstUncommonFrontier))
739 CommonLevels = SrcLevel;
740 MaxLevels -= CommonLevels;
745unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
751unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
753 if (
D > CommonLevels)
756 return D - CommonLevels + SrcLevels;
783 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
795 return isLoopInvariant(Expr, LoopNest);
802 const Loop *
L = LoopNest;
803 while (L && AddRec->
getLoop() != L)
804 L =
L->getParentLoop();
813 if (!isLoopInvariant(Step, LoopNest))
819 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
824bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
826 return checkSubscript(Src, LoopNest,
Loops,
true);
831bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
833 return checkSubscript(Dst, LoopNest,
Loops,
false);
839DependenceInfo::Subscript::ClassificationKind
840DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
841 const SCEV *Dst,
const Loop *DstLoopNest,
843 SmallBitVector SrcLoops(MaxLevels + 1);
844 SmallBitVector DstLoops(MaxLevels + 1);
845 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
846 return Subscript::NonLinear;
847 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
848 return Subscript::NonLinear;
851 unsigned N =
Loops.count();
853 return Subscript::ZIV;
855 return Subscript::SIV;
856 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
857 return Subscript::RDIV;
858 return Subscript::MIV;
868const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
869 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
870 const SCEV *UB = SE->getBackedgeTakenCount(L);
871 return SE->getTruncateOrZeroExtend(UB,
T);
879DependenceInfo::collectNonNegativeConstantUpperBound(
const Loop *L,
881 if (
const SCEV *UB = collectUpperBound(L,
T))
883 APInt Res =
C->getAPInt();
907 return Test != DependenceTestType::BanerjeeMIV;
921bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
969 bool UnderRuntimeAssumptions) {
973 const SCEV *Coeff = Src->getStepRecurrence(*SE);
974 assert(Coeff == Dst->getStepRecurrence(*SE) &&
975 "Expecting same coefficient in Strong SIV test");
976 const SCEV *SrcConst = Src->getStart();
977 const SCEV *DstConst = Dst->getStart();
985 ++StrongSIVapplications;
986 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
999 APInt Distance = ConstDelta;
1000 APInt Remainder = ConstDelta;
1005 if (Remainder != 0) {
1007 ++StrongSIVindependence;
1008 ++StrongSIVsuccesses;
1011 Result.DV[
Level].Distance = SE->getConstant(Distance);
1012 if (Distance.
sgt(0))
1014 else if (Distance.
slt(0))
1018 ++StrongSIVsuccesses;
1019 }
else if (Delta->
isZero()) {
1023 if (SE->isKnownNonZero(Coeff)) {
1025 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1028 if (UnderRuntimeAssumptions) {
1029 const SCEVPredicate *Pred = SE->getComparePredicate(
1031 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1037 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1038 <<
" != 0, but not allowed. Failing this test.\n");
1045 ++StrongSIVsuccesses;
1047 if (Coeff->
isOne()) {
1053 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1054 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1055 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1056 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1057 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1062 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1063 (DeltaMaybeNegative && CoeffMaybeNegative))
1067 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1068 (DeltaMaybePositive && CoeffMaybeNegative))
1070 if (NewDirection <
Result.DV[Level].Direction)
1071 ++StrongSIVsuccesses;
1105bool DependenceInfo::weakCrossingSIVtest(
const SCEVAddRecExpr *Src,
1112 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1113 const SCEV *SrcConst = Src->getStart();
1114 const SCEV *DstConst = Dst->getStart();
1116 assert(Coeff == SE->getNegativeSCEV(Dst->getStepRecurrence(*SE)) &&
1117 "Unexpected input for weakCrossingSIVtest");
1123 ++WeakCrossingSIVapplications;
1124 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1139 ConstantRange SrcRange = SE->getSignedRange(Src);
1140 ConstantRange DstRange = SE->getSignedRange(Dst);
1145 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1146 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1147 ++WeakCrossingSIVsuccesses;
1148 if (!
Result.DV[Level].Direction) {
1149 ++WeakCrossingSIVindependence;
1157 APInt APDelta = ConstDelta->
getAPInt();
1158 APInt APCoeff = ConstCoeff->
getAPInt();
1159 APInt Distance = APDelta;
1160 APInt Remainder = APDelta;
1163 if (Remainder != 0) {
1165 ++WeakCrossingSIVindependence;
1166 ++WeakCrossingSIVsuccesses;
1174 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1175 ++WeakCrossingSIVsuccesses;
1199 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1200 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1204 return std::nullopt;
1213 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1214 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1221 X = AM.
slt(0) ? -A1 : A1;
1222 Y = BM.
slt(0) ? B1 : -B1;
1232static OverflowSafeSignedAPInt
1234 const OverflowSafeSignedAPInt &OB) {
1236 return OverflowSafeSignedAPInt();
1245 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1247 return OverflowSafeSignedAPInt(Q) - 1;
1250static OverflowSafeSignedAPInt
1252 const OverflowSafeSignedAPInt &OB) {
1254 return OverflowSafeSignedAPInt();
1263 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1264 return OverflowSafeSignedAPInt(Q) + 1;
1298static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1300 OverflowSafeSignedAPInt UB) {
1301 assert(
A &&
B &&
"A and B must be available");
1302 assert(*
A != 0 &&
"A must be non-zero");
1303 assert((!UB || UB->isNonNegative()) &&
"UB must be non-negative");
1304 OverflowSafeSignedAPInt TL, TU;
1307 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1311 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1314 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1318 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1320 return std::make_pair(TL, TU);
1349 ++ExactSIVapplications;
1350 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1352 bool Res = exactTestImpl(Src, Dst, Result, Level);
1354 ++ExactSIVsuccesses;
1355 ++ExactSIVindependence;
1365 return ConstDividend.
srem(ConstDivisor) == 0;
1368bool DependenceInfo::weakZeroSIVtestImpl(
const SCEVAddRecExpr *AR,
1369 const SCEV *Const,
unsigned Level,
1372 const SCEV *ARConst = AR->
getStart();
1374 if (Const == ARConst && SE->isKnownNonZero(ARCoeff)) {
1375 if (Level < CommonLevels) {
1377 ++WeakZeroSIVsuccesses;
1389 if (
const SCEV *UpperBound =
1392 bool OverlapAtLast = [&] {
1393 if (!SE->isKnownNonZero(ConstCoeff))
1398 if (OverlapAtLast) {
1400 if (Level < CommonLevels) {
1402 ++WeakZeroSIVsuccesses;
1411 ++WeakZeroSIVindependence;
1412 ++WeakZeroSIVsuccesses;
1447bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *SrcConst,
1457 [[maybe_unused]]
const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1458 [[maybe_unused]]
const SCEV *DstConst = Dst->getStart();
1463 ++WeakZeroSIVapplications;
1464 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1473 bool Res = weakZeroSIVtestImpl(Dst, SrcConst, Level, Result);
1507bool DependenceInfo::weakZeroDstSIVtest(
const SCEVAddRecExpr *Src,
1508 const SCEV *DstConst,
unsigned Level,
1515 [[maybe_unused]]
const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1516 [[maybe_unused]]
const SCEV *SrcConst = Src->getStart();
1521 ++WeakZeroSIVapplications;
1522 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1525 return weakZeroSIVtestImpl(Src, DstConst, Level, Result);
1541 ++ExactRDIVapplications;
1542 bool Res = exactTestImpl(Src, Dst, Result, std::nullopt);
1544 ++ExactRDIVindependence;
1551 std::optional<unsigned> Level)
const {
1552 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1553 const SCEV *SrcConst = Src->getStart();
1554 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1555 const SCEV *DstConst = Dst->getStart();
1568 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1573 APInt AM = ConstSrcCoeff->
getAPInt();
1574 APInt BM = ConstDstCoeff->
getAPInt();
1577 std::optional<bool> GCDRes =
findGCD(Bits, AM, BM, CM,
G,
X,
Y);
1590 std::optional<APInt> SrcUM =
1591 collectNonNegativeConstantUpperBound(Src->getLoop(), Delta->
getType());
1595 std::optional<APInt> DstUM =
1596 collectNonNegativeConstantUpperBound(Dst->getLoop(), Delta->
getType());
1602 OverflowSafeSignedAPInt TC = CM.
sdiv(
G);
1603 OverflowSafeSignedAPInt TX = OverflowSafeSignedAPInt(
X) * TC;
1604 OverflowSafeSignedAPInt TY = OverflowSafeSignedAPInt(
Y) * TC;
1605 if (!TC || !TX || !TY)
1629 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1630 const OverflowSafeSignedAPInt &
V1,
1631 bool IsMin) -> std::optional<APInt> {
1638 return std::nullopt;
1641 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1642 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1643 if (!OptTL || !OptTU)
1646 TL = std::move(*OptTL);
1647 TU = std::move(*OptTU);
1656 assert(SrcUM == DstUM &&
"Expecting same upper bound for Src and Dst");
1660 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1661 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1665 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1666 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1668 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1669 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1672 if (!LowerDistance || !UpperDistance)
1675 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1676 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1678 if (LowerDistance->sle(0) && UpperDistance->sge(0))
1680 if (LowerDistance->slt(0))
1682 if (UpperDistance->sgt(0))
1700bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
1702 bool UnderRuntimeAssumptions) {
1707 if (SrcAddRec && DstAddRec) {
1710 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1711 [[maybe_unused]]
const Loop *CurDstLoop = DstAddRec->
getLoop();
1712 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
1713 "Loops in the SIV test should have the same iteration space and "
1715 Level = mapSrcLoop(CurSrcLoop);
1716 bool disproven =
false;
1717 if (SrcCoeff == DstCoeff)
1718 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
1719 UnderRuntimeAssumptions);
1720 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
1721 disproven = weakCrossingSIVtest(SrcAddRec, DstAddRec, Level, Result);
1722 return disproven || exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
1725 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1726 Level = mapSrcLoop(CurSrcLoop);
1727 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result);
1730 const Loop *CurDstLoop = DstAddRec->
getLoop();
1731 Level = mapDstLoop(CurDstLoop);
1732 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result);
1748bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
1754 assert(SrcAddRec && DstAddRec &&
"Unexpected non-addrec input");
1755 return exactRDIVtest(SrcAddRec, DstAddRec, Result) ||
1756 gcdMIVtest(Src, Dst, Result);
1762bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
1767 return gcdMIVtest(Src, Dst, Result) ||
1768 banerjeeMIVtest(Src, Dst,
Loops, Result);
1781 if (Product->hasNoSignedWrap())
1783 return std::nullopt;
1786const SCEV *DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
1787 const Loop *CurLoop,
1788 const SCEV *&CurLoopCoeff,
1789 APInt &RunningGCD)
const {
1792 assert(isLoopInvariant(Expr, CurLoop) &&
1793 "Expected loop invariant expression");
1800 if (AddRec->
getLoop() == CurLoop) {
1801 CurLoopCoeff = Step;
1815 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
1835bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
1842 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
1845 const SCEV *Dummy =
nullptr;
1846 const SCEV *SrcConst =
1847 accumulateCoefficientsGCD(Src,
nullptr, Dummy, RunningGCD);
1850 const SCEV *DstConst =
1851 accumulateCoefficientsGCD(Dst,
nullptr, Dummy, RunningGCD);
1864 if (ConstDelta == 0)
1867 APInt Remainder = ConstDelta.
srem(RunningGCD);
1868 if (Remainder != 0) {
1882 bool Improved =
false;
1883 const SCEV *Coefficients = Src;
1884 while (
const SCEVAddRecExpr *AddRec =
1887 const Loop *CurLoop = AddRec->
getLoop();
1890 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
1892 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
1893 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
1908 if (RunningGCD != 0) {
1909 Remainder = ConstDelta.
srem(RunningGCD);
1911 if (Remainder != 0) {
1912 unsigned Level = mapSrcLoop(CurLoop);
1913 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
1957bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
1964 ++BanerjeeApplications;
1968 collectCoeffInfo(Src,
true, A0,
A);
1972 collectCoeffInfo(Dst,
false, B0,
B);
1981 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
1982 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
1985 findBoundsALL(
A,
B, Bound, K);
2000 bool Disproved =
false;
2003 unsigned DepthExpanded = 0;
2005 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2007 bool Improved =
false;
2008 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2010 unsigned Old =
Result.DV[
K - 1].Direction;
2011 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2012 Improved |= Old !=
Result.DV[
K - 1].Direction;
2013 if (!
Result.DV[K - 1].Direction) {
2021 ++BanerjeeSuccesses;
2023 ++BanerjeeIndependence;
2027 ++BanerjeeIndependence;
2038unsigned DependenceInfo::exploreDirections(
2041 unsigned &DepthExpanded,
const SCEV *Delta)
const {
2047 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2048 "direction exploration is terminated.\n");
2049 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2055 if (Level > CommonLevels) {
2058 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2060 Bound[
K].DirSet |= Bound[
K].Direction;
2085 if (Level > DepthExpanded) {
2086 DepthExpanded =
Level;
2088 findBoundsLT(
A,
B, Bound, Level);
2089 findBoundsGT(
A,
B, Bound, Level);
2090 findBoundsEQ(
A,
B, Bound, Level);
2129 unsigned NewDeps = 0;
2133 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2138 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2143 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2149 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2154bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2156 const SCEV *Delta)
const {
2157 Bound[
Level].Direction = DirKind;
2158 if (
const SCEV *LowerBound = getLowerBound(Bound))
2161 if (
const SCEV *UpperBound = getUpperBound(Bound))
2190 if (Bound[K].Iterations) {
2192 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2194 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2199 SE->getZero(
A[K].Coeff->
getType());
2202 SE->getZero(
A[K].Coeff->
getType());
2229 if (Bound[K].Iterations) {
2230 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2231 const SCEV *NegativePart = getNegativePart(Delta);
2233 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2234 const SCEV *PositivePart = getPositivePart(Delta);
2236 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2240 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2241 const SCEV *NegativePart = getNegativePart(Delta);
2242 if (NegativePart->
isZero())
2244 const SCEV *PositivePart = getPositivePart(Delta);
2245 if (PositivePart->
isZero())
2271 if (Bound[K].Iterations) {
2272 const SCEV *Iter_1 = SE->getMinusSCEV(
2273 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2274 const SCEV *NegPart =
2275 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2277 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2278 const SCEV *PosPart =
2279 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2281 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2285 const SCEV *NegPart =
2286 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2289 const SCEV *PosPart =
2290 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2317 if (Bound[K].Iterations) {
2318 const SCEV *Iter_1 = SE->getMinusSCEV(
2319 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2320 const SCEV *NegPart =
2321 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2323 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2324 const SCEV *PosPart =
2325 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2327 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2331 const SCEV *NegPart =
2332 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2335 const SCEV *PosPart =
2336 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2343const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2344 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2348const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2349 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2355void DependenceInfo::collectCoeffInfo(
2358 const SCEV *
Zero = SE->getZero(Subscript->getType());
2359 CI.
resize(MaxLevels + 1);
2360 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2362 CI[
K].PosPart =
Zero;
2363 CI[
K].NegPart =
Zero;
2364 CI[
K].Iterations =
nullptr;
2368 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2370 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2371 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2372 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2378 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2385 if (CI[K].Iterations)
2400 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2401 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2415 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2416 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2435 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2436 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2437 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2438 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2439 const SCEVUnknown *SrcBase =
2441 const SCEVUnknown *DstBase =
2444 if (!SrcBase || !DstBase || SrcBase != DstBase)
2449 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2450 SrcSubscripts, DstSubscripts) &&
2451 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2452 SrcSubscripts, DstSubscripts))
2455 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2456 isLoopInvariant(DstBase, DstLoop) &&
2457 "Expected SrcBase and DstBase to be loop invariant");
2461 dbgs() <<
"\nSrcSubscripts: ";
2462 for (
int I = 0;
I <
Size;
I++)
2463 dbgs() << *SrcSubscripts[
I];
2464 dbgs() <<
"\nDstSubscripts: ";
2465 for (
int I = 0;
I <
Size;
I++)
2466 dbgs() << *DstSubscripts[
I];
2475 for (
int I = 0;
I <
Size; ++
I) {
2476 Pair[
I].Src = SrcSubscripts[
I];
2477 Pair[
I].Dst = DstSubscripts[
I];
2479 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2480 "Unexpected different types for the subscripts");
2489bool DependenceInfo::tryDelinearizeFixedSize(
2494 const SCEVUnknown *SrcBase =
2496 const SCEVUnknown *DstBase =
2498 assert(SrcBase && DstBase && SrcBase == DstBase &&
2499 "expected src and dst scev unknowns to be equal");
2502 const SCEV *ElemSize = SE->getElementSize(Src);
2503 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2506 SrcSubscripts, SrcSizes, ElemSize) ||
2508 DstSubscripts, DstSizes, ElemSize))
2513 if (SrcSizes.
size() != DstSizes.
size() ||
2514 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2515 SrcSubscripts.
clear();
2516 DstSubscripts.
clear();
2521 "Expected equal number of entries in the list of SrcSubscripts and "
2533 SrcSubscripts.
clear();
2534 DstSubscripts.
clear();
2539 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2546bool DependenceInfo::tryDelinearizeParametricSize(
2551 const SCEVUnknown *SrcBase =
2553 const SCEVUnknown *DstBase =
2555 assert(SrcBase && DstBase && SrcBase == DstBase &&
2556 "expected src and dst scev unknowns to be equal");
2558 const SCEV *ElementSize = SE->getElementSize(Src);
2559 if (ElementSize != SE->getElementSize(Dst))
2562 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2563 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2584 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2585 SrcSubscripts.
size() != DstSubscripts.
size())
2608 for (
unsigned VI : BV.
set_bits()) {
2618 FunctionAnalysisManager::Invalidator &Inv) {
2625 return Inv.invalidate<
AAManager>(F, PA) ||
2639std::unique_ptr<Dependence>
2641 bool UnderRuntimeAssumptions) {
2643 bool PossiblyLoopIndependent =
true;
2645 PossiblyLoopIndependent =
false;
2647 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2653 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2654 return std::make_unique<Dependence>(Src, Dst,
2666 return std::make_unique<Dependence>(Src, Dst,
2680 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2681 return std::make_unique<Dependence>(Src, Dst,
2687 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2688 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2691 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2692 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2693 if (SrcBase != DstBase) {
2700 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2701 return std::make_unique<Dependence>(Src, Dst,
2709 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2710 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2711 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2712 !isLoopInvariant(DstBase, DstLoop)) {
2713 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2714 return std::make_unique<Dependence>(Src, Dst,
2719 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2720 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2723 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2724 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2725 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2726 return std::make_unique<Dependence>(Src, Dst,
2731 if (!Assume.empty() && !UnderRuntimeAssumptions)
2732 return std::make_unique<Dependence>(Src, Dst,
2737 Pair[0].Src = SrcEv;
2738 Pair[0].Dst = DstEv;
2740 if (tryDelinearize(Src, Dst, Pair)) {
2742 Pairs = Pair.
size();
2747 establishNestingLevels(Src, Dst);
2749 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2750 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2751 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2754 CommonLevels += SameSDLevels;
2755 MaxLevels -= SameSDLevels;
2756 if (SameSDLevels > 0) {
2759 for (
unsigned P = 0;
P < Pairs; ++
P) {
2761 Subscript::ClassificationKind TestClass =
2762 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2763 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2765 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2766 TestClass != Subscript::RDIV) {
2768 CommonLevels -= SameSDLevels;
2769 MaxLevels += SameSDLevels;
2776 if (SameSDLevels > 0)
2780 PossiblyLoopIndependent, CommonLevels);
2783 for (
unsigned P = 0;
P < Pairs; ++
P) {
2784 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2785 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2786 Pair[
P].Loops.
resize(MaxLevels + 1);
2787 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2789 Pair[
P].Classification =
2790 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2791 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2792 Pair[
P].GroupLoops = Pair[
P].Loops;
2793 Pair[
P].Group.set(
P);
2803 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2812 switch (Pair[
SI].Classification) {
2813 case Subscript::NonLinear:
2815 ++NonlinearSubscriptPairs;
2816 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2818 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2821 case Subscript::ZIV:
2823 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2826 case Subscript::SIV: {
2829 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2830 UnderRuntimeAssumptions))
2834 case Subscript::RDIV:
2836 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2839 case Subscript::MIV:
2841 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2849 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2850 CompleteLoops |= Pair[
SI].
Loops;
2851 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2852 if (CompleteLoops[
II])
2853 Result.DV[
II - 1].Scalar =
false;
2858 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2860 if (Result.DV[
II - 1].Distance ==
nullptr)
2861 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2863 assert(Result.DV[
II - 1].Distance->isZero() &&
2864 "Inconsistency between distance and direction");
2870 const SCEV *Distance = Result.getDistance(
II);
2871 if (Distance && Distance->
isZero())
2873 "Distance is zero, but direction is not EQ");
2877 if (SameSDLevels > 0) {
2880 assert(CommonLevels >= SameSDLevels);
2881 CommonLevels -= SameSDLevels;
2882 MaxLevels += SameSDLevels;
2883 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2884 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2885 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2886 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2887 DV[Level] = Result.DV[Level];
2888 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2889 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2890 Result.DV = std::move(DV);
2891 Result.DVSameSD = std::move(DVSameSD);
2892 Result.Levels = CommonLevels;
2893 Result.SameSDLevels = SameSDLevels;
2896 if (PossiblyLoopIndependent) {
2900 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2902 Result.LoopIndependent =
false;
2910 bool AllEqual =
true;
2911 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2917 if (AllEqual && Result.Assumptions.getPredicates().empty())
2921 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 std::optional< bool > findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
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 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< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::Default), 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::Default, "default", "Enable all dependence test routines except " "Banerjee MIV (default)."), 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 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.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
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()
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.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
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
LLVM_ABI void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
LLVM_ABI 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)
LLVM_ABI 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.
LLVM_ABI 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)...
LLVM_ABI 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...