70#define DEBUG_TYPE "da"
76STATISTIC(SeparableSubscriptPairs,
"Separable subscript pairs");
77STATISTIC(CoupledSubscriptPairs,
"Coupled subscript pairs");
78STATISTIC(NonlinearSubscriptPairs,
"Nonlinear subscript pairs");
81STATISTIC(StrongSIVapplications,
"Strong SIV applications");
82STATISTIC(StrongSIVsuccesses,
"Strong SIV successes");
83STATISTIC(StrongSIVindependence,
"Strong SIV independence");
84STATISTIC(WeakCrossingSIVapplications,
"Weak-Crossing SIV applications");
85STATISTIC(WeakCrossingSIVsuccesses,
"Weak-Crossing SIV successes");
86STATISTIC(WeakCrossingSIVindependence,
"Weak-Crossing SIV independence");
87STATISTIC(ExactSIVapplications,
"Exact SIV applications");
89STATISTIC(ExactSIVindependence,
"Exact SIV independence");
90STATISTIC(WeakZeroSIVapplications,
"Weak-Zero SIV applications");
91STATISTIC(WeakZeroSIVsuccesses,
"Weak-Zero SIV successes");
92STATISTIC(WeakZeroSIVindependence,
"Weak-Zero SIV independence");
93STATISTIC(ExactRDIVapplications,
"Exact RDIV applications");
94STATISTIC(ExactRDIVindependence,
"Exact RDIV independence");
95STATISTIC(SymbolicRDIVapplications,
"Symbolic RDIV applications");
96STATISTIC(SymbolicRDIVindependence,
"Symbolic RDIV independence");
104STATISTIC(BanerjeeApplications,
"Banerjee applications");
105STATISTIC(BanerjeeIndependence,
"Banerjee independence");
107STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
111 cl::desc(
"Try to delinearize array references."));
113 "da-disable-delinearization-checks",
cl::Hidden,
115 "Disable checks that try to statically verify validity of "
116 "delinearized subscripts. Enabling this option may result in incorrect "
117 "dependence vectors for languages that allow the subscript of one "
118 "dimension to underflow or overflow into another dimension."));
122 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
123 "explore MIV direction vectors."));
128enum class DependenceTestType {
143 "da-enable-dependence-test",
cl::init(DependenceTestType::All),
145 cl::desc(
"Run only specified dependence test routine and disable others. "
146 "The purpose is mainly to exclude the influence of other "
147 "dependence test routines in regression tests. If set to All, all "
148 "dependence test routines are enabled."),
150 "Enable all dependence test routines."),
151 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
152 "Enable only Strong SIV test."),
153 clEnumValN(DependenceTestType::WeakCrossingSIV,
155 "Enable only Weak-Crossing SIV test."),
156 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
157 "Enable only Exact SIV test."),
158 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
159 "Enable only Weak-Zero SIV test."),
160 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
161 "Enable only Exact RDIV test."),
162 clEnumValN(DependenceTestType::SymbolicRDIV,
"symbolic-rdiv",
163 "Enable only Symbolic RDIV test."),
164 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
165 "Enable only GCD MIV test."),
166 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
167 "Enable only Banerjee MIV test.")));
173 cl::desc(
"Check if the subscripts are monotonic. If it's not, dependence "
174 "is reported as unknown."));
179 "When printing analysis, dump the results of monotonicity checks."));
195 "Dependence Analysis",
true,
true)
268enum class SCEVMonotonicityType {
280 MultivariateSignedMonotonic,
283struct SCEVMonotonicity {
284 SCEVMonotonicity(SCEVMonotonicityType
Type,
285 const SCEV *FailurePoint =
nullptr);
287 SCEVMonotonicityType
getType()
const {
return Type; }
289 const SCEV *getFailurePoint()
const {
return FailurePoint; }
291 bool isUnknown()
const {
return Type == SCEVMonotonicityType::Unknown; }
293 void print(raw_ostream &OS,
unsigned Depth)
const;
296 SCEVMonotonicityType
Type;
299 const SCEV *FailurePoint;
306struct SCEVMonotonicityChecker
307 :
public SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity> {
309 SCEVMonotonicityChecker(ScalarEvolution *SE) : SE(SE) {}
314 SCEVMonotonicity checkMonotonicity(
const SCEV *Expr,
315 const Loop *OutermostLoop);
321 const Loop *OutermostLoop;
324 SCEVMonotonicity invariantOrUnknown(
const SCEV *Expr);
328 bool isLoopInvariant(
const SCEV *Expr)
const;
331 SCEVMonotonicity createUnknown(
const SCEV *FailurePoint) {
332 return SCEVMonotonicity(SCEVMonotonicityType::Unknown, FailurePoint);
335 SCEVMonotonicity visitAddRecExpr(
const SCEVAddRecExpr *Expr);
337 SCEVMonotonicity visitConstant(
const SCEVConstant *) {
338 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
340 SCEVMonotonicity visitVScale(
const SCEVVScale *) {
341 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
345 SCEVMonotonicity visitZeroExtendExpr(
const SCEVZeroExtendExpr *Expr) {
346 return invariantOrUnknown(Expr);
348 SCEVMonotonicity visitSignExtendExpr(
const SCEVSignExtendExpr *Expr) {
349 return invariantOrUnknown(Expr);
351 SCEVMonotonicity visitAddExpr(
const SCEVAddExpr *Expr) {
352 return invariantOrUnknown(Expr);
354 SCEVMonotonicity visitMulExpr(
const SCEVMulExpr *Expr) {
355 return invariantOrUnknown(Expr);
357 SCEVMonotonicity visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
358 return invariantOrUnknown(Expr);
360 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
361 return invariantOrUnknown(Expr);
363 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
364 return invariantOrUnknown(Expr);
366 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
367 return invariantOrUnknown(Expr);
369 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
370 return invariantOrUnknown(Expr);
372 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
373 return invariantOrUnknown(Expr);
375 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
376 return invariantOrUnknown(Expr);
378 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
379 return invariantOrUnknown(Expr);
381 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
382 return invariantOrUnknown(Expr);
384 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
385 return invariantOrUnknown(Expr);
388 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
399 bool NormalizeResults) {
400 auto *
F = DA->getFunction();
403 SCEVMonotonicityChecker Checker(&SE);
404 OS <<
"Monotonicity check:\n";
412 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, L);
413 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
414 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
422 if (SrcI->mayReadOrWriteMemory()) {
425 if (DstI->mayReadOrWriteMemory()) {
426 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
427 OS <<
" da analyze - ";
428 if (
auto D = DA->depends(&*SrcI, &*DstI,
434 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
435 const SCEV *Distance =
D->getDistance(Level);
436 bool IsDistanceZero = Distance && Distance->
isZero();
439 assert(IsDistanceZero == IsDirectionEQ &&
440 "Inconsistent distance and direction.");
445 if (NormalizeResults &&
D->normalize(&SE))
446 OS <<
"normalized - ";
448 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
449 if (
D->isSplitable(Level)) {
450 OS <<
" da analyze - split level = " << Level;
451 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
463 OS <<
"Runtime Assumptions:\n";
464 Assumptions.
print(OS, 0);
477 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
490 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
495 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
500 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
505 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
519 bool PossiblyLoopIndependent,
520 unsigned CommonLevels)
521 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
522 LoopIndependent(PossiblyLoopIndependent) {
526 DV = std::make_unique<
DVEntry[]>(CommonLevels);
545 for (
unsigned Level = 1; Level <= Levels; ++Level) {
546 unsigned char Direction = DV[Level - 1].Direction;
561 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
564 for (
unsigned Level = 1; Level <= Levels; ++Level) {
565 unsigned char Direction = DV[Level - 1].Direction;
573 DV[Level - 1].Direction = RevDirection;
575 if (DV[Level - 1].Distance !=
nullptr)
579 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
626 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
627 "Level out of range");
628 return Level > Levels;
636const SCEV *DependenceInfo::Constraint::getX()
const {
637 assert(Kind == Point &&
"Kind should be Point");
643const SCEV *DependenceInfo::Constraint::getY()
const {
644 assert(Kind == Point &&
"Kind should be Point");
650const SCEV *DependenceInfo::Constraint::getA()
const {
651 assert((Kind == Line || Kind == Distance) &&
652 "Kind should be Line (or Distance)");
658const SCEV *DependenceInfo::Constraint::getB()
const {
659 assert((Kind == Line || Kind == Distance) &&
660 "Kind should be Line (or Distance)");
666const SCEV *DependenceInfo::Constraint::getC()
const {
667 assert((Kind == Line || Kind == Distance) &&
668 "Kind should be Line (or Distance)");
674const SCEV *DependenceInfo::Constraint::getD()
const {
675 assert(Kind == Distance &&
"Kind should be Distance");
676 return SE->getNegativeSCEV(
C);
680const Loop *DependenceInfo::Constraint::getAssociatedSrcLoop()
const {
681 assert((Kind == Distance || Kind == Line || Kind == Point) &&
682 "Kind should be Distance, Line, or Point");
683 return AssociatedSrcLoop;
687const Loop *DependenceInfo::Constraint::getAssociatedDstLoop()
const {
688 assert((Kind == Distance || Kind == Line || Kind == Point) &&
689 "Kind should be Distance, Line, or Point");
690 return AssociatedDstLoop;
693void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
694 const Loop *CurSrcLoop,
695 const Loop *CurDstLoop) {
699 AssociatedSrcLoop = CurSrcLoop;
700 AssociatedDstLoop = CurDstLoop;
703void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
704 const SCEV *CC,
const Loop *CurSrcLoop,
705 const Loop *CurDstLoop) {
710 AssociatedSrcLoop = CurSrcLoop;
711 AssociatedDstLoop = CurDstLoop;
714void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
715 const Loop *CurSrcLoop,
716 const Loop *CurDstLoop) {
718 A = SE->getOne(
D->getType());
719 B = SE->getNegativeSCEV(
A);
720 C = SE->getNegativeSCEV(
D);
721 AssociatedSrcLoop = CurSrcLoop;
722 AssociatedDstLoop = CurDstLoop;
725void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
727void DependenceInfo::Constraint::setAny(ScalarEvolution *NewSE) {
732#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
734LLVM_DUMP_METHOD void DependenceInfo::Constraint::dump(raw_ostream &OS)
const {
740 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
741 else if (isDistance())
742 OS <<
" Distance is " << *getD() <<
" (" << *getA() <<
"*X + " << *getB()
743 <<
"*Y = " << *getC() <<
")\n";
745 OS <<
" Line is " << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC()
759bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
764 assert(!
Y->isPoint() &&
"Y must not be a Point");
778 if (
X->isDistance() &&
Y->isDistance()) {
802 assert(!(
X->isPoint() &&
Y->isPoint()) &&
803 "We shouldn't ever see X->isPoint() && Y->isPoint()");
805 if (
X->isLine() &&
Y->isLine()) {
807 const SCEV *Prod1 = SE->getMulExpr(
X->getA(),
Y->getB());
808 const SCEV *Prod2 = SE->getMulExpr(
X->getB(),
Y->getA());
812 Prod1 = SE->getMulExpr(
X->getC(),
Y->getB());
813 Prod2 = SE->getMulExpr(
X->getB(),
Y->getC());
826 const SCEV *C1B2 = SE->getMulExpr(
X->getC(),
Y->getB());
827 const SCEV *C1A2 = SE->getMulExpr(
X->getC(),
Y->getA());
828 const SCEV *C2B1 = SE->getMulExpr(
Y->getC(),
X->getB());
829 const SCEV *C2A1 = SE->getMulExpr(
Y->getC(),
X->getA());
830 const SCEV *A1B2 = SE->getMulExpr(
X->getA(),
Y->getB());
831 const SCEV *A2B1 = SE->getMulExpr(
Y->getA(),
X->getB());
832 const SCEVConstant *C1A2_C2A1 =
834 const SCEVConstant *C1B2_C2B1 =
836 const SCEVConstant *A1B2_A2B1 =
838 const SCEVConstant *A2B1_A1B2 =
840 if (!C1B2_C2B1 || !C1A2_C2A1 || !A1B2_A2B1 || !A2B1_A1B2)
856 if (Xr != 0 || Yr != 0) {
862 if (Xq.
slt(0) || Yq.
slt(0)) {
867 if (
const SCEVConstant *CUB = collectConstantUpperBound(
868 X->getAssociatedSrcLoop(), Prod1->
getType())) {
869 const APInt &UpperBound = CUB->getAPInt();
871 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
877 X->setPoint(SE->getConstant(Xq), SE->getConstant(Yq),
878 X->getAssociatedSrcLoop(),
X->getAssociatedDstLoop());
886 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
888 if (
X->isPoint() &&
Y->isLine()) {
890 const SCEV *A1X1 = SE->getMulExpr(
Y->getA(),
X->getX());
891 const SCEV *B1Y1 = SE->getMulExpr(
Y->getB(),
X->getY());
892 const SCEV *Sum = SE->getAddExpr(A1X1, B1Y1);
910SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
911 const SCEV *FailurePoint)
912 :
Type(
Type), FailurePoint(FailurePoint) {
914 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
915 "FailurePoint must be provided iff Type is Unknown");
921 case SCEVMonotonicityType::Unknown:
922 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
924 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
926 case SCEVMonotonicityType::Invariant:
929 case SCEVMonotonicityType::MultivariateSignedMonotonic:
930 OS <<
"MultivariateSignedMonotonic\n";
935bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
936 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
939SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
940 if (isLoopInvariant(Expr))
941 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
942 return createUnknown(Expr);
946SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
947 const Loop *OutermostLoop) {
949 this->OutermostLoop = OutermostLoop;
965SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
967 return createUnknown(Expr);
972 SCEVMonotonicity StartMon =
visit(Start);
973 if (StartMon.isUnknown())
976 if (!isLoopInvariant(Step))
977 return createUnknown(Expr);
979 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
1002 if (SameSDLevels > 0) {
1003 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
1010 if (!Assumptions.isAlwaysTrue()) {
1011 OS <<
" Runtime Assumptions:\n";
1012 Assumptions.print(OS, 2);
1019 bool Splitable =
false;
1022 bool OnSameSD =
false;
1023 unsigned LevelNum = Levels;
1025 LevelNum += SameSDLevels;
1027 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
1106 return LI->isUnordered();
1108 return SI->isUnordered();
1116bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
1117 const Loop *DstLoop)
const {
1118 if (SrcLoop == DstLoop)
1124 if (!SrcLoop || !SrcLoop->
getLoopLatch() || !DstLoop ||
1128 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
1129 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
1130 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
1131 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
1132 DstUP = SE->getBackedgeTakenCount(DstLoop);
1134 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
1135 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
1136 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
1137 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
1208void DependenceInfo::establishNestingLevels(
const Instruction *Src,
1210 const BasicBlock *SrcBlock = Src->getParent();
1211 const BasicBlock *DstBlock = Dst->getParent();
1212 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
1213 unsigned DstLevel = LI->getLoopDepth(DstBlock);
1214 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
1215 const Loop *DstLoop = LI->getLoopFor(DstBlock);
1216 SrcLevels = SrcLevel;
1217 MaxLevels = SrcLevel + DstLevel;
1219 while (SrcLevel > DstLevel) {
1223 while (DstLevel > SrcLevel) {
1229 while (SrcLoop != DstLoop) {
1231 if (!haveSameSD(SrcLoop, DstLoop))
1237 CommonLevels = SrcLevel;
1238 MaxLevels -= CommonLevels;
1243unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1249unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1251 if (
D > CommonLevels)
1254 return D - CommonLevels + SrcLevels;
1281 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1289 unsigned widestWidthSeen = 0;
1294 for (Subscript *Pair : Pairs) {
1295 const SCEV *Src = Pair->Src;
1296 const SCEV *Dst = Pair->Dst;
1299 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1301 "This function only unify integer types and "
1302 "expect Src and Dst share the same type otherwise.");
1315 assert(widestWidthSeen > 0);
1318 for (Subscript *Pair : Pairs) {
1319 const SCEV *Src = Pair->Src;
1320 const SCEV *Dst = Pair->Dst;
1323 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1325 "This function only unify integer types and "
1326 "expect Src and Dst share the same type otherwise.");
1331 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1334 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1343void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1344 const SCEV *Src = Pair->Src;
1345 const SCEV *Dst = Pair->Dst;
1350 const SCEV *SrcCastOp = SrcCast->
getOperand();
1351 const SCEV *DstCastOp = DstCast->
getOperand();
1353 Pair->Src = SrcCastOp;
1354 Pair->Dst = DstCastOp;
1365 return isLoopInvariant(Expr, LoopNest);
1372 const Loop *
L = LoopNest;
1373 while (L && AddRec->
getLoop() != L)
1374 L =
L->getParentLoop();
1380 if (!isLoopInvariant(Step, LoopNest))
1386 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1391bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1393 return checkSubscript(Src, LoopNest,
Loops,
true);
1398bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1400 return checkSubscript(Dst, LoopNest,
Loops,
false);
1406DependenceInfo::Subscript::ClassificationKind
1407DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1408 const SCEV *Dst,
const Loop *DstLoopNest,
1410 SmallBitVector SrcLoops(MaxLevels + 1);
1411 SmallBitVector DstLoops(MaxLevels + 1);
1412 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1413 return Subscript::NonLinear;
1414 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1415 return Subscript::NonLinear;
1418 unsigned N =
Loops.count();
1420 return Subscript::ZIV;
1422 return Subscript::SIV;
1423 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1424 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1425 return Subscript::RDIV;
1426 return Subscript::MIV;
1440 const SCEV *
Y)
const {
1454 if (SE->isKnownPredicate(Pred,
X,
Y))
1461 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1466 return SE->isKnownNonZero(Delta);
1468 return SE->isKnownNonNegative(Delta);
1470 return SE->isKnownNonPositive(Delta);
1472 return SE->isKnownPositive(Delta);
1474 return SE->isKnownNegative(Delta);
1486bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1490 if (!SType || !SizeType)
1493 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1494 S = SE->getTruncateOrZeroExtend(S, MaxType);
1495 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1497 auto CheckAddRecBECount = [&]() {
1501 const SCEV *BECount = collectUpperBound(AddRec->
getLoop(), MaxType);
1508 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1509 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1514 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1519 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1524 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1530 if (CheckAddRecBECount())
1534 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1535 return SE->isKnownNegative(LimitedBound);
1538bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1539 bool Inbounds =
false;
1541 Inbounds = SrcGEP->isInBounds();
1547 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1548 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1554 return SE->isKnownNonNegative(S);
1564const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1565 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1566 const SCEV *UB = SE->getBackedgeTakenCount(L);
1567 return SE->getTruncateOrZeroExtend(UB,
T);
1574const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1576 if (
const SCEV *UB = collectUpperBound(L,
T))
1624bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1639 Result.Consistent =
false;
1670bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1671 const SCEV *DstConst,
const Loop *CurSrcLoop,
1672 const Loop *CurDstLoop,
unsigned Level,
1674 Constraint &NewConstraint)
const {
1685 ++StrongSIVapplications;
1686 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1689 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1694 bool IsDeltaLarge = [&] {
1695 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1703 if (!AbsDelta || !AbsCoeff)
1705 const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
1710 ++StrongSIVindependence;
1711 ++StrongSIVsuccesses;
1719 APInt Distance = ConstDelta;
1720 APInt Remainder = ConstDelta;
1725 if (Remainder != 0) {
1727 ++StrongSIVindependence;
1728 ++StrongSIVsuccesses;
1731 Result.DV[
Level].Distance = SE->getConstant(Distance);
1732 NewConstraint.setDistance(SE->getConstant(Distance), CurSrcLoop,
1734 if (Distance.
sgt(0))
1736 else if (Distance.
slt(0))
1740 ++StrongSIVsuccesses;
1741 }
else if (Delta->
isZero()) {
1744 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1746 ++StrongSIVsuccesses;
1748 if (Coeff->
isOne()) {
1751 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1753 Result.Consistent =
false;
1754 NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
1755 SE->getNegativeSCEV(Delta), CurSrcLoop, CurDstLoop);
1759 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1760 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1761 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1762 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1763 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1768 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1769 (DeltaMaybeNegative && CoeffMaybeNegative))
1773 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1774 (DeltaMaybePositive && CoeffMaybeNegative))
1776 if (NewDirection <
Result.DV[Level].Direction)
1777 ++StrongSIVsuccesses;
1811bool DependenceInfo::weakCrossingSIVtest(
1812 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1813 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
1815 const SCEV *&SplitIter)
const {
1823 ++WeakCrossingSIVapplications;
1824 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1826 Result.Consistent =
false;
1827 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1829 NewConstraint.setLine(Coeff, Coeff, Delta, CurSrcLoop, CurDstLoop);
1831 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1832 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1833 ++WeakCrossingSIVsuccesses;
1834 if (!
Result.DV[Level].Direction) {
1835 ++WeakCrossingSIVindependence;
1846 if (SE->isKnownNegative(ConstCoeff)) {
1849 "dynamic cast of negative of ConstCoeff should yield constant");
1850 Delta = SE->getNegativeSCEV(Delta);
1852 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1855 SplitIter = SE->getUDivExpr(
1856 SE->getSMaxExpr(SE->getZero(Delta->
getType()), Delta),
1857 SE->getMulExpr(SE->getConstant(Delta->
getType(), 2), ConstCoeff));
1868 if (SE->isKnownNegative(Delta)) {
1870 ++WeakCrossingSIVindependence;
1871 ++WeakCrossingSIVsuccesses;
1877 if (
const SCEV *UpperBound =
1878 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1880 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1882 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1886 ++WeakCrossingSIVindependence;
1887 ++WeakCrossingSIVsuccesses;
1892 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1893 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1894 ++WeakCrossingSIVsuccesses;
1895 if (!
Result.DV[Level].Direction) {
1896 ++WeakCrossingSIVindependence;
1906 APInt APDelta = ConstDelta->
getAPInt();
1907 APInt APCoeff = ConstCoeff->
getAPInt();
1908 APInt Distance = APDelta;
1909 APInt Remainder = APDelta;
1912 if (Remainder != 0) {
1914 ++WeakCrossingSIVindependence;
1915 ++WeakCrossingSIVsuccesses;
1921 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1922 Remainder = Distance.
srem(Two);
1924 if (Remainder != 0) {
1926 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1927 ++WeakCrossingSIVsuccesses;
1944 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1945 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1953 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1954 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1961 X = AM.
slt(0) ? -A1 : A1;
1962 Y = BM.
slt(0) ? B1 : -B1;
1978 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1990 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
2025static std::pair<std::optional<APInt>, std::optional<APInt>>
2027 const std::optional<APInt> &UB) {
2028 assert(
A != 0 &&
"A must be non-zero");
2029 std::optional<APInt> TL, TU;
2049 return std::make_pair(TL, TU);
2071bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2072 const SCEV *SrcConst,
const SCEV *DstConst,
2073 const Loop *CurSrcLoop,
2074 const Loop *CurDstLoop,
unsigned Level,
2076 Constraint &NewConstraint)
const {
2081 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2082 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2085 ++ExactSIVapplications;
2086 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
2088 Result.Consistent =
false;
2093 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
2094 CurSrcLoop, CurDstLoop);
2098 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2103 APInt AM = ConstSrcCoeff->
getAPInt();
2104 APInt BM = ConstDstCoeff->
getAPInt();
2109 ++ExactSIVindependence;
2110 ++ExactSIVsuccesses;
2117 std::optional<APInt> UM;
2119 if (
const SCEVConstant *CUB =
2120 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
2121 UM = CUB->getAPInt();
2127 APInt TC = CM.
sdiv(
G);
2149 auto CreateVec = [](
const std::optional<APInt> &V0,
2150 const std::optional<APInt> &V1) {
2173 ++ExactSIVindependence;
2174 ++ExactSIVsuccesses;
2180 APInt LowerDistance, UpperDistance;
2183 LowerDistance = (TY - TX) + (TA - TB) * TL;
2184 UpperDistance = (TY - TX) + (TA - TB) * TU;
2186 LowerDistance = (TY - TX) + (TA - TB) * TU;
2187 UpperDistance = (TY - TX) + (TA - TB) * TL;
2190 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
2191 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
2193 APInt
Zero(Bits, 0,
true);
2194 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
2196 ++ExactSIVsuccesses;
2198 if (LowerDistance.
slt(0)) {
2200 ++ExactSIVsuccesses;
2202 if (UpperDistance.
sgt(0)) {
2204 ++ExactSIVsuccesses;
2210 ++ExactSIVindependence;
2221 return ConstDividend.
srem(ConstDivisor) == 0;
2255bool DependenceInfo::weakZeroSrcSIVtest(
2256 const SCEV *DstCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2257 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2269 ++WeakZeroSIVapplications;
2270 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
2272 Result.Consistent =
false;
2273 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
2274 NewConstraint.setLine(SE->getZero(Delta->
getType()), DstCoeff, Delta,
2275 CurSrcLoop, CurDstLoop);
2278 if (Level < CommonLevels) {
2281 ++WeakZeroSIVsuccesses;
2291 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2292 ? SE->getNegativeSCEV(ConstCoeff)
2294 const SCEV *NewDelta =
2295 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2299 if (
const SCEV *UpperBound =
2300 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2302 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2304 ++WeakZeroSIVindependence;
2305 ++WeakZeroSIVsuccesses;
2310 if (Level < CommonLevels) {
2313 ++WeakZeroSIVsuccesses;
2321 if (SE->isKnownNegative(NewDelta)) {
2323 ++WeakZeroSIVindependence;
2324 ++WeakZeroSIVsuccesses;
2331 ++WeakZeroSIVindependence;
2332 ++WeakZeroSIVsuccesses;
2369bool DependenceInfo::weakZeroDstSIVtest(
2370 const SCEV *SrcCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2371 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2382 ++WeakZeroSIVapplications;
2383 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2385 Result.Consistent =
false;
2386 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2387 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->
getType()), Delta,
2388 CurSrcLoop, CurDstLoop);
2391 if (Level < CommonLevels) {
2394 ++WeakZeroSIVsuccesses;
2404 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2405 ? SE->getNegativeSCEV(ConstCoeff)
2407 const SCEV *NewDelta =
2408 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2412 if (
const SCEV *UpperBound =
2413 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2415 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2417 ++WeakZeroSIVindependence;
2418 ++WeakZeroSIVsuccesses;
2423 if (Level < CommonLevels) {
2426 ++WeakZeroSIVsuccesses;
2434 if (SE->isKnownNegative(NewDelta)) {
2436 ++WeakZeroSIVindependence;
2437 ++WeakZeroSIVsuccesses;
2444 ++WeakZeroSIVindependence;
2445 ++WeakZeroSIVsuccesses;
2458bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2459 const SCEV *SrcConst,
const SCEV *DstConst,
2460 const Loop *SrcLoop,
const Loop *DstLoop,
2466 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2467 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2470 ++ExactRDIVapplications;
2471 Result.Consistent =
false;
2472 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2477 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2482 APInt AM = ConstSrcCoeff->
getAPInt();
2483 APInt BM = ConstDstCoeff->
getAPInt();
2488 ++ExactRDIVindependence;
2495 std::optional<APInt> SrcUM;
2497 if (
const SCEVConstant *UpperBound =
2498 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2499 SrcUM = UpperBound->getAPInt();
2503 std::optional<APInt> DstUM;
2505 if (
const SCEVConstant *UpperBound =
2506 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2507 DstUM = UpperBound->getAPInt();
2513 APInt TC = CM.
sdiv(
G);
2538 auto CreateVec = [](
const std::optional<APInt> &V0,
2539 const std::optional<APInt> &V1) {
2559 ++ExactRDIVindependence;
2605bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2608 const Loop *Loop2)
const {
2612 ++SymbolicRDIVapplications;
2619 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2620 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2623 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2624 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2627 if (SE->isKnownNonNegative(A1)) {
2628 if (SE->isKnownNonNegative(A2)) {
2632 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2635 ++SymbolicRDIVindependence;
2641 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2644 ++SymbolicRDIVindependence;
2648 }
else if (SE->isKnownNonPositive(A2)) {
2652 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2653 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2654 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2655 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2657 ++SymbolicRDIVindependence;
2662 if (SE->isKnownNegative(C2_C1)) {
2663 ++SymbolicRDIVindependence;
2667 }
else if (SE->isKnownNonPositive(A1)) {
2668 if (SE->isKnownNonNegative(A2)) {
2672 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2673 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2674 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2675 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2677 ++SymbolicRDIVindependence;
2682 if (SE->isKnownPositive(C2_C1)) {
2683 ++SymbolicRDIVindependence;
2686 }
else if (SE->isKnownNonPositive(A2)) {
2690 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2693 ++SymbolicRDIVindependence;
2699 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2702 ++SymbolicRDIVindependence;
2719bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2721 const SCEV *&SplitIter)
const {
2726 if (SrcAddRec && DstAddRec) {
2727 const SCEV *SrcConst = SrcAddRec->
getStart();
2728 const SCEV *DstConst = DstAddRec->
getStart();
2731 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2732 const Loop *CurDstLoop = DstAddRec->
getLoop();
2733 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2734 "Loops in the SIV test should have the same iteration space and "
2736 Level = mapSrcLoop(CurSrcLoop);
2738 if (SrcCoeff == DstCoeff)
2739 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2740 CurDstLoop, Level, Result, NewConstraint);
2741 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2742 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2743 CurDstLoop, Level, Result, NewConstraint,
2747 exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2748 CurDstLoop, Level, Result, NewConstraint);
2749 return disproven || gcdMIVtest(Src, Dst, Result) ||
2750 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2754 const SCEV *SrcConst = SrcAddRec->
getStart();
2756 const SCEV *DstConst = Dst;
2757 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2758 Level = mapSrcLoop(CurSrcLoop);
2759 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2760 CurSrcLoop, Level, Result, NewConstraint) ||
2761 gcdMIVtest(Src, Dst, Result);
2764 const SCEV *DstConst = DstAddRec->
getStart();
2766 const SCEV *SrcConst = Src;
2767 const Loop *CurDstLoop = DstAddRec->
getLoop();
2768 Level = mapDstLoop(CurDstLoop);
2769 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2770 CurDstLoop, Level, Result, NewConstraint) ||
2771 gcdMIVtest(Src, Dst, Result);
2790bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2798 const SCEV *SrcConst, *DstConst;
2799 const SCEV *SrcCoeff, *DstCoeff;
2800 const Loop *SrcLoop, *DstLoop;
2806 if (SrcAddRec && DstAddRec) {
2809 SrcLoop = SrcAddRec->
getLoop();
2812 DstLoop = DstAddRec->
getLoop();
2813 }
else if (SrcAddRec) {
2814 if (
const SCEVAddRecExpr *tmpAddRec =
2816 SrcConst = tmpAddRec->getStart();
2817 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2818 SrcLoop = tmpAddRec->getLoop();
2821 DstLoop = SrcAddRec->
getLoop();
2824 }
else if (DstAddRec) {
2825 if (
const SCEVAddRecExpr *tmpAddRec =
2827 DstConst = tmpAddRec->getStart();
2828 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2829 DstLoop = tmpAddRec->getLoop();
2832 SrcLoop = DstAddRec->
getLoop();
2837 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2839 gcdMIVtest(Src, Dst, Result) ||
2840 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2847bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2852 Result.Consistent =
false;
2853 return gcdMIVtest(Src, Dst, Result) ||
2854 banerjeeMIVtest(Src, Dst,
Loops, Result);
2867 if (Product->hasNoSignedWrap())
2869 return std::nullopt;
2872bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2873 const Loop *CurLoop,
2874 const SCEV *&CurLoopCoeff,
2875 APInt &RunningGCD)
const {
2878 if (RunningGCD == 1)
2883 assert(isLoopInvariant(Expr, CurLoop) &&
2884 "Expected loop invariant expression");
2891 if (AddRec->
getLoop() == CurLoop) {
2892 CurLoopCoeff = Step;
2906 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2927bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2934 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2941 const SCEV *Coefficients = Src;
2942 while (
const SCEVAddRecExpr *AddRec =
2953 const SCEV *SrcConst = Coefficients;
2960 while (
const SCEVAddRecExpr *AddRec =
2971 const SCEV *DstConst = Coefficients;
2974 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2979 for (
const SCEV *Operand : Sum->
operands()) {
2981 assert(!Constant &&
"Surprised to find multiple constants");
2998 if (ConstDelta == 0)
3002 APInt Remainder = ConstDelta.
srem(RunningGCD);
3003 if (Remainder != 0) {
3022 bool Improved =
false;
3024 while (
const SCEVAddRecExpr *AddRec =
3027 const Loop *CurLoop = AddRec->
getLoop();
3028 RunningGCD = ExtraGCD;
3030 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
3032 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
3033 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
3036 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
3046 if (RunningGCD != 0) {
3047 Remainder = ConstDelta.
srem(RunningGCD);
3049 if (Remainder != 0) {
3050 unsigned Level = mapSrcLoop(CurLoop);
3051 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
3095bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
3102 ++BanerjeeApplications;
3105 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
3108 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
3109 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
3110 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
3115 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3116 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
3119 findBoundsALL(
A,
B, Bound, K);
3134 bool Disproved =
false;
3137 unsigned DepthExpanded = 0;
3139 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
3141 bool Improved =
false;
3142 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3144 unsigned Old =
Result.DV[
K - 1].Direction;
3145 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
3146 Improved |= Old !=
Result.DV[
K - 1].Direction;
3147 if (!
Result.DV[K - 1].Direction) {
3155 ++BanerjeeSuccesses;
3157 ++BanerjeeIndependence;
3161 ++BanerjeeIndependence;
3175unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
3176 CoefficientInfo *
B, BoundInfo *Bound,
3178 unsigned &DepthExpanded,
3179 const SCEV *Delta)
const {
3185 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
3186 "direction exploration is terminated.\n");
3187 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
3193 if (Level > CommonLevels) {
3196 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3198 Bound[
K].DirSet |= Bound[
K].Direction;
3223 if (Level > DepthExpanded) {
3224 DepthExpanded =
Level;
3226 findBoundsLT(
A,
B, Bound, Level);
3227 findBoundsGT(
A,
B, Bound, Level);
3228 findBoundsEQ(
A,
B, Bound, Level);
3267 unsigned NewDeps = 0;
3271 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3276 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3281 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3287 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3292bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
3293 BoundInfo *Bound,
const SCEV *Delta)
const {
3294 Bound[
Level].Direction = DirKind;
3295 if (
const SCEV *LowerBound = getLowerBound(Bound))
3298 if (
const SCEV *UpperBound = getUpperBound(Bound))
3319void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
3320 BoundInfo *Bound,
unsigned K)
const {
3325 if (Bound[K].Iterations) {
3327 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3329 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3334 SE->getZero(
A[K].Coeff->
getType());
3337 SE->getZero(
A[K].Coeff->
getType());
3356void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3357 BoundInfo *Bound,
unsigned K)
const {
3362 if (Bound[K].Iterations) {
3363 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3364 const SCEV *NegativePart = getNegativePart(Delta);
3366 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3367 const SCEV *PositivePart = getPositivePart(Delta);
3369 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3373 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3374 const SCEV *NegativePart = getNegativePart(Delta);
3375 if (NegativePart->
isZero())
3377 const SCEV *PositivePart = getPositivePart(Delta);
3378 if (PositivePart->
isZero())
3396void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3397 BoundInfo *Bound,
unsigned K)
const {
3402 if (Bound[K].Iterations) {
3403 const SCEV *Iter_1 = SE->getMinusSCEV(
3404 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3405 const SCEV *NegPart =
3406 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3408 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3409 const SCEV *PosPart =
3410 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3412 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3416 const SCEV *NegPart =
3417 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3420 const SCEV *PosPart =
3421 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3440void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3441 BoundInfo *Bound,
unsigned K)
const {
3446 if (Bound[K].Iterations) {
3447 const SCEV *Iter_1 = SE->getMinusSCEV(
3448 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3449 const SCEV *NegPart =
3450 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3452 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3453 const SCEV *PosPart =
3454 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3456 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3460 const SCEV *NegPart =
3461 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3464 const SCEV *PosPart =
3465 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3472const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3473 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3477const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3478 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3484DependenceInfo::CoefficientInfo *
3485DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3487 const SCEV *
Zero = SE->getZero(Subscript->getType());
3488 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3489 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3491 CI[
K].PosPart =
Zero;
3492 CI[
K].NegPart =
Zero;
3493 CI[
K].Iterations =
nullptr;
3497 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3499 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3500 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3501 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3507 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3514 if (CI[K].Iterations)
3529const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3530 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3531 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3544const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3545 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3546 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3564const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3565 const Loop *TargetLoop)
const {
3568 return SE->getZero(Expr->
getType());
3569 if (AddRec->
getLoop() == TargetLoop)
3571 return findCoefficient(AddRec->
getStart(), TargetLoop);
3579const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3580 const Loop *TargetLoop)
const {
3584 if (AddRec->
getLoop() == TargetLoop)
3586 return SE->getAddRecExpr(zeroCoefficient(AddRec->
getStart(), TargetLoop),
3596const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3597 const Loop *TargetLoop,
3601 return SE->getAddRecExpr(Expr,
Value, TargetLoop,
3603 if (AddRec->
getLoop() == TargetLoop) {
3610 if (SE->isLoopInvariant(AddRec, TargetLoop))
3612 return SE->getAddRecExpr(
3628bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3633 for (
unsigned LI :
Loops.set_bits()) {
3636 if (Constraints[LI].isDistance())
3637 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3638 else if (Constraints[LI].isLine())
3639 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3640 else if (Constraints[LI].isPoint())
3641 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3651bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3652 Constraint &CurConstraint,
3654 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3655 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3657 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3660 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3661 Src = SE->getMinusSCEV(Src, DA_K);
3662 Src = zeroCoefficient(Src, CurSrcLoop);
3665 Dst = addToCoefficient(Dst, CurDstLoop, SE->getNegativeSCEV(A_K));
3667 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3677bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3678 Constraint &CurConstraint,
3680 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3681 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3682 const SCEV *
A = CurConstraint.getA();
3683 const SCEV *
B = CurConstraint.getB();
3684 const SCEV *
C = CurConstraint.getC();
3692 if (!Bconst || !Cconst)
3695 APInt Charlie = Cconst->
getAPInt();
3696 APInt CdivB = Charlie.
sdiv(Beta);
3697 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3698 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3699 Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
3700 Dst = zeroCoefficient(Dst, CurDstLoop);
3701 if (!findCoefficient(Src, CurSrcLoop)->
isZero())
3703 }
else if (
B->isZero()) {
3706 if (!Aconst || !Cconst)
3709 APInt Charlie = Cconst->
getAPInt();
3710 APInt CdivA = Charlie.
sdiv(Alpha);
3711 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3712 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3713 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3714 Src = zeroCoefficient(Src, CurSrcLoop);
3715 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3720 if (!Aconst || !Cconst)
3723 APInt Charlie = Cconst->
getAPInt();
3724 APInt CdivA = Charlie.
sdiv(Alpha);
3725 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3726 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3727 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3728 Src = zeroCoefficient(Src, CurSrcLoop);
3729 Dst = addToCoefficient(Dst, CurDstLoop, A_K);
3730 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3734 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3735 Src = SE->getMulExpr(Src,
A);
3736 Dst = SE->getMulExpr(Dst,
A);
3737 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K,
C));
3738 Src = zeroCoefficient(Src, CurSrcLoop);
3739 Dst = addToCoefficient(Dst, CurDstLoop, SE->getMulExpr(A_K,
B));
3740 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3751bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3752 Constraint &CurConstraint) {
3753 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3754 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3755 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3756 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3757 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3758 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3760 Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
3761 Src = zeroCoefficient(Src, CurSrcLoop);
3764 Dst = zeroCoefficient(Dst, CurDstLoop);
3771 const Constraint &CurConstraint)
const {
3774 if (CurConstraint.isAny())
3776 else if (CurConstraint.isDistance()) {
3778 Level.Scalar =
false;
3779 Level.Distance = CurConstraint.getD();
3781 if (!SE->isKnownNonZero(
Level.Distance))
3783 if (!SE->isKnownNonPositive(
Level.Distance))
3785 if (!SE->isKnownNonNegative(
Level.Distance))
3787 Level.Direction &= NewDirection;
3788 }
else if (CurConstraint.isLine()) {
3789 Level.Scalar =
false;
3790 Level.Distance =
nullptr;
3792 }
else if (CurConstraint.isPoint()) {
3793 Level.Scalar =
false;
3794 Level.Distance =
nullptr;
3797 CurConstraint.getX()))
3801 CurConstraint.getX()))
3805 CurConstraint.getX()))
3808 Level.Direction &= NewDirection;
3823 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3824 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3825 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3826 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3827 const SCEVUnknown *SrcBase =
3829 const SCEVUnknown *DstBase =
3832 if (!SrcBase || !DstBase || SrcBase != DstBase)
3837 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3838 SrcSubscripts, DstSubscripts) &&
3839 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3840 SrcSubscripts, DstSubscripts))
3843 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3844 isLoopInvariant(DstBase, DstLoop) &&
3845 "Expected SrcBase and DstBase to be loop invariant");
3849 dbgs() <<
"\nSrcSubscripts: ";
3850 for (
int I = 0;
I <
Size;
I++)
3851 dbgs() << *SrcSubscripts[
I];
3852 dbgs() <<
"\nDstSubscripts: ";
3853 for (
int I = 0;
I <
Size;
I++)
3854 dbgs() << *DstSubscripts[
I];
3862 SCEVMonotonicityChecker MonChecker(SE);
3863 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3864 for (
int I = 0;
I <
Size; ++
I) {
3865 Pair[
I].Src = SrcSubscripts[
I];
3866 Pair[
I].Dst = DstSubscripts[
I];
3867 unifySubscriptType(&Pair[
I]);
3870 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3872 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3883bool DependenceInfo::tryDelinearizeFixedSize(
3888 const SCEVUnknown *SrcBase =
3890 const SCEVUnknown *DstBase =
3892 assert(SrcBase && DstBase && SrcBase == DstBase &&
3893 "expected src and dst scev unknowns to be equal");
3896 SmallVector<int, 4> SrcSizes;
3897 SmallVector<int, 4> DstSizes;
3906 if (SrcSizes.size() != DstSizes.
size() ||
3907 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3908 SrcSubscripts.
clear();
3909 DstSubscripts.
clear();
3914 "Expected equal number of entries in the list of SrcSubscripts and "
3927 auto AllIndicesInRange = [&](SmallVector<int, 4> &DimensionSizes,
3928 SmallVectorImpl<const SCEV *> &Subscripts,
3930 size_t SSize = Subscripts.
size();
3931 for (
size_t I = 1;
I < SSize; ++
I) {
3932 const SCEV *S = Subscripts[
I];
3935 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3936 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *
Ptr <<
"\n";
3941 const SCEV *
Range = SE->getConstant(
3942 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3943 if (!isKnownLessThan(S,
Range)) {
3945 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3946 dbgs() <<
" S: " << *S <<
"\n"
3947 <<
" Range: " << *
Range <<
"\n";
3956 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3957 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3959 SrcSubscripts.
clear();
3960 DstSubscripts.
clear();
3965 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3966 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3967 <<
"DstGEP:" << *DstPtr <<
"\n";
3972bool DependenceInfo::tryDelinearizeParametricSize(
3979 const SCEVUnknown *SrcBase =
3981 const SCEVUnknown *DstBase =
3983 assert(SrcBase && DstBase && SrcBase == DstBase &&
3984 "expected src and dst scev unknowns to be equal");
3986 const SCEV *ElementSize = SE->getElementSize(Src);
3987 if (ElementSize != SE->getElementSize(Dst))
3990 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3991 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
4012 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
4013 SrcSubscripts.
size() != DstSubscripts.
size())
4016 size_t Size = SrcSubscripts.
size();
4025 for (
size_t I = 1;
I <
Size; ++
I) {
4028 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
4029 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
4030 if (SNN && DNN && SLT && DLT)
4034 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
4036 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
4038 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
4040 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
4041 << *
Sizes[
I - 1] <<
")\n";
4043 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
4044 << *
Sizes[
I - 1] <<
")\n";
4058 for (
unsigned VI : BV.
set_bits()) {
4068 FunctionAnalysisManager::Invalidator &Inv) {
4075 return Inv.invalidate<
AAManager>(F, PA) ||
4095std::unique_ptr<Dependence>
4097 bool UnderRuntimeAssumptions) {
4099 bool PossiblyLoopIndependent =
true;
4101 PossiblyLoopIndependent =
false;
4103 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
4109 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
4110 return std::make_unique<Dependence>(Src, Dst,
4122 return std::make_unique<Dependence>(Src, Dst,
4136 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
4137 return std::make_unique<Dependence>(Src, Dst,
4143 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4144 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4147 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
4148 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
4149 if (SrcBase != DstBase) {
4156 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
4157 return std::make_unique<Dependence>(Src, Dst,
4165 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
4166 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
4167 if (!isLoopInvariant(SrcBase, SrcLoop) ||
4168 !isLoopInvariant(DstBase, DstLoop)) {
4169 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
4170 return std::make_unique<Dependence>(Src, Dst,
4175 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
4176 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
4179 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
4180 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
4181 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
4182 return std::make_unique<Dependence>(Src, Dst,
4186 if (!Assume.empty()) {
4187 if (!UnderRuntimeAssumptions)
4188 return std::make_unique<Dependence>(Src, Dst,
4191 unsigned N = Assumptions.size();
4193 bool Implied =
false;
4194 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
4195 if (Assumptions[
I]->implies(
P, *SE))
4198 Assumptions.push_back(
P);
4204 Pair[0].Src = SrcEv;
4205 Pair[0].Dst = DstEv;
4207 SCEVMonotonicityChecker MonChecker(SE);
4210 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
4211 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
4212 return std::make_unique<Dependence>(Src, Dst,
4216 if (tryDelinearize(Src, Dst, Pair)) {
4218 Pairs = Pair.
size();
4223 establishNestingLevels(Src, Dst);
4225 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
4226 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
4227 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
4230 CommonLevels += SameSDLevels;
4231 MaxLevels -= SameSDLevels;
4232 if (SameSDLevels > 0) {
4235 for (
unsigned P = 0;
P < Pairs; ++
P) {
4237 Subscript::ClassificationKind TestClass =
4238 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
4239 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
4241 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
4242 TestClass != Subscript::RDIV) {
4244 CommonLevels -= SameSDLevels;
4245 MaxLevels += SameSDLevels;
4252 if (SameSDLevels > 0)
4256 PossiblyLoopIndependent, CommonLevels);
4259 for (
unsigned P = 0;
P < Pairs; ++
P) {
4260 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4261 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4262 Pair[
P].Loops.
resize(MaxLevels + 1);
4263 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4265 removeMatchingExtensions(&Pair[
P]);
4266 Pair[
P].Classification =
4267 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4268 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4269 Pair[
P].GroupLoops = Pair[
P].Loops;
4270 Pair[
P].Group.set(
P);
4339 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4340 if (Pair[
SI].Classification == Subscript::NonLinear) {
4342 ++NonlinearSubscriptPairs;
4343 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4345 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4347 Result.Consistent =
false;
4348 }
else if (Pair[
SI].Classification == Subscript::ZIV) {
4354 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4356 Intersection &= Pair[SJ].GroupLoops;
4357 if (Intersection.
any()) {
4359 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4361 Pair[SJ].Group |= Pair[
SI].Group;
4366 if (Pair[
SI].Group.count() == 1) {
4368 ++SeparableSubscriptPairs;
4371 ++CoupledSubscriptPairs;
4382 Constraint NewConstraint;
4383 NewConstraint.setAny(SE);
4388 switch (Pair[
SI].Classification) {
4389 case Subscript::ZIV:
4391 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4394 case Subscript::SIV: {
4397 const SCEV *SplitIter =
nullptr;
4398 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4403 case Subscript::RDIV:
4405 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4408 case Subscript::MIV:
4410 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
4418 if (Coupled.
count()) {
4421 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
4423 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4424 Constraints[
II].setAny(SE);
4432 for (
unsigned SJ : Group.set_bits()) {
4434 if (Pair[SJ].Classification == Subscript::SIV)
4440 unifySubscriptType(PairsInGroup);
4442 while (Sivs.
any()) {
4444 for (
unsigned SJ : Sivs.
set_bits()) {
4448 const SCEV *SplitIter =
nullptr;
4450 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4453 ConstrainedLevels.
set(Level);
4454 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
4455 if (Constraints[Level].isEmpty()) {
4456 ++DeltaIndependence;
4468 for (
unsigned SJ : Mivs.
set_bits()) {
4471 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
4472 Constraints, Result.Consistent)) {
4474 ++DeltaPropagations;
4475 Pair[SJ].Classification = classifyPair(
4476 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4477 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4478 switch (Pair[SJ].Classification) {
4479 case Subscript::ZIV:
4481 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4485 case Subscript::SIV:
4489 case Subscript::RDIV:
4490 case Subscript::MIV:
4501 for (
unsigned SJ : Mivs.
set_bits()) {
4502 if (Pair[SJ].Classification == Subscript::RDIV) {
4504 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4514 for (
unsigned SJ : Mivs.
set_bits()) {
4515 if (Pair[SJ].Classification == Subscript::MIV) {
4517 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
4525 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
4526 if (SJ > CommonLevels)
4528 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
4537 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
4538 CompleteLoops |= Pair[
SI].
Loops;
4539 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
4540 if (CompleteLoops[
II])
4541 Result.DV[
II - 1].Scalar =
false;
4546 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
4548 if (Result.DV[
II - 1].Distance ==
nullptr)
4549 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
4551 assert(Result.DV[
II - 1].Distance->isZero() &&
4552 "Inconsistency between distance and direction");
4558 const SCEV *Distance = Result.getDistance(
II);
4559 if (Distance && Distance->
isZero())
4561 "Distance is zero, but direction is not EQ");
4565 if (SameSDLevels > 0) {
4568 assert(CommonLevels >= SameSDLevels);
4569 CommonLevels -= SameSDLevels;
4570 MaxLevels += SameSDLevels;
4571 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
4572 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
4573 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
4574 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
4575 DV[Level] = Result.DV[Level];
4576 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
4577 DVSameSD[Level] = Result.DV[CommonLevels + Level];
4578 Result.DV = std::move(DV);
4579 Result.DVSameSD = std::move(DVSameSD);
4580 Result.Levels = CommonLevels;
4581 Result.SameSDLevels = SameSDLevels;
4583 Result.Consistent =
false;
4586 if (PossiblyLoopIndependent) {
4590 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4592 Result.LoopIndependent =
false;
4599 bool AllEqual =
true;
4600 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4610 return std::make_unique<FullDependence>(std::move(Result));
4661 unsigned SplitLevel) {
4663 "Dep should be splitable at SplitLevel");
4666 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4667 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4677 establishNestingLevels(Src, Dst);
4679 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4683 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4684 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4685 Pair[0].Src = SE->removePointerBase(SrcSCEV);
4686 Pair[0].Dst = SE->removePointerBase(DstSCEV);
4689 if (tryDelinearize(Src, Dst, Pair)) {
4691 Pairs = Pair.
size();
4695 for (
unsigned P = 0;
P < Pairs; ++
P) {
4696 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4697 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4698 Pair[
P].Loops.
resize(MaxLevels + 1);
4699 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4701 removeMatchingExtensions(&Pair[
P]);
4702 Pair[
P].Classification =
4703 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4704 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4705 Pair[
P].GroupLoops = Pair[
P].Loops;
4706 Pair[
P].Group.set(
P);
4713 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4714 if (Pair[
SI].Classification == Subscript::NonLinear) {
4716 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4718 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4720 Result.Consistent =
false;
4721 }
else if (Pair[
SI].Classification == Subscript::ZIV)
4726 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4728 Intersection &= Pair[SJ].GroupLoops;
4729 if (Intersection.
any()) {
4731 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4733 Pair[SJ].Group |= Pair[
SI].Group;
4738 if (Pair[
SI].Group.count() == 1)
4746 Constraint NewConstraint;
4747 NewConstraint.setAny(SE);
4751 switch (Pair[
SI].Classification) {
4752 case Subscript::SIV: {
4754 const SCEV *SplitIter =
nullptr;
4755 (void)testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4757 if (Level == SplitLevel) {
4758 assert(SplitIter !=
nullptr);
4763 case Subscript::ZIV:
4764 case Subscript::RDIV:
4765 case Subscript::MIV:
4772 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4776 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4777 Constraints[
II].setAny(SE);
4783 for (
unsigned SJ : Group.set_bits()) {
4784 if (Pair[SJ].Classification == Subscript::SIV)
4789 while (Sivs.
any()) {
4791 for (
unsigned SJ : Sivs.
set_bits()) {
4794 const SCEV *SplitIter =
nullptr;
4795 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4797 if (Level == SplitLevel && SplitIter)
4799 ConstrainedLevels.
set(Level);
4800 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4807 for (
unsigned SJ : Mivs.
set_bits()) {
4809 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4812 Pair[SJ].Classification = classifyPair(
4813 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4814 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4815 switch (Pair[SJ].Classification) {
4816 case Subscript::ZIV:
4819 case Subscript::SIV:
4823 case Subscript::RDIV:
4824 case Subscript::MIV:
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)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
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 void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, LoopInfo &LI, bool NormalizeResults)
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 APInt ceilingOfQuotient(const APInt &A, const APInt &B)
static APInt floorOfQuotient(const APInt &A, const APInt &B)
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 > getConstanCoefficient(const SCEV *Expr)
Given a SCEVMulExpr, returns its first operand if its first operand is a constant and the product doe...
static std::pair< std::optional< APInt >, std::optional< APInt > > inferDomainOfAffine(const APInt &A, const APInt &B, const std::optional< APInt > &UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
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 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.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Loop::LoopBounds::Direction Direction
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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)
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
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.
bool sle(const APInt &RHS) const
Signed less or equal comparison.
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.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI const SCEV * getSplitIteration(const Dependence &Dep, unsigned Level)
getSplitIteration - Give a dependence that's splittable at some particular level, return the iteratio...
LLVM_ABI SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns all the runtime assumptions under which the dependence test is valid.
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.
Dependence - This class represents a dependence between two memory memory references in a function.
Instruction * getDst() const
getDst - Returns the destination instruction for this dependence.
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 isSplitable(unsigned Level, bool SameSD=false) const
isSplitable - Returns true if splitting the loop will break the dependence.
Instruction * getSrc() const
getSrc - Returns the source instruction for this 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 isSplitable(unsigned Level, bool SameSD=false) const override
isSplitable - Returns true if splitting the loop will break the dependence.
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.
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
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
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
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
const SCEV * getOperand(unsigned i) const
This class represents an assumption made using SCEV expressions which can be checked at run-time.
This class represents a composition of other SCEV predicates, and is the class that most clients will...
void print(raw_ostream &OS, unsigned Depth) const override
Prints a textual representation of this predicate with an indentation of Depth.
bool isAlwaysTrue() const override
Implementation of the SCEVPredicate interface.
This class represents an analyzed expression in the program.
LLVM_ABI ArrayRef< const SCEV * > operands() const
Return operands of this SCEV expression.
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 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.
bool any() const
Returns true if any bit is set.
bool empty() const
Tests whether there are no bits in this bitvector.
size_type count() const
Returns the number of bits which are set.
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.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
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.
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)
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)...
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()).
bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Implementation of fixed size array delinearization.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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 isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
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.