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;
1198 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1199 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1207 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1208 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1215 X = AM.
slt(0) ? -A1 : A1;
1216 Y = BM.
slt(0) ? B1 : -B1;
1226static OverflowSafeSignedAPInt
1228 const OverflowSafeSignedAPInt &OB) {
1230 return OverflowSafeSignedAPInt();
1239 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1241 return OverflowSafeSignedAPInt(Q) - 1;
1244static OverflowSafeSignedAPInt
1246 const OverflowSafeSignedAPInt &OB) {
1248 return OverflowSafeSignedAPInt();
1257 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1258 return OverflowSafeSignedAPInt(Q) + 1;
1292static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1294 OverflowSafeSignedAPInt UB) {
1295 assert(
A &&
B &&
"A and B must be available");
1296 assert(*
A != 0 &&
"A must be non-zero");
1297 assert((!UB || UB->isNonNegative()) &&
"UB must be non-negative");
1298 OverflowSafeSignedAPInt TL, TU;
1301 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1305 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1308 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1312 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1314 return std::make_pair(TL, TU);
1343 ++ExactSIVapplications;
1344 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1346 bool Res = exactTestImpl(Src, Dst, Result, Level);
1348 ++ExactSIVsuccesses;
1349 ++ExactSIVindependence;
1359 return ConstDividend.
srem(ConstDivisor) == 0;
1362bool DependenceInfo::weakZeroSIVtestImpl(
const SCEVAddRecExpr *AR,
1363 const SCEV *Const,
unsigned Level,
1366 const SCEV *ARConst = AR->
getStart();
1368 if (Const == ARConst && SE->isKnownNonZero(ARCoeff)) {
1369 if (Level < CommonLevels) {
1371 ++WeakZeroSIVsuccesses;
1383 if (
const SCEV *UpperBound =
1386 bool OverlapAtLast = [&] {
1387 if (!SE->isKnownNonZero(ConstCoeff))
1392 if (OverlapAtLast) {
1394 if (Level < CommonLevels) {
1396 ++WeakZeroSIVsuccesses;
1405 ++WeakZeroSIVindependence;
1406 ++WeakZeroSIVsuccesses;
1441bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *SrcConst,
1451 [[maybe_unused]]
const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1452 [[maybe_unused]]
const SCEV *DstConst = Dst->getStart();
1457 ++WeakZeroSIVapplications;
1458 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1467 bool Res = weakZeroSIVtestImpl(Dst, SrcConst, Level, Result);
1501bool DependenceInfo::weakZeroDstSIVtest(
const SCEVAddRecExpr *Src,
1502 const SCEV *DstConst,
unsigned Level,
1509 [[maybe_unused]]
const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1510 [[maybe_unused]]
const SCEV *SrcConst = Src->getStart();
1515 ++WeakZeroSIVapplications;
1516 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1519 return weakZeroSIVtestImpl(Src, DstConst, Level, Result);
1535 ++ExactRDIVapplications;
1536 bool Res = exactTestImpl(Src, Dst, Result, std::nullopt);
1538 ++ExactRDIVindependence;
1545 std::optional<unsigned> Level)
const {
1546 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1547 const SCEV *SrcConst = Src->getStart();
1548 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1549 const SCEV *DstConst = Dst->getStart();
1562 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1567 APInt AM = ConstSrcCoeff->
getAPInt();
1568 APInt BM = ConstDstCoeff->
getAPInt();
1579 std::optional<APInt> SrcUM =
1580 collectNonNegativeConstantUpperBound(Src->getLoop(), Delta->
getType());
1584 std::optional<APInt> DstUM =
1585 collectNonNegativeConstantUpperBound(Dst->getLoop(), Delta->
getType());
1591 OverflowSafeSignedAPInt TC = CM.
sdiv(
G);
1592 OverflowSafeSignedAPInt TX = OverflowSafeSignedAPInt(
X) * TC;
1593 OverflowSafeSignedAPInt TY = OverflowSafeSignedAPInt(
Y) * TC;
1594 if (!TC || !TX || !TY)
1618 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1619 const OverflowSafeSignedAPInt &V1,
1620 bool IsMin) -> std::optional<APInt> {
1627 return std::nullopt;
1630 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1631 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1632 if (!OptTL || !OptTU)
1635 TL = std::move(*OptTL);
1636 TU = std::move(*OptTU);
1645 assert(SrcUM == DstUM &&
"Expecting same upper bound for Src and Dst");
1649 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1650 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1654 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1655 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1657 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1658 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1661 if (!LowerDistance || !UpperDistance)
1664 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1665 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1667 if (LowerDistance->sle(0) && UpperDistance->sge(0))
1669 if (LowerDistance->slt(0))
1671 if (UpperDistance->sgt(0))
1689bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
1691 bool UnderRuntimeAssumptions) {
1696 if (SrcAddRec && DstAddRec) {
1699 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1700 [[maybe_unused]]
const Loop *CurDstLoop = DstAddRec->
getLoop();
1701 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
1702 "Loops in the SIV test should have the same iteration space and "
1704 Level = mapSrcLoop(CurSrcLoop);
1705 bool disproven =
false;
1706 if (SrcCoeff == DstCoeff)
1707 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
1708 UnderRuntimeAssumptions);
1709 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
1710 disproven = weakCrossingSIVtest(SrcAddRec, DstAddRec, Level, Result);
1711 return disproven || exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
1714 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1715 Level = mapSrcLoop(CurSrcLoop);
1716 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result);
1719 const Loop *CurDstLoop = DstAddRec->
getLoop();
1720 Level = mapDstLoop(CurDstLoop);
1721 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result);
1737bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
1743 assert(SrcAddRec && DstAddRec &&
"Unexpected non-addrec input");
1744 return exactRDIVtest(SrcAddRec, DstAddRec, Result) ||
1745 gcdMIVtest(Src, Dst, Result);
1751bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
1756 return gcdMIVtest(Src, Dst, Result) ||
1757 banerjeeMIVtest(Src, Dst,
Loops, Result);
1770 if (Product->hasNoSignedWrap())
1772 return std::nullopt;
1775const SCEV *DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
1776 const Loop *CurLoop,
1777 const SCEV *&CurLoopCoeff,
1778 APInt &RunningGCD)
const {
1781 assert(isLoopInvariant(Expr, CurLoop) &&
1782 "Expected loop invariant expression");
1789 if (AddRec->
getLoop() == CurLoop) {
1790 CurLoopCoeff = Step;
1804 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
1824bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
1831 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
1834 const SCEV *Dummy =
nullptr;
1835 const SCEV *SrcConst =
1836 accumulateCoefficientsGCD(Src,
nullptr, Dummy, RunningGCD);
1839 const SCEV *DstConst =
1840 accumulateCoefficientsGCD(Dst,
nullptr, Dummy, RunningGCD);
1853 if (ConstDelta == 0)
1856 APInt Remainder = ConstDelta.
srem(RunningGCD);
1857 if (Remainder != 0) {
1871 bool Improved =
false;
1872 const SCEV *Coefficients = Src;
1873 while (
const SCEVAddRecExpr *AddRec =
1876 const Loop *CurLoop = AddRec->
getLoop();
1879 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
1881 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
1882 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
1897 if (RunningGCD != 0) {
1898 Remainder = ConstDelta.
srem(RunningGCD);
1900 if (Remainder != 0) {
1901 unsigned Level = mapSrcLoop(CurLoop);
1902 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
1946bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
1953 ++BanerjeeApplications;
1957 collectCoeffInfo(Src,
true, A0,
A);
1961 collectCoeffInfo(Dst,
false, B0,
B);
1970 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
1971 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
1974 findBoundsALL(
A,
B, Bound, K);
1989 bool Disproved =
false;
1992 unsigned DepthExpanded = 0;
1994 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
1996 bool Improved =
false;
1997 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
1999 unsigned Old =
Result.DV[
K - 1].Direction;
2000 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2001 Improved |= Old !=
Result.DV[
K - 1].Direction;
2002 if (!
Result.DV[K - 1].Direction) {
2010 ++BanerjeeSuccesses;
2012 ++BanerjeeIndependence;
2016 ++BanerjeeIndependence;
2027unsigned DependenceInfo::exploreDirections(
2030 unsigned &DepthExpanded,
const SCEV *Delta)
const {
2036 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2037 "direction exploration is terminated.\n");
2038 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2044 if (Level > CommonLevels) {
2047 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2049 Bound[
K].DirSet |= Bound[
K].Direction;
2074 if (Level > DepthExpanded) {
2075 DepthExpanded =
Level;
2077 findBoundsLT(
A,
B, Bound, Level);
2078 findBoundsGT(
A,
B, Bound, Level);
2079 findBoundsEQ(
A,
B, Bound, Level);
2118 unsigned NewDeps = 0;
2122 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2127 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2132 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2138 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2143bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2145 const SCEV *Delta)
const {
2146 Bound[
Level].Direction = DirKind;
2147 if (
const SCEV *LowerBound = getLowerBound(Bound))
2150 if (
const SCEV *UpperBound = getUpperBound(Bound))
2179 if (Bound[K].Iterations) {
2181 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2183 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2188 SE->getZero(
A[K].Coeff->
getType());
2191 SE->getZero(
A[K].Coeff->
getType());
2218 if (Bound[K].Iterations) {
2219 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2220 const SCEV *NegativePart = getNegativePart(Delta);
2222 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2223 const SCEV *PositivePart = getPositivePart(Delta);
2225 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2229 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2230 const SCEV *NegativePart = getNegativePart(Delta);
2231 if (NegativePart->
isZero())
2233 const SCEV *PositivePart = getPositivePart(Delta);
2234 if (PositivePart->
isZero())
2260 if (Bound[K].Iterations) {
2261 const SCEV *Iter_1 = SE->getMinusSCEV(
2262 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2263 const SCEV *NegPart =
2264 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2266 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2267 const SCEV *PosPart =
2268 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2270 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2274 const SCEV *NegPart =
2275 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2278 const SCEV *PosPart =
2279 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2306 if (Bound[K].Iterations) {
2307 const SCEV *Iter_1 = SE->getMinusSCEV(
2308 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2309 const SCEV *NegPart =
2310 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2312 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2313 const SCEV *PosPart =
2314 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2316 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2320 const SCEV *NegPart =
2321 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2324 const SCEV *PosPart =
2325 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2332const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2333 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2337const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2338 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2344void DependenceInfo::collectCoeffInfo(
2347 const SCEV *
Zero = SE->getZero(Subscript->getType());
2348 CI.
resize(MaxLevels + 1);
2349 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2351 CI[
K].PosPart =
Zero;
2352 CI[
K].NegPart =
Zero;
2353 CI[
K].Iterations =
nullptr;
2357 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2359 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2360 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2361 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2367 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2374 if (CI[K].Iterations)
2389 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2390 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2404 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2405 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2424 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2425 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2426 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2427 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2428 const SCEVUnknown *SrcBase =
2430 const SCEVUnknown *DstBase =
2433 if (!SrcBase || !DstBase || SrcBase != DstBase)
2438 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2439 SrcSubscripts, DstSubscripts) &&
2440 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2441 SrcSubscripts, DstSubscripts))
2444 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2445 isLoopInvariant(DstBase, DstLoop) &&
2446 "Expected SrcBase and DstBase to be loop invariant");
2450 dbgs() <<
"\nSrcSubscripts: ";
2451 for (
int I = 0;
I <
Size;
I++)
2452 dbgs() << *SrcSubscripts[
I];
2453 dbgs() <<
"\nDstSubscripts: ";
2454 for (
int I = 0;
I <
Size;
I++)
2455 dbgs() << *DstSubscripts[
I];
2464 for (
int I = 0;
I <
Size; ++
I) {
2465 Pair[
I].Src = SrcSubscripts[
I];
2466 Pair[
I].Dst = DstSubscripts[
I];
2468 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2469 "Unexpected different types for the subscripts");
2478bool DependenceInfo::tryDelinearizeFixedSize(
2483 const SCEVUnknown *SrcBase =
2485 const SCEVUnknown *DstBase =
2487 assert(SrcBase && DstBase && SrcBase == DstBase &&
2488 "expected src and dst scev unknowns to be equal");
2491 const SCEV *ElemSize = SE->getElementSize(Src);
2492 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2495 SrcSubscripts, SrcSizes, ElemSize) ||
2497 DstSubscripts, DstSizes, ElemSize))
2502 if (SrcSizes.
size() != DstSizes.
size() ||
2503 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2504 SrcSubscripts.
clear();
2505 DstSubscripts.
clear();
2510 "Expected equal number of entries in the list of SrcSubscripts and "
2522 SrcSubscripts.
clear();
2523 DstSubscripts.
clear();
2528 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2535bool DependenceInfo::tryDelinearizeParametricSize(
2540 const SCEVUnknown *SrcBase =
2542 const SCEVUnknown *DstBase =
2544 assert(SrcBase && DstBase && SrcBase == DstBase &&
2545 "expected src and dst scev unknowns to be equal");
2547 const SCEV *ElementSize = SE->getElementSize(Src);
2548 if (ElementSize != SE->getElementSize(Dst))
2551 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2552 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2573 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2574 SrcSubscripts.
size() != DstSubscripts.
size())
2597 for (
unsigned VI : BV.
set_bits()) {
2607 FunctionAnalysisManager::Invalidator &Inv) {
2614 return Inv.invalidate<
AAManager>(F, PA) ||
2628std::unique_ptr<Dependence>
2630 bool UnderRuntimeAssumptions) {
2632 bool PossiblyLoopIndependent =
true;
2634 PossiblyLoopIndependent =
false;
2636 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2642 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2643 return std::make_unique<Dependence>(Src, Dst,
2655 return std::make_unique<Dependence>(Src, Dst,
2669 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2670 return std::make_unique<Dependence>(Src, Dst,
2676 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2677 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2680 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2681 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2682 if (SrcBase != DstBase) {
2689 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2690 return std::make_unique<Dependence>(Src, Dst,
2698 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2699 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2700 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2701 !isLoopInvariant(DstBase, DstLoop)) {
2702 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2703 return std::make_unique<Dependence>(Src, Dst,
2708 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2709 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2712 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2713 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2714 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2715 return std::make_unique<Dependence>(Src, Dst,
2720 if (!Assume.empty() && !UnderRuntimeAssumptions)
2721 return std::make_unique<Dependence>(Src, Dst,
2726 Pair[0].Src = SrcEv;
2727 Pair[0].Dst = DstEv;
2729 if (tryDelinearize(Src, Dst, Pair)) {
2731 Pairs = Pair.
size();
2736 establishNestingLevels(Src, Dst);
2738 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2739 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2740 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2743 CommonLevels += SameSDLevels;
2744 MaxLevels -= SameSDLevels;
2745 if (SameSDLevels > 0) {
2748 for (
unsigned P = 0;
P < Pairs; ++
P) {
2750 Subscript::ClassificationKind TestClass =
2751 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2752 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2754 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2755 TestClass != Subscript::RDIV) {
2757 CommonLevels -= SameSDLevels;
2758 MaxLevels += SameSDLevels;
2765 if (SameSDLevels > 0)
2769 PossiblyLoopIndependent, CommonLevels);
2772 for (
unsigned P = 0;
P < Pairs; ++
P) {
2773 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2774 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2775 Pair[
P].Loops.
resize(MaxLevels + 1);
2776 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2778 Pair[
P].Classification =
2779 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2780 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2781 Pair[
P].GroupLoops = Pair[
P].Loops;
2782 Pair[
P].Group.set(
P);
2792 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2801 switch (Pair[
SI].Classification) {
2802 case Subscript::NonLinear:
2804 ++NonlinearSubscriptPairs;
2805 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2807 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2810 case Subscript::ZIV:
2812 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2815 case Subscript::SIV: {
2818 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2819 UnderRuntimeAssumptions))
2823 case Subscript::RDIV:
2825 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2828 case Subscript::MIV:
2830 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2838 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2839 CompleteLoops |= Pair[
SI].
Loops;
2840 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2841 if (CompleteLoops[
II])
2842 Result.DV[
II - 1].Scalar =
false;
2847 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2849 if (Result.DV[
II - 1].Distance ==
nullptr)
2850 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2852 assert(Result.DV[
II - 1].Distance->isZero() &&
2853 "Inconsistency between distance and direction");
2859 const SCEV *Distance = Result.getDistance(
II);
2860 if (Distance && Distance->
isZero())
2862 "Distance is zero, but direction is not EQ");
2866 if (SameSDLevels > 0) {
2869 assert(CommonLevels >= SameSDLevels);
2870 CommonLevels -= SameSDLevels;
2871 MaxLevels += SameSDLevels;
2872 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2873 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2874 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2875 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2876 DV[Level] = Result.DV[Level];
2877 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2878 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2879 Result.DV = std::move(DV);
2880 Result.DVSameSD = std::move(DVSameSD);
2881 Result.Levels = CommonLevels;
2882 Result.SameSDLevels = SameSDLevels;
2885 if (PossiblyLoopIndependent) {
2889 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2891 Result.LoopIndependent =
false;
2899 bool AllEqual =
true;
2900 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2906 if (AllEqual && Result.Assumptions.getPredicates().empty())
2910 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isLoadOrStore(const Instruction *I)
static OverflowSafeSignedAPInt floorOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
static OverflowSafeSignedAPInt ceilingOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static bool isDependenceTestEnabled(DependenceTestType Test)
Returns true iff Test is enabled.
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static std::pair< OverflowSafeSignedAPInt, OverflowSafeSignedAPInt > inferDomainOfAffine(OverflowSafeSignedAPInt A, OverflowSafeSignedAPInt B, OverflowSafeSignedAPInt UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static cl::opt< 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.
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...