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;
2594 if (ConstDelta == 0)
2597 APInt Remainder = ConstDelta.
srem(RunningGCD);
2598 if (Remainder != 0) {
2617 bool Improved =
false;
2619 while (
const SCEVAddRecExpr *AddRec =
2622 const Loop *CurLoop = AddRec->
getLoop();
2623 RunningGCD = ExtraGCD;
2625 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2627 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2628 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2631 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2641 if (RunningGCD != 0) {
2642 Remainder = ConstDelta.
srem(RunningGCD);
2644 if (Remainder != 0) {
2645 unsigned Level = mapSrcLoop(CurLoop);
2646 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2690bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2697 ++BanerjeeApplications;
2700 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2703 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2704 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2705 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2710 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2711 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2714 findBoundsALL(
A,
B, Bound, K);
2729 bool Disproved =
false;
2732 unsigned DepthExpanded = 0;
2734 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2736 bool Improved =
false;
2737 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2739 unsigned Old =
Result.DV[
K - 1].Direction;
2740 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2741 Improved |= Old !=
Result.DV[
K - 1].Direction;
2742 if (!
Result.DV[K - 1].Direction) {
2750 ++BanerjeeSuccesses;
2752 ++BanerjeeIndependence;
2756 ++BanerjeeIndependence;
2770unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2771 CoefficientInfo *
B, BoundInfo *Bound,
2773 unsigned &DepthExpanded,
2774 const SCEV *Delta)
const {
2780 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2781 "direction exploration is terminated.\n");
2782 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2788 if (Level > CommonLevels) {
2791 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2793 Bound[
K].DirSet |= Bound[
K].Direction;
2818 if (Level > DepthExpanded) {
2819 DepthExpanded =
Level;
2821 findBoundsLT(
A,
B, Bound, Level);
2822 findBoundsGT(
A,
B, Bound, Level);
2823 findBoundsEQ(
A,
B, Bound, Level);
2862 unsigned NewDeps = 0;
2866 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2871 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2876 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2882 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2887bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2888 BoundInfo *Bound,
const SCEV *Delta)
const {
2889 Bound[
Level].Direction = DirKind;
2890 if (
const SCEV *LowerBound = getLowerBound(Bound))
2893 if (
const SCEV *UpperBound = getUpperBound(Bound))
2914void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2915 BoundInfo *Bound,
unsigned K)
const {
2920 if (Bound[K].Iterations) {
2922 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2924 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2929 SE->getZero(
A[K].Coeff->
getType());
2932 SE->getZero(
A[K].Coeff->
getType());
2951void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2952 BoundInfo *Bound,
unsigned K)
const {
2957 if (Bound[K].Iterations) {
2958 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2959 const SCEV *NegativePart = getNegativePart(Delta);
2961 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2962 const SCEV *PositivePart = getPositivePart(Delta);
2964 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2968 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2969 const SCEV *NegativePart = getNegativePart(Delta);
2970 if (NegativePart->
isZero())
2972 const SCEV *PositivePart = getPositivePart(Delta);
2973 if (PositivePart->
isZero())
2991void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2992 BoundInfo *Bound,
unsigned K)
const {
2997 if (Bound[K].Iterations) {
2998 const SCEV *Iter_1 = SE->getMinusSCEV(
2999 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3000 const SCEV *NegPart =
3001 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3003 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3004 const SCEV *PosPart =
3005 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3007 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3011 const SCEV *NegPart =
3012 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3015 const SCEV *PosPart =
3016 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3035void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3036 BoundInfo *Bound,
unsigned K)
const {
3041 if (Bound[K].Iterations) {
3042 const SCEV *Iter_1 = SE->getMinusSCEV(
3043 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3044 const SCEV *NegPart =
3045 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3047 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3048 const SCEV *PosPart =
3049 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3051 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3055 const SCEV *NegPart =
3056 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3059 const SCEV *PosPart =
3060 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3067const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3068 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3072const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3073 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3079DependenceInfo::CoefficientInfo *
3080DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3082 const SCEV *
Zero = SE->getZero(Subscript->getType());
3083 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3084 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3086 CI[
K].PosPart =
Zero;
3087 CI[
K].NegPart =
Zero;
3088 CI[
K].Iterations =
nullptr;
3092 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3094 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3095 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3096 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3102 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3109 if (CI[K].Iterations)
3124const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3125 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3126 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3139const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3140 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3141 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3160 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3161 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3162 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3163 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3164 const SCEVUnknown *SrcBase =
3166 const SCEVUnknown *DstBase =
3169 if (!SrcBase || !DstBase || SrcBase != DstBase)
3174 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3175 SrcSubscripts, DstSubscripts) &&
3176 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3177 SrcSubscripts, DstSubscripts))
3180 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3181 isLoopInvariant(DstBase, DstLoop) &&
3182 "Expected SrcBase and DstBase to be loop invariant");
3186 dbgs() <<
"\nSrcSubscripts: ";
3187 for (
int I = 0;
I <
Size;
I++)
3188 dbgs() << *SrcSubscripts[
I];
3189 dbgs() <<
"\nDstSubscripts: ";
3190 for (
int I = 0;
I <
Size;
I++)
3191 dbgs() << *DstSubscripts[
I];
3199 SCEVMonotonicityChecker MonChecker(SE);
3200 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3201 for (
int I = 0;
I <
Size; ++
I) {
3202 Pair[
I].Src = SrcSubscripts[
I];
3203 Pair[
I].Dst = DstSubscripts[
I];
3204 unifySubscriptType(&Pair[
I]);
3207 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3209 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3220bool DependenceInfo::tryDelinearizeFixedSize(
3225 const SCEVUnknown *SrcBase =
3227 const SCEVUnknown *DstBase =
3229 assert(SrcBase && DstBase && SrcBase == DstBase &&
3230 "expected src and dst scev unknowns to be equal");
3233 const SCEV *ElemSize = SE->getElementSize(Src);
3234 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3237 SrcSubscripts, SrcSizes, ElemSize) ||
3239 DstSubscripts, DstSizes, ElemSize))
3244 if (SrcSizes.
size() != DstSizes.
size() ||
3245 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3246 SrcSubscripts.
clear();
3247 DstSubscripts.
clear();
3252 "Expected equal number of entries in the list of SrcSubscripts and "
3267 SrcSubscripts.
clear();
3268 DstSubscripts.
clear();
3273 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3274 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3275 <<
"DstGEP:" << *DstPtr <<
"\n";
3280bool DependenceInfo::tryDelinearizeParametricSize(
3287 const SCEVUnknown *SrcBase =
3289 const SCEVUnknown *DstBase =
3291 assert(SrcBase && DstBase && SrcBase == DstBase &&
3292 "expected src and dst scev unknowns to be equal");
3294 const SCEV *ElementSize = SE->getElementSize(Src);
3295 if (ElementSize != SE->getElementSize(Dst))
3298 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3299 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3320 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3321 SrcSubscripts.
size() != DstSubscripts.
size())
3344 for (
unsigned VI : BV.
set_bits()) {
3354 FunctionAnalysisManager::Invalidator &Inv) {
3361 return Inv.invalidate<
AAManager>(F, PA) ||
3375std::unique_ptr<Dependence>
3377 bool UnderRuntimeAssumptions) {
3379 bool PossiblyLoopIndependent =
true;
3381 PossiblyLoopIndependent =
false;
3383 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3389 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3390 return std::make_unique<Dependence>(Src, Dst,
3402 return std::make_unique<Dependence>(Src, Dst,
3416 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3417 return std::make_unique<Dependence>(Src, Dst,
3423 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3424 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3427 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3428 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3429 if (SrcBase != DstBase) {
3436 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3437 return std::make_unique<Dependence>(Src, Dst,
3445 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3446 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3447 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3448 !isLoopInvariant(DstBase, DstLoop)) {
3449 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3450 return std::make_unique<Dependence>(Src, Dst,
3455 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3456 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3459 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3460 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3461 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3462 return std::make_unique<Dependence>(Src, Dst,
3466 if (!Assume.empty() && !UnderRuntimeAssumptions) {
3468 return std::make_unique<Dependence>(Src, Dst,
3474 Pair[0].Src = SrcEv;
3475 Pair[0].Dst = DstEv;
3477 SCEVMonotonicityChecker MonChecker(SE);
3480 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3481 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3482 return std::make_unique<Dependence>(Src, Dst,
3486 if (tryDelinearize(Src, Dst, Pair)) {
3488 Pairs = Pair.
size();
3493 establishNestingLevels(Src, Dst);
3495 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3496 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3497 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3500 CommonLevels += SameSDLevels;
3501 MaxLevels -= SameSDLevels;
3502 if (SameSDLevels > 0) {
3505 for (
unsigned P = 0;
P < Pairs; ++
P) {
3507 Subscript::ClassificationKind TestClass =
3508 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3509 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3511 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3512 TestClass != Subscript::RDIV) {
3514 CommonLevels -= SameSDLevels;
3515 MaxLevels += SameSDLevels;
3522 if (SameSDLevels > 0)
3526 PossiblyLoopIndependent, CommonLevels);
3529 for (
unsigned P = 0;
P < Pairs; ++
P) {
3530 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3531 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3532 Pair[
P].Loops.
resize(MaxLevels + 1);
3533 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3535 removeMatchingExtensions(&Pair[
P]);
3536 Pair[
P].Classification =
3537 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3538 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3539 Pair[
P].GroupLoops = Pair[
P].Loops;
3540 Pair[
P].Group.set(
P);
3550 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3552 switch (Pair[
SI].Classification) {
3553 case Subscript::NonLinear:
3555 ++NonlinearSubscriptPairs;
3556 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3558 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3560 Result.Consistent =
false;
3562 case Subscript::ZIV:
3564 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3567 case Subscript::SIV: {
3570 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result))
3574 case Subscript::RDIV:
3576 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3579 case Subscript::MIV:
3581 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3589 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3590 CompleteLoops |= Pair[
SI].
Loops;
3591 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3592 if (CompleteLoops[
II])
3593 Result.DV[
II - 1].Scalar =
false;
3598 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3600 if (Result.DV[
II - 1].Distance ==
nullptr)
3601 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3603 assert(Result.DV[
II - 1].Distance->isZero() &&
3604 "Inconsistency between distance and direction");
3610 const SCEV *Distance = Result.getDistance(
II);
3611 if (Distance && Distance->
isZero())
3613 "Distance is zero, but direction is not EQ");
3617 if (SameSDLevels > 0) {
3620 assert(CommonLevels >= SameSDLevels);
3621 CommonLevels -= SameSDLevels;
3622 MaxLevels += SameSDLevels;
3623 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3624 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3625 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3626 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3627 DV[Level] = Result.DV[Level];
3628 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3629 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3630 Result.DV = std::move(DV);
3631 Result.DVSameSD = std::move(DVSameSD);
3632 Result.Levels = CommonLevels;
3633 Result.SameSDLevels = SameSDLevels;
3635 Result.Consistent =
false;
3638 if (PossiblyLoopIndependent) {
3642 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3644 Result.LoopIndependent =
false;
3651 bool AllEqual =
true;
3652 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3662 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.