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 visitPtrToAddrExpr(
const SCEVPtrToAddrExpr *Expr) {
347 return invariantOrUnknown(Expr);
349 SCEVMonotonicity visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
350 return invariantOrUnknown(Expr);
352 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
353 return invariantOrUnknown(Expr);
355 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
356 return invariantOrUnknown(Expr);
358 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
359 return invariantOrUnknown(Expr);
361 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
362 return invariantOrUnknown(Expr);
364 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
365 return invariantOrUnknown(Expr);
367 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
368 return invariantOrUnknown(Expr);
370 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
371 return invariantOrUnknown(Expr);
373 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
374 return invariantOrUnknown(Expr);
376 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
377 return invariantOrUnknown(Expr);
380 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
391struct OverflowSafeSignedAPInt {
392 OverflowSafeSignedAPInt() :
Value(std::nullopt) {}
393 OverflowSafeSignedAPInt(
const APInt &V) :
Value(
V) {}
394 OverflowSafeSignedAPInt(
const std::optional<APInt> &V) :
Value(
V) {}
396 OverflowSafeSignedAPInt
operator+(
const OverflowSafeSignedAPInt &
RHS)
const {
398 return OverflowSafeSignedAPInt();
402 return OverflowSafeSignedAPInt();
403 return OverflowSafeSignedAPInt(Result);
408 return OverflowSafeSignedAPInt();
409 return *
this + fromInt(
RHS);
412 OverflowSafeSignedAPInt
operator-(
const OverflowSafeSignedAPInt &
RHS)
const {
414 return OverflowSafeSignedAPInt();
418 return OverflowSafeSignedAPInt();
419 return OverflowSafeSignedAPInt(Result);
424 return OverflowSafeSignedAPInt();
425 return *
this - fromInt(
RHS);
428 OverflowSafeSignedAPInt
operator*(
const OverflowSafeSignedAPInt &
RHS)
const {
430 return OverflowSafeSignedAPInt();
434 return OverflowSafeSignedAPInt();
435 return OverflowSafeSignedAPInt(Result);
438 OverflowSafeSignedAPInt
operator-()
const {
440 return OverflowSafeSignedAPInt();
441 if (
Value->isMinSignedValue())
442 return OverflowSafeSignedAPInt();
443 return OverflowSafeSignedAPInt(-*
Value);
446 operator bool()
const {
return Value.has_value(); }
455 const APInt *operator->()
const {
463 std::optional<APInt>
Value;
465 OverflowSafeSignedAPInt fromInt(uint64_t V)
const {
467 return OverflowSafeSignedAPInt(
468 APInt(
Value->getBitWidth(), V,
true));
480 bool NormalizeResults) {
481 auto *
F = DA->getFunction();
484 SCEVMonotonicityChecker Checker(&SE);
485 OS <<
"Monotonicity check:\n";
491 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
494 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
495 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
496 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
504 if (SrcI->mayReadOrWriteMemory()) {
507 if (DstI->mayReadOrWriteMemory()) {
508 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
509 OS <<
" da analyze - ";
510 if (
auto D = DA->depends(&*SrcI, &*DstI,
516 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
517 const SCEV *Distance =
D->getDistance(Level);
518 bool IsDistanceZero = Distance && Distance->
isZero();
521 assert(IsDistanceZero == IsDirectionEQ &&
522 "Inconsistent distance and direction.");
527 if (NormalizeResults &&
D->normalize(&SE))
528 OS <<
"normalized - ";
547 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
560 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
565 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
570 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
575 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
589 bool PossiblyLoopIndependent,
590 unsigned CommonLevels)
591 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
592 LoopIndependent(PossiblyLoopIndependent) {
595 DV = std::make_unique<
DVEntry[]>(CommonLevels);
614 for (
unsigned Level = 1; Level <= Levels; ++Level) {
615 unsigned char Direction = DV[Level - 1].Direction;
630 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
633 for (
unsigned Level = 1; Level <= Levels; ++Level) {
634 unsigned char Direction = DV[Level - 1].Direction;
642 DV[Level - 1].Direction = RevDirection;
644 if (DV[Level - 1].Distance !=
nullptr)
648 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
678 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
679 "Level out of range");
680 return Level > Levels;
686SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
687 const SCEV *FailurePoint)
688 :
Type(
Type), FailurePoint(FailurePoint) {
690 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
691 "FailurePoint must be provided iff Type is Unknown");
697 case SCEVMonotonicityType::Unknown:
698 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
700 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
702 case SCEVMonotonicityType::Invariant:
705 case SCEVMonotonicityType::MultivariateSignedMonotonic:
706 OS <<
"MultivariateSignedMonotonic\n";
711bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
712 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
715SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
716 if (isLoopInvariant(Expr))
717 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
718 return createUnknown(Expr);
722SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
723 const Loop *OutermostLoop) {
725 "OutermostLoop must be outermost");
727 this->OutermostLoop = OutermostLoop;
743SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
745 return createUnknown(Expr);
750 SCEVMonotonicity StartMon =
visit(Start);
751 if (StartMon.isUnknown())
754 if (!isLoopInvariant(Step))
755 return createUnknown(Expr);
757 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
778 if (SameSDLevels > 0) {
779 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
786 if (!Assumptions.isAlwaysTrue()) {
787 OS <<
" Runtime Assumptions:\n";
788 Assumptions.print(OS, 2);
797 bool OnSameSD =
false;
798 unsigned LevelNum = Levels;
800 LevelNum += SameSDLevels;
802 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
873 return LI->isUnordered();
875 return SI->isUnordered();
883bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
884 const Loop *DstLoop)
const {
885 if (SrcLoop == DstLoop)
895 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
896 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
897 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
898 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
899 DstUP = SE->getBackedgeTakenCount(DstLoop);
901 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
902 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
903 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
904 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
975void DependenceInfo::establishNestingLevels(
const Instruction *Src,
977 const BasicBlock *SrcBlock = Src->getParent();
978 const BasicBlock *DstBlock = Dst->getParent();
979 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
980 unsigned DstLevel = LI->getLoopDepth(DstBlock);
981 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
982 const Loop *DstLoop = LI->getLoopFor(DstBlock);
983 SrcLevels = SrcLevel;
984 MaxLevels = SrcLevel + DstLevel;
986 while (SrcLevel > DstLevel) {
990 while (DstLevel > SrcLevel) {
996 while (SrcLoop != DstLoop) {
998 if (!haveSameSD(SrcLoop, DstLoop))
1004 CommonLevels = SrcLevel;
1005 MaxLevels -= CommonLevels;
1010unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1016unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1018 if (
D > CommonLevels)
1021 return D - CommonLevels + SrcLevels;
1048 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1060 return isLoopInvariant(Expr, LoopNest);
1067 const Loop *
L = LoopNest;
1068 while (L && AddRec->
getLoop() != L)
1069 L =
L->getParentLoop();
1075 if (!isLoopInvariant(Step, LoopNest))
1081 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1086bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1088 return checkSubscript(Src, LoopNest,
Loops,
true);
1093bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1095 return checkSubscript(Dst, LoopNest,
Loops,
false);
1101DependenceInfo::Subscript::ClassificationKind
1102DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1103 const SCEV *Dst,
const Loop *DstLoopNest,
1105 SmallBitVector SrcLoops(MaxLevels + 1);
1106 SmallBitVector DstLoops(MaxLevels + 1);
1107 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1108 return Subscript::NonLinear;
1109 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1110 return Subscript::NonLinear;
1113 unsigned N =
Loops.count();
1115 return Subscript::ZIV;
1117 return Subscript::SIV;
1118 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
1119 return Subscript::RDIV;
1120 return Subscript::MIV;
1130const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1131 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1132 const SCEV *UB = SE->getBackedgeTakenCount(L);
1133 return SE->getTruncateOrZeroExtend(UB,
T);
1140const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1142 if (
const SCEV *UB = collectUpperBound(L,
T))
1173bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1221 bool UnderRuntimeAssumptions) {
1225 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1228 const SCEV *Coeff = Src->getStepRecurrence(*SE);
1229 assert(Coeff == Dst->getStepRecurrence(*SE) &&
1230 "Expecting same coefficient in Strong SIV test");
1231 const SCEV *SrcConst = Src->getStart();
1232 const SCEV *DstConst = Dst->getStart();
1240 ++StrongSIVapplications;
1241 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1245 ConstantRange SrcRange = SE->getSignedRange(Src);
1246 ConstantRange DstRange = SE->getSignedRange(Dst);
1248 ++StrongSIVindependence;
1249 ++StrongSIVsuccesses;
1263 APInt Distance = ConstDelta;
1264 APInt Remainder = ConstDelta;
1269 if (Remainder != 0) {
1271 ++StrongSIVindependence;
1272 ++StrongSIVsuccesses;
1275 Result.DV[
Level].Distance = SE->getConstant(Distance);
1276 if (Distance.
sgt(0))
1278 else if (Distance.
slt(0))
1282 ++StrongSIVsuccesses;
1283 }
else if (Delta->
isZero()) {
1287 if (SE->isKnownNonZero(Coeff)) {
1289 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1292 if (UnderRuntimeAssumptions) {
1293 const SCEVPredicate *Pred = SE->getComparePredicate(
1295 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1301 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1302 <<
" != 0, but not allowed. Failing this test.\n");
1309 ++StrongSIVsuccesses;
1311 if (Coeff->
isOne()) {
1317 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1318 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1319 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1320 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1321 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1326 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1327 (DeltaMaybeNegative && CoeffMaybeNegative))
1331 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1332 (DeltaMaybePositive && CoeffMaybeNegative))
1334 if (NewDirection <
Result.DV[Level].Direction)
1335 ++StrongSIVsuccesses;
1369bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1370 const SCEV *SrcConst,
1371 const SCEV *DstConst,
1372 const Loop *CurSrcLoop,
1373 const Loop *CurDstLoop,
unsigned Level,
1382 ++WeakCrossingSIVapplications;
1383 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1385 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1388 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1389 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1390 ++WeakCrossingSIVsuccesses;
1391 if (!
Result.DV[Level].Direction) {
1392 ++WeakCrossingSIVindependence;
1402 if (SE->isKnownNegative(ConstCoeff)) {
1405 "dynamic cast of negative of ConstCoeff should yield constant");
1406 Delta = SE->getNegativeSCEV(Delta);
1408 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1418 if (SE->isKnownNegative(Delta)) {
1420 ++WeakCrossingSIVindependence;
1421 ++WeakCrossingSIVsuccesses;
1427 if (
const SCEV *UpperBound =
1428 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1430 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1432 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1436 ++WeakCrossingSIVindependence;
1437 ++WeakCrossingSIVsuccesses;
1442 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1443 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1444 ++WeakCrossingSIVsuccesses;
1445 if (!
Result.DV[Level].Direction) {
1446 ++WeakCrossingSIVindependence;
1455 APInt APDelta = ConstDelta->
getAPInt();
1456 APInt APCoeff = ConstCoeff->
getAPInt();
1457 APInt Distance = APDelta;
1458 APInt Remainder = APDelta;
1461 if (Remainder != 0) {
1463 ++WeakCrossingSIVindependence;
1464 ++WeakCrossingSIVsuccesses;
1470 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1471 Remainder = Distance.
srem(Two);
1473 if (Remainder != 0) {
1475 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1476 ++WeakCrossingSIVsuccesses;
1496 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1497 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1505 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1506 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1513 X = AM.
slt(0) ? -A1 : A1;
1514 Y = BM.
slt(0) ? B1 : -B1;
1524static OverflowSafeSignedAPInt
1526 const OverflowSafeSignedAPInt &OB) {
1528 return OverflowSafeSignedAPInt();
1537 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1539 return OverflowSafeSignedAPInt(Q) - 1;
1542static OverflowSafeSignedAPInt
1544 const OverflowSafeSignedAPInt &OB) {
1546 return OverflowSafeSignedAPInt();
1555 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1556 return OverflowSafeSignedAPInt(Q) + 1;
1589static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1591 OverflowSafeSignedAPInt UB) {
1592 assert(
A &&
B &&
"A and B must be available");
1593 assert(*
A != 0 &&
"A must be non-zero");
1594 OverflowSafeSignedAPInt TL, TU;
1597 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1601 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1604 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1608 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1610 return std::make_pair(TL, TU);
1632bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1633 const SCEV *SrcConst,
const SCEV *DstConst,
1634 const Loop *CurSrcLoop,
1635 const Loop *CurDstLoop,
unsigned Level,
1641 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1642 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1645 ++ExactSIVapplications;
1646 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1655 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1660 APInt AM = ConstSrcCoeff->
getAPInt();
1661 APInt BM = ConstDstCoeff->
getAPInt();
1666 ++ExactSIVindependence;
1667 ++ExactSIVsuccesses;
1674 std::optional<APInt> UM;
1676 if (
const SCEVConstant *CUB =
1677 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1678 UM = CUB->getAPInt();
1684 APInt TC = CM.
sdiv(
G);
1706 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1707 const OverflowSafeSignedAPInt &V1,
1708 bool IsMin) -> std::optional<APInt> {
1715 return std::nullopt;
1721 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1722 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1723 if (!OptTL || !OptTU)
1726 TL = std::move(*OptTL);
1727 TU = std::move(*OptTU);
1732 ++ExactSIVindependence;
1733 ++ExactSIVsuccesses;
1739 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1740 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1744 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1745 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1747 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1748 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1751 if (!LowerDistance || !UpperDistance)
1754 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1755 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1757 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1759 ++ExactSIVsuccesses;
1761 if (LowerDistance->slt(0)) {
1763 ++ExactSIVsuccesses;
1765 if (UpperDistance->sgt(0)) {
1767 ++ExactSIVsuccesses;
1773 ++ExactSIVindependence;
1784 return ConstDividend.
srem(ConstDivisor) == 0;
1816bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1817 const SCEV *SrcConst,
1818 const SCEV *DstConst,
1819 const Loop *CurSrcLoop,
1820 const Loop *CurDstLoop,
unsigned Level,
1832 ++WeakZeroSIVapplications;
1833 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1835 if (SrcConst == DstConst && SE->isKnownNonZero(DstCoeff)) {
1836 if (Level < CommonLevels) {
1838 ++WeakZeroSIVsuccesses;
1852 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1853 ? SE->getNegativeSCEV(ConstCoeff)
1855 const SCEV *NewDelta =
1856 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1860 if (
const SCEV *UpperBound =
1861 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1863 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1865 ++WeakZeroSIVindependence;
1866 ++WeakZeroSIVsuccesses;
1871 if (Level < CommonLevels) {
1873 ++WeakZeroSIVsuccesses;
1881 if (SE->isKnownNegative(NewDelta)) {
1883 ++WeakZeroSIVindependence;
1884 ++WeakZeroSIVsuccesses;
1891 ++WeakZeroSIVindependence;
1892 ++WeakZeroSIVsuccesses;
1927bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1928 const SCEV *SrcConst,
1929 const SCEV *DstConst,
1930 const Loop *CurSrcLoop,
1931 const Loop *CurDstLoop,
unsigned Level,
1942 ++WeakZeroSIVapplications;
1943 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1945 if (DstConst == SrcConst && SE->isKnownNonZero(SrcCoeff)) {
1946 if (Level < CommonLevels) {
1948 ++WeakZeroSIVsuccesses;
1962 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1963 ? SE->getNegativeSCEV(ConstCoeff)
1965 const SCEV *NewDelta =
1966 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1970 if (
const SCEV *UpperBound =
1971 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1973 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1975 ++WeakZeroSIVindependence;
1976 ++WeakZeroSIVsuccesses;
1981 if (Level < CommonLevels) {
1983 ++WeakZeroSIVsuccesses;
1991 if (SE->isKnownNegative(NewDelta)) {
1993 ++WeakZeroSIVindependence;
1994 ++WeakZeroSIVsuccesses;
2001 ++WeakZeroSIVindependence;
2002 ++WeakZeroSIVsuccesses;
2014bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2015 const SCEV *SrcConst,
const SCEV *DstConst,
2016 const Loop *SrcLoop,
const Loop *DstLoop,
2022 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2023 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2026 ++ExactRDIVapplications;
2027 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2032 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2037 APInt AM = ConstSrcCoeff->
getAPInt();
2038 APInt BM = ConstDstCoeff->
getAPInt();
2043 ++ExactRDIVindependence;
2050 std::optional<APInt> SrcUM;
2052 if (
const SCEVConstant *UpperBound =
2053 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2054 SrcUM = UpperBound->getAPInt();
2058 std::optional<APInt> DstUM;
2060 if (
const SCEVConstant *UpperBound =
2061 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2062 DstUM = UpperBound->getAPInt();
2068 APInt TC = CM.
sdiv(
G);
2093 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
2094 const OverflowSafeSignedAPInt &V1,
2095 bool IsMin) -> std::optional<APInt> {
2102 return std::nullopt;
2105 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
2106 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
2107 if (!OptTL || !OptTU)
2110 TL = std::move(*OptTL);
2111 TU = std::move(*OptTU);
2116 ++ExactRDIVindependence;
2162bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2165 const Loop *Loop2)
const {
2169 ++SymbolicRDIVapplications;
2176 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2177 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2180 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2181 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2184 if (SE->isKnownNonNegative(A1)) {
2185 if (SE->isKnownNonNegative(A2)) {
2189 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2192 ++SymbolicRDIVindependence;
2198 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2201 ++SymbolicRDIVindependence;
2205 }
else if (SE->isKnownNonPositive(A2)) {
2209 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2210 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2211 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2212 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2214 ++SymbolicRDIVindependence;
2219 if (SE->isKnownNegative(C2_C1)) {
2220 ++SymbolicRDIVindependence;
2224 }
else if (SE->isKnownNonPositive(A1)) {
2225 if (SE->isKnownNonNegative(A2)) {
2229 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2230 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2231 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2232 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2234 ++SymbolicRDIVindependence;
2239 if (SE->isKnownPositive(C2_C1)) {
2240 ++SymbolicRDIVindependence;
2243 }
else if (SE->isKnownNonPositive(A2)) {
2247 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2250 ++SymbolicRDIVindependence;
2256 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2259 ++SymbolicRDIVindependence;
2276bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2278 bool UnderRuntimeAssumptions) {
2283 if (SrcAddRec && DstAddRec) {
2284 const SCEV *SrcConst = SrcAddRec->
getStart();
2285 const SCEV *DstConst = DstAddRec->
getStart();
2288 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2289 const Loop *CurDstLoop = DstAddRec->
getLoop();
2290 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2291 "Loops in the SIV test should have the same iteration space and "
2293 Level = mapSrcLoop(CurSrcLoop);
2295 if (SrcCoeff == DstCoeff)
2296 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
2297 UnderRuntimeAssumptions);
2298 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2299 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2300 CurDstLoop, Level, Result);
2302 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2303 CurSrcLoop, CurDstLoop, Level, Result);
2304 return disproven || gcdMIVtest(Src, Dst, Result) ||
2305 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2309 const SCEV *SrcConst = SrcAddRec->
getStart();
2311 const SCEV *DstConst = Dst;
2312 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2313 Level = mapSrcLoop(CurSrcLoop);
2314 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2315 CurSrcLoop, Level, Result) ||
2316 gcdMIVtest(Src, Dst, Result);
2319 const SCEV *DstConst = DstAddRec->
getStart();
2321 const SCEV *SrcConst = Src;
2322 const Loop *CurDstLoop = DstAddRec->
getLoop();
2323 Level = mapDstLoop(CurDstLoop);
2324 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2325 CurDstLoop, Level, Result) ||
2326 gcdMIVtest(Src, Dst, Result);
2342bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2344 const SCEV *SrcConst, *DstConst;
2345 const SCEV *SrcCoeff, *DstCoeff;
2346 const Loop *SrcLoop, *DstLoop;
2352 if (SrcAddRec && DstAddRec) {
2355 SrcLoop = SrcAddRec->
getLoop();
2358 DstLoop = DstAddRec->
getLoop();
2361 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2363 gcdMIVtest(Src, Dst, Result) ||
2364 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2371bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2376 return gcdMIVtest(Src, Dst, Result) ||
2377 banerjeeMIVtest(Src, Dst,
Loops, Result);
2390 if (Product->hasNoSignedWrap())
2392 return std::nullopt;
2395bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2396 const Loop *CurLoop,
2397 const SCEV *&CurLoopCoeff,
2398 APInt &RunningGCD)
const {
2401 if (RunningGCD == 1)
2406 assert(isLoopInvariant(Expr, CurLoop) &&
2407 "Expected loop invariant expression");
2414 if (AddRec->
getLoop() == CurLoop) {
2415 CurLoopCoeff = Step;
2429 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2449bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2456 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2463 const SCEV *Coefficients = Src;
2464 while (
const SCEVAddRecExpr *AddRec =
2475 const SCEV *SrcConst = Coefficients;
2482 while (
const SCEVAddRecExpr *AddRec =
2493 const SCEV *DstConst = Coefficients;
2505 if (ConstDelta == 0)
2508 APInt Remainder = ConstDelta.
srem(RunningGCD);
2509 if (Remainder != 0) {
2528 bool Improved =
false;
2530 while (
const SCEVAddRecExpr *AddRec =
2533 const Loop *CurLoop = AddRec->
getLoop();
2534 RunningGCD = ExtraGCD;
2536 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2538 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2539 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2542 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2552 if (RunningGCD != 0) {
2553 Remainder = ConstDelta.
srem(RunningGCD);
2555 if (Remainder != 0) {
2556 unsigned Level = mapSrcLoop(CurLoop);
2557 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2601bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2608 ++BanerjeeApplications;
2611 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2614 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2615 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2616 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2621 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2622 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2625 findBoundsALL(
A,
B, Bound, K);
2640 bool Disproved =
false;
2643 unsigned DepthExpanded = 0;
2645 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2647 bool Improved =
false;
2648 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2650 unsigned Old =
Result.DV[
K - 1].Direction;
2651 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2652 Improved |= Old !=
Result.DV[
K - 1].Direction;
2653 if (!
Result.DV[K - 1].Direction) {
2661 ++BanerjeeSuccesses;
2663 ++BanerjeeIndependence;
2667 ++BanerjeeIndependence;
2681unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2682 CoefficientInfo *
B, BoundInfo *Bound,
2684 unsigned &DepthExpanded,
2685 const SCEV *Delta)
const {
2691 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2692 "direction exploration is terminated.\n");
2693 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2699 if (Level > CommonLevels) {
2702 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2704 Bound[
K].DirSet |= Bound[
K].Direction;
2729 if (Level > DepthExpanded) {
2730 DepthExpanded =
Level;
2732 findBoundsLT(
A,
B, Bound, Level);
2733 findBoundsGT(
A,
B, Bound, Level);
2734 findBoundsEQ(
A,
B, Bound, Level);
2773 unsigned NewDeps = 0;
2777 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2782 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2787 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2793 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2798bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2799 BoundInfo *Bound,
const SCEV *Delta)
const {
2800 Bound[
Level].Direction = DirKind;
2801 if (
const SCEV *LowerBound = getLowerBound(Bound))
2804 if (
const SCEV *UpperBound = getUpperBound(Bound))
2825void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2826 BoundInfo *Bound,
unsigned K)
const {
2831 if (Bound[K].Iterations) {
2833 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2835 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2840 SE->getZero(
A[K].Coeff->
getType());
2843 SE->getZero(
A[K].Coeff->
getType());
2862void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2863 BoundInfo *Bound,
unsigned K)
const {
2868 if (Bound[K].Iterations) {
2869 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2870 const SCEV *NegativePart = getNegativePart(Delta);
2872 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2873 const SCEV *PositivePart = getPositivePart(Delta);
2875 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2879 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2880 const SCEV *NegativePart = getNegativePart(Delta);
2881 if (NegativePart->
isZero())
2883 const SCEV *PositivePart = getPositivePart(Delta);
2884 if (PositivePart->
isZero())
2902void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2903 BoundInfo *Bound,
unsigned K)
const {
2908 if (Bound[K].Iterations) {
2909 const SCEV *Iter_1 = SE->getMinusSCEV(
2910 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2911 const SCEV *NegPart =
2912 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2914 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2915 const SCEV *PosPart =
2916 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2918 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2922 const SCEV *NegPart =
2923 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2926 const SCEV *PosPart =
2927 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2946void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2947 BoundInfo *Bound,
unsigned K)
const {
2952 if (Bound[K].Iterations) {
2953 const SCEV *Iter_1 = SE->getMinusSCEV(
2954 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2955 const SCEV *NegPart =
2956 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2958 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2959 const SCEV *PosPart =
2960 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2962 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2966 const SCEV *NegPart =
2967 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2970 const SCEV *PosPart =
2971 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2978const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2979 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2983const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2984 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2990DependenceInfo::CoefficientInfo *
2991DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
2993 const SCEV *
Zero = SE->getZero(Subscript->getType());
2994 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
2995 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2997 CI[
K].PosPart =
Zero;
2998 CI[
K].NegPart =
Zero;
2999 CI[
K].Iterations =
nullptr;
3003 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3005 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3006 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3007 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3013 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3020 if (CI[K].Iterations)
3035const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3036 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3037 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3050const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3051 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3052 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3071 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3072 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3073 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3074 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3075 const SCEVUnknown *SrcBase =
3077 const SCEVUnknown *DstBase =
3080 if (!SrcBase || !DstBase || SrcBase != DstBase)
3085 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3086 SrcSubscripts, DstSubscripts) &&
3087 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3088 SrcSubscripts, DstSubscripts))
3091 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3092 isLoopInvariant(DstBase, DstLoop) &&
3093 "Expected SrcBase and DstBase to be loop invariant");
3097 dbgs() <<
"\nSrcSubscripts: ";
3098 for (
int I = 0;
I <
Size;
I++)
3099 dbgs() << *SrcSubscripts[
I];
3100 dbgs() <<
"\nDstSubscripts: ";
3101 for (
int I = 0;
I <
Size;
I++)
3102 dbgs() << *DstSubscripts[
I];
3111 SCEVMonotonicityChecker MonChecker(SE);
3112 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3113 for (
int I = 0;
I <
Size; ++
I) {
3114 Pair[
I].Src = SrcSubscripts[
I];
3115 Pair[
I].Dst = DstSubscripts[
I];
3117 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
3118 "Unexpected different types for the subscripts");
3121 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3123 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3134bool DependenceInfo::tryDelinearizeFixedSize(
3139 const SCEVUnknown *SrcBase =
3141 const SCEVUnknown *DstBase =
3143 assert(SrcBase && DstBase && SrcBase == DstBase &&
3144 "expected src and dst scev unknowns to be equal");
3147 const SCEV *ElemSize = SE->getElementSize(Src);
3148 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3151 SrcSubscripts, SrcSizes, ElemSize) ||
3153 DstSubscripts, DstSizes, ElemSize))
3158 if (SrcSizes.
size() != DstSizes.
size() ||
3159 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3160 SrcSubscripts.
clear();
3161 DstSubscripts.
clear();
3166 "Expected equal number of entries in the list of SrcSubscripts and "
3178 SrcSubscripts.
clear();
3179 DstSubscripts.
clear();
3184 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3191bool DependenceInfo::tryDelinearizeParametricSize(
3196 const SCEVUnknown *SrcBase =
3198 const SCEVUnknown *DstBase =
3200 assert(SrcBase && DstBase && SrcBase == DstBase &&
3201 "expected src and dst scev unknowns to be equal");
3203 const SCEV *ElementSize = SE->getElementSize(Src);
3204 if (ElementSize != SE->getElementSize(Dst))
3207 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3208 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3229 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3230 SrcSubscripts.
size() != DstSubscripts.
size())
3253 for (
unsigned VI : BV.
set_bits()) {
3263 FunctionAnalysisManager::Invalidator &Inv) {
3270 return Inv.invalidate<
AAManager>(F, PA) ||
3284std::unique_ptr<Dependence>
3286 bool UnderRuntimeAssumptions) {
3288 bool PossiblyLoopIndependent =
true;
3290 PossiblyLoopIndependent =
false;
3292 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3298 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3299 return std::make_unique<Dependence>(Src, Dst,
3311 return std::make_unique<Dependence>(Src, Dst,
3325 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3326 return std::make_unique<Dependence>(Src, Dst,
3332 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3333 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3336 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3337 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3338 if (SrcBase != DstBase) {
3345 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3346 return std::make_unique<Dependence>(Src, Dst,
3354 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3355 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3356 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3357 !isLoopInvariant(DstBase, DstLoop)) {
3358 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3359 return std::make_unique<Dependence>(Src, Dst,
3364 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3365 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3368 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3369 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3370 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3371 return std::make_unique<Dependence>(Src, Dst,
3376 if (!Assume.empty() && !UnderRuntimeAssumptions)
3377 return std::make_unique<Dependence>(Src, Dst,
3382 Pair[0].Src = SrcEv;
3383 Pair[0].Dst = DstEv;
3385 SCEVMonotonicityChecker MonChecker(SE);
3388 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3389 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3390 return std::make_unique<Dependence>(Src, Dst,
3394 if (tryDelinearize(Src, Dst, Pair)) {
3396 Pairs = Pair.
size();
3401 establishNestingLevels(Src, Dst);
3403 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3404 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3405 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3408 CommonLevels += SameSDLevels;
3409 MaxLevels -= SameSDLevels;
3410 if (SameSDLevels > 0) {
3413 for (
unsigned P = 0;
P < Pairs; ++
P) {
3415 Subscript::ClassificationKind TestClass =
3416 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3417 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3419 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3420 TestClass != Subscript::RDIV) {
3422 CommonLevels -= SameSDLevels;
3423 MaxLevels += SameSDLevels;
3430 if (SameSDLevels > 0)
3434 PossiblyLoopIndependent, CommonLevels);
3437 for (
unsigned P = 0;
P < Pairs; ++
P) {
3438 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3439 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3440 Pair[
P].Loops.
resize(MaxLevels + 1);
3441 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3443 Pair[
P].Classification =
3444 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3445 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3446 Pair[
P].GroupLoops = Pair[
P].Loops;
3447 Pair[
P].Group.set(
P);
3457 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3459 switch (Pair[
SI].Classification) {
3460 case Subscript::NonLinear:
3462 ++NonlinearSubscriptPairs;
3463 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3465 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3468 case Subscript::ZIV:
3470 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3473 case Subscript::SIV: {
3476 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3477 UnderRuntimeAssumptions))
3481 case Subscript::RDIV:
3483 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3486 case Subscript::MIV:
3488 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3496 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3497 CompleteLoops |= Pair[
SI].
Loops;
3498 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3499 if (CompleteLoops[
II])
3500 Result.DV[
II - 1].Scalar =
false;
3505 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3507 if (Result.DV[
II - 1].Distance ==
nullptr)
3508 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3510 assert(Result.DV[
II - 1].Distance->isZero() &&
3511 "Inconsistency between distance and direction");
3517 const SCEV *Distance = Result.getDistance(
II);
3518 if (Distance && Distance->
isZero())
3520 "Distance is zero, but direction is not EQ");
3524 if (SameSDLevels > 0) {
3527 assert(CommonLevels >= SameSDLevels);
3528 CommonLevels -= SameSDLevels;
3529 MaxLevels += SameSDLevels;
3530 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3531 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3532 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3533 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3534 DV[Level] = Result.DV[Level];
3535 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3536 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3537 Result.DV = std::move(DV);
3538 Result.DVSameSD = std::move(DVSameSD);
3539 Result.Levels = CommonLevels;
3540 Result.SameSDLevels = SameSDLevels;
3543 if (PossiblyLoopIndependent) {
3547 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3549 Result.LoopIndependent =
false;
3557 bool AllEqual =
true;
3558 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3564 if (AllEqual && Result.Assumptions.getPredicates().empty())
3568 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 bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
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 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()
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_SLT
signed less than
@ ICMP_SGT
signed greater than
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
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.
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.
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
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(const SCEV *LHS, const SCEV *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.
@ 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.