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");
91STATISTIC(BanerjeeApplications,
"Banerjee applications");
92STATISTIC(BanerjeeIndependence,
"Banerjee independence");
94STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
98 cl::desc(
"Try to delinearize array references."));
100 "da-disable-delinearization-checks",
cl::Hidden,
102 "Disable checks that try to statically verify validity of "
103 "delinearized subscripts. Enabling this option may result in incorrect "
104 "dependence vectors for languages that allow the subscript of one "
105 "dimension to underflow or overflow into another dimension."));
109 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
110 "explore MIV direction vectors."));
115enum class DependenceTestType {
129 "da-enable-dependence-test",
cl::init(DependenceTestType::All),
131 cl::desc(
"Run only specified dependence test routine and disable others. "
132 "The purpose is mainly to exclude the influence of other "
133 "dependence test routines in regression tests. If set to All, all "
134 "dependence test routines are enabled."),
136 "Enable all dependence test routines."),
137 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
138 "Enable only Strong SIV test."),
139 clEnumValN(DependenceTestType::WeakCrossingSIV,
141 "Enable only Weak-Crossing SIV test."),
142 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
143 "Enable only Exact SIV test."),
144 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
145 "Enable only Weak-Zero SIV test."),
146 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
147 "Enable only Exact RDIV test."),
148 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
149 "Enable only GCD MIV test."),
150 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
151 "Enable only Banerjee MIV test.")));
157 cl::desc(
"Check if the subscripts are monotonic. If it's not, dependence "
158 "is reported as unknown."));
163 "When printing analysis, dump the results of monotonicity checks."));
179 "Dependence Analysis",
true,
true)
252enum class SCEVMonotonicityType {
264 MultivariateSignedMonotonic,
267struct SCEVMonotonicity {
268 SCEVMonotonicity(SCEVMonotonicityType
Type,
269 const SCEV *FailurePoint =
nullptr);
271 SCEVMonotonicityType
getType()
const {
return Type; }
273 const SCEV *getFailurePoint()
const {
return FailurePoint; }
275 bool isUnknown()
const {
return Type == SCEVMonotonicityType::Unknown; }
277 void print(raw_ostream &OS,
unsigned Depth)
const;
280 SCEVMonotonicityType
Type;
283 const SCEV *FailurePoint;
290struct SCEVMonotonicityChecker
291 :
public SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity> {
293 SCEVMonotonicityChecker(ScalarEvolution *SE) : SE(SE) {}
298 SCEVMonotonicity checkMonotonicity(
const SCEV *Expr,
299 const Loop *OutermostLoop);
305 const Loop *OutermostLoop;
308 SCEVMonotonicity invariantOrUnknown(
const SCEV *Expr);
312 bool isLoopInvariant(
const SCEV *Expr)
const;
315 SCEVMonotonicity createUnknown(
const SCEV *FailurePoint) {
316 return SCEVMonotonicity(SCEVMonotonicityType::Unknown, FailurePoint);
319 SCEVMonotonicity visitAddRecExpr(
const SCEVAddRecExpr *Expr);
321 SCEVMonotonicity visitConstant(
const SCEVConstant *) {
322 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
324 SCEVMonotonicity visitVScale(
const SCEVVScale *) {
325 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
329 SCEVMonotonicity visitZeroExtendExpr(
const SCEVZeroExtendExpr *Expr) {
330 return invariantOrUnknown(Expr);
332 SCEVMonotonicity visitSignExtendExpr(
const SCEVSignExtendExpr *Expr) {
333 return invariantOrUnknown(Expr);
335 SCEVMonotonicity visitAddExpr(
const SCEVAddExpr *Expr) {
336 return invariantOrUnknown(Expr);
338 SCEVMonotonicity visitMulExpr(
const SCEVMulExpr *Expr) {
339 return invariantOrUnknown(Expr);
341 SCEVMonotonicity visitPtrToAddrExpr(
const SCEVPtrToAddrExpr *Expr) {
342 return invariantOrUnknown(Expr);
344 SCEVMonotonicity visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
345 return invariantOrUnknown(Expr);
347 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
348 return invariantOrUnknown(Expr);
350 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
351 return invariantOrUnknown(Expr);
353 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
354 return invariantOrUnknown(Expr);
356 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
357 return invariantOrUnknown(Expr);
359 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
360 return invariantOrUnknown(Expr);
362 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
363 return invariantOrUnknown(Expr);
365 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
366 return invariantOrUnknown(Expr);
368 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
369 return invariantOrUnknown(Expr);
371 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
372 return invariantOrUnknown(Expr);
375 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
386struct OverflowSafeSignedAPInt {
387 OverflowSafeSignedAPInt() :
Value(std::nullopt) {}
388 OverflowSafeSignedAPInt(
const APInt &V) :
Value(
V) {}
389 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
391 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
393 return OverflowSafeSignedAPInt();
397 return OverflowSafeSignedAPInt();
398 return OverflowSafeSignedAPInt(Result);
403 return OverflowSafeSignedAPInt();
404 return *
this + fromInt(
RHS);
407 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
409 return OverflowSafeSignedAPInt();
413 return OverflowSafeSignedAPInt();
414 return OverflowSafeSignedAPInt(Result);
419 return OverflowSafeSignedAPInt();
420 return *
this - fromInt(
RHS);
423 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
425 return OverflowSafeSignedAPInt();
429 return OverflowSafeSignedAPInt();
430 return OverflowSafeSignedAPInt(Result);
433 OverflowSafeSignedAPInt
operator-()
const {
435 return OverflowSafeSignedAPInt();
436 if (
Value->isMinSignedValue())
437 return OverflowSafeSignedAPInt();
438 return OverflowSafeSignedAPInt(-*
Value);
441 operator bool()
const {
return Value.has_value(); }
450 const APInt *operator->()
const {
458 std::optional<APInt>
Value;
460 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
462 return OverflowSafeSignedAPInt(
463 APInt(
Value->getBitWidth(), V,
true));
475 bool NormalizeResults) {
476 auto *
F = DA->getFunction();
479 SCEVMonotonicityChecker Checker(&SE);
480 OS <<
"Monotonicity check:\n";
486 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
489 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
490 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
491 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
499 if (SrcI->mayReadOrWriteMemory()) {
502 if (DstI->mayReadOrWriteMemory()) {
503 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
504 OS <<
" da analyze - ";
505 if (
auto D = DA->depends(&*SrcI, &*DstI,
511 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
512 const SCEV *Distance =
D->getDistance(Level);
513 bool IsDistanceZero = Distance && Distance->
isZero();
516 assert(IsDistanceZero == IsDirectionEQ &&
517 "Inconsistent distance and direction.");
522 if (NormalizeResults &&
D->normalize(&SE))
523 OS <<
"normalized - ";
542 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
555 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
560 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
565 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
570 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
584 bool PossiblyLoopIndependent,
585 unsigned CommonLevels)
586 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
587 LoopIndependent(PossiblyLoopIndependent) {
590 DV = std::make_unique<
DVEntry[]>(CommonLevels);
609 for (
unsigned Level = 1; Level <= Levels; ++Level) {
610 unsigned char Direction = DV[Level - 1].Direction;
623 for (
unsigned Level = 1; Level <= Levels; ++Level) {
624 unsigned char Direction = DV[Level - 1].Direction;
632 DV[Level - 1].Direction = RevDirection;
634 if (DV[Level - 1].Distance !=
nullptr)
643 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
646 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
676 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
677 "Level out of range");
678 return Level > Levels;
684SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
685 const SCEV *FailurePoint)
686 :
Type(
Type), FailurePoint(FailurePoint) {
688 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
689 "FailurePoint must be provided iff Type is Unknown");
695 case SCEVMonotonicityType::Unknown:
696 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
698 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
700 case SCEVMonotonicityType::Invariant:
703 case SCEVMonotonicityType::MultivariateSignedMonotonic:
704 OS <<
"MultivariateSignedMonotonic\n";
709bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
710 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
713SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
714 if (isLoopInvariant(Expr))
715 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
716 return createUnknown(Expr);
720SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
721 const Loop *OutermostLoop) {
723 "OutermostLoop must be outermost");
725 this->OutermostLoop = OutermostLoop;
741SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
743 return createUnknown(Expr);
748 SCEVMonotonicity StartMon =
visit(Start);
749 if (StartMon.isUnknown())
752 if (!isLoopInvariant(Step))
753 return createUnknown(Expr);
755 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
776 if (SameSDLevels > 0) {
777 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
784 if (!Assumptions.isAlwaysTrue()) {
785 OS <<
" Runtime Assumptions:\n";
786 Assumptions.print(OS, 2);
795 bool OnSameSD =
false;
796 unsigned LevelNum = Levels;
798 LevelNum += SameSDLevels;
800 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
871 return LI->isUnordered();
873 return SI->isUnordered();
881bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
882 const Loop *DstLoop)
const {
883 if (SrcLoop == DstLoop)
893 const SCEV *SrcUB = SE->getBackedgeTakenCount(SrcLoop);
894 const SCEV *DstUB = SE->getBackedgeTakenCount(DstLoop);
899 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
900 DstUB = SE->getNoopOrZeroExtend(DstUB, WiderType);
972void DependenceInfo::establishNestingLevels(
const Instruction *Src,
974 const BasicBlock *SrcBlock = Src->getParent();
975 const BasicBlock *DstBlock = Dst->getParent();
976 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
977 unsigned DstLevel = LI->getLoopDepth(DstBlock);
978 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
979 const Loop *DstLoop = LI->getLoopFor(DstBlock);
980 SrcLevels = SrcLevel;
981 MaxLevels = SrcLevel + DstLevel;
983 while (SrcLevel > DstLevel) {
987 while (DstLevel > SrcLevel) {
992 const Loop *SrcUncommonFrontier =
nullptr, *DstUncommonFrontier =
nullptr;
995 while (SrcLoop != DstLoop) {
996 SrcUncommonFrontier = SrcLoop;
997 DstUncommonFrontier = DstLoop;
1002 if (SrcUncommonFrontier && DstUncommonFrontier &&
1003 haveSameSD(SrcUncommonFrontier, DstUncommonFrontier))
1005 CommonLevels = SrcLevel;
1006 MaxLevels -= CommonLevels;
1011unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1017unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1019 if (
D > CommonLevels)
1022 return D - CommonLevels + SrcLevels;
1049 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1061 return isLoopInvariant(Expr, LoopNest);
1068 const Loop *
L = LoopNest;
1069 while (L && AddRec->
getLoop() != L)
1070 L =
L->getParentLoop();
1076 if (!isLoopInvariant(Step, LoopNest))
1082 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1087bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1089 return checkSubscript(Src, LoopNest,
Loops,
true);
1094bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1096 return checkSubscript(Dst, LoopNest,
Loops,
false);
1102DependenceInfo::Subscript::ClassificationKind
1103DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1104 const SCEV *Dst,
const Loop *DstLoopNest,
1106 SmallBitVector SrcLoops(MaxLevels + 1);
1107 SmallBitVector DstLoops(MaxLevels + 1);
1108 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1109 return Subscript::NonLinear;
1110 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1111 return Subscript::NonLinear;
1114 unsigned N =
Loops.count();
1116 return Subscript::ZIV;
1118 return Subscript::SIV;
1119 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
1120 return Subscript::RDIV;
1121 return Subscript::MIV;
1131const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1132 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1133 const SCEV *UB = SE->getBackedgeTakenCount(L);
1134 return SE->getTruncateOrZeroExtend(UB,
T);
1142DependenceInfo::collectNonNegativeConstantUpperBound(
const Loop *L,
1144 if (
const SCEV *UB = collectUpperBound(L,
T))
1146 APInt Res =
C->getAPInt();
1150 return std::nullopt;
1179bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1227 bool UnderRuntimeAssumptions) {
1231 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1234 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1235 assert(Coeff == Dst->getStepRecurrence(*SE) &&
1236 "Expecting same coefficient in Strong SIV test");
1237 const SCEV *SrcConst = Src->getStart();
1238 const SCEV *DstConst = Dst->getStart();
1246 ++StrongSIVapplications;
1247 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1260 APInt Distance = ConstDelta;
1261 APInt Remainder = ConstDelta;
1266 if (Remainder != 0) {
1268 ++StrongSIVindependence;
1269 ++StrongSIVsuccesses;
1272 Result.DV[
Level].Distance = SE->getConstant(Distance);
1273 if (Distance.
sgt(0))
1275 else if (Distance.
slt(0))
1279 ++StrongSIVsuccesses;
1280 }
else if (Delta->
isZero()) {
1284 if (SE->isKnownNonZero(Coeff)) {
1286 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1289 if (UnderRuntimeAssumptions) {
1290 const SCEVPredicate *Pred = SE->getComparePredicate(
1292 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1298 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1299 <<
" != 0, but not allowed. Failing this test.\n");
1306 ++StrongSIVsuccesses;
1308 if (Coeff->
isOne()) {
1314 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1315 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1316 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1317 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1318 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1323 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1324 (DeltaMaybeNegative && CoeffMaybeNegative))
1328 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1329 (DeltaMaybePositive && CoeffMaybeNegative))
1331 if (NewDirection <
Result.DV[Level].Direction)
1332 ++StrongSIVsuccesses;
1366bool DependenceInfo::weakCrossingSIVtest(
const SCEVAddRecExpr *Src,
1373 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1376 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1377 const SCEV *SrcConst = Src->getStart();
1378 const SCEV *DstConst = Dst->getStart();
1380 assert(Coeff == SE->getNegativeSCEV(Dst->getStepRecurrence(*SE)) &&
1381 "Unexpected input for weakCrossingSIVtest");
1387 ++WeakCrossingSIVapplications;
1388 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1390 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1396 if (SE->isKnownNegative(ConstCoeff)) {
1399 "dynamic cast of negative of ConstCoeff should yield constant");
1400 Delta = SE->getNegativeSCEV(Delta);
1402 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1412 if (SE->isKnownNegative(Delta)) {
1414 ++WeakCrossingSIVindependence;
1415 ++WeakCrossingSIVsuccesses;
1419 ConstantRange SrcRange = SE->getSignedRange(Src);
1420 ConstantRange DstRange = SE->getSignedRange(Dst);
1425 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1426 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1427 ++WeakCrossingSIVsuccesses;
1428 if (!
Result.DV[Level].Direction) {
1429 ++WeakCrossingSIVindependence;
1437 APInt APDelta = ConstDelta->
getAPInt();
1438 APInt APCoeff = ConstCoeff->
getAPInt();
1439 APInt Distance = APDelta;
1440 APInt Remainder = APDelta;
1443 if (Remainder != 0) {
1445 ++WeakCrossingSIVindependence;
1446 ++WeakCrossingSIVsuccesses;
1454 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1455 ++WeakCrossingSIVsuccesses;
1475 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1476 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1484 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1485 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1492 X = AM.
slt(0) ? -A1 : A1;
1493 Y = BM.
slt(0) ? B1 : -B1;
1503static OverflowSafeSignedAPInt
1505 const OverflowSafeSignedAPInt &OB) {
1507 return OverflowSafeSignedAPInt();
1516 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1518 return OverflowSafeSignedAPInt(Q) - 1;
1521static OverflowSafeSignedAPInt
1523 const OverflowSafeSignedAPInt &OB) {
1525 return OverflowSafeSignedAPInt();
1534 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1535 return OverflowSafeSignedAPInt(Q) + 1;
1569static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1571 OverflowSafeSignedAPInt UB) {
1572 assert(
A &&
B &&
"A and B must be available");
1573 assert(*
A != 0 &&
"A must be non-zero");
1574 assert((!UB || UB->isNonNegative()) &&
"UB must be non-negative");
1575 OverflowSafeSignedAPInt TL, TU;
1578 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1582 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1585 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1589 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1591 return std::make_pair(TL, TU);
1619 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1620 const SCEV *SrcConst = Src->getStart();
1621 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1622 const SCEV *DstConst = Dst->getStart();
1624 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1625 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1628 ++ExactSIVapplications;
1629 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1632 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1642 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1647 APInt AM = ConstSrcCoeff->
getAPInt();
1648 APInt BM = ConstDstCoeff->
getAPInt();
1653 ++ExactSIVindependence;
1654 ++ExactSIVsuccesses;
1661 std::optional<APInt> UM =
1662 collectNonNegativeConstantUpperBound(Src->getLoop(), Delta->
getType());
1668 APInt TC = CM.
sdiv(
G);
1690 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1691 const OverflowSafeSignedAPInt &V1,
1692 bool IsMin) -> std::optional<APInt> {
1699 return std::nullopt;
1705 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1706 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1707 if (!OptTL || !OptTU)
1710 TL = std::move(*OptTL);
1711 TU = std::move(*OptTU);
1716 ++ExactSIVindependence;
1717 ++ExactSIVsuccesses;
1723 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1724 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1728 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1729 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1731 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1732 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1735 if (!LowerDistance || !UpperDistance)
1738 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1739 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1741 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1743 ++ExactSIVsuccesses;
1745 if (LowerDistance->slt(0)) {
1747 ++ExactSIVsuccesses;
1749 if (UpperDistance->sgt(0)) {
1751 ++ExactSIVsuccesses;
1757 ++ExactSIVindependence;
1768 return ConstDividend.
srem(ConstDivisor) == 0;
1771bool DependenceInfo::weakZeroSIVtestImpl(
const SCEVAddRecExpr *AR,
1772 const SCEV *Const,
unsigned Level,
1775 const SCEV *ARConst = AR->
getStart();
1780 if (Const == ARConst && SE->isKnownNonZero(ARCoeff)) {
1781 if (Level < CommonLevels) {
1783 ++WeakZeroSIVsuccesses;
1795 if (
const SCEV *UpperBound =
1798 bool OverlapAtLast = [&] {
1799 if (!SE->isKnownNonZero(ConstCoeff))
1804 if (OverlapAtLast) {
1806 if (Level < CommonLevels) {
1808 ++WeakZeroSIVsuccesses;
1817 ++WeakZeroSIVindependence;
1818 ++WeakZeroSIVsuccesses;
1853bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *SrcConst,
1863 [[maybe_unused]]
const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1864 [[maybe_unused]]
const SCEV *DstConst = Dst->getStart();
1869 ++WeakZeroSIVapplications;
1870 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1879 bool Res = weakZeroSIVtestImpl(Dst, SrcConst, Level, Result);
1913bool DependenceInfo::weakZeroDstSIVtest(
const SCEVAddRecExpr *Src,
1914 const SCEV *DstConst,
unsigned Level,
1921 [[maybe_unused]]
const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1922 [[maybe_unused]]
const SCEV *SrcConst = Src->getStart();
1927 ++WeakZeroSIVapplications;
1928 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1931 return weakZeroSIVtestImpl(Src, DstConst, Level, Result);
1946 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1947 const SCEV *SrcConst = Src->getStart();
1948 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1949 const SCEV *DstConst = Dst->getStart();
1951 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1952 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1955 ++ExactRDIVapplications;
1957 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1967 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1972 APInt AM = ConstSrcCoeff->
getAPInt();
1973 APInt BM = ConstDstCoeff->
getAPInt();
1978 ++ExactRDIVindependence;
1985 std::optional<APInt> SrcUM =
1986 collectNonNegativeConstantUpperBound(Src->getLoop(), Delta->
getType());
1990 std::optional<APInt> DstUM =
1991 collectNonNegativeConstantUpperBound(Dst->getLoop(), Delta->
getType());
1997 APInt TC = CM.
sdiv(
G);
2022 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
2023 const OverflowSafeSignedAPInt &V1,
2024 bool IsMin) -> std::optional<APInt> {
2031 return std::nullopt;
2034 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
2035 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
2036 if (!OptTL || !OptTU)
2039 TL = std::move(*OptTL);
2040 TU = std::move(*OptTU);
2045 ++ExactRDIVindependence;
2057bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2059 bool UnderRuntimeAssumptions) {
2064 if (SrcAddRec && DstAddRec) {
2067 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2068 [[maybe_unused]]
const Loop *CurDstLoop = DstAddRec->
getLoop();
2069 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2070 "Loops in the SIV test should have the same iteration space and "
2072 Level = mapSrcLoop(CurSrcLoop);
2073 bool disproven =
false;
2074 if (SrcCoeff == DstCoeff)
2075 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
2076 UnderRuntimeAssumptions);
2077 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2078 disproven = weakCrossingSIVtest(SrcAddRec, DstAddRec, Level, Result);
2079 return disproven || exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
2082 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2083 Level = mapSrcLoop(CurSrcLoop);
2084 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result);
2087 const Loop *CurDstLoop = DstAddRec->
getLoop();
2088 Level = mapDstLoop(CurDstLoop);
2089 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result);
2105bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2111 assert(SrcAddRec && DstAddRec &&
"Unexpected non-addrec input");
2112 return exactRDIVtest(SrcAddRec, DstAddRec, Result) ||
2113 gcdMIVtest(Src, Dst, Result);
2119bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2124 return gcdMIVtest(Src, Dst, Result) ||
2125 banerjeeMIVtest(Src, Dst,
Loops, Result);
2138 if (Product->hasNoSignedWrap())
2140 return std::nullopt;
2143bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2144 const Loop *CurLoop,
2145 const SCEV *&CurLoopCoeff,
2146 APInt &RunningGCD)
const {
2149 if (RunningGCD == 1)
2154 assert(isLoopInvariant(Expr, CurLoop) &&
2155 "Expected loop invariant expression");
2162 if (AddRec->
getLoop() == CurLoop) {
2163 CurLoopCoeff = Step;
2177 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2197bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2204 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2211 const SCEV *Coefficients = Src;
2212 while (
const SCEVAddRecExpr *AddRec =
2223 const SCEV *SrcConst = Coefficients;
2230 while (
const SCEVAddRecExpr *AddRec =
2241 const SCEV *DstConst = Coefficients;
2252 if (ConstDelta == 0)
2255 APInt Remainder = ConstDelta.
srem(RunningGCD);
2256 if (Remainder != 0) {
2270 bool Improved =
false;
2272 while (
const SCEVAddRecExpr *AddRec =
2275 const Loop *CurLoop = AddRec->
getLoop();
2278 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2280 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2281 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2296 if (RunningGCD != 0) {
2297 Remainder = ConstDelta.
srem(RunningGCD);
2299 if (Remainder != 0) {
2300 unsigned Level = mapSrcLoop(CurLoop);
2301 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2345bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2352 ++BanerjeeApplications;
2355 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2358 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2359 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2360 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2365 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2366 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2369 findBoundsALL(
A,
B, Bound, K);
2384 bool Disproved =
false;
2387 unsigned DepthExpanded = 0;
2389 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2391 bool Improved =
false;
2392 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2394 unsigned Old =
Result.DV[
K - 1].Direction;
2395 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2396 Improved |= Old !=
Result.DV[
K - 1].Direction;
2397 if (!
Result.DV[K - 1].Direction) {
2405 ++BanerjeeSuccesses;
2407 ++BanerjeeIndependence;
2411 ++BanerjeeIndependence;
2425unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2426 CoefficientInfo *
B, BoundInfo *Bound,
2428 unsigned &DepthExpanded,
2429 const SCEV *Delta)
const {
2435 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2436 "direction exploration is terminated.\n");
2437 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2443 if (Level > CommonLevels) {
2446 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2448 Bound[
K].DirSet |= Bound[
K].Direction;
2473 if (Level > DepthExpanded) {
2474 DepthExpanded =
Level;
2476 findBoundsLT(
A,
B, Bound, Level);
2477 findBoundsGT(
A,
B, Bound, Level);
2478 findBoundsEQ(
A,
B, Bound, Level);
2517 unsigned NewDeps = 0;
2521 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2526 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2531 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2537 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2542bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2543 BoundInfo *Bound,
const SCEV *Delta)
const {
2544 Bound[
Level].Direction = DirKind;
2545 if (
const SCEV *LowerBound = getLowerBound(Bound))
2548 if (
const SCEV *UpperBound = getUpperBound(Bound))
2569void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2570 BoundInfo *Bound,
unsigned K)
const {
2575 if (Bound[K].Iterations) {
2577 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2579 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2584 SE->getZero(
A[K].Coeff->
getType());
2587 SE->getZero(
A[K].Coeff->
getType());
2606void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2607 BoundInfo *Bound,
unsigned K)
const {
2612 if (Bound[K].Iterations) {
2613 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2614 const SCEV *NegativePart = getNegativePart(Delta);
2616 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2617 const SCEV *PositivePart = getPositivePart(Delta);
2619 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2623 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2624 const SCEV *NegativePart = getNegativePart(Delta);
2625 if (NegativePart->
isZero())
2627 const SCEV *PositivePart = getPositivePart(Delta);
2628 if (PositivePart->
isZero())
2646void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2647 BoundInfo *Bound,
unsigned K)
const {
2652 if (Bound[K].Iterations) {
2653 const SCEV *Iter_1 = SE->getMinusSCEV(
2654 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2655 const SCEV *NegPart =
2656 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2658 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2659 const SCEV *PosPart =
2660 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2662 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2666 const SCEV *NegPart =
2667 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2670 const SCEV *PosPart =
2671 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2690void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2691 BoundInfo *Bound,
unsigned K)
const {
2696 if (Bound[K].Iterations) {
2697 const SCEV *Iter_1 = SE->getMinusSCEV(
2698 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2699 const SCEV *NegPart =
2700 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2702 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2703 const SCEV *PosPart =
2704 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2706 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2710 const SCEV *NegPart =
2711 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2714 const SCEV *PosPart =
2715 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2722const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2723 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2727const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2728 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2734DependenceInfo::CoefficientInfo *
2735DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
2737 const SCEV *
Zero = SE->getZero(Subscript->getType());
2738 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
2739 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2741 CI[
K].PosPart =
Zero;
2742 CI[
K].NegPart =
Zero;
2743 CI[
K].Iterations =
nullptr;
2747 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2749 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2750 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2751 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2757 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2764 if (CI[K].Iterations)
2779const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
2780 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2781 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2794const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
2795 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2796 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2815 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2816 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2817 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2818 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2819 const SCEVUnknown *SrcBase =
2821 const SCEVUnknown *DstBase =
2824 if (!SrcBase || !DstBase || SrcBase != DstBase)
2829 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
2830 SrcSubscripts, DstSubscripts) &&
2831 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
2832 SrcSubscripts, DstSubscripts))
2835 assert(isLoopInvariant(SrcBase, SrcLoop) &&
2836 isLoopInvariant(DstBase, DstLoop) &&
2837 "Expected SrcBase and DstBase to be loop invariant");
2841 dbgs() <<
"\nSrcSubscripts: ";
2842 for (
int I = 0;
I <
Size;
I++)
2843 dbgs() << *SrcSubscripts[
I];
2844 dbgs() <<
"\nDstSubscripts: ";
2845 for (
int I = 0;
I <
Size;
I++)
2846 dbgs() << *DstSubscripts[
I];
2855 SCEVMonotonicityChecker MonChecker(SE);
2856 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
2857 for (
int I = 0;
I <
Size; ++
I) {
2858 Pair[
I].Src = SrcSubscripts[
I];
2859 Pair[
I].Dst = DstSubscripts[
I];
2861 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
2862 "Unexpected different types for the subscripts");
2865 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
2867 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
2878bool DependenceInfo::tryDelinearizeFixedSize(
2883 const SCEVUnknown *SrcBase =
2885 const SCEVUnknown *DstBase =
2887 assert(SrcBase && DstBase && SrcBase == DstBase &&
2888 "expected src and dst scev unknowns to be equal");
2891 const SCEV *ElemSize = SE->getElementSize(Src);
2892 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
2895 SrcSubscripts, SrcSizes, ElemSize) ||
2897 DstSubscripts, DstSizes, ElemSize))
2902 if (SrcSizes.
size() != DstSizes.
size() ||
2903 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
2904 SrcSubscripts.
clear();
2905 DstSubscripts.
clear();
2910 "Expected equal number of entries in the list of SrcSubscripts and "
2922 SrcSubscripts.
clear();
2923 DstSubscripts.
clear();
2928 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
2935bool DependenceInfo::tryDelinearizeParametricSize(
2940 const SCEVUnknown *SrcBase =
2942 const SCEVUnknown *DstBase =
2944 assert(SrcBase && DstBase && SrcBase == DstBase &&
2945 "expected src and dst scev unknowns to be equal");
2947 const SCEV *ElementSize = SE->getElementSize(Src);
2948 if (ElementSize != SE->getElementSize(Dst))
2951 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
2952 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
2973 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
2974 SrcSubscripts.
size() != DstSubscripts.
size())
2997 for (
unsigned VI : BV.
set_bits()) {
3007 FunctionAnalysisManager::Invalidator &Inv) {
3014 return Inv.invalidate<
AAManager>(F, PA) ||
3028std::unique_ptr<Dependence>
3030 bool UnderRuntimeAssumptions) {
3032 bool PossiblyLoopIndependent =
true;
3034 PossiblyLoopIndependent =
false;
3036 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3042 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3043 return std::make_unique<Dependence>(Src, Dst,
3055 return std::make_unique<Dependence>(Src, Dst,
3069 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3070 return std::make_unique<Dependence>(Src, Dst,
3076 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3077 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3080 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3081 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3082 if (SrcBase != DstBase) {
3089 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3090 return std::make_unique<Dependence>(Src, Dst,
3098 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3099 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3100 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3101 !isLoopInvariant(DstBase, DstLoop)) {
3102 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3103 return std::make_unique<Dependence>(Src, Dst,
3108 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3109 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3112 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3113 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3114 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3115 return std::make_unique<Dependence>(Src, Dst,
3120 if (!Assume.empty() && !UnderRuntimeAssumptions)
3121 return std::make_unique<Dependence>(Src, Dst,
3126 Pair[0].Src = SrcEv;
3127 Pair[0].Dst = DstEv;
3129 SCEVMonotonicityChecker MonChecker(SE);
3132 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3133 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3134 return std::make_unique<Dependence>(Src, Dst,
3138 if (tryDelinearize(Src, Dst, Pair)) {
3140 Pairs = Pair.
size();
3145 establishNestingLevels(Src, Dst);
3147 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3148 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3149 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3152 CommonLevels += SameSDLevels;
3153 MaxLevels -= SameSDLevels;
3154 if (SameSDLevels > 0) {
3157 for (
unsigned P = 0;
P < Pairs; ++
P) {
3159 Subscript::ClassificationKind TestClass =
3160 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3161 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3163 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3164 TestClass != Subscript::RDIV) {
3166 CommonLevels -= SameSDLevels;
3167 MaxLevels += SameSDLevels;
3174 if (SameSDLevels > 0)
3178 PossiblyLoopIndependent, CommonLevels);
3181 for (
unsigned P = 0;
P < Pairs; ++
P) {
3182 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3183 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3184 Pair[
P].Loops.
resize(MaxLevels + 1);
3185 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3187 Pair[
P].Classification =
3188 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3189 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3190 Pair[
P].GroupLoops = Pair[
P].Loops;
3191 Pair[
P].Group.set(
P);
3201 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3210 switch (Pair[
SI].Classification) {
3211 case Subscript::NonLinear:
3213 ++NonlinearSubscriptPairs;
3214 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3216 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3219 case Subscript::ZIV:
3221 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3224 case Subscript::SIV: {
3227 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3228 UnderRuntimeAssumptions))
3232 case Subscript::RDIV:
3234 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3237 case Subscript::MIV:
3239 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3247 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3248 CompleteLoops |= Pair[
SI].
Loops;
3249 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3250 if (CompleteLoops[
II])
3251 Result.DV[
II - 1].Scalar =
false;
3256 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3258 if (Result.DV[
II - 1].Distance ==
nullptr)
3259 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3261 assert(Result.DV[
II - 1].Distance->isZero() &&
3262 "Inconsistency between distance and direction");
3268 const SCEV *Distance = Result.getDistance(
II);
3269 if (Distance && Distance->
isZero())
3271 "Distance is zero, but direction is not EQ");
3275 if (SameSDLevels > 0) {
3278 assert(CommonLevels >= SameSDLevels);
3279 CommonLevels -= SameSDLevels;
3280 MaxLevels += SameSDLevels;
3281 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3282 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3283 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3284 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3285 DV[Level] = Result.DV[Level];
3286 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3287 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3288 Result.DV = std::move(DV);
3289 Result.DVSameSD = std::move(DVSameSD);
3290 Result.Levels = CommonLevels;
3291 Result.SameSDLevels = SameSDLevels;
3294 if (PossiblyLoopIndependent) {
3298 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3300 Result.LoopIndependent =
false;
3308 bool AllEqual =
true;
3309 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3315 if (AllEqual && Result.Assumptions.getPredicates().empty())
3319 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 bool isLoadOrStore(const Instruction *I)
static OverflowSafeSignedAPInt floorOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
static OverflowSafeSignedAPInt ceilingOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static bool isDependenceTestEnabled(DependenceTestType Test)
Returns true iff Test is enabled.
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static std::pair< OverflowSafeSignedAPInt, OverflowSafeSignedAPInt > inferDomainOfAffine(OverflowSafeSignedAPInt A, OverflowSafeSignedAPInt B, OverflowSafeSignedAPInt UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static cl::opt< 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::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< bool > EnableMonotonicityCheck("da-enable-monotonicity-check", cl::init(false), cl::Hidden, cl::desc("Check if the subscripts are monotonic. If it's not, dependence " "is reported as unknown."))
static cl::opt< bool > DumpMonotonicityReport("da-dump-monotonicity-report", cl::init(false), cl::Hidden, cl::desc("When printing analysis, dump the results of monotonicity checks."))
static cl::opt< unsigned > MIVMaxLevelThreshold("da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors."))
static cl::opt< bool > DisableDelinearizationChecks("da-disable-delinearization-checks", cl::Hidden, cl::desc("Disable checks that try to statically verify validity of " "delinearized subscripts. Enabling this option may result in incorrect " "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension."))
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static 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 isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
@ ICMP_SGT
signed greater than
This class represents a range of values.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns the runtime assumptions under which this Dependence relation is valid...
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual 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.
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.
void negate(ScalarEvolution &SE) override
Negate the dependence by swapping the source and destination, and reversing the direction and distanc...
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 inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
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
SCEVUse getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
This class represents a constant integer value.
const APInt & getAPInt() const
bool hasNoSignedWrap() const
This class represents a composition of other SCEV predicates, and is the class that most clients will...
This class represents an analyzed expression in the program.
LLVM_ABI bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI const SCEV * removePointerBase(const SCEV *S)
Compute an expression equivalent to S - getPointerBase(S).
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
APInt operator+(APInt a, const APInt &b)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...
This class defines a simple visitor class that may be used for various SCEV analysis purposes.