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;
1773bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
1774 const Loop *CurLoop,
1775 const SCEV *&CurLoopCoeff,
1776 APInt &RunningGCD)
const {
1779 if (RunningGCD == 1)
1784 assert(isLoopInvariant(Expr, CurLoop) &&
1785 "Expected loop invariant expression");
1792 if (AddRec->
getLoop() == CurLoop) {
1793 CurLoopCoeff = Step;
1807 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
1827 return Coefficients;
1847bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
1854 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
1874 if (ConstDelta == 0)
1877 APInt Remainder = ConstDelta.
srem(RunningGCD);
1878 if (Remainder != 0) {
1892 bool Improved =
false;
1893 const SCEV *Coefficients = Src;
1894 while (
const SCEVAddRecExpr *AddRec =
1897 const Loop *CurLoop = AddRec->
getLoop();
1900 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
1902 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
1903 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
1918 if (RunningGCD != 0) {
1919 Remainder = ConstDelta.
srem(RunningGCD);
1921 if (Remainder != 0) {
1922 unsigned Level = mapSrcLoop(CurLoop);
1923 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
1967bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
1974 ++BanerjeeApplications;
1978 collectCoeffInfo(Src,
true, A0,
A);
1982 collectCoeffInfo(Dst,
false, B0,
B);
1991 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
1992 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
1995 findBoundsALL(
A,
B, Bound, K);
2010 bool Disproved =
false;
2013 unsigned DepthExpanded = 0;
2015 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2017 bool Improved =
false;
2018 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2020 unsigned Old =
Result.DV[
K - 1].Direction;
2021 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2022 Improved |= Old !=
Result.DV[
K - 1].Direction;
2023 if (!
Result.DV[K - 1].Direction) {
2031 ++BanerjeeSuccesses;
2033 ++BanerjeeIndependence;
2037 ++BanerjeeIndependence;
2048unsigned DependenceInfo::exploreDirections(
2051 unsigned &DepthExpanded,
const SCEV *Delta)
const {
2057 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2058 "direction exploration is terminated.\n");
2059 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2065 if (Level > CommonLevels) {
2068 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2070 Bound[
K].DirSet |= Bound[
K].Direction;
2095 if (Level > DepthExpanded) {
2096 DepthExpanded =
Level;
2098 findBoundsLT(
A,
B, Bound, Level);
2099 findBoundsGT(
A,
B, Bound, Level);
2100 findBoundsEQ(
A,
B, Bound, Level);
2139 unsigned NewDeps = 0;
2143 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2148 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2153 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2159 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2164bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2166 const SCEV *Delta)
const {
2167 Bound[
Level].Direction = DirKind;
2168 if (
const SCEV *LowerBound = getLowerBound(Bound))
2171 if (
const SCEV *UpperBound = getUpperBound(Bound))
2200 if (Bound[K].Iterations) {
2202 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2204 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2209 SE->getZero(
A[K].Coeff->
getType());
2212 SE->getZero(
A[K].Coeff->
getType());
2239 if (Bound[K].Iterations) {
2240 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2241 const SCEV *NegativePart = getNegativePart(Delta);
2243 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2244 const SCEV *PositivePart = getPositivePart(Delta);
2246 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2250 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2251 const SCEV *NegativePart = getNegativePart(Delta);
2252 if (NegativePart->
isZero())
2254 const SCEV *PositivePart = getPositivePart(Delta);
2255 if (PositivePart->
isZero())
2281 if (Bound[K].Iterations) {
2282 const SCEV *Iter_1 = SE->getMinusSCEV(
2283 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2284 const SCEV *NegPart =
2285 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2287 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2288 const SCEV *PosPart =
2289 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2291 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2295 const SCEV *NegPart =
2296 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2299 const SCEV *PosPart =
2300 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2327 if (Bound[K].Iterations) {
2328 const SCEV *Iter_1 = SE->getMinusSCEV(
2329 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2330 const SCEV *NegPart =
2331 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2333 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2334 const SCEV *PosPart =
2335 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2337 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2341 const SCEV *NegPart =
2342 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2345 const SCEV *PosPart =
2346 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2353const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2354 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2358const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2359 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2365void DependenceInfo::collectCoeffInfo(
2368 const SCEV *
Zero = SE->getZero(Subscript->getType());
2369 CI.
resize(MaxLevels + 1);
2370 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2372 CI[
K].PosPart =
Zero;
2373 CI[
K].NegPart =
Zero;
2374 CI[
K].Iterations =
nullptr;
2378 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2380 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2381 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2382 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2388 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2395 if (CI[K].Iterations)
2410 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2411 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2425 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2426 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2445 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2446 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2447 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2448 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2449 const SCEVUnknown *SrcBase =
2451 const SCEVUnknown *DstBase =
2454 if (!SrcBase || !DstBase || SrcBase != DstBase)
2459 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2460 SrcSubscripts, DstSubscripts) &&
2461 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2462 SrcSubscripts, DstSubscripts))
2465 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2466 isLoopInvariant(DstBase, DstLoop) &&
2467 "Expected SrcBase and DstBase to be loop invariant");
2471 dbgs() <<
"\nSrcSubscripts: ";
2472 for (
int I = 0;
I <
Size;
I++)
2473 dbgs() << *SrcSubscripts[
I];
2474 dbgs() <<
"\nDstSubscripts: ";
2475 for (
int I = 0;
I <
Size;
I++)
2476 dbgs() << *DstSubscripts[
I];
2485 for (
int I = 0;
I <
Size; ++
I) {
2486 Pair[
I].Src = SrcSubscripts[
I];
2487 Pair[
I].Dst = DstSubscripts[
I];
2489 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2490 "Unexpected different types for the subscripts");
2499bool DependenceInfo::tryDelinearizeFixedSize(
2504 const SCEVUnknown *SrcBase =
2506 const SCEVUnknown *DstBase =
2508 assert(SrcBase && DstBase && SrcBase == DstBase &&
2509 "expected src and dst scev unknowns to be equal");
2512 const SCEV *ElemSize = SE->getElementSize(Src);
2513 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2516 SrcSubscripts, SrcSizes, ElemSize) ||
2518 DstSubscripts, DstSizes, ElemSize))
2523 if (SrcSizes.
size() != DstSizes.
size() ||
2524 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2525 SrcSubscripts.
clear();
2526 DstSubscripts.
clear();
2531 "Expected equal number of entries in the list of SrcSubscripts and "
2543 SrcSubscripts.
clear();
2544 DstSubscripts.
clear();
2549 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2556bool DependenceInfo::tryDelinearizeParametricSize(
2561 const SCEVUnknown *SrcBase =
2563 const SCEVUnknown *DstBase =
2565 assert(SrcBase && DstBase && SrcBase == DstBase &&
2566 "expected src and dst scev unknowns to be equal");
2568 const SCEV *ElementSize = SE->getElementSize(Src);
2569 if (ElementSize != SE->getElementSize(Dst))
2572 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2573 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2594 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2595 SrcSubscripts.
size() != DstSubscripts.
size())
2618 for (
unsigned VI : BV.
set_bits()) {
2628 FunctionAnalysisManager::Invalidator &Inv) {
2635 return Inv.invalidate<
AAManager>(F, PA) ||
2649std::unique_ptr<Dependence>
2651 bool UnderRuntimeAssumptions) {
2653 bool PossiblyLoopIndependent =
true;
2655 PossiblyLoopIndependent =
false;
2657 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
2663 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
2664 return std::make_unique<Dependence>(Src, Dst,
2676 return std::make_unique<Dependence>(Src, Dst,
2690 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
2691 return std::make_unique<Dependence>(Src, Dst,
2697 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
2698 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
2701 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
2702 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
2703 if (SrcBase != DstBase) {
2710 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
2711 return std::make_unique<Dependence>(Src, Dst,
2719 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2720 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2721 if (!isLoopInvariant(SrcBase, SrcLoop) ||
2722 !isLoopInvariant(DstBase, DstLoop)) {
2723 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
2724 return std::make_unique<Dependence>(Src, Dst,
2729 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
2730 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
2733 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
2734 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
2735 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
2736 return std::make_unique<Dependence>(Src, Dst,
2741 if (!Assume.empty() && !UnderRuntimeAssumptions)
2742 return std::make_unique<Dependence>(Src, Dst,
2747 Pair[0].Src = SrcEv;
2748 Pair[0].Dst = DstEv;
2750 if (tryDelinearize(Src, Dst, Pair)) {
2752 Pairs = Pair.
size();
2757 establishNestingLevels(Src, Dst);
2759 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
2760 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
2761 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
2764 CommonLevels += SameSDLevels;
2765 MaxLevels -= SameSDLevels;
2766 if (SameSDLevels > 0) {
2769 for (
unsigned P = 0;
P < Pairs; ++
P) {
2771 Subscript::ClassificationKind TestClass =
2772 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
2773 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
2775 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
2776 TestClass != Subscript::RDIV) {
2778 CommonLevels -= SameSDLevels;
2779 MaxLevels += SameSDLevels;
2786 if (SameSDLevels > 0)
2790 PossiblyLoopIndependent, CommonLevels);
2793 for (
unsigned P = 0;
P < Pairs; ++
P) {
2794 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
2795 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
2796 Pair[
P].Loops.
resize(MaxLevels + 1);
2797 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
2799 Pair[
P].Classification =
2800 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
2801 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
2802 Pair[
P].GroupLoops = Pair[
P].Loops;
2803 Pair[
P].Group.set(
P);
2813 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
2822 switch (Pair[
SI].Classification) {
2823 case Subscript::NonLinear:
2825 ++NonlinearSubscriptPairs;
2826 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
2828 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
2831 case Subscript::ZIV:
2833 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2836 case Subscript::SIV: {
2839 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
2840 UnderRuntimeAssumptions))
2844 case Subscript::RDIV:
2846 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
2849 case Subscript::MIV:
2851 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
2859 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
2860 CompleteLoops |= Pair[
SI].
Loops;
2861 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
2862 if (CompleteLoops[
II])
2863 Result.DV[
II - 1].Scalar =
false;
2868 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
2870 if (Result.DV[
II - 1].Distance ==
nullptr)
2871 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
2873 assert(Result.DV[
II - 1].Distance->isZero() &&
2874 "Inconsistency between distance and direction");
2880 const SCEV *Distance = Result.getDistance(
II);
2881 if (Distance && Distance->
isZero())
2883 "Distance is zero, but direction is not EQ");
2887 if (SameSDLevels > 0) {
2890 assert(CommonLevels >= SameSDLevels);
2891 CommonLevels -= SameSDLevels;
2892 MaxLevels += SameSDLevels;
2893 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
2894 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
2895 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
2896 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
2897 DV[Level] = Result.DV[Level];
2898 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
2899 DVSameSD[Level] = Result.DV[CommonLevels + Level];
2900 Result.DV = std::move(DV);
2901 Result.DVSameSD = std::move(DVSameSD);
2902 Result.Levels = CommonLevels;
2903 Result.SameSDLevels = SameSDLevels;
2906 if (PossiblyLoopIndependent) {
2910 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2912 Result.LoopIndependent =
false;
2920 bool AllEqual =
true;
2921 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
2927 if (AllEqual && Result.Assumptions.getPredicates().empty())
2931 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 const SCEV * analyzeCoefficientsForGCD(const SCEV *Coefficients, APInt &RunningGCD, ScalarEvolution *SE)
Compute RunningGCD and return the start value of the innermost SCEVAddRecExpr.
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< 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()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
@ ICMP_SGT
signed greater than
This class represents a range of values.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns the runtime assumptions under which this Dependence relation is valid...
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
virtual unsigned getDirection(unsigned Level, bool SameSD=false) const
getDirection - Returns the direction associated with a particular common or SameSD level.
virtual bool isScalar(unsigned Level, bool SameSD=false) const
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
virtual bool inSameSDLoops(unsigned Level) const
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
unsigned getDirection(unsigned Level, bool SameSD=false) const override
getDirection - Returns the direction associated with a particular common or SameSD level.
bool isScalar(unsigned Level, bool SameSD=false) const override
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isDirectionNegative() const override
Check if the direction vector is negative.
void negate(ScalarEvolution &SE) override
Negate the dependence by swapping the source and destination, and reversing the direction and distanc...
const SCEV * getDistance(unsigned Level, bool SameSD=false) const override
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
DVEntry getDVEntry(unsigned Level, bool IsSameSD) const
getDVEntry - Returns the DV entry associated with a regular or a SameSD level.
bool inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
This class represents a constant integer value.
const APInt & getAPInt() const
bool hasNoSignedWrap() const
This class represents a composition of other SCEV predicates, and is the class that most clients will...
This class represents an analyzed expression in the program.
LLVM_ABI bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
constexpr bool operator!(E Val)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
APInt operator+(APInt a, const APInt &b)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...