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 visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
347 return invariantOrUnknown(Expr);
349 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
350 return invariantOrUnknown(Expr);
352 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
353 return invariantOrUnknown(Expr);
355 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
356 return invariantOrUnknown(Expr);
358 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
359 return invariantOrUnknown(Expr);
361 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
362 return invariantOrUnknown(Expr);
364 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
365 return invariantOrUnknown(Expr);
367 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
368 return invariantOrUnknown(Expr);
370 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
371 return invariantOrUnknown(Expr);
373 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
374 return invariantOrUnknown(Expr);
377 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
388 bool NormalizeResults) {
389 auto *
F = DA->getFunction();
392 SCEVMonotonicityChecker Checker(&SE);
393 OS <<
"Monotonicity check:\n";
399 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
402 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
403 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
404 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
412 if (SrcI->mayReadOrWriteMemory()) {
415 if (DstI->mayReadOrWriteMemory()) {
416 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
417 OS <<
" da analyze - ";
418 if (
auto D = DA->depends(&*SrcI, &*DstI,
424 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
425 const SCEV *Distance =
D->getDistance(Level);
426 bool IsDistanceZero = Distance && Distance->
isZero();
429 assert(IsDistanceZero == IsDirectionEQ &&
430 "Inconsistent distance and direction.");
435 if (NormalizeResults &&
D->normalize(&SE))
436 OS <<
"normalized - ";
455 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
468 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
473 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
478 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
483 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
497 bool PossiblyLoopIndependent,
498 unsigned CommonLevels)
499 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
500 LoopIndependent(PossiblyLoopIndependent) {
504 DV = std::make_unique<
DVEntry[]>(CommonLevels);
523 for (
unsigned Level = 1; Level <= Levels; ++Level) {
524 unsigned char Direction = DV[Level - 1].Direction;
539 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
542 for (
unsigned Level = 1; Level <= Levels; ++Level) {
543 unsigned char Direction = DV[Level - 1].Direction;
551 DV[Level - 1].Direction = RevDirection;
553 if (DV[Level - 1].Distance !=
nullptr)
557 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
599 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
600 "Level out of range");
601 return Level > Levels;
607SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
608 const SCEV *FailurePoint)
609 :
Type(
Type), FailurePoint(FailurePoint) {
611 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
612 "FailurePoint must be provided iff Type is Unknown");
618 case SCEVMonotonicityType::Unknown:
619 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
621 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
623 case SCEVMonotonicityType::Invariant:
626 case SCEVMonotonicityType::MultivariateSignedMonotonic:
627 OS <<
"MultivariateSignedMonotonic\n";
632bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
633 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
636SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
637 if (isLoopInvariant(Expr))
638 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
639 return createUnknown(Expr);
643SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
644 const Loop *OutermostLoop) {
646 "OutermostLoop must be outermost");
648 this->OutermostLoop = OutermostLoop;
664SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
666 return createUnknown(Expr);
671 SCEVMonotonicity StartMon =
visit(Start);
672 if (StartMon.isUnknown())
675 if (!isLoopInvariant(Step))
676 return createUnknown(Expr);
678 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
701 if (SameSDLevels > 0) {
702 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
709 if (!Assumptions.isAlwaysTrue()) {
710 OS <<
" Runtime Assumptions:\n";
711 Assumptions.print(OS, 2);
720 bool OnSameSD =
false;
721 unsigned LevelNum = Levels;
723 LevelNum += SameSDLevels;
725 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
800 return LI->isUnordered();
802 return SI->isUnordered();
810bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
811 const Loop *DstLoop)
const {
812 if (SrcLoop == DstLoop)
822 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
823 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
824 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
825 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
826 DstUP = SE->getBackedgeTakenCount(DstLoop);
828 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
829 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
830 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
831 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
902void DependenceInfo::establishNestingLevels(
const Instruction *Src,
904 const BasicBlock *SrcBlock = Src->getParent();
905 const BasicBlock *DstBlock = Dst->getParent();
906 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
907 unsigned DstLevel = LI->getLoopDepth(DstBlock);
908 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
909 const Loop *DstLoop = LI->getLoopFor(DstBlock);
910 SrcLevels = SrcLevel;
911 MaxLevels = SrcLevel + DstLevel;
913 while (SrcLevel > DstLevel) {
917 while (DstLevel > SrcLevel) {
923 while (SrcLoop != DstLoop) {
925 if (!haveSameSD(SrcLoop, DstLoop))
931 CommonLevels = SrcLevel;
932 MaxLevels -= CommonLevels;
937unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
943unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
945 if (
D > CommonLevels)
948 return D - CommonLevels + SrcLevels;
975 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
983 unsigned widestWidthSeen = 0;
988 for (Subscript *Pair : Pairs) {
989 const SCEV *Src = Pair->Src;
990 const SCEV *Dst = Pair->Dst;
993 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
995 "This function only unify integer types and "
996 "expect Src and Dst share the same type otherwise.");
1009 assert(widestWidthSeen > 0);
1012 for (Subscript *Pair : Pairs) {
1013 const SCEV *Src = Pair->Src;
1014 const SCEV *Dst = Pair->Dst;
1017 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1019 "This function only unify integer types and "
1020 "expect Src and Dst share the same type otherwise.");
1025 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1028 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1037void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1038 const SCEV *Src = Pair->Src;
1039 const SCEV *Dst = Pair->Dst;
1044 const SCEV *SrcCastOp = SrcCast->
getOperand();
1045 const SCEV *DstCastOp = DstCast->
getOperand();
1047 Pair->Src = SrcCastOp;
1048 Pair->Dst = DstCastOp;
1059 return isLoopInvariant(Expr, LoopNest);
1066 const Loop *
L = LoopNest;
1067 while (L && AddRec->
getLoop() != L)
1068 L =
L->getParentLoop();
1074 if (!isLoopInvariant(Step, LoopNest))
1080 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1085bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1087 return checkSubscript(Src, LoopNest,
Loops,
true);
1092bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1094 return checkSubscript(Dst, LoopNest,
Loops,
false);
1100DependenceInfo::Subscript::ClassificationKind
1101DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1102 const SCEV *Dst,
const Loop *DstLoopNest,
1104 SmallBitVector SrcLoops(MaxLevels + 1);
1105 SmallBitVector DstLoops(MaxLevels + 1);
1106 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1107 return Subscript::NonLinear;
1108 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1109 return Subscript::NonLinear;
1112 unsigned N =
Loops.count();
1114 return Subscript::ZIV;
1116 return Subscript::SIV;
1117 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1118 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1119 return Subscript::RDIV;
1120 return Subscript::MIV;
1134 const SCEV *
Y)
const {
1148 if (SE->isKnownPredicate(Pred,
X,
Y))
1155 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1160 return SE->isKnownNonZero(Delta);
1162 return SE->isKnownNonNegative(Delta);
1164 return SE->isKnownNonPositive(Delta);
1166 return SE->isKnownPositive(Delta);
1168 return SE->isKnownNegative(Delta);
1181const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1182 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1183 const SCEV *UB = SE->getBackedgeTakenCount(L);
1184 return SE->getTruncateOrZeroExtend(UB,
T);
1191const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1193 if (
const SCEV *UB = collectUpperBound(L,
T))
1250bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1265 Result.Consistent =
false;
1296bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1297 const SCEV *DstConst,
const Loop *CurSrcLoop,
1298 const Loop *CurDstLoop,
unsigned Level,
1310 ++StrongSIVapplications;
1311 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1316 Result.Consistent =
false;
1323 bool IsDeltaLarge = [&] {
1324 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1332 if (!AbsDelta || !AbsCoeff)
1341 ++StrongSIVindependence;
1342 ++StrongSIVsuccesses;
1350 APInt Distance = ConstDelta;
1351 APInt Remainder = ConstDelta;
1356 if (Remainder != 0) {
1358 ++StrongSIVindependence;
1359 ++StrongSIVsuccesses;
1362 Result.DV[
Level].Distance = SE->getConstant(Distance);
1363 if (Distance.
sgt(0))
1365 else if (Distance.
slt(0))
1369 ++StrongSIVsuccesses;
1370 }
else if (Delta->
isZero()) {
1374 ++StrongSIVsuccesses;
1376 if (Coeff->
isOne()) {
1380 Result.Consistent =
false;
1384 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1385 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1386 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1387 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1388 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1393 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1394 (DeltaMaybeNegative && CoeffMaybeNegative))
1398 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1399 (DeltaMaybePositive && CoeffMaybeNegative))
1401 if (NewDirection <
Result.DV[Level].Direction)
1402 ++StrongSIVsuccesses;
1436bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1437 const SCEV *SrcConst,
1438 const SCEV *DstConst,
1439 const Loop *CurSrcLoop,
1440 const Loop *CurDstLoop,
unsigned Level,
1449 ++WeakCrossingSIVapplications;
1450 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1452 Result.Consistent =
false;
1453 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1456 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1457 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1458 ++WeakCrossingSIVsuccesses;
1459 if (!
Result.DV[Level].Direction) {
1460 ++WeakCrossingSIVindependence;
1470 if (SE->isKnownNegative(ConstCoeff)) {
1473 "dynamic cast of negative of ConstCoeff should yield constant");
1474 Delta = SE->getNegativeSCEV(Delta);
1476 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1486 if (SE->isKnownNegative(Delta)) {
1488 ++WeakCrossingSIVindependence;
1489 ++WeakCrossingSIVsuccesses;
1495 if (
const SCEV *UpperBound =
1496 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1498 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1500 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1504 ++WeakCrossingSIVindependence;
1505 ++WeakCrossingSIVsuccesses;
1510 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1511 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1512 ++WeakCrossingSIVsuccesses;
1513 if (!
Result.DV[Level].Direction) {
1514 ++WeakCrossingSIVindependence;
1523 APInt APDelta = ConstDelta->
getAPInt();
1524 APInt APCoeff = ConstCoeff->
getAPInt();
1525 APInt Distance = APDelta;
1526 APInt Remainder = APDelta;
1529 if (Remainder != 0) {
1531 ++WeakCrossingSIVindependence;
1532 ++WeakCrossingSIVsuccesses;
1538 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1539 Remainder = Distance.
srem(Two);
1541 if (Remainder != 0) {
1543 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1544 ++WeakCrossingSIVsuccesses;
1561 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1562 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1570 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1571 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1578 X = AM.
slt(0) ? -A1 : A1;
1579 Y = BM.
slt(0) ? B1 : -B1;
1595 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1607 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1642static std::pair<std::optional<APInt>, std::optional<APInt>>
1644 const std::optional<APInt> &UB) {
1645 assert(
A != 0 &&
"A must be non-zero");
1646 std::optional<APInt> TL, TU;
1666 return std::make_pair(TL, TU);
1688bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1689 const SCEV *SrcConst,
const SCEV *DstConst,
1690 const Loop *CurSrcLoop,
1691 const Loop *CurDstLoop,
unsigned Level,
1697 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1698 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1701 ++ExactSIVapplications;
1702 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1704 Result.Consistent =
false;
1712 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1717 APInt AM = ConstSrcCoeff->
getAPInt();
1718 APInt BM = ConstDstCoeff->
getAPInt();
1723 ++ExactSIVindependence;
1724 ++ExactSIVsuccesses;
1731 std::optional<APInt> UM;
1733 if (
const SCEVConstant *CUB =
1734 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1735 UM = CUB->getAPInt();
1741 APInt TC = CM.
sdiv(
G);
1763 auto CreateVec = [](
const std::optional<APInt> &V0,
1764 const std::optional<APInt> &V1) {
1787 ++ExactSIVindependence;
1788 ++ExactSIVsuccesses;
1794 APInt LowerDistance, UpperDistance;
1797 LowerDistance = (TY - TX) + (TA - TB) * TL;
1798 UpperDistance = (TY - TX) + (TA - TB) * TU;
1800 LowerDistance = (TY - TX) + (TA - TB) * TU;
1801 UpperDistance = (TY - TX) + (TA - TB) * TL;
1804 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1805 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1807 APInt
Zero(Bits, 0,
true);
1808 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1810 ++ExactSIVsuccesses;
1812 if (LowerDistance.
slt(0)) {
1814 ++ExactSIVsuccesses;
1816 if (UpperDistance.
sgt(0)) {
1818 ++ExactSIVsuccesses;
1824 ++ExactSIVindependence;
1835 return ConstDividend.
srem(ConstDivisor) == 0;
1869bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1870 const SCEV *SrcConst,
1871 const SCEV *DstConst,
1872 const Loop *CurSrcLoop,
1873 const Loop *CurDstLoop,
unsigned Level,
1885 ++WeakZeroSIVapplications;
1886 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1888 Result.Consistent =
false;
1889 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1892 if (Level < CommonLevels) {
1895 ++WeakZeroSIVsuccesses;
1905 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1906 ? SE->getNegativeSCEV(ConstCoeff)
1908 const SCEV *NewDelta =
1909 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1913 if (
const SCEV *UpperBound =
1914 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1916 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1918 ++WeakZeroSIVindependence;
1919 ++WeakZeroSIVsuccesses;
1924 if (Level < CommonLevels) {
1927 ++WeakZeroSIVsuccesses;
1935 if (SE->isKnownNegative(NewDelta)) {
1937 ++WeakZeroSIVindependence;
1938 ++WeakZeroSIVsuccesses;
1945 ++WeakZeroSIVindependence;
1946 ++WeakZeroSIVsuccesses;
1983bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1984 const SCEV *SrcConst,
1985 const SCEV *DstConst,
1986 const Loop *CurSrcLoop,
1987 const Loop *CurDstLoop,
unsigned Level,
1998 ++WeakZeroSIVapplications;
1999 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2001 Result.Consistent =
false;
2002 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2005 if (Level < CommonLevels) {
2008 ++WeakZeroSIVsuccesses;
2018 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2019 ? SE->getNegativeSCEV(ConstCoeff)
2021 const SCEV *NewDelta =
2022 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2026 if (
const SCEV *UpperBound =
2027 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2029 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2031 ++WeakZeroSIVindependence;
2032 ++WeakZeroSIVsuccesses;
2037 if (Level < CommonLevels) {
2040 ++WeakZeroSIVsuccesses;
2048 if (SE->isKnownNegative(NewDelta)) {
2050 ++WeakZeroSIVindependence;
2051 ++WeakZeroSIVsuccesses;
2058 ++WeakZeroSIVindependence;
2059 ++WeakZeroSIVsuccesses;
2072bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2073 const SCEV *SrcConst,
const SCEV *DstConst,
2074 const Loop *SrcLoop,
const Loop *DstLoop,
2080 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2081 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2084 ++ExactRDIVapplications;
2085 Result.Consistent =
false;
2086 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2091 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2096 APInt AM = ConstSrcCoeff->
getAPInt();
2097 APInt BM = ConstDstCoeff->
getAPInt();
2102 ++ExactRDIVindependence;
2109 std::optional<APInt> SrcUM;
2111 if (
const SCEVConstant *UpperBound =
2112 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2113 SrcUM = UpperBound->getAPInt();
2117 std::optional<APInt> DstUM;
2119 if (
const SCEVConstant *UpperBound =
2120 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2121 DstUM = UpperBound->getAPInt();
2127 APInt TC = CM.
sdiv(
G);
2152 auto CreateVec = [](
const std::optional<APInt> &V0,
2153 const std::optional<APInt> &V1) {
2173 ++ExactRDIVindependence;
2219bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2222 const Loop *Loop2)
const {
2226 ++SymbolicRDIVapplications;
2233 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2234 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2237 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2238 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2241 if (SE->isKnownNonNegative(A1)) {
2242 if (SE->isKnownNonNegative(A2)) {
2246 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2249 ++SymbolicRDIVindependence;
2255 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2258 ++SymbolicRDIVindependence;
2262 }
else if (SE->isKnownNonPositive(A2)) {
2266 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2267 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2268 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2269 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2271 ++SymbolicRDIVindependence;
2276 if (SE->isKnownNegative(C2_C1)) {
2277 ++SymbolicRDIVindependence;
2281 }
else if (SE->isKnownNonPositive(A1)) {
2282 if (SE->isKnownNonNegative(A2)) {
2286 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2287 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2288 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2289 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2291 ++SymbolicRDIVindependence;
2296 if (SE->isKnownPositive(C2_C1)) {
2297 ++SymbolicRDIVindependence;
2300 }
else if (SE->isKnownNonPositive(A2)) {
2304 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2307 ++SymbolicRDIVindependence;
2313 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2316 ++SymbolicRDIVindependence;
2333bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2339 if (SrcAddRec && DstAddRec) {
2340 const SCEV *SrcConst = SrcAddRec->
getStart();
2341 const SCEV *DstConst = DstAddRec->
getStart();
2344 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2345 const Loop *CurDstLoop = DstAddRec->
getLoop();
2346 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2347 "Loops in the SIV test should have the same iteration space and "
2349 Level = mapSrcLoop(CurSrcLoop);
2351 if (SrcCoeff == DstCoeff)
2352 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2353 CurDstLoop, Level, Result);
2354 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2355 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2356 CurDstLoop, Level, Result);
2358 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2359 CurSrcLoop, CurDstLoop, Level, Result);
2360 return disproven || gcdMIVtest(Src, Dst, Result) ||
2361 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2365 const SCEV *SrcConst = SrcAddRec->
getStart();
2367 const SCEV *DstConst = Dst;
2368 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2369 Level = mapSrcLoop(CurSrcLoop);
2370 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2371 CurSrcLoop, Level, Result) ||
2372 gcdMIVtest(Src, Dst, Result);
2375 const SCEV *DstConst = DstAddRec->
getStart();
2377 const SCEV *SrcConst = Src;
2378 const Loop *CurDstLoop = DstAddRec->
getLoop();
2379 Level = mapDstLoop(CurDstLoop);
2380 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2381 CurDstLoop, Level, Result) ||
2382 gcdMIVtest(Src, Dst, Result);
2401bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2409 const SCEV *SrcConst, *DstConst;
2410 const SCEV *SrcCoeff, *DstCoeff;
2411 const Loop *SrcLoop, *DstLoop;
2417 if (SrcAddRec && DstAddRec) {
2420 SrcLoop = SrcAddRec->
getLoop();
2423 DstLoop = DstAddRec->
getLoop();
2424 }
else if (SrcAddRec) {
2425 if (
const SCEVAddRecExpr *tmpAddRec =
2427 SrcConst = tmpAddRec->getStart();
2428 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2429 SrcLoop = tmpAddRec->getLoop();
2432 DstLoop = SrcAddRec->
getLoop();
2435 }
else if (DstAddRec) {
2436 if (
const SCEVAddRecExpr *tmpAddRec =
2438 DstConst = tmpAddRec->getStart();
2439 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2440 DstLoop = tmpAddRec->getLoop();
2443 SrcLoop = DstAddRec->
getLoop();
2448 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2450 gcdMIVtest(Src, Dst, Result) ||
2451 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2458bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2463 Result.Consistent =
false;
2464 return gcdMIVtest(Src, Dst, Result) ||
2465 banerjeeMIVtest(Src, Dst,
Loops, Result);
2478 if (Product->hasNoSignedWrap())
2480 return std::nullopt;
2483bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2484 const Loop *CurLoop,
2485 const SCEV *&CurLoopCoeff,
2486 APInt &RunningGCD)
const {
2489 if (RunningGCD == 1)
2494 assert(isLoopInvariant(Expr, CurLoop) &&
2495 "Expected loop invariant expression");
2502 if (AddRec->
getLoop() == CurLoop) {
2503 CurLoopCoeff = Step;
2517 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2538bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2545 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2552 const SCEV *Coefficients = Src;
2553 while (
const SCEVAddRecExpr *AddRec =
2564 const SCEV *SrcConst = Coefficients;
2571 while (
const SCEVAddRecExpr *AddRec =
2582 const SCEV *DstConst = Coefficients;
2585 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2590 for (
const SCEV *Operand : Sum->operands()) {
2592 assert(!Constant &&
"Surprised to find multiple constants");
2609 if (ConstDelta == 0)
2613 APInt Remainder = ConstDelta.
srem(RunningGCD);
2614 if (Remainder != 0) {
2633 bool Improved =
false;
2635 while (
const SCEVAddRecExpr *AddRec =
2638 const Loop *CurLoop = AddRec->
getLoop();
2639 RunningGCD = ExtraGCD;
2641 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2643 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2644 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2647 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2657 if (RunningGCD != 0) {
2658 Remainder = ConstDelta.
srem(RunningGCD);
2660 if (Remainder != 0) {
2661 unsigned Level = mapSrcLoop(CurLoop);
2662 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2706bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2713 ++BanerjeeApplications;
2716 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2719 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2720 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2721 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2726 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2727 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2730 findBoundsALL(
A,
B, Bound, K);
2745 bool Disproved =
false;
2748 unsigned DepthExpanded = 0;
2750 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2752 bool Improved =
false;
2753 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2755 unsigned Old =
Result.DV[
K - 1].Direction;
2756 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2757 Improved |= Old !=
Result.DV[
K - 1].Direction;
2758 if (!
Result.DV[K - 1].Direction) {
2766 ++BanerjeeSuccesses;
2768 ++BanerjeeIndependence;
2772 ++BanerjeeIndependence;
2786unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2787 CoefficientInfo *
B, BoundInfo *Bound,
2789 unsigned &DepthExpanded,
2790 const SCEV *Delta)
const {
2796 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2797 "direction exploration is terminated.\n");
2798 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2804 if (Level > CommonLevels) {
2807 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2809 Bound[
K].DirSet |= Bound[
K].Direction;
2834 if (Level > DepthExpanded) {
2835 DepthExpanded =
Level;
2837 findBoundsLT(
A,
B, Bound, Level);
2838 findBoundsGT(
A,
B, Bound, Level);
2839 findBoundsEQ(
A,
B, Bound, Level);
2878 unsigned NewDeps = 0;
2882 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2887 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2892 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2898 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2903bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2904 BoundInfo *Bound,
const SCEV *Delta)
const {
2905 Bound[
Level].Direction = DirKind;
2906 if (
const SCEV *LowerBound = getLowerBound(Bound))
2909 if (
const SCEV *UpperBound = getUpperBound(Bound))
2930void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2931 BoundInfo *Bound,
unsigned K)
const {
2936 if (Bound[K].Iterations) {
2938 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2940 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2945 SE->getZero(
A[K].Coeff->
getType());
2948 SE->getZero(
A[K].Coeff->
getType());
2967void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2968 BoundInfo *Bound,
unsigned K)
const {
2973 if (Bound[K].Iterations) {
2974 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2975 const SCEV *NegativePart = getNegativePart(Delta);
2977 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2978 const SCEV *PositivePart = getPositivePart(Delta);
2980 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2984 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2985 const SCEV *NegativePart = getNegativePart(Delta);
2986 if (NegativePart->
isZero())
2988 const SCEV *PositivePart = getPositivePart(Delta);
2989 if (PositivePart->
isZero())
3007void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3008 BoundInfo *Bound,
unsigned K)
const {
3013 if (Bound[K].Iterations) {
3014 const SCEV *Iter_1 = SE->getMinusSCEV(
3015 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3016 const SCEV *NegPart =
3017 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3019 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3020 const SCEV *PosPart =
3021 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3023 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3027 const SCEV *NegPart =
3028 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3031 const SCEV *PosPart =
3032 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3051void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3052 BoundInfo *Bound,
unsigned K)
const {
3057 if (Bound[K].Iterations) {
3058 const SCEV *Iter_1 = SE->getMinusSCEV(
3059 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3060 const SCEV *NegPart =
3061 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3063 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3064 const SCEV *PosPart =
3065 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3067 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3071 const SCEV *NegPart =
3072 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3075 const SCEV *PosPart =
3076 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3083const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3084 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3088const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3089 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3095DependenceInfo::CoefficientInfo *
3096DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3098 const SCEV *
Zero = SE->getZero(Subscript->getType());
3099 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3100 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3102 CI[
K].PosPart =
Zero;
3103 CI[
K].NegPart =
Zero;
3104 CI[
K].Iterations =
nullptr;
3108 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3110 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3111 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3112 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3118 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3125 if (CI[K].Iterations)
3140const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3141 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3142 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3155const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3156 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3157 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3176 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3177 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3178 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3179 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3180 const SCEVUnknown *SrcBase =
3182 const SCEVUnknown *DstBase =
3185 if (!SrcBase || !DstBase || SrcBase != DstBase)
3190 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3191 SrcSubscripts, DstSubscripts) &&
3192 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3193 SrcSubscripts, DstSubscripts))
3196 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3197 isLoopInvariant(DstBase, DstLoop) &&
3198 "Expected SrcBase and DstBase to be loop invariant");
3202 dbgs() <<
"\nSrcSubscripts: ";
3203 for (
int I = 0;
I <
Size;
I++)
3204 dbgs() << *SrcSubscripts[
I];
3205 dbgs() <<
"\nDstSubscripts: ";
3206 for (
int I = 0;
I <
Size;
I++)
3207 dbgs() << *DstSubscripts[
I];
3215 SCEVMonotonicityChecker MonChecker(SE);
3216 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3217 for (
int I = 0;
I <
Size; ++
I) {
3218 Pair[
I].Src = SrcSubscripts[
I];
3219 Pair[
I].Dst = DstSubscripts[
I];
3220 unifySubscriptType(&Pair[
I]);
3223 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3225 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3236bool DependenceInfo::tryDelinearizeFixedSize(
3241 const SCEVUnknown *SrcBase =
3243 const SCEVUnknown *DstBase =
3245 assert(SrcBase && DstBase && SrcBase == DstBase &&
3246 "expected src and dst scev unknowns to be equal");
3249 const SCEV *ElemSize = SE->getElementSize(Src);
3250 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3253 SrcSubscripts, SrcSizes, ElemSize) ||
3255 DstSubscripts, DstSizes, ElemSize))
3260 if (SrcSizes.
size() != DstSizes.
size() ||
3261 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3262 SrcSubscripts.
clear();
3263 DstSubscripts.
clear();
3268 "Expected equal number of entries in the list of SrcSubscripts and "
3283 SrcSubscripts.
clear();
3284 DstSubscripts.
clear();
3289 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3290 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3291 <<
"DstGEP:" << *DstPtr <<
"\n";
3296bool DependenceInfo::tryDelinearizeParametricSize(
3303 const SCEVUnknown *SrcBase =
3305 const SCEVUnknown *DstBase =
3307 assert(SrcBase && DstBase && SrcBase == DstBase &&
3308 "expected src and dst scev unknowns to be equal");
3310 const SCEV *ElementSize = SE->getElementSize(Src);
3311 if (ElementSize != SE->getElementSize(Dst))
3314 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3315 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3336 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3337 SrcSubscripts.
size() != DstSubscripts.
size())
3360 for (
unsigned VI : BV.
set_bits()) {
3370 FunctionAnalysisManager::Invalidator &Inv) {
3377 return Inv.invalidate<
AAManager>(F, PA) ||
3391std::unique_ptr<Dependence>
3393 bool UnderRuntimeAssumptions) {
3395 bool PossiblyLoopIndependent =
true;
3397 PossiblyLoopIndependent =
false;
3399 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3405 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3406 return std::make_unique<Dependence>(Src, Dst,
3418 return std::make_unique<Dependence>(Src, Dst,
3432 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3433 return std::make_unique<Dependence>(Src, Dst,
3439 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3440 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3443 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3444 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3445 if (SrcBase != DstBase) {
3452 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3453 return std::make_unique<Dependence>(Src, Dst,
3461 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3462 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3463 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3464 !isLoopInvariant(DstBase, DstLoop)) {
3465 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3466 return std::make_unique<Dependence>(Src, Dst,
3471 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3472 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3475 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3476 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3477 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3478 return std::make_unique<Dependence>(Src, Dst,
3482 if (!Assume.empty() && !UnderRuntimeAssumptions) {
3484 return std::make_unique<Dependence>(Src, Dst,
3490 Pair[0].Src = SrcEv;
3491 Pair[0].Dst = DstEv;
3493 SCEVMonotonicityChecker MonChecker(SE);
3496 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3497 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3498 return std::make_unique<Dependence>(Src, Dst,
3502 if (tryDelinearize(Src, Dst, Pair)) {
3504 Pairs = Pair.
size();
3509 establishNestingLevels(Src, Dst);
3511 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3512 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3513 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3516 CommonLevels += SameSDLevels;
3517 MaxLevels -= SameSDLevels;
3518 if (SameSDLevels > 0) {
3521 for (
unsigned P = 0;
P < Pairs; ++
P) {
3523 Subscript::ClassificationKind TestClass =
3524 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3525 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3527 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3528 TestClass != Subscript::RDIV) {
3530 CommonLevels -= SameSDLevels;
3531 MaxLevels += SameSDLevels;
3538 if (SameSDLevels > 0)
3542 PossiblyLoopIndependent, CommonLevels);
3545 for (
unsigned P = 0;
P < Pairs; ++
P) {
3546 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3547 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3548 Pair[
P].Loops.
resize(MaxLevels + 1);
3549 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3551 removeMatchingExtensions(&Pair[
P]);
3552 Pair[
P].Classification =
3553 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3554 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3555 Pair[
P].GroupLoops = Pair[
P].Loops;
3556 Pair[
P].Group.set(
P);
3566 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3568 switch (Pair[
SI].Classification) {
3569 case Subscript::NonLinear:
3571 ++NonlinearSubscriptPairs;
3572 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3574 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3576 Result.Consistent =
false;
3578 case Subscript::ZIV:
3580 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3583 case Subscript::SIV: {
3586 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result))
3590 case Subscript::RDIV:
3592 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3595 case Subscript::MIV:
3597 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3605 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3606 CompleteLoops |= Pair[
SI].
Loops;
3607 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3608 if (CompleteLoops[
II])
3609 Result.DV[
II - 1].Scalar =
false;
3614 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3616 if (Result.DV[
II - 1].Distance ==
nullptr)
3617 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3619 assert(Result.DV[
II - 1].Distance->isZero() &&
3620 "Inconsistency between distance and direction");
3626 const SCEV *Distance = Result.getDistance(
II);
3627 if (Distance && Distance->
isZero())
3629 "Distance is zero, but direction is not EQ");
3633 if (SameSDLevels > 0) {
3636 assert(CommonLevels >= SameSDLevels);
3637 CommonLevels -= SameSDLevels;
3638 MaxLevels += SameSDLevels;
3639 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3640 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3641 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3642 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3643 DV[Level] = Result.DV[Level];
3644 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3645 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3646 Result.DV = std::move(DV);
3647 Result.DVSameSD = std::move(DVSameSD);
3648 Result.Levels = CommonLevels;
3649 Result.SameSDLevels = SameSDLevels;
3651 Result.Consistent =
false;
3654 if (PossiblyLoopIndependent) {
3658 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3660 Result.LoopIndependent =
false;
3667 bool AllEqual =
true;
3668 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3678 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 void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
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 APInt ceilingOfQuotient(const APInt &A, const APInt &B)
static APInt floorOfQuotient(const APInt &A, const APInt &B)
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 > getConstanCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static std::pair< std::optional< APInt >, std::optional< APInt > > inferDomainOfAffine(const APInt &A, const APInt &B, const std::optional< APInt > &UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * absSCEVNoSignedOverflow(const SCEV *A, ScalarEvolution &SE)
Returns the absolute value of A.
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static const SCEV * mulSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A * B if it guaranteed not to signed wrap.
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)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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.
bool sle(const APInt &RHS) const
Signed less or equal comparison.
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.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
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)
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
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.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
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
const SCEV * getOperand() 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 * getAbsExpr(const SCEV *Op, bool IsNSW)
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 * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
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.
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.
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.
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)
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)
@ SMin
Signed integer min implemented in terms of select(cmp()).
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts, const Value *Ptr=nullptr)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
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.