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,
1300 bool UnderRuntimeAssumptions) {
1311 ++StrongSIVapplications;
1312 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1317 Result.Consistent =
false;
1324 bool IsDeltaLarge = [&] {
1325 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1333 if (!AbsDelta || !AbsCoeff)
1342 ++StrongSIVindependence;
1343 ++StrongSIVsuccesses;
1351 APInt Distance = ConstDelta;
1352 APInt Remainder = ConstDelta;
1357 if (Remainder != 0) {
1359 ++StrongSIVindependence;
1360 ++StrongSIVsuccesses;
1363 Result.DV[
Level].Distance = SE->getConstant(Distance);
1364 if (Distance.
sgt(0))
1366 else if (Distance.
slt(0))
1370 ++StrongSIVsuccesses;
1371 }
else if (Delta->
isZero()) {
1375 if (SE->isKnownNonZero(Coeff)) {
1377 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1380 if (UnderRuntimeAssumptions) {
1381 const SCEVPredicate *Pred = SE->getComparePredicate(
1383 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1389 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1390 <<
" != 0, but not allowed. Failing this test.\n");
1397 ++StrongSIVsuccesses;
1399 if (Coeff->
isOne()) {
1403 Result.Consistent =
false;
1407 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1408 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1409 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1410 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1411 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1416 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1417 (DeltaMaybeNegative && CoeffMaybeNegative))
1421 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1422 (DeltaMaybePositive && CoeffMaybeNegative))
1424 if (NewDirection <
Result.DV[Level].Direction)
1425 ++StrongSIVsuccesses;
1459bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1460 const SCEV *SrcConst,
1461 const SCEV *DstConst,
1462 const Loop *CurSrcLoop,
1463 const Loop *CurDstLoop,
unsigned Level,
1472 ++WeakCrossingSIVapplications;
1473 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1475 Result.Consistent =
false;
1476 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1479 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1480 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1481 ++WeakCrossingSIVsuccesses;
1482 if (!
Result.DV[Level].Direction) {
1483 ++WeakCrossingSIVindependence;
1493 if (SE->isKnownNegative(ConstCoeff)) {
1496 "dynamic cast of negative of ConstCoeff should yield constant");
1497 Delta = SE->getNegativeSCEV(Delta);
1499 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1509 if (SE->isKnownNegative(Delta)) {
1511 ++WeakCrossingSIVindependence;
1512 ++WeakCrossingSIVsuccesses;
1518 if (
const SCEV *UpperBound =
1519 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1521 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1523 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1527 ++WeakCrossingSIVindependence;
1528 ++WeakCrossingSIVsuccesses;
1533 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1534 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1535 ++WeakCrossingSIVsuccesses;
1536 if (!
Result.DV[Level].Direction) {
1537 ++WeakCrossingSIVindependence;
1546 APInt APDelta = ConstDelta->
getAPInt();
1547 APInt APCoeff = ConstCoeff->
getAPInt();
1548 APInt Distance = APDelta;
1549 APInt Remainder = APDelta;
1552 if (Remainder != 0) {
1554 ++WeakCrossingSIVindependence;
1555 ++WeakCrossingSIVsuccesses;
1561 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1562 Remainder = Distance.
srem(Two);
1564 if (Remainder != 0) {
1566 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1567 ++WeakCrossingSIVsuccesses;
1584 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1585 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1593 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1594 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1601 X = AM.
slt(0) ? -A1 : A1;
1602 Y = BM.
slt(0) ? B1 : -B1;
1618 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1630 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1665static std::pair<std::optional<APInt>, std::optional<APInt>>
1667 const std::optional<APInt> &UB) {
1668 assert(
A != 0 &&
"A must be non-zero");
1669 std::optional<APInt> TL, TU;
1689 return std::make_pair(TL, TU);
1711bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1712 const SCEV *SrcConst,
const SCEV *DstConst,
1713 const Loop *CurSrcLoop,
1714 const Loop *CurDstLoop,
unsigned Level,
1720 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1721 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1724 ++ExactSIVapplications;
1725 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1727 Result.Consistent =
false;
1735 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1740 APInt AM = ConstSrcCoeff->
getAPInt();
1741 APInt BM = ConstDstCoeff->
getAPInt();
1746 ++ExactSIVindependence;
1747 ++ExactSIVsuccesses;
1754 std::optional<APInt> UM;
1756 if (
const SCEVConstant *CUB =
1757 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1758 UM = CUB->getAPInt();
1764 APInt TC = CM.
sdiv(
G);
1786 auto CreateVec = [](
const std::optional<APInt> &V0,
1787 const std::optional<APInt> &V1) {
1810 ++ExactSIVindependence;
1811 ++ExactSIVsuccesses;
1817 APInt LowerDistance, UpperDistance;
1820 LowerDistance = (TY - TX) + (TA - TB) * TL;
1821 UpperDistance = (TY - TX) + (TA - TB) * TU;
1823 LowerDistance = (TY - TX) + (TA - TB) * TU;
1824 UpperDistance = (TY - TX) + (TA - TB) * TL;
1827 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1828 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1830 APInt
Zero(Bits, 0,
true);
1831 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1833 ++ExactSIVsuccesses;
1835 if (LowerDistance.
slt(0)) {
1837 ++ExactSIVsuccesses;
1839 if (UpperDistance.
sgt(0)) {
1841 ++ExactSIVsuccesses;
1847 ++ExactSIVindependence;
1858 return ConstDividend.
srem(ConstDivisor) == 0;
1892bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1893 const SCEV *SrcConst,
1894 const SCEV *DstConst,
1895 const Loop *CurSrcLoop,
1896 const Loop *CurDstLoop,
unsigned Level,
1908 ++WeakZeroSIVapplications;
1909 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1911 Result.Consistent =
false;
1912 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1915 if (Level < CommonLevels) {
1918 ++WeakZeroSIVsuccesses;
1928 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1929 ? SE->getNegativeSCEV(ConstCoeff)
1931 const SCEV *NewDelta =
1932 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1936 if (
const SCEV *UpperBound =
1937 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1939 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1941 ++WeakZeroSIVindependence;
1942 ++WeakZeroSIVsuccesses;
1947 if (Level < CommonLevels) {
1950 ++WeakZeroSIVsuccesses;
1958 if (SE->isKnownNegative(NewDelta)) {
1960 ++WeakZeroSIVindependence;
1961 ++WeakZeroSIVsuccesses;
1968 ++WeakZeroSIVindependence;
1969 ++WeakZeroSIVsuccesses;
2006bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
2007 const SCEV *SrcConst,
2008 const SCEV *DstConst,
2009 const Loop *CurSrcLoop,
2010 const Loop *CurDstLoop,
unsigned Level,
2021 ++WeakZeroSIVapplications;
2022 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2024 Result.Consistent =
false;
2025 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2028 if (Level < CommonLevels) {
2031 ++WeakZeroSIVsuccesses;
2041 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2042 ? SE->getNegativeSCEV(ConstCoeff)
2044 const SCEV *NewDelta =
2045 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2049 if (
const SCEV *UpperBound =
2050 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2052 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2054 ++WeakZeroSIVindependence;
2055 ++WeakZeroSIVsuccesses;
2060 if (Level < CommonLevels) {
2063 ++WeakZeroSIVsuccesses;
2071 if (SE->isKnownNegative(NewDelta)) {
2073 ++WeakZeroSIVindependence;
2074 ++WeakZeroSIVsuccesses;
2081 ++WeakZeroSIVindependence;
2082 ++WeakZeroSIVsuccesses;
2095bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2096 const SCEV *SrcConst,
const SCEV *DstConst,
2097 const Loop *SrcLoop,
const Loop *DstLoop,
2103 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2104 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2107 ++ExactRDIVapplications;
2108 Result.Consistent =
false;
2109 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2114 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2119 APInt AM = ConstSrcCoeff->
getAPInt();
2120 APInt BM = ConstDstCoeff->
getAPInt();
2125 ++ExactRDIVindependence;
2132 std::optional<APInt> SrcUM;
2134 if (
const SCEVConstant *UpperBound =
2135 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2136 SrcUM = UpperBound->getAPInt();
2140 std::optional<APInt> DstUM;
2142 if (
const SCEVConstant *UpperBound =
2143 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2144 DstUM = UpperBound->getAPInt();
2150 APInt TC = CM.
sdiv(
G);
2175 auto CreateVec = [](
const std::optional<APInt> &V0,
2176 const std::optional<APInt> &V1) {
2196 ++ExactRDIVindependence;
2242bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2245 const Loop *Loop2)
const {
2249 ++SymbolicRDIVapplications;
2256 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2257 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2260 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2261 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2264 if (SE->isKnownNonNegative(A1)) {
2265 if (SE->isKnownNonNegative(A2)) {
2269 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2272 ++SymbolicRDIVindependence;
2278 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2281 ++SymbolicRDIVindependence;
2285 }
else if (SE->isKnownNonPositive(A2)) {
2289 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2290 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2291 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2292 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2294 ++SymbolicRDIVindependence;
2299 if (SE->isKnownNegative(C2_C1)) {
2300 ++SymbolicRDIVindependence;
2304 }
else if (SE->isKnownNonPositive(A1)) {
2305 if (SE->isKnownNonNegative(A2)) {
2309 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2310 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2311 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2312 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2314 ++SymbolicRDIVindependence;
2319 if (SE->isKnownPositive(C2_C1)) {
2320 ++SymbolicRDIVindependence;
2323 }
else if (SE->isKnownNonPositive(A2)) {
2327 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2330 ++SymbolicRDIVindependence;
2336 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2339 ++SymbolicRDIVindependence;
2356bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2358 bool UnderRuntimeAssumptions) {
2363 if (SrcAddRec && DstAddRec) {
2364 const SCEV *SrcConst = SrcAddRec->
getStart();
2365 const SCEV *DstConst = DstAddRec->
getStart();
2368 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2369 const Loop *CurDstLoop = DstAddRec->
getLoop();
2370 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2371 "Loops in the SIV test should have the same iteration space and "
2373 Level = mapSrcLoop(CurSrcLoop);
2375 if (SrcCoeff == DstCoeff)
2377 strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop, CurDstLoop,
2378 Level, Result, UnderRuntimeAssumptions);
2379 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2380 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2381 CurDstLoop, Level, Result);
2383 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2384 CurSrcLoop, CurDstLoop, Level, Result);
2385 return disproven || gcdMIVtest(Src, Dst, Result) ||
2386 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2390 const SCEV *SrcConst = SrcAddRec->
getStart();
2392 const SCEV *DstConst = Dst;
2393 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2394 Level = mapSrcLoop(CurSrcLoop);
2395 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2396 CurSrcLoop, Level, Result) ||
2397 gcdMIVtest(Src, Dst, Result);
2400 const SCEV *DstConst = DstAddRec->
getStart();
2402 const SCEV *SrcConst = Src;
2403 const Loop *CurDstLoop = DstAddRec->
getLoop();
2404 Level = mapDstLoop(CurDstLoop);
2405 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2406 CurDstLoop, Level, Result) ||
2407 gcdMIVtest(Src, Dst, Result);
2426bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2434 const SCEV *SrcConst, *DstConst;
2435 const SCEV *SrcCoeff, *DstCoeff;
2436 const Loop *SrcLoop, *DstLoop;
2442 if (SrcAddRec && DstAddRec) {
2445 SrcLoop = SrcAddRec->
getLoop();
2448 DstLoop = DstAddRec->
getLoop();
2449 }
else if (SrcAddRec) {
2450 if (
const SCEVAddRecExpr *tmpAddRec =
2452 SrcConst = tmpAddRec->getStart();
2453 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2454 SrcLoop = tmpAddRec->getLoop();
2457 DstLoop = SrcAddRec->
getLoop();
2460 }
else if (DstAddRec) {
2461 if (
const SCEVAddRecExpr *tmpAddRec =
2463 DstConst = tmpAddRec->getStart();
2464 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2465 DstLoop = tmpAddRec->getLoop();
2468 SrcLoop = DstAddRec->
getLoop();
2473 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2475 gcdMIVtest(Src, Dst, Result) ||
2476 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2483bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2488 Result.Consistent =
false;
2489 return gcdMIVtest(Src, Dst, Result) ||
2490 banerjeeMIVtest(Src, Dst,
Loops, Result);
2503 if (Product->hasNoSignedWrap())
2505 return std::nullopt;
2508bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2509 const Loop *CurLoop,
2510 const SCEV *&CurLoopCoeff,
2511 APInt &RunningGCD)
const {
2514 if (RunningGCD == 1)
2519 assert(isLoopInvariant(Expr, CurLoop) &&
2520 "Expected loop invariant expression");
2527 if (AddRec->
getLoop() == CurLoop) {
2528 CurLoopCoeff = Step;
2542 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2563bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2570 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2577 const SCEV *Coefficients = Src;
2578 while (
const SCEVAddRecExpr *AddRec =
2589 const SCEV *SrcConst = Coefficients;
2596 while (
const SCEVAddRecExpr *AddRec =
2607 const SCEV *DstConst = Coefficients;
2619 if (ConstDelta == 0)
2622 APInt Remainder = ConstDelta.
srem(RunningGCD);
2623 if (Remainder != 0) {
2642 bool Improved =
false;
2644 while (
const SCEVAddRecExpr *AddRec =
2647 const Loop *CurLoop = AddRec->
getLoop();
2648 RunningGCD = ExtraGCD;
2650 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2652 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2653 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2656 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2666 if (RunningGCD != 0) {
2667 Remainder = ConstDelta.
srem(RunningGCD);
2669 if (Remainder != 0) {
2670 unsigned Level = mapSrcLoop(CurLoop);
2671 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2715bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2722 ++BanerjeeApplications;
2725 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2728 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2729 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2730 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2735 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2736 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2739 findBoundsALL(
A,
B, Bound, K);
2754 bool Disproved =
false;
2757 unsigned DepthExpanded = 0;
2759 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2761 bool Improved =
false;
2762 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2764 unsigned Old =
Result.DV[
K - 1].Direction;
2765 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2766 Improved |= Old !=
Result.DV[
K - 1].Direction;
2767 if (!
Result.DV[K - 1].Direction) {
2775 ++BanerjeeSuccesses;
2777 ++BanerjeeIndependence;
2781 ++BanerjeeIndependence;
2795unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2796 CoefficientInfo *
B, BoundInfo *Bound,
2798 unsigned &DepthExpanded,
2799 const SCEV *Delta)
const {
2805 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2806 "direction exploration is terminated.\n");
2807 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2813 if (Level > CommonLevels) {
2816 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2818 Bound[
K].DirSet |= Bound[
K].Direction;
2843 if (Level > DepthExpanded) {
2844 DepthExpanded =
Level;
2846 findBoundsLT(
A,
B, Bound, Level);
2847 findBoundsGT(
A,
B, Bound, Level);
2848 findBoundsEQ(
A,
B, Bound, Level);
2887 unsigned NewDeps = 0;
2891 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2896 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2901 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2907 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2912bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2913 BoundInfo *Bound,
const SCEV *Delta)
const {
2914 Bound[
Level].Direction = DirKind;
2915 if (
const SCEV *LowerBound = getLowerBound(Bound))
2918 if (
const SCEV *UpperBound = getUpperBound(Bound))
2939void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2940 BoundInfo *Bound,
unsigned K)
const {
2945 if (Bound[K].Iterations) {
2947 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2949 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2954 SE->getZero(
A[K].Coeff->
getType());
2957 SE->getZero(
A[K].Coeff->
getType());
2976void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2977 BoundInfo *Bound,
unsigned K)
const {
2982 if (Bound[K].Iterations) {
2983 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2984 const SCEV *NegativePart = getNegativePart(Delta);
2986 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2987 const SCEV *PositivePart = getPositivePart(Delta);
2989 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2993 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2994 const SCEV *NegativePart = getNegativePart(Delta);
2995 if (NegativePart->
isZero())
2997 const SCEV *PositivePart = getPositivePart(Delta);
2998 if (PositivePart->
isZero())
3016void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3017 BoundInfo *Bound,
unsigned K)
const {
3022 if (Bound[K].Iterations) {
3023 const SCEV *Iter_1 = SE->getMinusSCEV(
3024 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3025 const SCEV *NegPart =
3026 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3028 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3029 const SCEV *PosPart =
3030 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3032 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3036 const SCEV *NegPart =
3037 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3040 const SCEV *PosPart =
3041 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3060void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3061 BoundInfo *Bound,
unsigned K)
const {
3066 if (Bound[K].Iterations) {
3067 const SCEV *Iter_1 = SE->getMinusSCEV(
3068 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3069 const SCEV *NegPart =
3070 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3072 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3073 const SCEV *PosPart =
3074 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3076 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3080 const SCEV *NegPart =
3081 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3084 const SCEV *PosPart =
3085 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3092const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3093 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3097const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3098 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3104DependenceInfo::CoefficientInfo *
3105DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3107 const SCEV *
Zero = SE->getZero(Subscript->getType());
3108 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3109 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3111 CI[
K].PosPart =
Zero;
3112 CI[
K].NegPart =
Zero;
3113 CI[
K].Iterations =
nullptr;
3117 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3119 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3120 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3121 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3127 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3134 if (CI[K].Iterations)
3149const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3150 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3151 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3164const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3165 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3166 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3185 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3186 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3187 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3188 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3189 const SCEVUnknown *SrcBase =
3191 const SCEVUnknown *DstBase =
3194 if (!SrcBase || !DstBase || SrcBase != DstBase)
3199 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3200 SrcSubscripts, DstSubscripts) &&
3201 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3202 SrcSubscripts, DstSubscripts))
3205 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3206 isLoopInvariant(DstBase, DstLoop) &&
3207 "Expected SrcBase and DstBase to be loop invariant");
3211 dbgs() <<
"\nSrcSubscripts: ";
3212 for (
int I = 0;
I <
Size;
I++)
3213 dbgs() << *SrcSubscripts[
I];
3214 dbgs() <<
"\nDstSubscripts: ";
3215 for (
int I = 0;
I <
Size;
I++)
3216 dbgs() << *DstSubscripts[
I];
3224 SCEVMonotonicityChecker MonChecker(SE);
3225 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3226 for (
int I = 0;
I <
Size; ++
I) {
3227 Pair[
I].Src = SrcSubscripts[
I];
3228 Pair[
I].Dst = DstSubscripts[
I];
3229 unifySubscriptType(&Pair[
I]);
3232 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3234 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3245bool DependenceInfo::tryDelinearizeFixedSize(
3250 const SCEVUnknown *SrcBase =
3252 const SCEVUnknown *DstBase =
3254 assert(SrcBase && DstBase && SrcBase == DstBase &&
3255 "expected src and dst scev unknowns to be equal");
3258 const SCEV *ElemSize = SE->getElementSize(Src);
3259 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3262 SrcSubscripts, SrcSizes, ElemSize) ||
3264 DstSubscripts, DstSizes, ElemSize))
3269 if (SrcSizes.
size() != DstSizes.
size() ||
3270 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3271 SrcSubscripts.
clear();
3272 DstSubscripts.
clear();
3277 "Expected equal number of entries in the list of SrcSubscripts and "
3292 SrcSubscripts.
clear();
3293 DstSubscripts.
clear();
3298 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3299 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3300 <<
"DstGEP:" << *DstPtr <<
"\n";
3305bool DependenceInfo::tryDelinearizeParametricSize(
3312 const SCEVUnknown *SrcBase =
3314 const SCEVUnknown *DstBase =
3316 assert(SrcBase && DstBase && SrcBase == DstBase &&
3317 "expected src and dst scev unknowns to be equal");
3319 const SCEV *ElementSize = SE->getElementSize(Src);
3320 if (ElementSize != SE->getElementSize(Dst))
3323 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3324 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3345 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3346 SrcSubscripts.
size() != DstSubscripts.
size())
3369 for (
unsigned VI : BV.
set_bits()) {
3379 FunctionAnalysisManager::Invalidator &Inv) {
3386 return Inv.invalidate<
AAManager>(F, PA) ||
3400std::unique_ptr<Dependence>
3402 bool UnderRuntimeAssumptions) {
3404 bool PossiblyLoopIndependent =
true;
3406 PossiblyLoopIndependent =
false;
3408 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3414 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3415 return std::make_unique<Dependence>(Src, Dst,
3427 return std::make_unique<Dependence>(Src, Dst,
3441 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3442 return std::make_unique<Dependence>(Src, Dst,
3448 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3449 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3452 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3453 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3454 if (SrcBase != DstBase) {
3461 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3462 return std::make_unique<Dependence>(Src, Dst,
3470 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3471 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3472 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3473 !isLoopInvariant(DstBase, DstLoop)) {
3474 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3475 return std::make_unique<Dependence>(Src, Dst,
3480 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3481 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3484 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3485 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3486 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3487 return std::make_unique<Dependence>(Src, Dst,
3492 if (!Assume.empty() && !UnderRuntimeAssumptions)
3493 return std::make_unique<Dependence>(Src, Dst,
3498 Pair[0].Src = SrcEv;
3499 Pair[0].Dst = DstEv;
3501 SCEVMonotonicityChecker MonChecker(SE);
3504 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3505 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3506 return std::make_unique<Dependence>(Src, Dst,
3510 if (tryDelinearize(Src, Dst, Pair)) {
3512 Pairs = Pair.
size();
3517 establishNestingLevels(Src, Dst);
3519 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3520 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3521 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3524 CommonLevels += SameSDLevels;
3525 MaxLevels -= SameSDLevels;
3526 if (SameSDLevels > 0) {
3529 for (
unsigned P = 0;
P < Pairs; ++
P) {
3531 Subscript::ClassificationKind TestClass =
3532 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3533 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3535 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3536 TestClass != Subscript::RDIV) {
3538 CommonLevels -= SameSDLevels;
3539 MaxLevels += SameSDLevels;
3546 if (SameSDLevels > 0)
3550 PossiblyLoopIndependent, CommonLevels);
3553 for (
unsigned P = 0;
P < Pairs; ++
P) {
3554 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3555 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3556 Pair[
P].Loops.
resize(MaxLevels + 1);
3557 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3559 removeMatchingExtensions(&Pair[
P]);
3560 Pair[
P].Classification =
3561 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3562 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3563 Pair[
P].GroupLoops = Pair[
P].Loops;
3564 Pair[
P].Group.set(
P);
3574 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3576 switch (Pair[
SI].Classification) {
3577 case Subscript::NonLinear:
3579 ++NonlinearSubscriptPairs;
3580 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3582 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3584 Result.Consistent =
false;
3586 case Subscript::ZIV:
3588 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3591 case Subscript::SIV: {
3594 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3595 UnderRuntimeAssumptions))
3599 case Subscript::RDIV:
3601 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3604 case Subscript::MIV:
3606 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3614 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3615 CompleteLoops |= Pair[
SI].
Loops;
3616 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3617 if (CompleteLoops[
II])
3618 Result.DV[
II - 1].Scalar =
false;
3623 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3625 if (Result.DV[
II - 1].Distance ==
nullptr)
3626 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3628 assert(Result.DV[
II - 1].Distance->isZero() &&
3629 "Inconsistency between distance and direction");
3635 const SCEV *Distance = Result.getDistance(
II);
3636 if (Distance && Distance->
isZero())
3638 "Distance is zero, but direction is not EQ");
3642 if (SameSDLevels > 0) {
3645 assert(CommonLevels >= SameSDLevels);
3646 CommonLevels -= SameSDLevels;
3647 MaxLevels += SameSDLevels;
3648 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3649 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3650 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3651 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3652 DV[Level] = Result.DV[Level];
3653 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3654 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3655 Result.DV = std::move(DV);
3656 Result.DVSameSD = std::move(DVSameSD);
3657 Result.Levels = CommonLevels;
3658 Result.SameSDLevels = SameSDLevels;
3660 Result.Consistent =
false;
3663 if (PossiblyLoopIndependent) {
3667 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3669 Result.LoopIndependent =
false;
3677 bool AllEqual =
true;
3678 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3684 if (AllEqual && Result.Assumptions.getPredicates().empty())
3688 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::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 std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static 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.