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) {
596 DV = std::make_unique<
DVEntry[]>(CommonLevels);
615 for (
unsigned Level = 1; Level <= Levels; ++Level) {
616 unsigned char Direction = DV[Level - 1].Direction;
631 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
634 for (
unsigned Level = 1; Level <= Levels; ++Level) {
635 unsigned char Direction = DV[Level - 1].Direction;
643 DV[Level - 1].Direction = RevDirection;
645 if (DV[Level - 1].Distance !=
nullptr)
649 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
691 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
692 "Level out of range");
693 return Level > Levels;
699SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
700 const SCEV *FailurePoint)
701 :
Type(
Type), FailurePoint(FailurePoint) {
703 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
704 "FailurePoint must be provided iff Type is Unknown");
710 case SCEVMonotonicityType::Unknown:
711 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
713 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
715 case SCEVMonotonicityType::Invariant:
718 case SCEVMonotonicityType::MultivariateSignedMonotonic:
719 OS <<
"MultivariateSignedMonotonic\n";
724bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
725 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
728SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
729 if (isLoopInvariant(Expr))
730 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
731 return createUnknown(Expr);
735SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
736 const Loop *OutermostLoop) {
738 "OutermostLoop must be outermost");
740 this->OutermostLoop = OutermostLoop;
756SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
758 return createUnknown(Expr);
763 SCEVMonotonicity StartMon =
visit(Start);
764 if (StartMon.isUnknown())
767 if (!isLoopInvariant(Step))
768 return createUnknown(Expr);
770 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
793 if (SameSDLevels > 0) {
794 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
801 if (!Assumptions.isAlwaysTrue()) {
802 OS <<
" Runtime Assumptions:\n";
803 Assumptions.print(OS, 2);
812 bool OnSameSD =
false;
813 unsigned LevelNum = Levels;
815 LevelNum += SameSDLevels;
817 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
892 return LI->isUnordered();
894 return SI->isUnordered();
902bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
903 const Loop *DstLoop)
const {
904 if (SrcLoop == DstLoop)
914 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
915 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
916 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
917 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
918 DstUP = SE->getBackedgeTakenCount(DstLoop);
920 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
921 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
922 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
923 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
994void DependenceInfo::establishNestingLevels(
const Instruction *Src,
996 const BasicBlock *SrcBlock = Src->getParent();
997 const BasicBlock *DstBlock = Dst->getParent();
998 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
999 unsigned DstLevel = LI->getLoopDepth(DstBlock);
1000 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
1001 const Loop *DstLoop = LI->getLoopFor(DstBlock);
1002 SrcLevels = SrcLevel;
1003 MaxLevels = SrcLevel + DstLevel;
1005 while (SrcLevel > DstLevel) {
1009 while (DstLevel > SrcLevel) {
1015 while (SrcLoop != DstLoop) {
1017 if (!haveSameSD(SrcLoop, DstLoop))
1023 CommonLevels = SrcLevel;
1024 MaxLevels -= CommonLevels;
1029unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1035unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1037 if (
D > CommonLevels)
1040 return D - CommonLevels + SrcLevels;
1067 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1075 unsigned widestWidthSeen = 0;
1080 for (Subscript *Pair : Pairs) {
1081 const SCEV *Src = Pair->Src;
1082 const SCEV *Dst = Pair->Dst;
1085 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1087 "This function only unify integer types and "
1088 "expect Src and Dst share the same type otherwise.");
1101 assert(widestWidthSeen > 0);
1104 for (Subscript *Pair : Pairs) {
1105 const SCEV *Src = Pair->Src;
1106 const SCEV *Dst = Pair->Dst;
1109 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1111 "This function only unify integer types and "
1112 "expect Src and Dst share the same type otherwise.");
1117 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1120 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1129void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1130 const SCEV *Src = Pair->Src;
1131 const SCEV *Dst = Pair->Dst;
1136 const SCEV *SrcCastOp = SrcCast->
getOperand();
1137 const SCEV *DstCastOp = DstCast->
getOperand();
1139 Pair->Src = SrcCastOp;
1140 Pair->Dst = DstCastOp;
1151 return isLoopInvariant(Expr, LoopNest);
1158 const Loop *
L = LoopNest;
1159 while (L && AddRec->
getLoop() != L)
1160 L =
L->getParentLoop();
1166 if (!isLoopInvariant(Step, LoopNest))
1172 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1177bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1179 return checkSubscript(Src, LoopNest,
Loops,
true);
1184bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1186 return checkSubscript(Dst, LoopNest,
Loops,
false);
1192DependenceInfo::Subscript::ClassificationKind
1193DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1194 const SCEV *Dst,
const Loop *DstLoopNest,
1196 SmallBitVector SrcLoops(MaxLevels + 1);
1197 SmallBitVector DstLoops(MaxLevels + 1);
1198 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1199 return Subscript::NonLinear;
1200 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1201 return Subscript::NonLinear;
1204 unsigned N =
Loops.count();
1206 return Subscript::ZIV;
1208 return Subscript::SIV;
1209 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1210 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1211 return Subscript::RDIV;
1212 return Subscript::MIV;
1222const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1223 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1224 const SCEV *UB = SE->getBackedgeTakenCount(L);
1225 return SE->getTruncateOrZeroExtend(UB,
T);
1232const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1234 if (
const SCEV *UB = collectUpperBound(L,
T))
1291bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1306 Result.Consistent =
false;
1337bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1338 const SCEV *DstConst,
const Loop *CurSrcLoop,
1339 const Loop *CurDstLoop,
unsigned Level,
1341 bool UnderRuntimeAssumptions) {
1352 ++StrongSIVapplications;
1353 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1358 Result.Consistent =
false;
1365 bool IsDeltaLarge = [&] {
1366 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1374 if (!AbsDelta || !AbsCoeff)
1383 ++StrongSIVindependence;
1384 ++StrongSIVsuccesses;
1392 APInt Distance = ConstDelta;
1393 APInt Remainder = ConstDelta;
1398 if (Remainder != 0) {
1400 ++StrongSIVindependence;
1401 ++StrongSIVsuccesses;
1404 Result.DV[
Level].Distance = SE->getConstant(Distance);
1405 if (Distance.
sgt(0))
1407 else if (Distance.
slt(0))
1411 ++StrongSIVsuccesses;
1412 }
else if (Delta->
isZero()) {
1416 if (SE->isKnownNonZero(Coeff)) {
1418 dbgs() <<
"\t Coefficient proven non-zero by SCEV analysis\n");
1421 if (UnderRuntimeAssumptions) {
1422 const SCEVPredicate *Pred = SE->getComparePredicate(
1424 Result.Assumptions =
Result.Assumptions.getUnionWith(Pred, *SE);
1430 LLVM_DEBUG(
dbgs() <<
"\t Would need runtime assumption " << *Coeff
1431 <<
" != 0, but not allowed. Failing this test.\n");
1438 ++StrongSIVsuccesses;
1440 if (Coeff->
isOne()) {
1444 Result.Consistent =
false;
1448 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1449 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1450 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1451 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1452 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1457 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1458 (DeltaMaybeNegative && CoeffMaybeNegative))
1462 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1463 (DeltaMaybePositive && CoeffMaybeNegative))
1465 if (NewDirection <
Result.DV[Level].Direction)
1466 ++StrongSIVsuccesses;
1500bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1501 const SCEV *SrcConst,
1502 const SCEV *DstConst,
1503 const Loop *CurSrcLoop,
1504 const Loop *CurDstLoop,
unsigned Level,
1513 ++WeakCrossingSIVapplications;
1514 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1516 Result.Consistent =
false;
1517 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1520 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1521 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1522 ++WeakCrossingSIVsuccesses;
1523 if (!
Result.DV[Level].Direction) {
1524 ++WeakCrossingSIVindependence;
1534 if (SE->isKnownNegative(ConstCoeff)) {
1537 "dynamic cast of negative of ConstCoeff should yield constant");
1538 Delta = SE->getNegativeSCEV(Delta);
1540 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1550 if (SE->isKnownNegative(Delta)) {
1552 ++WeakCrossingSIVindependence;
1553 ++WeakCrossingSIVsuccesses;
1559 if (
const SCEV *UpperBound =
1560 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1562 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1564 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1568 ++WeakCrossingSIVindependence;
1569 ++WeakCrossingSIVsuccesses;
1574 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1575 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1576 ++WeakCrossingSIVsuccesses;
1577 if (!
Result.DV[Level].Direction) {
1578 ++WeakCrossingSIVindependence;
1587 APInt APDelta = ConstDelta->
getAPInt();
1588 APInt APCoeff = ConstCoeff->
getAPInt();
1589 APInt Distance = APDelta;
1590 APInt Remainder = APDelta;
1593 if (Remainder != 0) {
1595 ++WeakCrossingSIVindependence;
1596 ++WeakCrossingSIVsuccesses;
1602 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1603 Remainder = Distance.
srem(Two);
1605 if (Remainder != 0) {
1607 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1608 ++WeakCrossingSIVsuccesses;
1628 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1629 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1637 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1638 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1645 X = AM.
slt(0) ? -A1 : A1;
1646 Y = BM.
slt(0) ? B1 : -B1;
1656static OverflowSafeSignedAPInt
1658 const OverflowSafeSignedAPInt &OB) {
1660 return OverflowSafeSignedAPInt();
1669 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1671 return OverflowSafeSignedAPInt(Q) - 1;
1674static OverflowSafeSignedAPInt
1676 const OverflowSafeSignedAPInt &OB) {
1678 return OverflowSafeSignedAPInt();
1687 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1688 return OverflowSafeSignedAPInt(Q) + 1;
1721static std::pair<OverflowSafeSignedAPInt, OverflowSafeSignedAPInt>
1723 OverflowSafeSignedAPInt UB) {
1724 assert(
A &&
B &&
"A and B must be available");
1725 assert(*
A != 0 &&
"A must be non-zero");
1726 OverflowSafeSignedAPInt TL, TU;
1729 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1733 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1736 LLVM_DEBUG(
if (TU)
dbgs() <<
"\t Possible TU = " << *TU <<
"\n");
1740 LLVM_DEBUG(
if (TL)
dbgs() <<
"\t Possible TL = " << *TL <<
"\n");
1742 return std::make_pair(TL, TU);
1764bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1765 const SCEV *SrcConst,
const SCEV *DstConst,
1766 const Loop *CurSrcLoop,
1767 const Loop *CurDstLoop,
unsigned Level,
1773 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1774 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1777 ++ExactSIVapplications;
1778 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1780 Result.Consistent =
false;
1788 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1793 APInt AM = ConstSrcCoeff->
getAPInt();
1794 APInt BM = ConstDstCoeff->
getAPInt();
1799 ++ExactSIVindependence;
1800 ++ExactSIVsuccesses;
1807 std::optional<APInt> UM;
1809 if (
const SCEVConstant *CUB =
1810 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1811 UM = CUB->getAPInt();
1817 APInt TC = CM.
sdiv(
G);
1839 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
1840 const OverflowSafeSignedAPInt &V1) {
1863 ++ExactSIVindependence;
1864 ++ExactSIVsuccesses;
1870 OverflowSafeSignedAPInt LowerDistance, UpperDistance;
1871 OverflowSafeSignedAPInt OTY(TY), OTX(TX), OTA(TA), OTB(TB), OTL(TL), OTU(TU);
1875 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1876 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1878 LowerDistance = (OTY - OTX) + (OTA - OTB) * OTU;
1879 UpperDistance = (OTY - OTX) + (OTA - OTB) * OTL;
1882 if (!LowerDistance || !UpperDistance)
1885 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << *LowerDistance <<
"\n");
1886 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << *UpperDistance <<
"\n");
1888 if (LowerDistance->sle(0) && UpperDistance->sge(0)) {
1890 ++ExactSIVsuccesses;
1892 if (LowerDistance->slt(0)) {
1894 ++ExactSIVsuccesses;
1896 if (UpperDistance->sgt(0)) {
1898 ++ExactSIVsuccesses;
1904 ++ExactSIVindependence;
1915 return ConstDividend.
srem(ConstDivisor) == 0;
1949bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1950 const SCEV *SrcConst,
1951 const SCEV *DstConst,
1952 const Loop *CurSrcLoop,
1953 const Loop *CurDstLoop,
unsigned Level,
1965 ++WeakZeroSIVapplications;
1966 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1968 Result.Consistent =
false;
1969 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1972 if (Level < CommonLevels) {
1975 ++WeakZeroSIVsuccesses;
1985 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1986 ? SE->getNegativeSCEV(ConstCoeff)
1988 const SCEV *NewDelta =
1989 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1993 if (
const SCEV *UpperBound =
1994 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1996 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1998 ++WeakZeroSIVindependence;
1999 ++WeakZeroSIVsuccesses;
2004 if (Level < CommonLevels) {
2007 ++WeakZeroSIVsuccesses;
2015 if (SE->isKnownNegative(NewDelta)) {
2017 ++WeakZeroSIVindependence;
2018 ++WeakZeroSIVsuccesses;
2025 ++WeakZeroSIVindependence;
2026 ++WeakZeroSIVsuccesses;
2063bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
2064 const SCEV *SrcConst,
2065 const SCEV *DstConst,
2066 const Loop *CurSrcLoop,
2067 const Loop *CurDstLoop,
unsigned Level,
2078 ++WeakZeroSIVapplications;
2079 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2081 Result.Consistent =
false;
2082 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2085 if (Level < CommonLevels) {
2088 ++WeakZeroSIVsuccesses;
2098 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2099 ? SE->getNegativeSCEV(ConstCoeff)
2101 const SCEV *NewDelta =
2102 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2106 if (
const SCEV *UpperBound =
2107 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2109 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2111 ++WeakZeroSIVindependence;
2112 ++WeakZeroSIVsuccesses;
2117 if (Level < CommonLevels) {
2120 ++WeakZeroSIVsuccesses;
2128 if (SE->isKnownNegative(NewDelta)) {
2130 ++WeakZeroSIVindependence;
2131 ++WeakZeroSIVsuccesses;
2138 ++WeakZeroSIVindependence;
2139 ++WeakZeroSIVsuccesses;
2152bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2153 const SCEV *SrcConst,
const SCEV *DstConst,
2154 const Loop *SrcLoop,
const Loop *DstLoop,
2160 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2161 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2164 ++ExactRDIVapplications;
2165 Result.Consistent =
false;
2166 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2171 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2176 APInt AM = ConstSrcCoeff->
getAPInt();
2177 APInt BM = ConstDstCoeff->
getAPInt();
2182 ++ExactRDIVindependence;
2189 std::optional<APInt> SrcUM;
2191 if (
const SCEVConstant *UpperBound =
2192 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2193 SrcUM = UpperBound->getAPInt();
2197 std::optional<APInt> DstUM;
2199 if (
const SCEVConstant *UpperBound =
2200 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2201 DstUM = UpperBound->getAPInt();
2207 APInt TC = CM.
sdiv(
G);
2232 auto CreateVec = [](
const OverflowSafeSignedAPInt &V0,
2233 const OverflowSafeSignedAPInt &V1) {
2253 ++ExactRDIVindependence;
2299bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2302 const Loop *Loop2)
const {
2306 ++SymbolicRDIVapplications;
2313 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2314 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2317 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2318 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2321 if (SE->isKnownNonNegative(A1)) {
2322 if (SE->isKnownNonNegative(A2)) {
2326 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2329 ++SymbolicRDIVindependence;
2335 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2338 ++SymbolicRDIVindependence;
2342 }
else if (SE->isKnownNonPositive(A2)) {
2346 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2347 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2348 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2349 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2351 ++SymbolicRDIVindependence;
2356 if (SE->isKnownNegative(C2_C1)) {
2357 ++SymbolicRDIVindependence;
2361 }
else if (SE->isKnownNonPositive(A1)) {
2362 if (SE->isKnownNonNegative(A2)) {
2366 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2367 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2368 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2369 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2371 ++SymbolicRDIVindependence;
2376 if (SE->isKnownPositive(C2_C1)) {
2377 ++SymbolicRDIVindependence;
2380 }
else if (SE->isKnownNonPositive(A2)) {
2384 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2387 ++SymbolicRDIVindependence;
2393 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2396 ++SymbolicRDIVindependence;
2413bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2415 bool UnderRuntimeAssumptions) {
2420 if (SrcAddRec && DstAddRec) {
2421 const SCEV *SrcConst = SrcAddRec->
getStart();
2422 const SCEV *DstConst = DstAddRec->
getStart();
2425 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2426 const Loop *CurDstLoop = DstAddRec->
getLoop();
2427 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2428 "Loops in the SIV test should have the same iteration space and "
2430 Level = mapSrcLoop(CurSrcLoop);
2432 if (SrcCoeff == DstCoeff)
2434 strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop, CurDstLoop,
2435 Level, Result, UnderRuntimeAssumptions);
2436 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2437 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2438 CurDstLoop, Level, Result);
2440 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2441 CurSrcLoop, CurDstLoop, Level, Result);
2442 return disproven || gcdMIVtest(Src, Dst, Result) ||
2443 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2447 const SCEV *SrcConst = SrcAddRec->
getStart();
2449 const SCEV *DstConst = Dst;
2450 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2451 Level = mapSrcLoop(CurSrcLoop);
2452 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2453 CurSrcLoop, Level, Result) ||
2454 gcdMIVtest(Src, Dst, Result);
2457 const SCEV *DstConst = DstAddRec->
getStart();
2459 const SCEV *SrcConst = Src;
2460 const Loop *CurDstLoop = DstAddRec->
getLoop();
2461 Level = mapDstLoop(CurDstLoop);
2462 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2463 CurDstLoop, Level, Result) ||
2464 gcdMIVtest(Src, Dst, Result);
2483bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2491 const SCEV *SrcConst, *DstConst;
2492 const SCEV *SrcCoeff, *DstCoeff;
2493 const Loop *SrcLoop, *DstLoop;
2499 if (SrcAddRec && DstAddRec) {
2502 SrcLoop = SrcAddRec->
getLoop();
2505 DstLoop = DstAddRec->
getLoop();
2506 }
else if (SrcAddRec) {
2507 if (
const SCEVAddRecExpr *tmpAddRec =
2509 SrcConst = tmpAddRec->getStart();
2510 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2511 SrcLoop = tmpAddRec->getLoop();
2514 DstLoop = SrcAddRec->
getLoop();
2517 }
else if (DstAddRec) {
2518 if (
const SCEVAddRecExpr *tmpAddRec =
2520 DstConst = tmpAddRec->getStart();
2521 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2522 DstLoop = tmpAddRec->getLoop();
2525 SrcLoop = DstAddRec->
getLoop();
2530 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2532 gcdMIVtest(Src, Dst, Result) ||
2533 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2540bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2545 Result.Consistent =
false;
2546 return gcdMIVtest(Src, Dst, Result) ||
2547 banerjeeMIVtest(Src, Dst,
Loops, Result);
2560 if (Product->hasNoSignedWrap())
2562 return std::nullopt;
2565bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2566 const Loop *CurLoop,
2567 const SCEV *&CurLoopCoeff,
2568 APInt &RunningGCD)
const {
2571 if (RunningGCD == 1)
2576 assert(isLoopInvariant(Expr, CurLoop) &&
2577 "Expected loop invariant expression");
2584 if (AddRec->
getLoop() == CurLoop) {
2585 CurLoopCoeff = Step;
2599 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2620bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2627 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2634 const SCEV *Coefficients = Src;
2635 while (
const SCEVAddRecExpr *AddRec =
2646 const SCEV *SrcConst = Coefficients;
2653 while (
const SCEVAddRecExpr *AddRec =
2664 const SCEV *DstConst = Coefficients;
2676 if (ConstDelta == 0)
2679 APInt Remainder = ConstDelta.
srem(RunningGCD);
2680 if (Remainder != 0) {
2699 bool Improved =
false;
2701 while (
const SCEVAddRecExpr *AddRec =
2704 const Loop *CurLoop = AddRec->
getLoop();
2705 RunningGCD = ExtraGCD;
2707 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2709 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2710 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2713 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2723 if (RunningGCD != 0) {
2724 Remainder = ConstDelta.
srem(RunningGCD);
2726 if (Remainder != 0) {
2727 unsigned Level = mapSrcLoop(CurLoop);
2728 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2772bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2779 ++BanerjeeApplications;
2782 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2785 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2786 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2787 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2792 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2793 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2796 findBoundsALL(
A,
B, Bound, K);
2811 bool Disproved =
false;
2814 unsigned DepthExpanded = 0;
2816 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2818 bool Improved =
false;
2819 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2821 unsigned Old =
Result.DV[
K - 1].Direction;
2822 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2823 Improved |= Old !=
Result.DV[
K - 1].Direction;
2824 if (!
Result.DV[K - 1].Direction) {
2832 ++BanerjeeSuccesses;
2834 ++BanerjeeIndependence;
2838 ++BanerjeeIndependence;
2852unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2853 CoefficientInfo *
B, BoundInfo *Bound,
2855 unsigned &DepthExpanded,
2856 const SCEV *Delta)
const {
2862 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2863 "direction exploration is terminated.\n");
2864 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2870 if (Level > CommonLevels) {
2873 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2875 Bound[
K].DirSet |= Bound[
K].Direction;
2900 if (Level > DepthExpanded) {
2901 DepthExpanded =
Level;
2903 findBoundsLT(
A,
B, Bound, Level);
2904 findBoundsGT(
A,
B, Bound, Level);
2905 findBoundsEQ(
A,
B, Bound, Level);
2944 unsigned NewDeps = 0;
2948 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2953 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2958 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2964 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2969bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2970 BoundInfo *Bound,
const SCEV *Delta)
const {
2971 Bound[
Level].Direction = DirKind;
2972 if (
const SCEV *LowerBound = getLowerBound(Bound))
2975 if (
const SCEV *UpperBound = getUpperBound(Bound))
2996void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2997 BoundInfo *Bound,
unsigned K)
const {
3002 if (Bound[K].Iterations) {
3004 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3006 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3011 SE->getZero(
A[K].Coeff->
getType());
3014 SE->getZero(
A[K].Coeff->
getType());
3033void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3034 BoundInfo *Bound,
unsigned K)
const {
3039 if (Bound[K].Iterations) {
3040 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3041 const SCEV *NegativePart = getNegativePart(Delta);
3043 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3044 const SCEV *PositivePart = getPositivePart(Delta);
3046 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3050 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3051 const SCEV *NegativePart = getNegativePart(Delta);
3052 if (NegativePart->
isZero())
3054 const SCEV *PositivePart = getPositivePart(Delta);
3055 if (PositivePart->
isZero())
3073void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3074 BoundInfo *Bound,
unsigned K)
const {
3079 if (Bound[K].Iterations) {
3080 const SCEV *Iter_1 = SE->getMinusSCEV(
3081 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3082 const SCEV *NegPart =
3083 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3085 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3086 const SCEV *PosPart =
3087 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3089 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3093 const SCEV *NegPart =
3094 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3097 const SCEV *PosPart =
3098 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3117void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3118 BoundInfo *Bound,
unsigned K)
const {
3123 if (Bound[K].Iterations) {
3124 const SCEV *Iter_1 = SE->getMinusSCEV(
3125 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3126 const SCEV *NegPart =
3127 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3129 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3130 const SCEV *PosPart =
3131 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3133 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3137 const SCEV *NegPart =
3138 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3141 const SCEV *PosPart =
3142 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3149const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3150 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3154const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3155 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3161DependenceInfo::CoefficientInfo *
3162DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3164 const SCEV *
Zero = SE->getZero(Subscript->getType());
3165 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3166 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3168 CI[
K].PosPart =
Zero;
3169 CI[
K].NegPart =
Zero;
3170 CI[
K].Iterations =
nullptr;
3174 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3176 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3177 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3178 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3184 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3191 if (CI[K].Iterations)
3206const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3207 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3208 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3221const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3222 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3223 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3242 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3243 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3244 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3245 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3246 const SCEVUnknown *SrcBase =
3248 const SCEVUnknown *DstBase =
3251 if (!SrcBase || !DstBase || SrcBase != DstBase)
3256 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3257 SrcSubscripts, DstSubscripts) &&
3258 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3259 SrcSubscripts, DstSubscripts))
3262 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3263 isLoopInvariant(DstBase, DstLoop) &&
3264 "Expected SrcBase and DstBase to be loop invariant");
3268 dbgs() <<
"\nSrcSubscripts: ";
3269 for (
int I = 0;
I <
Size;
I++)
3270 dbgs() << *SrcSubscripts[
I];
3271 dbgs() <<
"\nDstSubscripts: ";
3272 for (
int I = 0;
I <
Size;
I++)
3273 dbgs() << *DstSubscripts[
I];
3281 SCEVMonotonicityChecker MonChecker(SE);
3282 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3283 for (
int I = 0;
I <
Size; ++
I) {
3284 Pair[
I].Src = SrcSubscripts[
I];
3285 Pair[
I].Dst = DstSubscripts[
I];
3286 unifySubscriptType(&Pair[
I]);
3289 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3291 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3302bool DependenceInfo::tryDelinearizeFixedSize(
3307 const SCEVUnknown *SrcBase =
3309 const SCEVUnknown *DstBase =
3311 assert(SrcBase && DstBase && SrcBase == DstBase &&
3312 "expected src and dst scev unknowns to be equal");
3315 const SCEV *ElemSize = SE->getElementSize(Src);
3316 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3319 SrcSubscripts, SrcSizes, ElemSize) ||
3321 DstSubscripts, DstSizes, ElemSize))
3326 if (SrcSizes.
size() != DstSizes.
size() ||
3327 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3328 SrcSubscripts.
clear();
3329 DstSubscripts.
clear();
3334 "Expected equal number of entries in the list of SrcSubscripts and "
3346 SrcSubscripts.
clear();
3347 DstSubscripts.
clear();
3352 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3359bool DependenceInfo::tryDelinearizeParametricSize(
3364 const SCEVUnknown *SrcBase =
3366 const SCEVUnknown *DstBase =
3368 assert(SrcBase && DstBase && SrcBase == DstBase &&
3369 "expected src and dst scev unknowns to be equal");
3371 const SCEV *ElementSize = SE->getElementSize(Src);
3372 if (ElementSize != SE->getElementSize(Dst))
3375 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3376 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3397 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3398 SrcSubscripts.
size() != DstSubscripts.
size())
3421 for (
unsigned VI : BV.
set_bits()) {
3431 FunctionAnalysisManager::Invalidator &Inv) {
3438 return Inv.invalidate<
AAManager>(F, PA) ||
3452std::unique_ptr<Dependence>
3454 bool UnderRuntimeAssumptions) {
3456 bool PossiblyLoopIndependent =
true;
3458 PossiblyLoopIndependent =
false;
3460 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3466 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3467 return std::make_unique<Dependence>(Src, Dst,
3479 return std::make_unique<Dependence>(Src, Dst,
3493 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3494 return std::make_unique<Dependence>(Src, Dst,
3500 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3501 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3504 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3505 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3506 if (SrcBase != DstBase) {
3513 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3514 return std::make_unique<Dependence>(Src, Dst,
3522 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3523 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3524 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3525 !isLoopInvariant(DstBase, DstLoop)) {
3526 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3527 return std::make_unique<Dependence>(Src, Dst,
3532 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3533 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3536 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3537 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3538 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3539 return std::make_unique<Dependence>(Src, Dst,
3544 if (!Assume.empty() && !UnderRuntimeAssumptions)
3545 return std::make_unique<Dependence>(Src, Dst,
3550 Pair[0].Src = SrcEv;
3551 Pair[0].Dst = DstEv;
3553 SCEVMonotonicityChecker MonChecker(SE);
3556 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3557 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3558 return std::make_unique<Dependence>(Src, Dst,
3562 if (tryDelinearize(Src, Dst, Pair)) {
3564 Pairs = Pair.
size();
3569 establishNestingLevels(Src, Dst);
3571 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3572 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3573 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3576 CommonLevels += SameSDLevels;
3577 MaxLevels -= SameSDLevels;
3578 if (SameSDLevels > 0) {
3581 for (
unsigned P = 0;
P < Pairs; ++
P) {
3583 Subscript::ClassificationKind TestClass =
3584 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3585 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3587 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3588 TestClass != Subscript::RDIV) {
3590 CommonLevels -= SameSDLevels;
3591 MaxLevels += SameSDLevels;
3598 if (SameSDLevels > 0)
3602 PossiblyLoopIndependent, CommonLevels);
3605 for (
unsigned P = 0;
P < Pairs; ++
P) {
3606 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3607 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3608 Pair[
P].Loops.
resize(MaxLevels + 1);
3609 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3611 removeMatchingExtensions(&Pair[
P]);
3612 Pair[
P].Classification =
3613 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3614 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3615 Pair[
P].GroupLoops = Pair[
P].Loops;
3616 Pair[
P].Group.set(
P);
3626 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3628 switch (Pair[
SI].Classification) {
3629 case Subscript::NonLinear:
3631 ++NonlinearSubscriptPairs;
3632 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3634 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3636 Result.Consistent =
false;
3638 case Subscript::ZIV:
3640 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3643 case Subscript::SIV: {
3646 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result,
3647 UnderRuntimeAssumptions))
3651 case Subscript::RDIV:
3653 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3656 case Subscript::MIV:
3658 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3666 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3667 CompleteLoops |= Pair[
SI].
Loops;
3668 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3669 if (CompleteLoops[
II])
3670 Result.DV[
II - 1].Scalar =
false;
3675 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3677 if (Result.DV[
II - 1].Distance ==
nullptr)
3678 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3680 assert(Result.DV[
II - 1].Distance->isZero() &&
3681 "Inconsistency between distance and direction");
3687 const SCEV *Distance = Result.getDistance(
II);
3688 if (Distance && Distance->
isZero())
3690 "Distance is zero, but direction is not EQ");
3694 if (SameSDLevels > 0) {
3697 assert(CommonLevels >= SameSDLevels);
3698 CommonLevels -= SameSDLevels;
3699 MaxLevels += SameSDLevels;
3700 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3701 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3702 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3703 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3704 DV[Level] = Result.DV[Level];
3705 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3706 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3707 Result.DV = std::move(DV);
3708 Result.DVSameSD = std::move(DVSameSD);
3709 Result.Levels = CommonLevels;
3710 Result.SameSDLevels = SameSDLevels;
3712 Result.Consistent =
false;
3715 if (PossiblyLoopIndependent) {
3719 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3721 Result.LoopIndependent =
false;
3729 bool AllEqual =
true;
3730 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3736 if (AllEqual && Result.Assumptions.getPredicates().empty())
3740 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::All), cl::ReallyHidden, cl::desc("Run only specified dependence test routine and disable others. " "The purpose is mainly to exclude the influence of other " "dependence test routines in regression tests. If set to All, all " "dependence test routines are enabled."), cl::values(clEnumValN(DependenceTestType::All, "all", "Enable all dependence test routines."), clEnumValN(DependenceTestType::StrongSIV, "strong-siv", "Enable only Strong SIV test."), clEnumValN(DependenceTestType::WeakCrossingSIV, "weak-crossing-siv", "Enable only Weak-Crossing SIV test."), clEnumValN(DependenceTestType::ExactSIV, "exact-siv", "Enable only Exact SIV test."), clEnumValN(DependenceTestType::WeakZeroSIV, "weak-zero-siv", "Enable only Weak-Zero SIV test."), clEnumValN(DependenceTestType::ExactRDIV, "exact-rdiv", "Enable only Exact RDIV test."), clEnumValN(DependenceTestType::SymbolicRDIV, "symbolic-rdiv", "Enable only Symbolic RDIV test."), clEnumValN(DependenceTestType::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
static bool isLoadOrStore(const Instruction *I)
static OverflowSafeSignedAPInt floorOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
static OverflowSafeSignedAPInt ceilingOfQuotient(const OverflowSafeSignedAPInt &OA, const OverflowSafeSignedAPInt &OB)
static bool isDependenceTestEnabled(DependenceTestType Test)
Returns true iff Test is enabled.
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static std::pair< OverflowSafeSignedAPInt, OverflowSafeSignedAPInt > inferDomainOfAffine(OverflowSafeSignedAPInt A, OverflowSafeSignedAPInt B, OverflowSafeSignedAPInt UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::optional< APInt > getConstantCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static const SCEV * absSCEVNoSignedOverflow(const SCEV *A, ScalarEvolution &SE)
Returns the absolute value of A.
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static const SCEV * mulSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A * B if it guaranteed not to signed wrap.
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< bool > EnableMonotonicityCheck("da-enable-monotonicity-check", cl::init(false), cl::Hidden, cl::desc("Check if the subscripts are monotonic. If it's not, dependence " "is reported as unknown."))
static cl::opt< bool > DumpMonotonicityReport("da-dump-monotonicity-report", cl::init(false), cl::Hidden, cl::desc("When printing analysis, dump the results of monotonicity checks."))
static cl::opt< unsigned > MIVMaxLevelThreshold("da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors."))
static cl::opt< bool > DisableDelinearizationChecks("da-disable-delinearization-checks", cl::Hidden, cl::desc("Disable checks that try to statically verify validity of " "delinearized subscripts. Enabling this option may result in incorrect " "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension."))
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
static LLVM_ABI void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
APInt abs() const
Get the absolute value.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
@ ICMP_SLT
signed less than
@ ICMP_SGT
signed greater than
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns the runtime assumptions under which this Dependence relation is valid...
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual bool isPeelLast(unsigned Level, bool SameSD=false) const
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
virtual unsigned getDirection(unsigned Level, bool SameSD=false) const
getDirection - Returns the direction associated with a particular common or SameSD level.
virtual bool isScalar(unsigned Level, bool SameSD=false) const
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
virtual bool isPeelFirst(unsigned Level, bool SameSD=false) const
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
virtual bool inSameSDLoops(unsigned Level) const
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
unsigned getDirection(unsigned Level, bool SameSD=false) const override
getDirection - Returns the direction associated with a particular common or SameSD level.
bool isScalar(unsigned Level, bool SameSD=false) const override
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isDirectionNegative() const override
Check if the direction vector is negative.
const SCEV * getDistance(unsigned Level, bool SameSD=false) const override
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
DVEntry getDVEntry(unsigned Level, bool IsSameSD) const
getDVEntry - Returns the DV entry associated with a regular or a SameSD level.
bool isPeelLast(unsigned Level, bool SameSD=false) const override
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
bool isPeelFirst(unsigned Level, bool SameSD=false) const override
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStart() const
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
const SCEV * getOperand() const
This class represents a constant integer value.
const APInt & getAPInt() const
bool hasNoSignedWrap() const
This class represents a composition of other SCEV predicates, and is the class that most clients will...
This class represents an analyzed expression in the program.
LLVM_ABI bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI const SCEV * getAbsExpr(const SCEV *Op, bool IsNSW)
LLVM_ABI const SCEV * removePointerBase(const SCEV *S)
Compute an expression equivalent to S - getPointerBase(S).
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
constexpr bool operator!(E Val)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
@ SMin
Signed integer min implemented in terms of select(cmp()).
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
APInt operator+(APInt a, const APInt &b)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...
This class defines a simple visitor class that may be used for various SCEV analysis purposes.