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");
88STATISTIC(SymbolicRDIVapplications,
"Symbolic RDIV applications");
89STATISTIC(SymbolicRDIVindependence,
"Symbolic RDIV independence");
93STATISTIC(BanerjeeApplications,
"Banerjee applications");
94STATISTIC(BanerjeeIndependence,
"Banerjee independence");
96STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
100 cl::desc(
"Try to delinearize array references."));
102 "da-disable-delinearization-checks",
cl::Hidden,
104 "Disable checks that try to statically verify validity of "
105 "delinearized subscripts. Enabling this option may result in incorrect "
106 "dependence vectors for languages that allow the subscript of one "
107 "dimension to underflow or overflow into another dimension."));
111 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
112 "explore MIV direction vectors."));
117enum class DependenceTestType {
132 "da-enable-dependence-test",
cl::init(DependenceTestType::All),
134 cl::desc(
"Run only specified dependence test routine and disable others. "
135 "The purpose is mainly to exclude the influence of other "
136 "dependence test routines in regression tests. If set to All, all "
137 "dependence test routines are enabled."),
139 "Enable all dependence test routines."),
140 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
141 "Enable only Strong SIV test."),
142 clEnumValN(DependenceTestType::WeakCrossingSIV,
144 "Enable only Weak-Crossing SIV test."),
145 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
146 "Enable only Exact SIV test."),
147 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
148 "Enable only Weak-Zero SIV test."),
149 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
150 "Enable only Exact RDIV test."),
151 clEnumValN(DependenceTestType::SymbolicRDIV,
"symbolic-rdiv",
152 "Enable only Symbolic RDIV test."),
153 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
154 "Enable only GCD MIV test."),
155 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
156 "Enable only Banerjee MIV test.")));
162 cl::desc(
"Check if the subscripts are monotonic. If it's not, dependence "
163 "is reported as unknown."));
168 "When printing analysis, dump the results of monotonicity checks."));
184 "Dependence Analysis",
true,
true)
257enum class SCEVMonotonicityType {
269 MultivariateSignedMonotonic,
272struct SCEVMonotonicity {
273 SCEVMonotonicity(SCEVMonotonicityType
Type,
274 const SCEV *FailurePoint =
nullptr);
276 SCEVMonotonicityType
getType()
const {
return Type; }
278 const SCEV *getFailurePoint()
const {
return FailurePoint; }
280 bool isUnknown()
const {
return Type == SCEVMonotonicityType::Unknown; }
282 void print(raw_ostream &OS,
unsigned Depth)
const;
285 SCEVMonotonicityType
Type;
288 const SCEV *FailurePoint;
295struct SCEVMonotonicityChecker
296 :
public SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity> {
298 SCEVMonotonicityChecker(ScalarEvolution *SE) : SE(SE) {}
303 SCEVMonotonicity checkMonotonicity(
const SCEV *Expr,
304 const Loop *OutermostLoop);
310 const Loop *OutermostLoop;
313 SCEVMonotonicity invariantOrUnknown(
const SCEV *Expr);
317 bool isLoopInvariant(
const SCEV *Expr)
const;
320 SCEVMonotonicity createUnknown(
const SCEV *FailurePoint) {
321 return SCEVMonotonicity(SCEVMonotonicityType::Unknown, FailurePoint);
324 SCEVMonotonicity visitAddRecExpr(
const SCEVAddRecExpr *Expr);
326 SCEVMonotonicity visitConstant(
const SCEVConstant *) {
327 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
329 SCEVMonotonicity visitVScale(
const SCEVVScale *) {
330 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
334 SCEVMonotonicity visitZeroExtendExpr(
const SCEVZeroExtendExpr *Expr) {
335 return invariantOrUnknown(Expr);
337 SCEVMonotonicity visitSignExtendExpr(
const SCEVSignExtendExpr *Expr) {
338 return invariantOrUnknown(Expr);
340 SCEVMonotonicity visitAddExpr(
const SCEVAddExpr *Expr) {
341 return invariantOrUnknown(Expr);
343 SCEVMonotonicity visitMulExpr(
const SCEVMulExpr *Expr) {
344 return invariantOrUnknown(Expr);
346 SCEVMonotonicity visitPtrToAddrExpr(
const SCEVPtrToAddrExpr *Expr) {
347 return invariantOrUnknown(Expr);
349 SCEVMonotonicity visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
350 return invariantOrUnknown(Expr);
352 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
353 return invariantOrUnknown(Expr);
355 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
356 return invariantOrUnknown(Expr);
358 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
359 return invariantOrUnknown(Expr);
361 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
362 return invariantOrUnknown(Expr);
364 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
365 return invariantOrUnknown(Expr);
367 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
368 return invariantOrUnknown(Expr);
370 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
371 return invariantOrUnknown(Expr);
373 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
374 return invariantOrUnknown(Expr);
376 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
377 return invariantOrUnknown(Expr);
380 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
391struct OverflowSafeSignedAPInt {
392 OverflowSafeSignedAPInt() :
Value(std::nullopt) {}
393 OverflowSafeSignedAPInt(
const APInt &V) :
Value(
V) {}
394 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
396 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
398 return OverflowSafeSignedAPInt();
402 return OverflowSafeSignedAPInt();
403 return OverflowSafeSignedAPInt(Result);
408 return OverflowSafeSignedAPInt();
409 return *
this + fromInt(
RHS);
412 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
414 return OverflowSafeSignedAPInt();
418 return OverflowSafeSignedAPInt();
419 return OverflowSafeSignedAPInt(Result);
424 return OverflowSafeSignedAPInt();
425 return *
this - fromInt(
RHS);
428 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
430 return OverflowSafeSignedAPInt();
434 return OverflowSafeSignedAPInt();
435 return OverflowSafeSignedAPInt(Result);
438 OverflowSafeSignedAPInt
operator-()
const {
440 return OverflowSafeSignedAPInt();
441 if (
Value->isMinSignedValue())
442 return OverflowSafeSignedAPInt();
443 return OverflowSafeSignedAPInt(-*
Value);
446 operator bool()
const {
return Value.has_value(); }
455 const APInt *operator->()
const {
463 std::optional<APInt>
Value;
465 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
467 return OverflowSafeSignedAPInt(
468 APInt(
Value->getBitWidth(), V,
true));
480 bool NormalizeResults) {
481 auto *
F = DA->getFunction();
484 SCEVMonotonicityChecker Checker(&SE);
485 OS <<
"Monotonicity check:\n";
491 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
494 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
495 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
496 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
504 if (SrcI->mayReadOrWriteMemory()) {
507 if (DstI->mayReadOrWriteMemory()) {
508 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
509 OS <<
" da analyze - ";
510 if (
auto D = DA->depends(&*SrcI, &*DstI,
516 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
517 const SCEV *Distance =
D->getDistance(Level);
518 bool IsDistanceZero = Distance && Distance->
isZero();
521 assert(IsDistanceZero == IsDirectionEQ &&
522 "Inconsistent distance and direction.");
527 if (NormalizeResults &&
D->normalize(&SE))
528 OS <<
"normalized - ";
547 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
560 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
565 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
570 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
575 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
589 bool PossiblyLoopIndependent,
590 unsigned CommonLevels)
591 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
592 LoopIndependent(PossiblyLoopIndependent) {
596 DV = std::make_unique<
DVEntry[]>(CommonLevels);
615 for (
unsigned Level = 1; Level <= Levels; ++Level) {
616 unsigned char Direction = DV[Level - 1].Direction;
631 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
634 for (
unsigned Level = 1; Level <= Levels; ++Level) {
635 unsigned char Direction = DV[Level - 1].Direction;
643 DV[Level - 1].Direction = RevDirection;
645 if (DV[Level - 1].Distance !=
nullptr)
649 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
691 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
692 "Level out of range");
693 return Level > Levels;
699SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
700 const SCEV *FailurePoint)
701 :
Type(
Type), FailurePoint(FailurePoint) {
703 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
704 "FailurePoint must be provided iff Type is Unknown");
710 case SCEVMonotonicityType::Unknown:
711 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
713 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
715 case SCEVMonotonicityType::Invariant:
718 case SCEVMonotonicityType::MultivariateSignedMonotonic:
719 OS <<
"MultivariateSignedMonotonic\n";
724bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
725 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
728SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
729 if (isLoopInvariant(Expr))
730 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
731 return createUnknown(Expr);
735SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
736 const Loop *OutermostLoop) {
738 "OutermostLoop must be outermost");
740 this->OutermostLoop = OutermostLoop;
756SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
758 return createUnknown(Expr);
763 SCEVMonotonicity StartMon =
visit(Start);
764 if (StartMon.isUnknown())
767 if (!isLoopInvariant(Step))
768 return createUnknown(Expr);
770 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
793 if (SameSDLevels > 0) {
794 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
801 if (!Assumptions.isAlwaysTrue()) {
802 OS <<
" Runtime Assumptions:\n";
803 Assumptions.print(OS, 2);
812 bool OnSameSD =
false;
813 unsigned LevelNum = Levels;
815 LevelNum += SameSDLevels;
817 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
892 return LI->isUnordered();
894 return SI->isUnordered();
902bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
903 const Loop *DstLoop)
const {
904 if (SrcLoop == DstLoop)
914 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
915 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
916 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
917 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
918 DstUP = SE->getBackedgeTakenCount(DstLoop);
920 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
921 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
922 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
923 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
994void DependenceInfo::establishNestingLevels(
const Instruction *Src,
996 const BasicBlock *SrcBlock = Src->getParent();
997 const BasicBlock *DstBlock = Dst->getParent();
998 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
999 unsigned DstLevel = LI->getLoopDepth(DstBlock);
1000 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
1001 const Loop *DstLoop = LI->getLoopFor(DstBlock);
1002 SrcLevels = SrcLevel;
1003 MaxLevels = SrcLevel + DstLevel;
1005 while (SrcLevel > DstLevel) {
1009 while (DstLevel > SrcLevel) {
1015 while (SrcLoop != DstLoop) {
1017 if (!haveSameSD(SrcLoop, DstLoop))
1023 CommonLevels = SrcLevel;
1024 MaxLevels -= CommonLevels;
1029unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1035unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1037 if (
D > CommonLevels)
1040 return D - CommonLevels + SrcLevels;
1067 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1079 return isLoopInvariant(Expr, LoopNest);
1086 const Loop *
L = LoopNest;
1087 while (L && AddRec->
getLoop() != L)
1088 L =
L->getParentLoop();
1094 if (!isLoopInvariant(Step, LoopNest))
1100 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1105bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1107 return checkSubscript(Src, LoopNest,
Loops,
true);
1112bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1114 return checkSubscript(Dst, LoopNest,
Loops,
false);
1120DependenceInfo::Subscript::ClassificationKind
1121DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1122 const SCEV *Dst,
const Loop *DstLoopNest,
1124 SmallBitVector SrcLoops(MaxLevels + 1);
1125 SmallBitVector DstLoops(MaxLevels + 1);
1126 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1127 return Subscript::NonLinear;
1128 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1129 return Subscript::NonLinear;
1132 unsigned N =
Loops.count();
1134 return Subscript::ZIV;
1136 return Subscript::SIV;
1137 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
1138 return Subscript::RDIV;
1139 return Subscript::MIV;
1149const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1150 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1151 const SCEV *UB = SE->getBackedgeTakenCount(L);
1152 return SE->getTruncateOrZeroExtend(UB,
T);
1159const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1161 if (
const SCEV *UB = collectUpperBound(L,
T))
1192bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1207 Result.Consistent =
false;
1241 bool UnderRuntimeAssumptions) {
1245 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1246 assert(Coeff == Dst->getStepRecurrence(*SE) &&
1247 "Expecting same coefficient in Strong SIV test");
1248 const SCEV *SrcConst = Src->getStart();
1249 const SCEV *DstConst = Dst->getStart();
1257 ++StrongSIVapplications;
1258 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1262 ConstantRange SrcRange = SE->getSignedRange(Src);
1263 ConstantRange DstRange = SE->getSignedRange(Dst);
1265 ++StrongSIVindependence;
1266 ++StrongSIVsuccesses;
1272 Result.Consistent =
false;
1282 APInt Distance = ConstDelta;
1283 APInt Remainder = ConstDelta;
1288 if (Remainder != 0) {
1290 ++StrongSIVindependence;
1291 ++StrongSIVsuccesses;
1294 Result.DV[
Level].Distance = SE->getConstant(Distance);
1295 if (Distance.
sgt(0))
1297 else if (Distance.
slt(0))
1301 ++StrongSIVsuccesses;
1302 }
else if (Delta->
isZero()) {
1306 if (SE->isKnownNonZero(Coeff)) {
1308 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1311 if (UnderRuntimeAssumptions) {
1312 const SCEVPredicate *Pred = SE->getComparePredicate(
1314 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1320 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1321 <<
" != 0, but not allowed. Failing this test.\n");
1328 ++StrongSIVsuccesses;
1330 if (Coeff->
isOne()) {
1334 Result.Consistent =
false;
1338 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1339 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1340 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1341 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1342 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1347 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1348 (DeltaMaybeNegative && CoeffMaybeNegative))
1352 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1353 (DeltaMaybePositive && CoeffMaybeNegative))
1355 if (NewDirection <
Result.DV[Level].Direction)
1356 ++StrongSIVsuccesses;
1390bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1391 const SCEV *SrcConst,
1392 const SCEV *DstConst,
1393 const Loop *CurSrcLoop,
1394 const Loop *CurDstLoop,
unsigned Level,
1403 ++WeakCrossingSIVapplications;
1404 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1406 Result.Consistent =
false;
1407 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1410 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1411 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1412 ++WeakCrossingSIVsuccesses;
1413 if (!
Result.DV[Level].Direction) {
1414 ++WeakCrossingSIVindependence;
1424 if (SE->isKnownNegative(ConstCoeff)) {
1427 "dynamic cast of negative of ConstCoeff should yield constant");
1428 Delta = SE->getNegativeSCEV(Delta);
1430 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1440 if (SE->isKnownNegative(Delta)) {
1442 ++WeakCrossingSIVindependence;
1443 ++WeakCrossingSIVsuccesses;
1449 if (
const SCEV *UpperBound =
1450 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1452 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1454 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1458 ++WeakCrossingSIVindependence;
1459 ++WeakCrossingSIVsuccesses;
1464 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1465 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1466 ++WeakCrossingSIVsuccesses;
1467 if (!
Result.DV[Level].Direction) {
1468 ++WeakCrossingSIVindependence;
1477 APInt APDelta = ConstDelta->
getAPInt();
1478 APInt APCoeff = ConstCoeff->
getAPInt();
1479 APInt Distance = APDelta;
1480 APInt Remainder = APDelta;
1483 if (Remainder != 0) {
1485 ++WeakCrossingSIVindependence;
1486 ++WeakCrossingSIVsuccesses;
1492 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1493 Remainder = Distance.
srem(Two);
1495 if (Remainder != 0) {
1497 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1498 ++WeakCrossingSIVsuccesses;
1518 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1519 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1527 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1528 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1535 X = AM.
slt(0) ? -A1 : A1;
1536 Y = BM.
slt(0) ? B1 : -B1;
1546static OverflowSafeSignedAPInt
1548 const OverflowSafeSignedAPInt &OB) {
1550 return OverflowSafeSignedAPInt();
1559 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1561 return OverflowSafeSignedAPInt(Q) - 1;
1564static OverflowSafeSignedAPInt
1566 const OverflowSafeSignedAPInt &OB) {
1568 return OverflowSafeSignedAPInt();
1577 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1578 return OverflowSafeSignedAPInt(Q) + 1;
1611static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1613 OverflowSafeSignedAPInt UB) {
1614 assert(
A &&
B &&
"A and B must be available");
1615 assert(*
A != 0 &&
"A must be non-zero");
1616 OverflowSafeSignedAPInt TL, TU;
1619 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1623 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1626 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1630 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1632 return std::make_pair(TL, TU);
1654bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1655 const SCEV *SrcConst,
const SCEV *DstConst,
1656 const Loop *CurSrcLoop,
1657 const Loop *CurDstLoop,
unsigned Level,
1663 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1664 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1667 ++ExactSIVapplications;
1668 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1670 Result.Consistent =
false;
1678 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1683 APInt AM = ConstSrcCoeff->
getAPInt();
1684 APInt BM = ConstDstCoeff->
getAPInt();
1689 ++ExactSIVindependence;
1690 ++ExactSIVsuccesses;
1697 std::optional<APInt> UM;
1699 if (
const SCEVConstant *CUB =
1700 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1701 UM = CUB->getAPInt();
1707 APInt TC = CM.
sdiv(
G);
1729 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
1730 const OverflowSafeSignedAPInt &V1) {
1753 ++ExactSIVindependence;
1754 ++ExactSIVsuccesses;
1760 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1761 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1765 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1766 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1768 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1769 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1772 if (!LowerDistance || !UpperDistance)
1775 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1776 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1778 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1780 ++ExactSIVsuccesses;
1782 if (LowerDistance->slt(0)) {
1784 ++ExactSIVsuccesses;
1786 if (UpperDistance->sgt(0)) {
1788 ++ExactSIVsuccesses;
1794 ++ExactSIVindependence;
1805 return ConstDividend.
srem(ConstDivisor) == 0;
1839bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1840 const SCEV *SrcConst,
1841 const SCEV *DstConst,
1842 const Loop *CurSrcLoop,
1843 const Loop *CurDstLoop,
unsigned Level,
1855 ++WeakZeroSIVapplications;
1856 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1858 Result.Consistent =
false;
1859 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1862 if (Level < CommonLevels) {
1865 ++WeakZeroSIVsuccesses;
1875 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1876 ? SE->getNegativeSCEV(ConstCoeff)
1878 const SCEV *NewDelta =
1879 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1883 if (
const SCEV *UpperBound =
1884 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1886 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1888 ++WeakZeroSIVindependence;
1889 ++WeakZeroSIVsuccesses;
1894 if (Level < CommonLevels) {
1897 ++WeakZeroSIVsuccesses;
1905 if (SE->isKnownNegative(NewDelta)) {
1907 ++WeakZeroSIVindependence;
1908 ++WeakZeroSIVsuccesses;
1915 ++WeakZeroSIVindependence;
1916 ++WeakZeroSIVsuccesses;
1953bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1954 const SCEV *SrcConst,
1955 const SCEV *DstConst,
1956 const Loop *CurSrcLoop,
1957 const Loop *CurDstLoop,
unsigned Level,
1968 ++WeakZeroSIVapplications;
1969 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1971 Result.Consistent =
false;
1972 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1975 if (Level < CommonLevels) {
1978 ++WeakZeroSIVsuccesses;
1988 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1989 ? SE->getNegativeSCEV(ConstCoeff)
1991 const SCEV *NewDelta =
1992 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1996 if (
const SCEV *UpperBound =
1997 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1999 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2001 ++WeakZeroSIVindependence;
2002 ++WeakZeroSIVsuccesses;
2007 if (Level < CommonLevels) {
2010 ++WeakZeroSIVsuccesses;
2018 if (SE->isKnownNegative(NewDelta)) {
2020 ++WeakZeroSIVindependence;
2021 ++WeakZeroSIVsuccesses;
2028 ++WeakZeroSIVindependence;
2029 ++WeakZeroSIVsuccesses;
2042bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2043 const SCEV *SrcConst,
const SCEV *DstConst,
2044 const Loop *SrcLoop,
const Loop *DstLoop,
2050 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2051 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2054 ++ExactRDIVapplications;
2055 Result.Consistent =
false;
2056 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2061 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2066 APInt AM = ConstSrcCoeff->
getAPInt();
2067 APInt BM = ConstDstCoeff->
getAPInt();
2072 ++ExactRDIVindependence;
2079 std::optional<APInt> SrcUM;
2081 if (
const SCEVConstant *UpperBound =
2082 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2083 SrcUM = UpperBound->getAPInt();
2087 std::optional<APInt> DstUM;
2089 if (
const SCEVConstant *UpperBound =
2090 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2091 DstUM = UpperBound->getAPInt();
2097 APInt TC = CM.
sdiv(
G);
2122 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
2123 const OverflowSafeSignedAPInt &V1) {
2143 ++ExactRDIVindependence;
2189bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2192 const Loop *Loop2)
const {
2196 ++SymbolicRDIVapplications;
2203 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2204 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2207 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2208 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2211 if (SE->isKnownNonNegative(A1)) {
2212 if (SE->isKnownNonNegative(A2)) {
2216 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2219 ++SymbolicRDIVindependence;
2225 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2228 ++SymbolicRDIVindependence;
2232 }
else if (SE->isKnownNonPositive(A2)) {
2236 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2237 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2238 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2239 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2241 ++SymbolicRDIVindependence;
2246 if (SE->isKnownNegative(C2_C1)) {
2247 ++SymbolicRDIVindependence;
2251 }
else if (SE->isKnownNonPositive(A1)) {
2252 if (SE->isKnownNonNegative(A2)) {
2256 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2257 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2258 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2259 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2261 ++SymbolicRDIVindependence;
2266 if (SE->isKnownPositive(C2_C1)) {
2267 ++SymbolicRDIVindependence;
2270 }
else if (SE->isKnownNonPositive(A2)) {
2274 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2277 ++SymbolicRDIVindependence;
2283 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2286 ++SymbolicRDIVindependence;
2303bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2305 bool UnderRuntimeAssumptions) {
2310 if (SrcAddRec && DstAddRec) {
2311 const SCEV *SrcConst = SrcAddRec->
getStart();
2312 const SCEV *DstConst = DstAddRec->
getStart();
2315 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2316 const Loop *CurDstLoop = DstAddRec->
getLoop();
2317 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2318 "Loops in the SIV test should have the same iteration space and "
2320 Level = mapSrcLoop(CurSrcLoop);
2322 if (SrcCoeff == DstCoeff)
2323 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
2324 UnderRuntimeAssumptions);
2325 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2326 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2327 CurDstLoop, Level, Result);
2329 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2330 CurSrcLoop, CurDstLoop, Level, Result);
2331 return disproven || gcdMIVtest(Src, Dst, Result) ||
2332 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2336 const SCEV *SrcConst = SrcAddRec->
getStart();
2338 const SCEV *DstConst = Dst;
2339 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2340 Level = mapSrcLoop(CurSrcLoop);
2341 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2342 CurSrcLoop, Level, Result) ||
2343 gcdMIVtest(Src, Dst, Result);
2346 const SCEV *DstConst = DstAddRec->
getStart();
2348 const SCEV *SrcConst = Src;
2349 const Loop *CurDstLoop = DstAddRec->
getLoop();
2350 Level = mapDstLoop(CurDstLoop);
2351 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2352 CurDstLoop, Level, Result) ||
2353 gcdMIVtest(Src, Dst, Result);
2369bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2371 const SCEV *SrcConst, *DstConst;
2372 const SCEV *SrcCoeff, *DstCoeff;
2373 const Loop *SrcLoop, *DstLoop;
2379 if (SrcAddRec && DstAddRec) {
2382 SrcLoop = SrcAddRec->
getLoop();
2385 DstLoop = DstAddRec->
getLoop();
2388 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2390 gcdMIVtest(Src, Dst, Result) ||
2391 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2398bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2403 Result.Consistent =
false;
2404 return gcdMIVtest(Src, Dst, Result) ||
2405 banerjeeMIVtest(Src, Dst,
Loops, Result);
2418 if (Product->hasNoSignedWrap())
2420 return std::nullopt;
2423bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2424 const Loop *CurLoop,
2425 const SCEV *&CurLoopCoeff,
2426 APInt &RunningGCD)
const {
2429 if (RunningGCD == 1)
2434 assert(isLoopInvariant(Expr, CurLoop) &&
2435 "Expected loop invariant expression");
2442 if (AddRec->
getLoop() == CurLoop) {
2443 CurLoopCoeff = Step;
2457 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2478bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2485 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2492 const SCEV *Coefficients = Src;
2493 while (
const SCEVAddRecExpr *AddRec =
2504 const SCEV *SrcConst = Coefficients;
2511 while (
const SCEVAddRecExpr *AddRec =
2522 const SCEV *DstConst = Coefficients;
2534 if (ConstDelta == 0)
2537 APInt Remainder = ConstDelta.
srem(RunningGCD);
2538 if (Remainder != 0) {
2557 bool Improved =
false;
2559 while (
const SCEVAddRecExpr *AddRec =
2562 const Loop *CurLoop = AddRec->
getLoop();
2563 RunningGCD = ExtraGCD;
2565 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2567 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2568 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2571 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2581 if (RunningGCD != 0) {
2582 Remainder = ConstDelta.
srem(RunningGCD);
2584 if (Remainder != 0) {
2585 unsigned Level = mapSrcLoop(CurLoop);
2586 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2630bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2637 ++BanerjeeApplications;
2640 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2643 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2644 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2645 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2650 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2651 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2654 findBoundsALL(
A,
B, Bound, K);
2669 bool Disproved =
false;
2672 unsigned DepthExpanded = 0;
2674 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2676 bool Improved =
false;
2677 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2679 unsigned Old =
Result.DV[
K - 1].Direction;
2680 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2681 Improved |= Old !=
Result.DV[
K - 1].Direction;
2682 if (!
Result.DV[K - 1].Direction) {
2690 ++BanerjeeSuccesses;
2692 ++BanerjeeIndependence;
2696 ++BanerjeeIndependence;
2710unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2711 CoefficientInfo *
B, BoundInfo *Bound,
2713 unsigned &DepthExpanded,
2714 const SCEV *Delta)
const {
2720 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2721 "direction exploration is terminated.\n");
2722 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2728 if (Level > CommonLevels) {
2731 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2733 Bound[
K].DirSet |= Bound[
K].Direction;
2758 if (Level > DepthExpanded) {
2759 DepthExpanded =
Level;
2761 findBoundsLT(
A,
B, Bound, Level);
2762 findBoundsGT(
A,
B, Bound, Level);
2763 findBoundsEQ(
A,
B, Bound, Level);
2802 unsigned NewDeps = 0;
2806 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2811 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2816 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2822 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2827bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2828 BoundInfo *Bound,
const SCEV *Delta)
const {
2829 Bound[
Level].Direction = DirKind;
2830 if (
const SCEV *LowerBound = getLowerBound(Bound))
2833 if (
const SCEV *UpperBound = getUpperBound(Bound))
2854void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2855 BoundInfo *Bound,
unsigned K)
const {
2860 if (Bound[K].Iterations) {
2862 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2864 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2869 SE->getZero(
A[K].Coeff->
getType());
2872 SE->getZero(
A[K].Coeff->
getType());
2891void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2892 BoundInfo *Bound,
unsigned K)
const {
2897 if (Bound[K].Iterations) {
2898 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2899 const SCEV *NegativePart = getNegativePart(Delta);
2901 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2902 const SCEV *PositivePart = getPositivePart(Delta);
2904 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2908 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2909 const SCEV *NegativePart = getNegativePart(Delta);
2910 if (NegativePart->
isZero())
2912 const SCEV *PositivePart = getPositivePart(Delta);
2913 if (PositivePart->
isZero())
2931void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2932 BoundInfo *Bound,
unsigned K)
const {
2937 if (Bound[K].Iterations) {
2938 const SCEV *Iter_1 = SE->getMinusSCEV(
2939 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2940 const SCEV *NegPart =
2941 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2943 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2944 const SCEV *PosPart =
2945 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2947 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2951 const SCEV *NegPart =
2952 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2955 const SCEV *PosPart =
2956 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2975void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2976 BoundInfo *Bound,
unsigned K)
const {
2981 if (Bound[K].Iterations) {
2982 const SCEV *Iter_1 = SE->getMinusSCEV(
2983 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2984 const SCEV *NegPart =
2985 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2987 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2988 const SCEV *PosPart =
2989 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2991 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2995 const SCEV *NegPart =
2996 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2999 const SCEV *PosPart =
3000 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3007const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3008 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3012const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3013 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3019DependenceInfo::CoefficientInfo *
3020DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3022 const SCEV *
Zero = SE->getZero(Subscript->getType());
3023 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3024 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3026 CI[
K].PosPart =
Zero;
3027 CI[
K].NegPart =
Zero;
3028 CI[
K].Iterations =
nullptr;
3032 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3034 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3035 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3036 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3042 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3049 if (CI[K].Iterations)
3064const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3065 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3066 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3079const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3080 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3081 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3100 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3101 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3102 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3103 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3104 const SCEVUnknown *SrcBase =
3106 const SCEVUnknown *DstBase =
3109 if (!SrcBase || !DstBase || SrcBase != DstBase)
3114 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3115 SrcSubscripts, DstSubscripts) &&
3116 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3117 SrcSubscripts, DstSubscripts))
3120 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3121 isLoopInvariant(DstBase, DstLoop) &&
3122 "Expected SrcBase and DstBase to be loop invariant");
3126 dbgs() <<
"\nSrcSubscripts: ";
3127 for (
int I = 0;
I <
Size;
I++)
3128 dbgs() << *SrcSubscripts[
I];
3129 dbgs() <<
"\nDstSubscripts: ";
3130 for (
int I = 0;
I <
Size;
I++)
3131 dbgs() << *DstSubscripts[
I];
3139 SCEVMonotonicityChecker MonChecker(SE);
3140 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3141 for (
int I = 0;
I <
Size; ++
I) {
3142 Pair[
I].Src = SrcSubscripts[
I];
3143 Pair[
I].Dst = DstSubscripts[
I];
3145 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
3146 "Unexpected different types for the subscripts");
3149 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3151 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3162bool DependenceInfo::tryDelinearizeFixedSize(
3167 const SCEVUnknown *SrcBase =
3169 const SCEVUnknown *DstBase =
3171 assert(SrcBase && DstBase && SrcBase == DstBase &&
3172 "expected src and dst scev unknowns to be equal");
3175 const SCEV *ElemSize = SE->getElementSize(Src);
3176 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3179 SrcSubscripts, SrcSizes, ElemSize) ||
3181 DstSubscripts, DstSizes, ElemSize))
3186 if (SrcSizes.
size() != DstSizes.
size() ||
3187 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3188 SrcSubscripts.
clear();
3189 DstSubscripts.
clear();
3194 "Expected equal number of entries in the list of SrcSubscripts and "
3206 SrcSubscripts.
clear();
3207 DstSubscripts.
clear();
3212 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3219bool DependenceInfo::tryDelinearizeParametricSize(
3224 const SCEVUnknown *SrcBase =
3226 const SCEVUnknown *DstBase =
3228 assert(SrcBase && DstBase && SrcBase == DstBase &&
3229 "expected src and dst scev unknowns to be equal");
3231 const SCEV *ElementSize = SE->getElementSize(Src);
3232 if (ElementSize != SE->getElementSize(Dst))
3235 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3236 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3257 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3258 SrcSubscripts.
size() != DstSubscripts.
size())
3281 for (
unsigned VI : BV.
set_bits()) {
3291 FunctionAnalysisManager::Invalidator &Inv) {
3298 return Inv.invalidate<
AAManager>(F, PA) ||
3312std::unique_ptr<Dependence>
3314 bool UnderRuntimeAssumptions) {
3316 bool PossiblyLoopIndependent =
true;
3318 PossiblyLoopIndependent =
false;
3320 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3326 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3327 return std::make_unique<Dependence>(Src, Dst,
3339 return std::make_unique<Dependence>(Src, Dst,
3353 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3354 return std::make_unique<Dependence>(Src, Dst,
3360 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3361 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3364 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3365 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3366 if (SrcBase != DstBase) {
3373 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3374 return std::make_unique<Dependence>(Src, Dst,
3382 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3383 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3384 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3385 !isLoopInvariant(DstBase, DstLoop)) {
3386 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3387 return std::make_unique<Dependence>(Src, Dst,
3392 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3393 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3396 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3397 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3398 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3399 return std::make_unique<Dependence>(Src, Dst,
3404 if (!Assume.empty() && !UnderRuntimeAssumptions)
3405 return std::make_unique<Dependence>(Src, Dst,
3410 Pair[0].Src = SrcEv;
3411 Pair[0].Dst = DstEv;
3413 SCEVMonotonicityChecker MonChecker(SE);
3416 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3417 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3418 return std::make_unique<Dependence>(Src, Dst,
3422 if (tryDelinearize(Src, Dst, Pair)) {
3424 Pairs = Pair.
size();
3429 establishNestingLevels(Src, Dst);
3431 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3432 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3433 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3436 CommonLevels += SameSDLevels;
3437 MaxLevels -= SameSDLevels;
3438 if (SameSDLevels > 0) {
3441 for (
unsigned P = 0;
P < Pairs; ++
P) {
3443 Subscript::ClassificationKind TestClass =
3444 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3445 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3447 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3448 TestClass != Subscript::RDIV) {
3450 CommonLevels -= SameSDLevels;
3451 MaxLevels += SameSDLevels;
3458 if (SameSDLevels > 0)
3462 PossiblyLoopIndependent, CommonLevels);
3465 for (
unsigned P = 0;
P < Pairs; ++
P) {
3466 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3467 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3468 Pair[
P].Loops.
resize(MaxLevels + 1);
3469 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3471 Pair[
P].Classification =
3472 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3473 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3474 Pair[
P].GroupLoops = Pair[
P].Loops;
3475 Pair[
P].Group.set(
P);
3485 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3487 switch (Pair[
SI].Classification) {
3488 case Subscript::NonLinear:
3490 ++NonlinearSubscriptPairs;
3491 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3493 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3495 Result.Consistent =
false;
3497 case Subscript::ZIV:
3499 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3502 case Subscript::SIV: {
3505 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3506 UnderRuntimeAssumptions))
3510 case Subscript::RDIV:
3512 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3515 case Subscript::MIV:
3517 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3525 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3526 CompleteLoops |= Pair[
SI].
Loops;
3527 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3528 if (CompleteLoops[
II])
3529 Result.DV[
II - 1].Scalar =
false;
3534 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3536 if (Result.DV[
II - 1].Distance ==
nullptr)
3537 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3539 assert(Result.DV[
II - 1].Distance->isZero() &&
3540 "Inconsistency between distance and direction");
3546 const SCEV *Distance = Result.getDistance(
II);
3547 if (Distance && Distance->
isZero())
3549 "Distance is zero, but direction is not EQ");
3553 if (SameSDLevels > 0) {
3556 assert(CommonLevels >= SameSDLevels);
3557 CommonLevels -= SameSDLevels;
3558 MaxLevels += SameSDLevels;
3559 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3560 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3561 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3562 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3563 DV[Level] = Result.DV[Level];
3564 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3565 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3566 Result.DV = std::move(DV);
3567 Result.DVSameSD = std::move(DVSameSD);
3568 Result.Levels = CommonLevels;
3569 Result.SameSDLevels = SameSDLevels;
3571 Result.Consistent =
false;
3574 if (PossiblyLoopIndependent) {
3578 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3580 Result.LoopIndependent =
false;
3588 bool AllEqual =
true;
3589 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3595 if (AllEqual && Result.Assumptions.getPredicates().empty())
3599 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
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 cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::All), 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::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::SymbolicRDIV, "symbolic-rdiv", "Enable only Symbolic RDIV test."), clEnumValN(DependenceTestType::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
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< bool > EnableMonotonicityCheck("da-enable-monotonicity-check", cl::init(false), cl::Hidden, cl::desc("Check if the subscripts are monotonic. If it's not, dependence " "is reported as unknown."))
static cl::opt< bool > DumpMonotonicityReport("da-dump-monotonicity-report", cl::init(false), cl::Hidden, cl::desc("When printing analysis, dump the results of monotonicity checks."))
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)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
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")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
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 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()
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_SLT
signed less than
@ ICMP_SGT
signed greater than
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
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 bool isPeelLast(unsigned Level, bool SameSD=false) const
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
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.
virtual bool isPeelFirst(unsigned Level, bool SameSD=false) const
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
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.
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 isPeelLast(unsigned Level, bool SameSD=false) const override
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
bool isPeelFirst(unsigned Level, bool SameSD=false) const override
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
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.
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
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.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
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.
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.
const SCEV * getStart() const
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
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
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 const SCEV * removePointerBase(const SCEV *S)
Compute an expression equivalent to S - getPointerBase(S).
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
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(const SCEV *LHS, const SCEV *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...
void push_back(const T &Elt)
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.
bool isIntegerTy() const
True if this is an instance of IntegerType.
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.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#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.
@ 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.
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...
This class defines a simple visitor class that may be used for various SCEV analysis purposes.