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 APInt TC = CM.
sdiv(
G);
1616 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1617 const OverflowSafeSignedAPInt &V1,
1618 bool IsMin) -> std::optional<APInt> {
1625 return std::nullopt;
1628 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1629 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1630 if (!OptTL || !OptTU)
1633 TL = std::move(*OptTL);
1634 TU = std::move(*OptTU);
1643 assert(SrcUM == DstUM &&
"Expecting same upper bound for Src and Dst");
1647 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1648 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1652 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1653 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1655 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1656 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1659 if (!LowerDistance || !UpperDistance)
1662 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1663 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1665 if (LowerDistance->sle(0) && UpperDistance->sge(0))
1667 if (LowerDistance->slt(0))
1669 if (UpperDistance->sgt(0))
1687bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
1689 bool UnderRuntimeAssumptions) {
1694 if (SrcAddRec && DstAddRec) {
1697 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1698 [[maybe_unused]]
const Loop *CurDstLoop = DstAddRec->
getLoop();
1699 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
1700 "Loops in the SIV test should have the same iteration space and "
1702 Level = mapSrcLoop(CurSrcLoop);
1703 bool disproven =
false;
1704 if (SrcCoeff == DstCoeff)
1705 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
1706 UnderRuntimeAssumptions);
1707 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
1708 disproven = weakCrossingSIVtest(SrcAddRec, DstAddRec, Level, Result);
1709 return disproven || exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
1712 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
1713 Level = mapSrcLoop(CurSrcLoop);
1714 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result);
1717 const Loop *CurDstLoop = DstAddRec->
getLoop();
1718 Level = mapDstLoop(CurDstLoop);
1719 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result);
1735bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
1741 assert(SrcAddRec && DstAddRec &&
"Unexpected non-addrec input");
1742 return exactRDIVtest(SrcAddRec, DstAddRec, Result) ||
1743 gcdMIVtest(Src, Dst, Result);
1749bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
1754 return gcdMIVtest(Src, Dst, Result) ||
1755 banerjeeMIVtest(Src, Dst,
Loops, Result);
1768 if (Product->hasNoSignedWrap())
1770 return std::nullopt;
1773const SCEV *DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
1774 const Loop *CurLoop,
1775 const SCEV *&CurLoopCoeff,
1776 APInt &RunningGCD)
const {
1779 assert(isLoopInvariant(Expr, CurLoop) &&
1780 "Expected loop invariant expression");
1787 if (AddRec->
getLoop() == CurLoop) {
1788 CurLoopCoeff = Step;
1802 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
1822bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
1829 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
1832 const SCEV *Dummy =
nullptr;
1833 const SCEV *SrcConst =
1834 accumulateCoefficientsGCD(Src,
nullptr, Dummy, RunningGCD);
1837 const SCEV *DstConst =
1838 accumulateCoefficientsGCD(Dst,
nullptr, Dummy, RunningGCD);
1851 if (ConstDelta == 0)
1854 APInt Remainder = ConstDelta.
srem(RunningGCD);
1855 if (Remainder != 0) {
1869 bool Improved =
false;
1870 const SCEV *Coefficients = Src;
1871 while (
const SCEVAddRecExpr *AddRec =
1874 const Loop *CurLoop = AddRec->
getLoop();
1877 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
1879 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
1880 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
1895 if (RunningGCD != 0) {
1896 Remainder = ConstDelta.
srem(RunningGCD);
1898 if (Remainder != 0) {
1899 unsigned Level = mapSrcLoop(CurLoop);
1900 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
1944bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
1951 ++BanerjeeApplications;
1955 collectCoeffInfo(Src,
true, A0,
A);
1959 collectCoeffInfo(Dst,
false, B0,
B);
1968 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
1969 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
1972 findBoundsALL(
A,
B, Bound, K);
1987 bool Disproved =
false;
1990 unsigned DepthExpanded = 0;
1992 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
1994 bool Improved =
false;
1995 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
1997 unsigned Old =
Result.DV[
K - 1].Direction;
1998 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
1999 Improved |= Old !=
Result.DV[
K - 1].Direction;
2000 if (!
Result.DV[K - 1].Direction) {
2008 ++BanerjeeSuccesses;
2010 ++BanerjeeIndependence;
2014 ++BanerjeeIndependence;
2025unsigned DependenceInfo::exploreDirections(
2028 unsigned &DepthExpanded,
const SCEV *Delta)
const {
2034 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2035 "direction exploration is terminated.\n");
2036 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2042 if (Level > CommonLevels) {
2045 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2047 Bound[
K].DirSet |= Bound[
K].Direction;
2072 if (Level > DepthExpanded) {
2073 DepthExpanded =
Level;
2075 findBoundsLT(
A,
B, Bound, Level);
2076 findBoundsGT(
A,
B, Bound, Level);
2077 findBoundsEQ(
A,
B, Bound, Level);
2116 unsigned NewDeps = 0;
2120 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2125 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2130 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2136 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2141bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2143 const SCEV *Delta)
const {
2144 Bound[
Level].Direction = DirKind;
2145 if (
const SCEV *LowerBound = getLowerBound(Bound))
2148 if (
const SCEV *UpperBound = getUpperBound(Bound))
2177 if (Bound[K].Iterations) {
2179 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2181 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2186 SE->getZero(
A[K].Coeff->
getType());
2189 SE->getZero(
A[K].Coeff->
getType());
2216 if (Bound[K].Iterations) {
2217 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2218 const SCEV *NegativePart = getNegativePart(Delta);
2220 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2221 const SCEV *PositivePart = getPositivePart(Delta);
2223 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2227 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2228 const SCEV *NegativePart = getNegativePart(Delta);
2229 if (NegativePart->
isZero())
2231 const SCEV *PositivePart = getPositivePart(Delta);
2232 if (PositivePart->
isZero())
2258 if (Bound[K].Iterations) {
2259 const SCEV *Iter_1 = SE->getMinusSCEV(
2260 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2261 const SCEV *NegPart =
2262 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2264 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2265 const SCEV *PosPart =
2266 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2268 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2272 const SCEV *NegPart =
2273 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2276 const SCEV *PosPart =
2277 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2304 if (Bound[K].Iterations) {
2305 const SCEV *Iter_1 = SE->getMinusSCEV(
2306 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2307 const SCEV *NegPart =
2308 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2310 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2311 const SCEV *PosPart =
2312 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2314 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2318 const SCEV *NegPart =
2319 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2322 const SCEV *PosPart =
2323 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2330const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2331 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2335const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2336 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2342void DependenceInfo::collectCoeffInfo(
2345 const SCEV *
Zero = SE->getZero(Subscript->getType());
2346 CI.
resize(MaxLevels + 1);
2347 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2349 CI[
K].PosPart =
Zero;
2350 CI[
K].NegPart =
Zero;
2351 CI[
K].Iterations =
nullptr;
2355 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2357 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2358 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2359 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2365 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2372 if (CI[K].Iterations)
2387 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2388 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2402 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2403 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2422 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2423 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2424 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2425 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2426 const SCEVUnknown *SrcBase =
2428 const SCEVUnknown *DstBase =
2431 if (!SrcBase || !DstBase || SrcBase != DstBase)
2436 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2437 SrcSubscripts, DstSubscripts) &&
2438 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2439 SrcSubscripts, DstSubscripts))
2442 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2443 isLoopInvariant(DstBase, DstLoop) &&
2444 "Expected SrcBase and DstBase to be loop invariant");
2448 dbgs() <<
"\nSrcSubscripts: ";
2449 for (
int I = 0;
I <
Size;
I++)
2450 dbgs() << *SrcSubscripts[
I];
2451 dbgs() <<
"\nDstSubscripts: ";
2452 for (
int I = 0;
I <
Size;
I++)
2453 dbgs() << *DstSubscripts[
I];
2462 for (
int I = 0;
I <
Size; ++
I) {
2463 Pair[
I].Src = SrcSubscripts[
I];
2464 Pair[
I].Dst = DstSubscripts[
I];
2466 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2467 "Unexpected different types for the subscripts");
2476bool DependenceInfo::tryDelinearizeFixedSize(
2481 const SCEVUnknown *SrcBase =
2483 const SCEVUnknown *DstBase =
2485 assert(SrcBase && DstBase && SrcBase == DstBase &&
2486 "expected src and dst scev unknowns to be equal");
2489 const SCEV *ElemSize = SE->getElementSize(Src);
2490 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2493 SrcSubscripts, SrcSizes, ElemSize) ||
2495 DstSubscripts, DstSizes, ElemSize))
2500 if (SrcSizes.
size() != DstSizes.
size() ||
2501 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2502 SrcSubscripts.
clear();
2503 DstSubscripts.
clear();
2508 "Expected equal number of entries in the list of SrcSubscripts and "
2520 SrcSubscripts.
clear();
2521 DstSubscripts.
clear();
2526 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2533bool DependenceInfo::tryDelinearizeParametricSize(
2538 const SCEVUnknown *SrcBase =
2540 const SCEVUnknown *DstBase =
2542 assert(SrcBase && DstBase && SrcBase == DstBase &&
2543 "expected src and dst scev unknowns to be equal");
2545 const SCEV *ElementSize = SE->getElementSize(Src);
2546 if (ElementSize != SE->getElementSize(Dst))
2549 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2550 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2571 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2572 SrcSubscripts.
size() != DstSubscripts.
size())
2595 for (
unsigned VI : BV.
set_bits()) {
2605 FunctionAnalysisManager::Invalidator &Inv) {
2612 return Inv.invalidate<
AAManager>(F, PA) ||
2626std::unique_ptr<Dependence>
2628 bool UnderRuntimeAssumptions) {
2630 bool PossiblyLoopIndependent =
true;
2632 PossiblyLoopIndependent =
false;
2634 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2640 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2641 return std::make_unique<Dependence>(Src, Dst,
2653 return std::make_unique<Dependence>(Src, Dst,
2667 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2668 return std::make_unique<Dependence>(Src, Dst,
2674 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2675 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2678 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2679 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2680 if (SrcBase != DstBase) {
2687 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2688 return std::make_unique<Dependence>(Src, Dst,
2696 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2697 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2698 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2699 !isLoopInvariant(DstBase, DstLoop)) {
2700 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2701 return std::make_unique<Dependence>(Src, Dst,
2706 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2707 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2710 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2711 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2712 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2713 return std::make_unique<Dependence>(Src, Dst,
2718 if (!Assume.empty() && !UnderRuntimeAssumptions)
2719 return std::make_unique<Dependence>(Src, Dst,
2724 Pair[0].Src = SrcEv;
2725 Pair[0].Dst = DstEv;
2727 if (tryDelinearize(Src, Dst, Pair)) {
2729 Pairs = Pair.
size();
2734 establishNestingLevels(Src, Dst);
2736 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2737 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2738 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2741 CommonLevels += SameSDLevels;
2742 MaxLevels -= SameSDLevels;
2743 if (SameSDLevels > 0) {
2746 for (
unsigned P = 0;
P < Pairs; ++
P) {
2748 Subscript::ClassificationKind TestClass =
2749 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2750 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2752 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2753 TestClass != Subscript::RDIV) {
2755 CommonLevels -= SameSDLevels;
2756 MaxLevels += SameSDLevels;
2763 if (SameSDLevels > 0)
2767 PossiblyLoopIndependent, CommonLevels);
2770 for (
unsigned P = 0;
P < Pairs; ++
P) {
2771 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2772 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2773 Pair[
P].Loops.
resize(MaxLevels + 1);
2774 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2776 Pair[
P].Classification =
2777 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2778 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2779 Pair[
P].GroupLoops = Pair[
P].Loops;
2780 Pair[
P].Group.set(
P);
2790 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2799 switch (Pair[
SI].Classification) {
2800 case Subscript::NonLinear:
2802 ++NonlinearSubscriptPairs;
2803 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2805 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2808 case Subscript::ZIV:
2810 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2813 case Subscript::SIV: {
2816 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2817 UnderRuntimeAssumptions))
2821 case Subscript::RDIV:
2823 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2826 case Subscript::MIV:
2828 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2836 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2837 CompleteLoops |= Pair[
SI].
Loops;
2838 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2839 if (CompleteLoops[
II])
2840 Result.DV[
II - 1].Scalar =
false;
2845 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2847 if (Result.DV[
II - 1].Distance ==
nullptr)
2848 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2850 assert(Result.DV[
II - 1].Distance->isZero() &&
2851 "Inconsistency between distance and direction");
2857 const SCEV *Distance = Result.getDistance(
II);
2858 if (Distance && Distance->
isZero())
2860 "Distance is zero, but direction is not EQ");
2864 if (SameSDLevels > 0) {
2867 assert(CommonLevels >= SameSDLevels);
2868 CommonLevels -= SameSDLevels;
2869 MaxLevels += SameSDLevels;
2870 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2871 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2872 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2873 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2874 DV[Level] = Result.DV[Level];
2875 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2876 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2877 Result.DV = std::move(DV);
2878 Result.DVSameSD = std::move(DVSameSD);
2879 Result.Levels = CommonLevels;
2880 Result.SameSDLevels = SameSDLevels;
2883 if (PossiblyLoopIndependent) {
2887 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2889 Result.LoopIndependent =
false;
2897 bool AllEqual =
true;
2898 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2904 if (AllEqual && Result.Assumptions.getPredicates().empty())
2908 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...