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>;
388struct OverflowSafeSignedAPInt {
389 OverflowSafeSignedAPInt() :
Value(std::nullopt) {}
390 OverflowSafeSignedAPInt(
const APInt &V) :
Value(
V) {}
391 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
393 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
395 return OverflowSafeSignedAPInt();
399 return OverflowSafeSignedAPInt();
400 return OverflowSafeSignedAPInt(Result);
405 return OverflowSafeSignedAPInt();
406 return *
this + fromInt(
RHS);
409 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
411 return OverflowSafeSignedAPInt();
415 return OverflowSafeSignedAPInt();
416 return OverflowSafeSignedAPInt(Result);
421 return OverflowSafeSignedAPInt();
422 return *
this - fromInt(
RHS);
425 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
427 return OverflowSafeSignedAPInt();
431 return OverflowSafeSignedAPInt();
432 return OverflowSafeSignedAPInt(Result);
435 OverflowSafeSignedAPInt
operator-()
const {
437 return OverflowSafeSignedAPInt();
438 if (
Value->isMinSignedValue())
439 return OverflowSafeSignedAPInt();
440 return OverflowSafeSignedAPInt(-*
Value);
443 operator bool()
const {
return Value.has_value(); }
452 const APInt *operator->()
const {
460 std::optional<APInt>
Value;
462 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
464 return OverflowSafeSignedAPInt(
465 APInt(
Value->getBitWidth(), V,
true));
477 bool NormalizeResults) {
478 auto *
F = DA->getFunction();
481 SCEVMonotonicityChecker Checker(&SE);
482 OS <<
"Monotonicity check:\n";
488 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
491 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
492 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
493 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
501 if (SrcI->mayReadOrWriteMemory()) {
504 if (DstI->mayReadOrWriteMemory()) {
505 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
506 OS <<
" da analyze - ";
507 if (
auto D = DA->depends(&*SrcI, &*DstI,
513 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
514 const SCEV *Distance =
D->getDistance(Level);
515 bool IsDistanceZero = Distance && Distance->
isZero();
518 assert(IsDistanceZero == IsDirectionEQ &&
519 "Inconsistent distance and direction.");
524 if (NormalizeResults &&
D->normalize(&SE))
525 OS <<
"normalized - ";
544 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
557 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
562 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
567 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
572 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
586 bool PossiblyLoopIndependent,
587 unsigned CommonLevels)
588 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
589 LoopIndependent(PossiblyLoopIndependent) {
593 DV = std::make_unique<
DVEntry[]>(CommonLevels);
612 for (
unsigned Level = 1; Level <= Levels; ++Level) {
613 unsigned char Direction = DV[Level - 1].Direction;
628 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
631 for (
unsigned Level = 1; Level <= Levels; ++Level) {
632 unsigned char Direction = DV[Level - 1].Direction;
640 DV[Level - 1].Direction = RevDirection;
642 if (DV[Level - 1].Distance !=
nullptr)
646 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
688 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
689 "Level out of range");
690 return Level > Levels;
696SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
697 const SCEV *FailurePoint)
698 :
Type(
Type), FailurePoint(FailurePoint) {
700 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
701 "FailurePoint must be provided iff Type is Unknown");
707 case SCEVMonotonicityType::Unknown:
708 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
710 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
712 case SCEVMonotonicityType::Invariant:
715 case SCEVMonotonicityType::MultivariateSignedMonotonic:
716 OS <<
"MultivariateSignedMonotonic\n";
721bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
722 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
725SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
726 if (isLoopInvariant(Expr))
727 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
728 return createUnknown(Expr);
732SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
733 const Loop *OutermostLoop) {
735 "OutermostLoop must be outermost");
737 this->OutermostLoop = OutermostLoop;
753SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
755 return createUnknown(Expr);
760 SCEVMonotonicity StartMon =
visit(Start);
761 if (StartMon.isUnknown())
764 if (!isLoopInvariant(Step))
765 return createUnknown(Expr);
767 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
790 if (SameSDLevels > 0) {
791 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
798 if (!Assumptions.isAlwaysTrue()) {
799 OS <<
" Runtime Assumptions:\n";
800 Assumptions.print(OS, 2);
809 bool OnSameSD =
false;
810 unsigned LevelNum = Levels;
812 LevelNum += SameSDLevels;
814 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
889 return LI->isUnordered();
891 return SI->isUnordered();
899bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
900 const Loop *DstLoop)
const {
901 if (SrcLoop == DstLoop)
911 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
912 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
913 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
914 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
915 DstUP = SE->getBackedgeTakenCount(DstLoop);
917 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
918 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
919 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
920 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
991void DependenceInfo::establishNestingLevels(
const Instruction *Src,
993 const BasicBlock *SrcBlock = Src->getParent();
994 const BasicBlock *DstBlock = Dst->getParent();
995 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
996 unsigned DstLevel = LI->getLoopDepth(DstBlock);
997 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
998 const Loop *DstLoop = LI->getLoopFor(DstBlock);
999 SrcLevels = SrcLevel;
1000 MaxLevels = SrcLevel + DstLevel;
1002 while (SrcLevel > DstLevel) {
1006 while (DstLevel > SrcLevel) {
1012 while (SrcLoop != DstLoop) {
1014 if (!haveSameSD(SrcLoop, DstLoop))
1020 CommonLevels = SrcLevel;
1021 MaxLevels -= CommonLevels;
1026unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1032unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1034 if (
D > CommonLevels)
1037 return D - CommonLevels + SrcLevels;
1064 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1072 unsigned widestWidthSeen = 0;
1077 for (Subscript *Pair : Pairs) {
1078 const SCEV *Src = Pair->Src;
1079 const SCEV *Dst = Pair->Dst;
1082 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1084 "This function only unify integer types and "
1085 "expect Src and Dst share the same type otherwise.");
1098 assert(widestWidthSeen > 0);
1101 for (Subscript *Pair : Pairs) {
1102 const SCEV *Src = Pair->Src;
1103 const SCEV *Dst = Pair->Dst;
1106 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1108 "This function only unify integer types and "
1109 "expect Src and Dst share the same type otherwise.");
1114 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1117 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1126void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1127 const SCEV *Src = Pair->Src;
1128 const SCEV *Dst = Pair->Dst;
1133 const SCEV *SrcCastOp = SrcCast->
getOperand();
1134 const SCEV *DstCastOp = DstCast->
getOperand();
1136 Pair->Src = SrcCastOp;
1137 Pair->Dst = DstCastOp;
1148 return isLoopInvariant(Expr, LoopNest);
1155 const Loop *
L = LoopNest;
1156 while (L && AddRec->
getLoop() != L)
1157 L =
L->getParentLoop();
1163 if (!isLoopInvariant(Step, LoopNest))
1169 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1174bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1176 return checkSubscript(Src, LoopNest,
Loops,
true);
1181bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1183 return checkSubscript(Dst, LoopNest,
Loops,
false);
1189DependenceInfo::Subscript::ClassificationKind
1190DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1191 const SCEV *Dst,
const Loop *DstLoopNest,
1193 SmallBitVector SrcLoops(MaxLevels + 1);
1194 SmallBitVector DstLoops(MaxLevels + 1);
1195 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1196 return Subscript::NonLinear;
1197 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1198 return Subscript::NonLinear;
1201 unsigned N =
Loops.count();
1203 return Subscript::ZIV;
1205 return Subscript::SIV;
1206 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1207 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1208 return Subscript::RDIV;
1209 return Subscript::MIV;
1223 const SCEV *
Y)
const {
1237 if (SE->isKnownPredicate(Pred,
X,
Y))
1244 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1249 return SE->isKnownNonZero(Delta);
1251 return SE->isKnownNonNegative(Delta);
1253 return SE->isKnownNonPositive(Delta);
1255 return SE->isKnownPositive(Delta);
1257 return SE->isKnownNegative(Delta);
1270const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1271 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1272 const SCEV *UB = SE->getBackedgeTakenCount(L);
1273 return SE->getTruncateOrZeroExtend(UB,
T);
1280const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1282 if (
const SCEV *UB = collectUpperBound(L,
T))
1339bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1354 Result.Consistent =
false;
1385bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1386 const SCEV *DstConst,
const Loop *CurSrcLoop,
1387 const Loop *CurDstLoop,
unsigned Level,
1389 bool UnderRuntimeAssumptions) {
1400 ++StrongSIVapplications;
1401 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1406 Result.Consistent =
false;
1413 bool IsDeltaLarge = [&] {
1414 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1422 if (!AbsDelta || !AbsCoeff)
1431 ++StrongSIVindependence;
1432 ++StrongSIVsuccesses;
1440 APInt Distance = ConstDelta;
1441 APInt Remainder = ConstDelta;
1446 if (Remainder != 0) {
1448 ++StrongSIVindependence;
1449 ++StrongSIVsuccesses;
1452 Result.DV[
Level].Distance = SE->getConstant(Distance);
1453 if (Distance.
sgt(0))
1455 else if (Distance.
slt(0))
1459 ++StrongSIVsuccesses;
1460 }
else if (Delta->
isZero()) {
1464 if (SE->isKnownNonZero(Coeff)) {
1466 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1469 if (UnderRuntimeAssumptions) {
1470 const SCEVPredicate *Pred = SE->getComparePredicate(
1472 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1478 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1479 <<
" != 0, but not allowed. Failing this test.\n");
1486 ++StrongSIVsuccesses;
1488 if (Coeff->
isOne()) {
1492 Result.Consistent =
false;
1496 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1497 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1498 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1499 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1500 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1505 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1506 (DeltaMaybeNegative && CoeffMaybeNegative))
1510 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1511 (DeltaMaybePositive && CoeffMaybeNegative))
1513 if (NewDirection <
Result.DV[Level].Direction)
1514 ++StrongSIVsuccesses;
1548bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1549 const SCEV *SrcConst,
1550 const SCEV *DstConst,
1551 const Loop *CurSrcLoop,
1552 const Loop *CurDstLoop,
unsigned Level,
1561 ++WeakCrossingSIVapplications;
1562 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1564 Result.Consistent =
false;
1565 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1568 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1569 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1570 ++WeakCrossingSIVsuccesses;
1571 if (!
Result.DV[Level].Direction) {
1572 ++WeakCrossingSIVindependence;
1582 if (SE->isKnownNegative(ConstCoeff)) {
1585 "dynamic cast of negative of ConstCoeff should yield constant");
1586 Delta = SE->getNegativeSCEV(Delta);
1588 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1598 if (SE->isKnownNegative(Delta)) {
1600 ++WeakCrossingSIVindependence;
1601 ++WeakCrossingSIVsuccesses;
1607 if (
const SCEV *UpperBound =
1608 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1610 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1612 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1616 ++WeakCrossingSIVindependence;
1617 ++WeakCrossingSIVsuccesses;
1622 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1623 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1624 ++WeakCrossingSIVsuccesses;
1625 if (!
Result.DV[Level].Direction) {
1626 ++WeakCrossingSIVindependence;
1635 APInt APDelta = ConstDelta->
getAPInt();
1636 APInt APCoeff = ConstCoeff->
getAPInt();
1637 APInt Distance = APDelta;
1638 APInt Remainder = APDelta;
1641 if (Remainder != 0) {
1643 ++WeakCrossingSIVindependence;
1644 ++WeakCrossingSIVsuccesses;
1650 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1651 Remainder = Distance.
srem(Two);
1653 if (Remainder != 0) {
1655 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1656 ++WeakCrossingSIVsuccesses;
1676 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1677 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1685 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1686 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1693 X = AM.
slt(0) ? -A1 : A1;
1694 Y = BM.
slt(0) ? B1 : -B1;
1704static OverflowSafeSignedAPInt
1706 const OverflowSafeSignedAPInt &OB) {
1708 return OverflowSafeSignedAPInt();
1717 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1719 return OverflowSafeSignedAPInt(Q) - 1;
1722static OverflowSafeSignedAPInt
1724 const OverflowSafeSignedAPInt &OB) {
1726 return OverflowSafeSignedAPInt();
1735 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1736 return OverflowSafeSignedAPInt(Q) + 1;
1769static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1771 OverflowSafeSignedAPInt UB) {
1772 assert(
A &&
B &&
"A and B must be available");
1773 assert(*
A != 0 &&
"A must be non-zero");
1774 OverflowSafeSignedAPInt TL, TU;
1777 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1781 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1784 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1788 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1790 return std::make_pair(TL, TU);
1812bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1813 const SCEV *SrcConst,
const SCEV *DstConst,
1814 const Loop *CurSrcLoop,
1815 const Loop *CurDstLoop,
unsigned Level,
1821 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1822 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1825 ++ExactSIVapplications;
1826 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1828 Result.Consistent =
false;
1836 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1841 APInt AM = ConstSrcCoeff->
getAPInt();
1842 APInt BM = ConstDstCoeff->
getAPInt();
1847 ++ExactSIVindependence;
1848 ++ExactSIVsuccesses;
1855 std::optional<APInt> UM;
1857 if (
const SCEVConstant *CUB =
1858 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1859 UM = CUB->getAPInt();
1865 APInt TC = CM.
sdiv(
G);
1887 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
1888 const OverflowSafeSignedAPInt &V1) {
1911 ++ExactSIVindependence;
1912 ++ExactSIVsuccesses;
1918 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1919 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1923 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1924 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1926 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1927 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1930 if (!LowerDistance || !UpperDistance)
1933 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1934 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1936 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1938 ++ExactSIVsuccesses;
1940 if (LowerDistance->slt(0)) {
1942 ++ExactSIVsuccesses;
1944 if (UpperDistance->sgt(0)) {
1946 ++ExactSIVsuccesses;
1952 ++ExactSIVindependence;
1963 return ConstDividend.
srem(ConstDivisor) == 0;
1997bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1998 const SCEV *SrcConst,
1999 const SCEV *DstConst,
2000 const Loop *CurSrcLoop,
2001 const Loop *CurDstLoop,
unsigned Level,
2013 ++WeakZeroSIVapplications;
2014 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
2016 Result.Consistent =
false;
2017 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
2020 if (Level < CommonLevels) {
2023 ++WeakZeroSIVsuccesses;
2033 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2034 ? SE->getNegativeSCEV(ConstCoeff)
2036 const SCEV *NewDelta =
2037 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2041 if (
const SCEV *UpperBound =
2042 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2044 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2046 ++WeakZeroSIVindependence;
2047 ++WeakZeroSIVsuccesses;
2052 if (Level < CommonLevels) {
2055 ++WeakZeroSIVsuccesses;
2063 if (SE->isKnownNegative(NewDelta)) {
2065 ++WeakZeroSIVindependence;
2066 ++WeakZeroSIVsuccesses;
2073 ++WeakZeroSIVindependence;
2074 ++WeakZeroSIVsuccesses;
2111bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
2112 const SCEV *SrcConst,
2113 const SCEV *DstConst,
2114 const Loop *CurSrcLoop,
2115 const Loop *CurDstLoop,
unsigned Level,
2126 ++WeakZeroSIVapplications;
2127 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2129 Result.Consistent =
false;
2130 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2133 if (Level < CommonLevels) {
2136 ++WeakZeroSIVsuccesses;
2146 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2147 ? SE->getNegativeSCEV(ConstCoeff)
2149 const SCEV *NewDelta =
2150 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2154 if (
const SCEV *UpperBound =
2155 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2157 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2159 ++WeakZeroSIVindependence;
2160 ++WeakZeroSIVsuccesses;
2165 if (Level < CommonLevels) {
2168 ++WeakZeroSIVsuccesses;
2176 if (SE->isKnownNegative(NewDelta)) {
2178 ++WeakZeroSIVindependence;
2179 ++WeakZeroSIVsuccesses;
2186 ++WeakZeroSIVindependence;
2187 ++WeakZeroSIVsuccesses;
2200bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2201 const SCEV *SrcConst,
const SCEV *DstConst,
2202 const Loop *SrcLoop,
const Loop *DstLoop,
2208 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2209 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2212 ++ExactRDIVapplications;
2213 Result.Consistent =
false;
2214 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2219 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2224 APInt AM = ConstSrcCoeff->
getAPInt();
2225 APInt BM = ConstDstCoeff->
getAPInt();
2230 ++ExactRDIVindependence;
2237 std::optional<APInt> SrcUM;
2239 if (
const SCEVConstant *UpperBound =
2240 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2241 SrcUM = UpperBound->getAPInt();
2245 std::optional<APInt> DstUM;
2247 if (
const SCEVConstant *UpperBound =
2248 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2249 DstUM = UpperBound->getAPInt();
2255 APInt TC = CM.
sdiv(
G);
2280 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
2281 const OverflowSafeSignedAPInt &V1) {
2301 ++ExactRDIVindependence;
2347bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2350 const Loop *Loop2)
const {
2354 ++SymbolicRDIVapplications;
2361 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2362 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2365 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2366 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2369 if (SE->isKnownNonNegative(A1)) {
2370 if (SE->isKnownNonNegative(A2)) {
2374 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2377 ++SymbolicRDIVindependence;
2383 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2386 ++SymbolicRDIVindependence;
2390 }
else if (SE->isKnownNonPositive(A2)) {
2394 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2395 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2396 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2397 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2399 ++SymbolicRDIVindependence;
2404 if (SE->isKnownNegative(C2_C1)) {
2405 ++SymbolicRDIVindependence;
2409 }
else if (SE->isKnownNonPositive(A1)) {
2410 if (SE->isKnownNonNegative(A2)) {
2414 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2415 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2416 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2417 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2419 ++SymbolicRDIVindependence;
2424 if (SE->isKnownPositive(C2_C1)) {
2425 ++SymbolicRDIVindependence;
2428 }
else if (SE->isKnownNonPositive(A2)) {
2432 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2435 ++SymbolicRDIVindependence;
2441 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2444 ++SymbolicRDIVindependence;
2461bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2463 bool UnderRuntimeAssumptions) {
2468 if (SrcAddRec && DstAddRec) {
2469 const SCEV *SrcConst = SrcAddRec->
getStart();
2470 const SCEV *DstConst = DstAddRec->
getStart();
2473 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2474 const Loop *CurDstLoop = DstAddRec->
getLoop();
2475 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2476 "Loops in the SIV test should have the same iteration space and "
2478 Level = mapSrcLoop(CurSrcLoop);
2480 if (SrcCoeff == DstCoeff)
2482 strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop, CurDstLoop,
2483 Level, Result, UnderRuntimeAssumptions);
2484 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2485 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2486 CurDstLoop, Level, Result);
2488 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2489 CurSrcLoop, CurDstLoop, Level, Result);
2490 return disproven || gcdMIVtest(Src, Dst, Result) ||
2491 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2495 const SCEV *SrcConst = SrcAddRec->
getStart();
2497 const SCEV *DstConst = Dst;
2498 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2499 Level = mapSrcLoop(CurSrcLoop);
2500 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2501 CurSrcLoop, Level, Result) ||
2502 gcdMIVtest(Src, Dst, Result);
2505 const SCEV *DstConst = DstAddRec->
getStart();
2507 const SCEV *SrcConst = Src;
2508 const Loop *CurDstLoop = DstAddRec->
getLoop();
2509 Level = mapDstLoop(CurDstLoop);
2510 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2511 CurDstLoop, Level, Result) ||
2512 gcdMIVtest(Src, Dst, Result);
2531bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2539 const SCEV *SrcConst, *DstConst;
2540 const SCEV *SrcCoeff, *DstCoeff;
2541 const Loop *SrcLoop, *DstLoop;
2547 if (SrcAddRec && DstAddRec) {
2550 SrcLoop = SrcAddRec->
getLoop();
2553 DstLoop = DstAddRec->
getLoop();
2554 }
else if (SrcAddRec) {
2555 if (
const SCEVAddRecExpr *tmpAddRec =
2557 SrcConst = tmpAddRec->getStart();
2558 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2559 SrcLoop = tmpAddRec->getLoop();
2562 DstLoop = SrcAddRec->
getLoop();
2565 }
else if (DstAddRec) {
2566 if (
const SCEVAddRecExpr *tmpAddRec =
2568 DstConst = tmpAddRec->getStart();
2569 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2570 DstLoop = tmpAddRec->getLoop();
2573 SrcLoop = DstAddRec->
getLoop();
2578 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2580 gcdMIVtest(Src, Dst, Result) ||
2581 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2588bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2593 Result.Consistent =
false;
2594 return gcdMIVtest(Src, Dst, Result) ||
2595 banerjeeMIVtest(Src, Dst,
Loops, Result);
2608 if (Product->hasNoSignedWrap())
2610 return std::nullopt;
2613bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2614 const Loop *CurLoop,
2615 const SCEV *&CurLoopCoeff,
2616 APInt &RunningGCD)
const {
2619 if (RunningGCD == 1)
2624 assert(isLoopInvariant(Expr, CurLoop) &&
2625 "Expected loop invariant expression");
2632 if (AddRec->
getLoop() == CurLoop) {
2633 CurLoopCoeff = Step;
2647 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2668bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2675 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2682 const SCEV *Coefficients = Src;
2683 while (
const SCEVAddRecExpr *AddRec =
2694 const SCEV *SrcConst = Coefficients;
2701 while (
const SCEVAddRecExpr *AddRec =
2712 const SCEV *DstConst = Coefficients;
2724 if (ConstDelta == 0)
2727 APInt Remainder = ConstDelta.
srem(RunningGCD);
2728 if (Remainder != 0) {
2747 bool Improved =
false;
2749 while (
const SCEVAddRecExpr *AddRec =
2752 const Loop *CurLoop = AddRec->
getLoop();
2753 RunningGCD = ExtraGCD;
2755 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2757 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2758 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2761 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2771 if (RunningGCD != 0) {
2772 Remainder = ConstDelta.
srem(RunningGCD);
2774 if (Remainder != 0) {
2775 unsigned Level = mapSrcLoop(CurLoop);
2776 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2820bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2827 ++BanerjeeApplications;
2830 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2833 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2834 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2835 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2840 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2841 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2844 findBoundsALL(
A,
B, Bound, K);
2859 bool Disproved =
false;
2862 unsigned DepthExpanded = 0;
2864 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2866 bool Improved =
false;
2867 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2869 unsigned Old =
Result.DV[
K - 1].Direction;
2870 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2871 Improved |= Old !=
Result.DV[
K - 1].Direction;
2872 if (!
Result.DV[K - 1].Direction) {
2880 ++BanerjeeSuccesses;
2882 ++BanerjeeIndependence;
2886 ++BanerjeeIndependence;
2900unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2901 CoefficientInfo *
B, BoundInfo *Bound,
2903 unsigned &DepthExpanded,
2904 const SCEV *Delta)
const {
2910 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2911 "direction exploration is terminated.\n");
2912 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2918 if (Level > CommonLevels) {
2921 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2923 Bound[
K].DirSet |= Bound[
K].Direction;
2948 if (Level > DepthExpanded) {
2949 DepthExpanded =
Level;
2951 findBoundsLT(
A,
B, Bound, Level);
2952 findBoundsGT(
A,
B, Bound, Level);
2953 findBoundsEQ(
A,
B, Bound, Level);
2992 unsigned NewDeps = 0;
2996 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3001 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3006 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3012 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3017bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
3018 BoundInfo *Bound,
const SCEV *Delta)
const {
3019 Bound[
Level].Direction = DirKind;
3020 if (
const SCEV *LowerBound = getLowerBound(Bound))
3023 if (
const SCEV *UpperBound = getUpperBound(Bound))
3044void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
3045 BoundInfo *Bound,
unsigned K)
const {
3050 if (Bound[K].Iterations) {
3052 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3054 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3059 SE->getZero(
A[K].Coeff->
getType());
3062 SE->getZero(
A[K].Coeff->
getType());
3081void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3082 BoundInfo *Bound,
unsigned K)
const {
3087 if (Bound[K].Iterations) {
3088 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3089 const SCEV *NegativePart = getNegativePart(Delta);
3091 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3092 const SCEV *PositivePart = getPositivePart(Delta);
3094 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3098 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3099 const SCEV *NegativePart = getNegativePart(Delta);
3100 if (NegativePart->
isZero())
3102 const SCEV *PositivePart = getPositivePart(Delta);
3103 if (PositivePart->
isZero())
3121void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3122 BoundInfo *Bound,
unsigned K)
const {
3127 if (Bound[K].Iterations) {
3128 const SCEV *Iter_1 = SE->getMinusSCEV(
3129 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3130 const SCEV *NegPart =
3131 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3133 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3134 const SCEV *PosPart =
3135 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3137 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3141 const SCEV *NegPart =
3142 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3145 const SCEV *PosPart =
3146 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3165void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3166 BoundInfo *Bound,
unsigned K)
const {
3171 if (Bound[K].Iterations) {
3172 const SCEV *Iter_1 = SE->getMinusSCEV(
3173 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3174 const SCEV *NegPart =
3175 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3177 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3178 const SCEV *PosPart =
3179 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3181 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3185 const SCEV *NegPart =
3186 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3189 const SCEV *PosPart =
3190 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3197const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3198 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3202const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3203 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3209DependenceInfo::CoefficientInfo *
3210DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3212 const SCEV *
Zero = SE->getZero(Subscript->getType());
3213 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3214 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3216 CI[
K].PosPart =
Zero;
3217 CI[
K].NegPart =
Zero;
3218 CI[
K].Iterations =
nullptr;
3222 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3224 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3225 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3226 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3232 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3239 if (CI[K].Iterations)
3254const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3255 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3256 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3269const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3270 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3271 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3290 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3291 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3292 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3293 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3294 const SCEVUnknown *SrcBase =
3296 const SCEVUnknown *DstBase =
3299 if (!SrcBase || !DstBase || SrcBase != DstBase)
3304 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3305 SrcSubscripts, DstSubscripts) &&
3306 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3307 SrcSubscripts, DstSubscripts))
3310 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3311 isLoopInvariant(DstBase, DstLoop) &&
3312 "Expected SrcBase and DstBase to be loop invariant");
3316 dbgs() <<
"\nSrcSubscripts: ";
3317 for (
int I = 0;
I <
Size;
I++)
3318 dbgs() << *SrcSubscripts[
I];
3319 dbgs() <<
"\nDstSubscripts: ";
3320 for (
int I = 0;
I <
Size;
I++)
3321 dbgs() << *DstSubscripts[
I];
3329 SCEVMonotonicityChecker MonChecker(SE);
3330 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3331 for (
int I = 0;
I <
Size; ++
I) {
3332 Pair[
I].Src = SrcSubscripts[
I];
3333 Pair[
I].Dst = DstSubscripts[
I];
3334 unifySubscriptType(&Pair[
I]);
3337 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3339 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3350bool DependenceInfo::tryDelinearizeFixedSize(
3355 const SCEVUnknown *SrcBase =
3357 const SCEVUnknown *DstBase =
3359 assert(SrcBase && DstBase && SrcBase == DstBase &&
3360 "expected src and dst scev unknowns to be equal");
3363 const SCEV *ElemSize = SE->getElementSize(Src);
3364 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3367 SrcSubscripts, SrcSizes, ElemSize) ||
3369 DstSubscripts, DstSizes, ElemSize))
3374 if (SrcSizes.
size() != DstSizes.
size() ||
3375 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3376 SrcSubscripts.
clear();
3377 DstSubscripts.
clear();
3382 "Expected equal number of entries in the list of SrcSubscripts and "
3394 SrcSubscripts.
clear();
3395 DstSubscripts.
clear();
3400 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3407bool DependenceInfo::tryDelinearizeParametricSize(
3412 const SCEVUnknown *SrcBase =
3414 const SCEVUnknown *DstBase =
3416 assert(SrcBase && DstBase && SrcBase == DstBase &&
3417 "expected src and dst scev unknowns to be equal");
3419 const SCEV *ElementSize = SE->getElementSize(Src);
3420 if (ElementSize != SE->getElementSize(Dst))
3423 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3424 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3445 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3446 SrcSubscripts.
size() != DstSubscripts.
size())
3469 for (
unsigned VI : BV.
set_bits()) {
3479 FunctionAnalysisManager::Invalidator &Inv) {
3486 return Inv.invalidate<
AAManager>(F, PA) ||
3500std::unique_ptr<Dependence>
3502 bool UnderRuntimeAssumptions) {
3504 bool PossiblyLoopIndependent =
true;
3506 PossiblyLoopIndependent =
false;
3508 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3514 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3515 return std::make_unique<Dependence>(Src, Dst,
3527 return std::make_unique<Dependence>(Src, Dst,
3541 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3542 return std::make_unique<Dependence>(Src, Dst,
3548 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3549 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3552 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3553 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3554 if (SrcBase != DstBase) {
3561 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3562 return std::make_unique<Dependence>(Src, Dst,
3570 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3571 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3572 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3573 !isLoopInvariant(DstBase, DstLoop)) {
3574 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3575 return std::make_unique<Dependence>(Src, Dst,
3580 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3581 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3584 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3585 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3586 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3587 return std::make_unique<Dependence>(Src, Dst,
3592 if (!Assume.empty() && !UnderRuntimeAssumptions)
3593 return std::make_unique<Dependence>(Src, Dst,
3598 Pair[0].Src = SrcEv;
3599 Pair[0].Dst = DstEv;
3601 SCEVMonotonicityChecker MonChecker(SE);
3604 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3605 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3606 return std::make_unique<Dependence>(Src, Dst,
3610 if (tryDelinearize(Src, Dst, Pair)) {
3612 Pairs = Pair.
size();
3617 establishNestingLevels(Src, Dst);
3619 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3620 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3621 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3624 CommonLevels += SameSDLevels;
3625 MaxLevels -= SameSDLevels;
3626 if (SameSDLevels > 0) {
3629 for (
unsigned P = 0;
P < Pairs; ++
P) {
3631 Subscript::ClassificationKind TestClass =
3632 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3633 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3635 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3636 TestClass != Subscript::RDIV) {
3638 CommonLevels -= SameSDLevels;
3639 MaxLevels += SameSDLevels;
3646 if (SameSDLevels > 0)
3650 PossiblyLoopIndependent, CommonLevels);
3653 for (
unsigned P = 0;
P < Pairs; ++
P) {
3654 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3655 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3656 Pair[
P].Loops.
resize(MaxLevels + 1);
3657 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3659 removeMatchingExtensions(&Pair[
P]);
3660 Pair[
P].Classification =
3661 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3662 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3663 Pair[
P].GroupLoops = Pair[
P].Loops;
3664 Pair[
P].Group.set(
P);
3674 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3676 switch (Pair[
SI].Classification) {
3677 case Subscript::NonLinear:
3679 ++NonlinearSubscriptPairs;
3680 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3682 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3684 Result.Consistent =
false;
3686 case Subscript::ZIV:
3688 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3691 case Subscript::SIV: {
3694 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3695 UnderRuntimeAssumptions))
3699 case Subscript::RDIV:
3701 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3704 case Subscript::MIV:
3706 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3714 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3715 CompleteLoops |= Pair[
SI].
Loops;
3716 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3717 if (CompleteLoops[
II])
3718 Result.DV[
II - 1].Scalar =
false;
3723 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3725 if (Result.DV[
II - 1].Distance ==
nullptr)
3726 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3728 assert(Result.DV[
II - 1].Distance->isZero() &&
3729 "Inconsistency between distance and direction");
3735 const SCEV *Distance = Result.getDistance(
II);
3736 if (Distance && Distance->
isZero())
3738 "Distance is zero, but direction is not EQ");
3742 if (SameSDLevels > 0) {
3745 assert(CommonLevels >= SameSDLevels);
3746 CommonLevels -= SameSDLevels;
3747 MaxLevels += SameSDLevels;
3748 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3749 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3750 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3751 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3752 DV[Level] = Result.DV[Level];
3753 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3754 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3755 Result.DV = std::move(DV);
3756 Result.DVSameSD = std::move(DVSameSD);
3757 Result.Levels = CommonLevels;
3758 Result.SameSDLevels = SameSDLevels;
3760 Result.Consistent =
false;
3763 if (PossiblyLoopIndependent) {
3767 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3769 Result.LoopIndependent =
false;
3777 bool AllEqual =
true;
3778 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3784 if (AllEqual && Result.Assumptions.getPredicates().empty())
3788 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::All), cl::ReallyHidden, cl::desc("Run only specified dependence test routine and disable others. " "The purpose is mainly to exclude the influence of other " "dependence test routines in regression tests. If set to All, all " "dependence test routines are enabled."), cl::values(clEnumValN(DependenceTestType::All, "all", "Enable all dependence test routines."), clEnumValN(DependenceTestType::StrongSIV, "strong-siv", "Enable only Strong SIV test."), clEnumValN(DependenceTestType::WeakCrossingSIV, "weak-crossing-siv", "Enable only Weak-Crossing SIV test."), clEnumValN(DependenceTestType::ExactSIV, "exact-siv", "Enable only Exact SIV test."), clEnumValN(DependenceTestType::WeakZeroSIV, "weak-zero-siv", "Enable only Weak-Zero SIV test."), clEnumValN(DependenceTestType::ExactRDIV, "exact-rdiv", "Enable only Exact RDIV test."), clEnumValN(DependenceTestType::SymbolicRDIV, "symbolic-rdiv", "Enable only Symbolic RDIV test."), clEnumValN(DependenceTestType::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
static bool isLoadOrStore(const Instruction *I)
static OverflowSafeSignedAPInt floorOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
static OverflowSafeSignedAPInt ceilingOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static bool isDependenceTestEnabled(DependenceTestType Test)
Returns true iff Test is enabled.
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static std::pair< OverflowSafeSignedAPInt, OverflowSafeSignedAPInt > inferDomainOfAffine(OverflowSafeSignedAPInt A, OverflowSafeSignedAPInt B, OverflowSafeSignedAPInt UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static 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.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
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.
LLVM_ABI Value(Type *Ty, unsigned scid)
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
constexpr bool operator!(E Val)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
@ 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.
APInt operator+(APInt a, const APInt &b)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...
This class defines a simple visitor class that may be used for various SCEV analysis purposes.