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;
628 for (
unsigned Level = 1; Level <= Levels; ++Level) {
629 unsigned char Direction = DV[Level - 1].Direction;
637 DV[Level - 1].Direction = RevDirection;
639 if (DV[Level - 1].Distance !=
nullptr)
648 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
651 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
681 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
682 "Level out of range");
683 return Level > Levels;
689SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
690 const SCEV *FailurePoint)
691 :
Type(
Type), FailurePoint(FailurePoint) {
693 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
694 "FailurePoint must be provided iff Type is Unknown");
700 case SCEVMonotonicityType::Unknown:
701 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
703 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
705 case SCEVMonotonicityType::Invariant:
708 case SCEVMonotonicityType::MultivariateSignedMonotonic:
709 OS <<
"MultivariateSignedMonotonic\n";
714bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
715 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
718SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
719 if (isLoopInvariant(Expr))
720 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
721 return createUnknown(Expr);
725SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
726 const Loop *OutermostLoop) {
728 "OutermostLoop must be outermost");
730 this->OutermostLoop = OutermostLoop;
746SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
748 return createUnknown(Expr);
753 SCEVMonotonicity StartMon =
visit(Start);
754 if (StartMon.isUnknown())
757 if (!isLoopInvariant(Step))
758 return createUnknown(Expr);
760 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
781 if (SameSDLevels > 0) {
782 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
789 if (!Assumptions.isAlwaysTrue()) {
790 OS <<
" Runtime Assumptions:\n";
791 Assumptions.print(OS, 2);
800 bool OnSameSD =
false;
801 unsigned LevelNum = Levels;
803 LevelNum += SameSDLevels;
805 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
876 return LI->isUnordered();
878 return SI->isUnordered();
886bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
887 const Loop *DstLoop)
const {
888 if (SrcLoop == DstLoop)
898 const SCEV *SrcUB = SE->getBackedgeTakenCount(SrcLoop);
899 const SCEV *DstUB = SE->getBackedgeTakenCount(DstLoop);
904 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
905 DstUB = SE->getNoopOrZeroExtend(DstUB, WiderType);
977void DependenceInfo::establishNestingLevels(
const Instruction *Src,
979 const BasicBlock *SrcBlock = Src->getParent();
980 const BasicBlock *DstBlock = Dst->getParent();
981 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
982 unsigned DstLevel = LI->getLoopDepth(DstBlock);
983 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
984 const Loop *DstLoop = LI->getLoopFor(DstBlock);
985 SrcLevels = SrcLevel;
986 MaxLevels = SrcLevel + DstLevel;
988 while (SrcLevel > DstLevel) {
992 while (DstLevel > SrcLevel) {
997 const Loop *SrcUncommonFrontier =
nullptr, *DstUncommonFrontier =
nullptr;
1000 while (SrcLoop != DstLoop) {
1001 SrcUncommonFrontier = SrcLoop;
1002 DstUncommonFrontier = DstLoop;
1007 if (SrcUncommonFrontier && DstUncommonFrontier &&
1008 haveSameSD(SrcUncommonFrontier, DstUncommonFrontier))
1010 CommonLevels = SrcLevel;
1011 MaxLevels -= CommonLevels;
1016unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1022unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1024 if (
D > CommonLevels)
1027 return D - CommonLevels + SrcLevels;
1054 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1066 return isLoopInvariant(Expr, LoopNest);
1073 const Loop *
L = LoopNest;
1074 while (L && AddRec->
getLoop() != L)
1075 L =
L->getParentLoop();
1081 if (!isLoopInvariant(Step, LoopNest))
1087 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1092bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1094 return checkSubscript(Src, LoopNest,
Loops,
true);
1099bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1101 return checkSubscript(Dst, LoopNest,
Loops,
false);
1107DependenceInfo::Subscript::ClassificationKind
1108DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1109 const SCEV *Dst,
const Loop *DstLoopNest,
1111 SmallBitVector SrcLoops(MaxLevels + 1);
1112 SmallBitVector DstLoops(MaxLevels + 1);
1113 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1114 return Subscript::NonLinear;
1115 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1116 return Subscript::NonLinear;
1119 unsigned N =
Loops.count();
1121 return Subscript::ZIV;
1123 return Subscript::SIV;
1124 if (
N == 2 && SrcLoops.count() == 1 && DstLoops.count() == 1)
1125 return Subscript::RDIV;
1126 return Subscript::MIV;
1136const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1137 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1138 const SCEV *UB = SE->getBackedgeTakenCount(L);
1139 return SE->getTruncateOrZeroExtend(UB,
T);
1146const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1148 if (
const SCEV *UB = collectUpperBound(L,
T))
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");
1251 ConstantRange SrcRange = SE->getSignedRange(Src);
1252 ConstantRange DstRange = SE->getSignedRange(Dst);
1254 ++StrongSIVindependence;
1255 ++StrongSIVsuccesses;
1269 APInt Distance = ConstDelta;
1270 APInt Remainder = ConstDelta;
1275 if (Remainder != 0) {
1277 ++StrongSIVindependence;
1278 ++StrongSIVsuccesses;
1281 Result.DV[
Level].Distance = SE->getConstant(Distance);
1282 if (Distance.
sgt(0))
1284 else if (Distance.
slt(0))
1288 ++StrongSIVsuccesses;
1289 }
else if (Delta->
isZero()) {
1293 if (SE->isKnownNonZero(Coeff)) {
1295 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1298 if (UnderRuntimeAssumptions) {
1299 const SCEVPredicate *Pred = SE->getComparePredicate(
1301 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1307 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1308 <<
" != 0, but not allowed. Failing this test.\n");
1315 ++StrongSIVsuccesses;
1317 if (Coeff->
isOne()) {
1323 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1324 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1325 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1326 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1327 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1332 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1333 (DeltaMaybeNegative && CoeffMaybeNegative))
1337 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1338 (DeltaMaybePositive && CoeffMaybeNegative))
1340 if (NewDirection <
Result.DV[Level].Direction)
1341 ++StrongSIVsuccesses;
1375bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1376 const SCEV *SrcConst,
1377 const SCEV *DstConst,
1378 const Loop *CurSrcLoop,
1379 const Loop *CurDstLoop,
unsigned Level,
1388 ++WeakCrossingSIVapplications;
1389 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1391 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1394 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1395 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1396 ++WeakCrossingSIVsuccesses;
1397 if (!
Result.DV[Level].Direction) {
1398 ++WeakCrossingSIVindependence;
1408 if (SE->isKnownNegative(ConstCoeff)) {
1411 "dynamic cast of negative of ConstCoeff should yield constant");
1412 Delta = SE->getNegativeSCEV(Delta);
1414 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1424 if (SE->isKnownNegative(Delta)) {
1426 ++WeakCrossingSIVindependence;
1427 ++WeakCrossingSIVsuccesses;
1433 if (
const SCEV *UpperBound =
1434 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1436 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1438 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1442 ++WeakCrossingSIVindependence;
1443 ++WeakCrossingSIVsuccesses;
1448 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1449 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1450 ++WeakCrossingSIVsuccesses;
1451 if (!
Result.DV[Level].Direction) {
1452 ++WeakCrossingSIVindependence;
1461 APInt APDelta = ConstDelta->
getAPInt();
1462 APInt APCoeff = ConstCoeff->
getAPInt();
1463 APInt Distance = APDelta;
1464 APInt Remainder = APDelta;
1467 if (Remainder != 0) {
1469 ++WeakCrossingSIVindependence;
1470 ++WeakCrossingSIVsuccesses;
1476 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1477 Remainder = Distance.
srem(Two);
1479 if (Remainder != 0) {
1481 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1482 ++WeakCrossingSIVsuccesses;
1502 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1503 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1511 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1512 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1519 X = AM.
slt(0) ? -A1 : A1;
1520 Y = BM.
slt(0) ? B1 : -B1;
1530static OverflowSafeSignedAPInt
1532 const OverflowSafeSignedAPInt &OB) {
1534 return OverflowSafeSignedAPInt();
1543 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1545 return OverflowSafeSignedAPInt(Q) - 1;
1548static OverflowSafeSignedAPInt
1550 const OverflowSafeSignedAPInt &OB) {
1552 return OverflowSafeSignedAPInt();
1561 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1562 return OverflowSafeSignedAPInt(Q) + 1;
1595static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1597 OverflowSafeSignedAPInt UB) {
1598 assert(
A &&
B &&
"A and B must be available");
1599 assert(*
A != 0 &&
"A must be non-zero");
1600 OverflowSafeSignedAPInt TL, TU;
1603 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1607 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1610 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1614 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1616 return std::make_pair(TL, TU);
1644 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1645 const SCEV *SrcConst = Src->getStart();
1646 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1647 const SCEV *DstConst = Dst->getStart();
1649 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1650 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1653 ++ExactSIVapplications;
1654 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1657 if (!Src->hasNoSignedWrap() || !Dst->hasNoSignedWrap())
1667 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1672 APInt AM = ConstSrcCoeff->
getAPInt();
1673 APInt BM = ConstDstCoeff->
getAPInt();
1678 ++ExactSIVindependence;
1679 ++ExactSIVsuccesses;
1686 std::optional<APInt> UM;
1688 if (
const SCEVConstant *CUB =
1689 collectConstantUpperBound(Src->getLoop(), Delta->
getType())) {
1690 UM = CUB->getAPInt();
1696 APInt TC = CM.
sdiv(
G);
1718 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
1719 const OverflowSafeSignedAPInt &V1,
1720 bool IsMin) -> std::optional<APInt> {
1727 return std::nullopt;
1733 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
1734 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
1735 if (!OptTL || !OptTU)
1738 TL = std::move(*OptTL);
1739 TU = std::move(*OptTU);
1744 ++ExactSIVindependence;
1745 ++ExactSIVsuccesses;
1751 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1752 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1756 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1757 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1759 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1760 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1763 if (!LowerDistance || !UpperDistance)
1766 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1767 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1769 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1771 ++ExactSIVsuccesses;
1773 if (LowerDistance->slt(0)) {
1775 ++ExactSIVsuccesses;
1777 if (UpperDistance->sgt(0)) {
1779 ++ExactSIVsuccesses;
1785 ++ExactSIVindependence;
1796 return ConstDividend.
srem(ConstDivisor) == 0;
1828bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *SrcConst,
1838 const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
1839 const SCEV *DstConst = Dst->getStart();
1844 ++WeakZeroSIVapplications;
1845 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1848 ConstantRange SrcRange = SE->getSignedRange(SrcConst);
1849 ConstantRange DstRange = SE->getSignedRange(Dst);
1851 ++WeakZeroSIVindependence;
1852 ++WeakZeroSIVsuccesses;
1856 if (SrcConst == DstConst && SE->isKnownNonZero(DstCoeff)) {
1857 if (Level < CommonLevels) {
1859 ++WeakZeroSIVsuccesses;
1873 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1874 ? SE->getNegativeSCEV(ConstCoeff)
1876 const SCEV *NewDelta =
1877 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1879 if (
const SCEV *UpperBound =
1880 collectUpperBound(Dst->getLoop(), Delta->
getType())) {
1882 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1885 if (Level < CommonLevels) {
1887 ++WeakZeroSIVsuccesses;
1895 if (SE->isKnownNegative(NewDelta)) {
1897 ++WeakZeroSIVindependence;
1898 ++WeakZeroSIVsuccesses;
1905 ++WeakZeroSIVindependence;
1906 ++WeakZeroSIVsuccesses;
1941bool DependenceInfo::weakZeroDstSIVtest(
const SCEVAddRecExpr *Src,
1942 const SCEV *DstConst,
unsigned Level,
1949 const SCEV *SrcCoeff = Src->getStepRecurrence(*SE);
1950 const SCEV *SrcConst = Src->getStart();
1955 ++WeakZeroSIVapplications;
1956 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1959 ConstantRange SrcRange = SE->getSignedRange(Src);
1960 ConstantRange DstRange = SE->getSignedRange(DstConst);
1962 ++WeakZeroSIVindependence;
1963 ++WeakZeroSIVsuccesses;
1967 if (DstConst == SrcConst && SE->isKnownNonZero(SrcCoeff)) {
1968 if (Level < CommonLevels) {
1970 ++WeakZeroSIVsuccesses;
1984 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1985 ? SE->getNegativeSCEV(ConstCoeff)
1987 const SCEV *NewDelta =
1988 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1990 if (
const SCEV *UpperBound =
1991 collectUpperBound(Src->getLoop(), Delta->
getType())) {
1993 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1996 if (Level < CommonLevels) {
1998 ++WeakZeroSIVsuccesses;
2006 if (SE->isKnownNegative(NewDelta)) {
2008 ++WeakZeroSIVindependence;
2009 ++WeakZeroSIVsuccesses;
2016 ++WeakZeroSIVindependence;
2017 ++WeakZeroSIVsuccesses;
2029bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2030 const SCEV *SrcConst,
const SCEV *DstConst,
2031 const Loop *SrcLoop,
const Loop *DstLoop,
2037 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2038 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2041 ++ExactRDIVapplications;
2042 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2047 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2052 APInt AM = ConstSrcCoeff->
getAPInt();
2053 APInt BM = ConstDstCoeff->
getAPInt();
2058 ++ExactRDIVindependence;
2065 std::optional<APInt> SrcUM;
2067 if (
const SCEVConstant *UpperBound =
2068 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2069 SrcUM = UpperBound->getAPInt();
2073 std::optional<APInt> DstUM;
2075 if (
const SCEVConstant *UpperBound =
2076 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2077 DstUM = UpperBound->getAPInt();
2083 APInt TC = CM.
sdiv(
G);
2108 auto GetMaxOrMin = [](
const OverflowSafeSignedAPInt &V0,
2109 const OverflowSafeSignedAPInt &V1,
2110 bool IsMin) -> std::optional<APInt> {
2117 return std::nullopt;
2120 std::optional<APInt> OptTL = GetMaxOrMin(TL0, TL1,
false);
2121 std::optional<APInt> OptTU = GetMaxOrMin(TU0, TU1,
true);
2122 if (!OptTL || !OptTU)
2125 TL = std::move(*OptTL);
2126 TU = std::move(*OptTU);
2131 ++ExactRDIVindependence;
2182 ++SymbolicRDIVapplications;
2184 ConstantRange SrcRange = SE->getSignedRange(Src);
2185 ConstantRange DstRange = SE->getSignedRange(Dst);
2189 ++SymbolicRDIVindependence;
2203bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2205 bool UnderRuntimeAssumptions) {
2210 if (SrcAddRec && DstAddRec) {
2211 const SCEV *SrcConst = SrcAddRec->
getStart();
2212 const SCEV *DstConst = DstAddRec->
getStart();
2215 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2216 const Loop *CurDstLoop = DstAddRec->
getLoop();
2217 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2218 "Loops in the SIV test should have the same iteration space and "
2220 Level = mapSrcLoop(CurSrcLoop);
2222 if (SrcCoeff == DstCoeff)
2223 disproven = strongSIVtest(SrcAddRec, DstAddRec, Level, Result,
2224 UnderRuntimeAssumptions);
2225 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2226 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2227 CurDstLoop, Level, Result);
2229 disproven = exactSIVtest(SrcAddRec, DstAddRec, Level, Result);
2230 return disproven || gcdMIVtest(Src, Dst, Result) ||
2231 symbolicRDIVtest(SrcAddRec, DstAddRec);
2234 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2235 Level = mapSrcLoop(CurSrcLoop);
2236 return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result) ||
2237 gcdMIVtest(Src, Dst, Result);
2240 const Loop *CurDstLoop = DstAddRec->
getLoop();
2241 Level = mapDstLoop(CurDstLoop);
2242 return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result) ||
2243 gcdMIVtest(Src, Dst, Result);
2259bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2261 const SCEV *SrcConst, *DstConst;
2262 const SCEV *SrcCoeff, *DstCoeff;
2263 const Loop *SrcLoop, *DstLoop;
2269 if (SrcAddRec && DstAddRec) {
2272 SrcLoop = SrcAddRec->
getLoop();
2275 DstLoop = DstAddRec->
getLoop();
2278 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2280 gcdMIVtest(Src, Dst, Result) || symbolicRDIVtest(SrcAddRec, DstAddRec);
2286bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2291 return gcdMIVtest(Src, Dst, Result) ||
2292 banerjeeMIVtest(Src, Dst,
Loops, Result);
2305 if (Product->hasNoSignedWrap())
2307 return std::nullopt;
2310bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2311 const Loop *CurLoop,
2312 const SCEV *&CurLoopCoeff,
2313 APInt &RunningGCD)
const {
2316 if (RunningGCD == 1)
2321 assert(isLoopInvariant(Expr, CurLoop) &&
2322 "Expected loop invariant expression");
2329 if (AddRec->
getLoop() == CurLoop) {
2330 CurLoopCoeff = Step;
2344 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2364bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2371 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2378 const SCEV *Coefficients = Src;
2379 while (
const SCEVAddRecExpr *AddRec =
2390 const SCEV *SrcConst = Coefficients;
2397 while (
const SCEVAddRecExpr *AddRec =
2408 const SCEV *DstConst = Coefficients;
2420 if (ConstDelta == 0)
2423 APInt Remainder = ConstDelta.
srem(RunningGCD);
2424 if (Remainder != 0) {
2443 bool Improved =
false;
2445 while (
const SCEVAddRecExpr *AddRec =
2448 const Loop *CurLoop = AddRec->
getLoop();
2449 RunningGCD = ExtraGCD;
2451 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2453 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2454 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2457 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2467 if (RunningGCD != 0) {
2468 Remainder = ConstDelta.
srem(RunningGCD);
2470 if (Remainder != 0) {
2471 unsigned Level = mapSrcLoop(CurLoop);
2472 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2516bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2523 ++BanerjeeApplications;
2526 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2529 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2530 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2531 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2536 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2537 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2540 findBoundsALL(
A,
B, Bound, K);
2555 bool Disproved =
false;
2558 unsigned DepthExpanded = 0;
2560 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2562 bool Improved =
false;
2563 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2565 unsigned Old =
Result.DV[
K - 1].Direction;
2566 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2567 Improved |= Old !=
Result.DV[
K - 1].Direction;
2568 if (!
Result.DV[K - 1].Direction) {
2576 ++BanerjeeSuccesses;
2578 ++BanerjeeIndependence;
2582 ++BanerjeeIndependence;
2596unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2597 CoefficientInfo *
B, BoundInfo *Bound,
2599 unsigned &DepthExpanded,
2600 const SCEV *Delta)
const {
2606 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2607 "direction exploration is terminated.\n");
2608 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2614 if (Level > CommonLevels) {
2617 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2619 Bound[
K].DirSet |= Bound[
K].Direction;
2644 if (Level > DepthExpanded) {
2645 DepthExpanded =
Level;
2647 findBoundsLT(
A,
B, Bound, Level);
2648 findBoundsGT(
A,
B, Bound, Level);
2649 findBoundsEQ(
A,
B, Bound, Level);
2688 unsigned NewDeps = 0;
2692 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2697 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2702 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2708 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2713bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2714 BoundInfo *Bound,
const SCEV *Delta)
const {
2715 Bound[
Level].Direction = DirKind;
2716 if (
const SCEV *LowerBound = getLowerBound(Bound))
2719 if (
const SCEV *UpperBound = getUpperBound(Bound))
2740void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2741 BoundInfo *Bound,
unsigned K)
const {
2746 if (Bound[K].Iterations) {
2748 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2750 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2755 SE->getZero(
A[K].Coeff->
getType());
2758 SE->getZero(
A[K].Coeff->
getType());
2777void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2778 BoundInfo *Bound,
unsigned K)
const {
2783 if (Bound[K].Iterations) {
2784 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2785 const SCEV *NegativePart = getNegativePart(Delta);
2787 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2788 const SCEV *PositivePart = getPositivePart(Delta);
2790 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2794 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2795 const SCEV *NegativePart = getNegativePart(Delta);
2796 if (NegativePart->
isZero())
2798 const SCEV *PositivePart = getPositivePart(Delta);
2799 if (PositivePart->
isZero())
2817void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2818 BoundInfo *Bound,
unsigned K)
const {
2823 if (Bound[K].Iterations) {
2824 const SCEV *Iter_1 = SE->getMinusSCEV(
2825 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2826 const SCEV *NegPart =
2827 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2829 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2830 const SCEV *PosPart =
2831 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2833 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2837 const SCEV *NegPart =
2838 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2841 const SCEV *PosPart =
2842 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2861void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2862 BoundInfo *Bound,
unsigned K)
const {
2867 if (Bound[K].Iterations) {
2868 const SCEV *Iter_1 = SE->getMinusSCEV(
2869 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2870 const SCEV *NegPart =
2871 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2873 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2874 const SCEV *PosPart =
2875 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2877 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2881 const SCEV *NegPart =
2882 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2885 const SCEV *PosPart =
2886 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2893const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2894 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2898const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2899 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2905DependenceInfo::CoefficientInfo *
2906DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
2908 const SCEV *
Zero = SE->getZero(Subscript->getType());
2909 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
2910 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2912 CI[
K].PosPart =
Zero;
2913 CI[
K].NegPart =
Zero;
2914 CI[
K].Iterations =
nullptr;
2918 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
2920 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
2921 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
2922 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
2928 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2935 if (CI[K].Iterations)
2950const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
2951 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
2952 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2965const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
2966 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
2967 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
2986 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
2987 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
2988 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
2989 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
2990 const SCEVUnknown *SrcBase =
2992 const SCEVUnknown *DstBase =
2995 if (!SrcBase || !DstBase || SrcBase != DstBase)
3000 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3001 SrcSubscripts, DstSubscripts) &&
3002 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3003 SrcSubscripts, DstSubscripts))
3006 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3007 isLoopInvariant(DstBase, DstLoop) &&
3008 "Expected SrcBase and DstBase to be loop invariant");
3012 dbgs() <<
"\nSrcSubscripts: ";
3013 for (
int I = 0;
I <
Size;
I++)
3014 dbgs() << *SrcSubscripts[
I];
3015 dbgs() <<
"\nDstSubscripts: ";
3016 for (
int I = 0;
I <
Size;
I++)
3017 dbgs() << *DstSubscripts[
I];
3026 SCEVMonotonicityChecker MonChecker(SE);
3027 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3028 for (
int I = 0;
I <
Size; ++
I) {
3029 Pair[
I].Src = SrcSubscripts[
I];
3030 Pair[
I].Dst = DstSubscripts[
I];
3032 assert(Pair[
I].Src->getType() == Pair[
I].Dst->getType() &&
3033 "Unexpected different types for the subscripts");
3036 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3038 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3049bool DependenceInfo::tryDelinearizeFixedSize(
3054 const SCEVUnknown *SrcBase =
3056 const SCEVUnknown *DstBase =
3058 assert(SrcBase && DstBase && SrcBase == DstBase &&
3059 "expected src and dst scev unknowns to be equal");
3062 const SCEV *ElemSize = SE->getElementSize(Src);
3063 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3066 SrcSubscripts, SrcSizes, ElemSize) ||
3068 DstSubscripts, DstSizes, ElemSize))
3073 if (SrcSizes.
size() != DstSizes.
size() ||
3074 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3075 SrcSubscripts.
clear();
3076 DstSubscripts.
clear();
3081 "Expected equal number of entries in the list of SrcSubscripts and "
3093 SrcSubscripts.
clear();
3094 DstSubscripts.
clear();
3099 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3106bool DependenceInfo::tryDelinearizeParametricSize(
3111 const SCEVUnknown *SrcBase =
3113 const SCEVUnknown *DstBase =
3115 assert(SrcBase && DstBase && SrcBase == DstBase &&
3116 "expected src and dst scev unknowns to be equal");
3118 const SCEV *ElementSize = SE->getElementSize(Src);
3119 if (ElementSize != SE->getElementSize(Dst))
3122 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3123 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3144 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3145 SrcSubscripts.
size() != DstSubscripts.
size())
3168 for (
unsigned VI : BV.
set_bits()) {
3178 FunctionAnalysisManager::Invalidator &Inv) {
3185 return Inv.invalidate<
AAManager>(F, PA) ||
3199std::unique_ptr<Dependence>
3201 bool UnderRuntimeAssumptions) {
3203 bool PossiblyLoopIndependent =
true;
3205 PossiblyLoopIndependent =
false;
3207 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3213 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3214 return std::make_unique<Dependence>(Src, Dst,
3226 return std::make_unique<Dependence>(Src, Dst,
3240 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3241 return std::make_unique<Dependence>(Src, Dst,
3247 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3248 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3251 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3252 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3253 if (SrcBase != DstBase) {
3260 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3261 return std::make_unique<Dependence>(Src, Dst,
3269 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3270 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3271 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3272 !isLoopInvariant(DstBase, DstLoop)) {
3273 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3274 return std::make_unique<Dependence>(Src, Dst,
3279 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3280 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3283 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3284 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3285 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3286 return std::make_unique<Dependence>(Src, Dst,
3291 if (!Assume.empty() && !UnderRuntimeAssumptions)
3292 return std::make_unique<Dependence>(Src, Dst,
3297 Pair[0].Src = SrcEv;
3298 Pair[0].Dst = DstEv;
3300 SCEVMonotonicityChecker MonChecker(SE);
3303 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3304 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3305 return std::make_unique<Dependence>(Src, Dst,
3309 if (tryDelinearize(Src, Dst, Pair)) {
3311 Pairs = Pair.
size();
3316 establishNestingLevels(Src, Dst);
3318 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3319 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3320 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3323 CommonLevels += SameSDLevels;
3324 MaxLevels -= SameSDLevels;
3325 if (SameSDLevels > 0) {
3328 for (
unsigned P = 0;
P < Pairs; ++
P) {
3330 Subscript::ClassificationKind TestClass =
3331 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3332 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3334 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3335 TestClass != Subscript::RDIV) {
3337 CommonLevels -= SameSDLevels;
3338 MaxLevels += SameSDLevels;
3345 if (SameSDLevels > 0)
3349 PossiblyLoopIndependent, CommonLevels);
3352 for (
unsigned P = 0;
P < Pairs; ++
P) {
3353 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3354 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3355 Pair[
P].Loops.
resize(MaxLevels + 1);
3356 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3358 Pair[
P].Classification =
3359 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3360 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3361 Pair[
P].GroupLoops = Pair[
P].Loops;
3362 Pair[
P].Group.set(
P);
3372 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3374 switch (Pair[
SI].Classification) {
3375 case Subscript::NonLinear:
3377 ++NonlinearSubscriptPairs;
3378 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3380 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3383 case Subscript::ZIV:
3385 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3388 case Subscript::SIV: {
3391 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3392 UnderRuntimeAssumptions))
3396 case Subscript::RDIV:
3398 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3401 case Subscript::MIV:
3403 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3411 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3412 CompleteLoops |= Pair[
SI].
Loops;
3413 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3414 if (CompleteLoops[
II])
3415 Result.DV[
II - 1].Scalar =
false;
3420 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3422 if (Result.DV[
II - 1].Distance ==
nullptr)
3423 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3425 assert(Result.DV[
II - 1].Distance->isZero() &&
3426 "Inconsistency between distance and direction");
3432 const SCEV *Distance = Result.getDistance(
II);
3433 if (Distance && Distance->
isZero())
3435 "Distance is zero, but direction is not EQ");
3439 if (SameSDLevels > 0) {
3442 assert(CommonLevels >= SameSDLevels);
3443 CommonLevels -= SameSDLevels;
3444 MaxLevels += SameSDLevels;
3445 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3446 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3447 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3448 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3449 DV[Level] = Result.DV[Level];
3450 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3451 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3452 Result.DV = std::move(DV);
3453 Result.DVSameSD = std::move(DVSameSD);
3454 Result.Levels = CommonLevels;
3455 Result.SameSDLevels = SameSDLevels;
3458 if (PossiblyLoopIndependent) {
3462 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3464 Result.LoopIndependent =
false;
3472 bool AllEqual =
true;
3473 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3479 if (AllEqual && Result.Assumptions.getPredicates().empty())
3483 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 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_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.
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.
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.
@ 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.