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;
1932struct BanerjeeInterval {
1936 BanerjeeInterval(
const SCEV *
Lower,
const SCEV *
Upper)
1939 bool isEmpty(ScalarEvolution &SE)
const {
1949 const BanerjeeInterval &
B,
1953 if (
A.Lower &&
B.Lower)
1955 if (
A.Upper &&
B.Upper)
1964 const BanerjeeInterval &
B,
1977 return BanerjeeInterval(
C,
C);
1995 return BanerjeeInterval(SE.
getSMinExpr(LowerValue, UpperValue),
2008 return BanerjeeInterval(
nullptr, Zero);
2010 return BanerjeeInterval(Zero,
nullptr);
2011 return BanerjeeInterval(
nullptr,
nullptr);
2072 assert(!
Values.empty() &&
"expected at least one value");
2096 for (
const SCEV *Subscript : {Src, Dst}) {
2124bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2131 ++BanerjeeApplications;
2134 unsigned BaseBits = SE->getTypeSizeInBits(
BaseType);
2144 unsigned WideBits = 2 * BaseBits + MaxLevels + 1;
2146 const SCEV *
Zero = SE->getZero(WideType);
2148 CoefficientInfo EmptyCoeff{
Zero,
Zero,
nullptr};
2150 assert(
Loops.size() > MaxLevels &&
"loop bit vector is too small");
2152 "direction vector is too small for common levels");
2154 const SCEV *A0 = collectCoeffInfo(Src,
true, WideType, CI);
2155 const SCEV *B0 = collectCoeffInfo(Dst,
false, WideType, CI);
2156 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2160 for (
unsigned K = 0;
K <= MaxLevels; ++
K) {
2164 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2165 findBoundsALL(CI, Bound, K);
2166 findBoundsLT(CI, Bound, K);
2167 findBoundsEQ(CI, Bound, K);
2168 findBoundsGT(CI, Bound, K);
2172 ++BanerjeeIndependence;
2176 unsigned NewDeps = exploreDirections(1, Bound,
Loops, Delta, Result);
2178 ++BanerjeeIndependence;
2182 bool Improved =
false;
2183 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2186 unsigned Old =
Result.DV[
K - 1].Direction;
2187 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2188 Improved |= Old !=
Result.DV[
K - 1].Direction;
2189 if (!
Result.DV[K - 1].Direction) {
2190 ++BanerjeeIndependence;
2196 ++BanerjeeSuccesses;
2205DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
2208 SmallBitVector SeenLevels(MaxLevels + 1);
2211 SrcFlag ? mapSrcLoop(AddRec->
getLoop()) : mapDstLoop(AddRec->getLoop());
2212 assert(K > 0 && K <= MaxLevels &&
"invalid mapped loop level");
2213 assert(!SeenLevels[K] &&
"duplicate recurrence for loop level");
2217 const SCEV *&Coeff = SrcFlag ? CI[
K].SrcCoeff : CI[
K].DstCoeff;
2218 Coeff = SE->getNoopOrSignExtend(Step, WideType);
2220 const SCEV *MaxIterIndex = SE->getBackedgeTakenCount(AddRec->
getLoop());
2226 CI[
K].MaxIterIndex =
2227 SE->isKnownNonNegative(MaxIterIndex)
2228 ? SE->getNoopOrSignExtend(MaxIterIndex, WideType)
2229 : SE->getNoopOrZeroExtend(MaxIterIndex, WideType);
2234 return SE->getNoopOrSignExtend(Subscript, WideType);
2239 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2240 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2250 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2251 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2261bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2263 const SCEV *Delta)
const {
2264 Bound[
Level].Direction = DirKind;
2265 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2266 unsigned char Direction = Bound[
K].Direction;
2272 if (
const SCEV *
Lower = getLowerBound(Bound))
2275 if (
const SCEV *
Upper = getUpperBound(Bound))
2282unsigned DependenceInfo::exploreDirections(
unsigned Level,
2288 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2289 "direction exploration is terminated.\n");
2290 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2296 if (Level > CommonLevels) {
2297 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2299 Bound[
K].DirSet |= Bound[
K].Direction;
2304 return exploreDirections(Level + 1, Bound,
Loops, Delta, Result);
2306 unsigned NewDeps = 0;
2307 unsigned OldDirections =
Result.DV[
Level - 1].Direction;
2310 if (!(OldDirections & Dir))
2312 if (testBounds(Dir, Level, Bound, Delta))
2313 NewDeps += exploreDirections(Level + 1, Bound,
Loops, Delta, Result);
2337 BanerjeeInterval SrcInterval =
2340 SE->getNegativeSCEV(CI[K].DstCoeff), CI[K].MaxIterIndex, *SE);
2359 CI[K].MaxIterIndex, *SE);
2380 const SCEV *ACoeff = CI[
K].SrcCoeff;
2381 const SCEV *BCoeff = CI[
K].DstCoeff;
2382 const SCEV *MaxIterIndex = CI[
K].MaxIterIndex;
2386 if (MaxIterIndex && MaxIterIndex->
isZero()) {
2388 }
else if (MaxIterIndex) {
2389 const SCEV *
Zero = SE->getZero(ACoeff->
getType());
2390 const SCEV *One = SE->getOne(ACoeff->
getType());
2391 const SCEV *MaxMinusOne = SE->getMinusSCEV(MaxIterIndex, One);
2398 MaxIterIndex, *SE));
2422 const SCEV *ACoeff = CI[
K].SrcCoeff;
2423 const SCEV *BCoeff = CI[
K].DstCoeff;
2424 const SCEV *MaxIterIndex = CI[
K].MaxIterIndex;
2428 if (MaxIterIndex && MaxIterIndex->
isZero()) {
2430 }
else if (MaxIterIndex) {
2431 const SCEV *
Zero = SE->getZero(ACoeff->
getType());
2432 const SCEV *One = SE->getOne(ACoeff->
getType());
2433 const SCEV *MaxMinusOne = SE->getMinusSCEV(MaxIterIndex, One);
2458 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2459 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2460 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2461 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2462 const SCEVUnknown *SrcBase =
2464 const SCEVUnknown *DstBase =
2467 if (!SrcBase || !DstBase || SrcBase != DstBase)
2472 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2473 SrcSubscripts, DstSubscripts) &&
2474 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2475 SrcSubscripts, DstSubscripts))
2478 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2479 isLoopInvariant(DstBase, DstLoop) &&
2480 "Expected SrcBase and DstBase to be loop invariant");
2484 dbgs() <<
"\nSrcSubscripts: ";
2485 for (
int I = 0;
I <
Size;
I++)
2486 dbgs() << *SrcSubscripts[
I];
2487 dbgs() <<
"\nDstSubscripts: ";
2488 for (
int I = 0;
I <
Size;
I++)
2489 dbgs() << *DstSubscripts[
I];
2498 for (
int I = 0;
I <
Size; ++
I) {
2499 Pair[
I].Src = SrcSubscripts[
I];
2500 Pair[
I].Dst = DstSubscripts[
I];
2502 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2503 "Unexpected different types for the subscripts");
2512bool DependenceInfo::tryDelinearizeFixedSize(
2517 const SCEVUnknown *SrcBase =
2519 const SCEVUnknown *DstBase =
2521 assert(SrcBase && DstBase && SrcBase == DstBase &&
2522 "expected src and dst scev unknowns to be equal");
2525 const SCEV *ElemSize = SE->getElementSize(Src);
2526 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2529 SrcSubscripts, SrcSizes, ElemSize) ||
2531 DstSubscripts, DstSizes, ElemSize))
2536 if (SrcSizes.
size() != DstSizes.
size() ||
2537 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2538 SrcSubscripts.
clear();
2539 DstSubscripts.
clear();
2544 "Expected equal number of entries in the list of SrcSubscripts and "
2556 SrcSubscripts.
clear();
2557 DstSubscripts.
clear();
2562 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2569bool DependenceInfo::tryDelinearizeParametricSize(
2574 const SCEVUnknown *SrcBase =
2576 const SCEVUnknown *DstBase =
2578 assert(SrcBase && DstBase && SrcBase == DstBase &&
2579 "expected src and dst scev unknowns to be equal");
2581 const SCEV *ElementSize = SE->getElementSize(Src);
2582 if (ElementSize != SE->getElementSize(Dst))
2585 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2586 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2607 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2608 SrcSubscripts.
size() != DstSubscripts.
size())
2631 for (
unsigned VI : BV.
set_bits()) {
2641 FunctionAnalysisManager::Invalidator &Inv) {
2648 return Inv.invalidate<
AAManager>(F, PA) ||
2662std::unique_ptr<Dependence>
2664 bool UnderRuntimeAssumptions) {
2666 bool PossiblyLoopIndependent =
true;
2668 PossiblyLoopIndependent =
false;
2670 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2676 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2677 return std::make_unique<Dependence>(Src, Dst,
2689 return std::make_unique<Dependence>(Src, Dst,
2703 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2704 return std::make_unique<Dependence>(Src, Dst,
2710 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2711 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2714 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2715 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2716 if (SrcBase != DstBase) {
2723 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2724 return std::make_unique<Dependence>(Src, Dst,
2732 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2733 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2734 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2735 !isLoopInvariant(DstBase, DstLoop)) {
2736 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2737 return std::make_unique<Dependence>(Src, Dst,
2742 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2743 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2746 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2747 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2748 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2749 return std::make_unique<Dependence>(Src, Dst,
2754 if (!Assume.empty() && !UnderRuntimeAssumptions)
2755 return std::make_unique<Dependence>(Src, Dst,
2760 Pair[0].Src = SrcEv;
2761 Pair[0].Dst = DstEv;
2763 if (tryDelinearize(Src, Dst, Pair)) {
2765 Pairs = Pair.
size();
2770 establishNestingLevels(Src, Dst);
2772 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2773 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2774 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2777 CommonLevels += SameSDLevels;
2778 MaxLevels -= SameSDLevels;
2779 if (SameSDLevels > 0) {
2782 for (
unsigned P = 0;
P < Pairs; ++
P) {
2784 Subscript::ClassificationKind TestClass =
2785 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2786 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2788 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2789 TestClass != Subscript::RDIV) {
2791 CommonLevels -= SameSDLevels;
2792 MaxLevels += SameSDLevels;
2799 if (SameSDLevels > 0)
2803 PossiblyLoopIndependent, CommonLevels);
2806 for (
unsigned P = 0;
P < Pairs; ++
P) {
2807 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2808 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2809 Pair[
P].Loops.
resize(MaxLevels + 1);
2810 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2812 Pair[
P].Classification =
2813 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2814 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2815 Pair[
P].GroupLoops = Pair[
P].Loops;
2816 Pair[
P].Group.set(
P);
2826 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2835 switch (Pair[
SI].Classification) {
2836 case Subscript::NonLinear:
2838 ++NonlinearSubscriptPairs;
2839 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2841 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2844 case Subscript::ZIV:
2846 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2849 case Subscript::SIV: {
2852 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2853 UnderRuntimeAssumptions))
2857 case Subscript::RDIV:
2859 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2862 case Subscript::MIV:
2864 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2872 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2873 CompleteLoops |= Pair[
SI].
Loops;
2874 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2875 if (CompleteLoops[
II])
2876 Result.DV[
II - 1].Scalar =
false;
2881 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2883 if (Result.DV[
II - 1].Distance ==
nullptr)
2884 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2886 assert(Result.DV[
II - 1].Distance->isZero() &&
2887 "Inconsistency between distance and direction");
2893 const SCEV *Distance = Result.getDistance(
II);
2894 if (Distance && Distance->
isZero())
2896 "Distance is zero, but direction is not EQ");
2900 if (SameSDLevels > 0) {
2903 assert(CommonLevels >= SameSDLevels);
2904 CommonLevels -= SameSDLevels;
2905 MaxLevels += SameSDLevels;
2906 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2907 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2908 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2909 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2910 DV[Level] = Result.DV[Level];
2911 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2912 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2913 Result.DV = std::move(DV);
2914 Result.DVSameSD = std::move(DVSameSD);
2915 Result.Levels = CommonLevels;
2916 Result.SameSDLevels = SameSDLevels;
2919 if (PossiblyLoopIndependent) {
2923 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2925 Result.LoopIndependent =
false;
2933 bool AllEqual =
true;
2934 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2940 if (AllEqual && Result.Assumptions.getPredicates().empty())
2944 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 BanerjeeInterval emptyInterval(Type *Ty, ScalarEvolution &SE)
Return the canonical empty interval [1, 0].
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 BanerjeeInterval constantInterval(const SCEV *C)
Return the singleton interval containing C.
static Type * getBanerjeeBaseType(const SCEV *Src, const SCEV *Dst, ScalarEvolution &SE)
Return the widest type used by a subscript or by an exact backedge-taken count of one of its recurren...
static BanerjeeInterval variableInterval(const SCEV *Coeff, const SCEV *Upper, ScalarEvolution &SE)
Compute the range of Coeff * X for 0 <= X <= Upper.
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 BanerjeeInterval strictDirectionIntervalWithUnknownUpperBound(const SCEV *ACoeff, const SCEV *BCoeff, unsigned char Direction, ScalarEvolution &SE)
Compute any finite one-sided bound on.
static const SCEV * evaluateSubscriptDifference(const SCEV *A, const SCEV *SrcIndex, const SCEV *B, const SCEV *DstIndex, ScalarEvolution &SE)
Evaluate one loop level's contribution A * SrcIndex - B * DstIndex to the complete source-minus-desti...
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static BanerjeeInterval signedRangeInterval(const SCEV *Coeff, const SCEV *Lower, const SCEV *Upper, ScalarEvolution &SE)
Compute the range of Coeff * X for Lower <=s X <=s Upper.
static BanerjeeInterval intervalFromValues(ArrayRef< const SCEV * > Values, ScalarEvolution &SE)
Return the smallest closed interval containing Values.
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static BanerjeeInterval addIntervals(const BanerjeeInterval &A, const BanerjeeInterval &B, ScalarEvolution &SE)
Add two intervals.
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 BanerjeeInterval intersectIntervals(const BanerjeeInterval &A, const BanerjeeInterval &B, ScalarEvolution &SE)
Intersect two intervals.
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
std::pair< uint64_t, uint64_t > Interval
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)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
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.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
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.
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 bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI Type * getWiderType(Type *Ty1, Type *Ty2) const
LLVM_ABI bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
LLVM_ABI bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI const SCEV * getSMinExpr(SCEVUse LHS, SCEVUse RHS)
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
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.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, SCEVUse LHS, SCEVUse RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
LLVM_ABI const SCEV * getSMaxExpr(SCEVUse LHS, SCEVUse 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)
@ 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.
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...
RelativeUniformCounterPtr Values
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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...