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 &&
1203void DependenceInfo::establishNestingLevels(
const Instruction *Src,
1205 const BasicBlock *SrcBlock = Src->getParent();
1206 const BasicBlock *DstBlock = Dst->getParent();
1207 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
1208 unsigned DstLevel = LI->getLoopDepth(DstBlock);
1209 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
1210 const Loop *DstLoop = LI->getLoopFor(DstBlock);
1211 SrcLevels = SrcLevel;
1212 MaxLevels = SrcLevel + DstLevel;
1214 while (SrcLevel > DstLevel) {
1218 while (DstLevel > SrcLevel) {
1224 while (SrcLoop != DstLoop) {
1226 if (!haveSameSD(SrcLoop, DstLoop))
1232 CommonLevels = SrcLevel;
1233 MaxLevels -= CommonLevels;
1238unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1244unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1246 if (
D > CommonLevels)
1249 return D - CommonLevels + SrcLevels;
1276 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1284 unsigned widestWidthSeen = 0;
1289 for (Subscript *Pair : Pairs) {
1290 const SCEV *Src = Pair->Src;
1291 const SCEV *Dst = Pair->Dst;
1294 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1296 "This function only unify integer types and "
1297 "expect Src and Dst share the same type otherwise.");
1310 assert(widestWidthSeen > 0);
1313 for (Subscript *Pair : Pairs) {
1314 const SCEV *Src = Pair->Src;
1315 const SCEV *Dst = Pair->Dst;
1318 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1320 "This function only unify integer types and "
1321 "expect Src and Dst share the same type otherwise.");
1326 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1329 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1338void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1339 const SCEV *Src = Pair->Src;
1340 const SCEV *Dst = Pair->Dst;
1345 const SCEV *SrcCastOp = SrcCast->
getOperand();
1346 const SCEV *DstCastOp = DstCast->
getOperand();
1348 Pair->Src = SrcCastOp;
1349 Pair->Dst = DstCastOp;
1360 return isLoopInvariant(Expr, LoopNest);
1367 const Loop *
L = LoopNest;
1368 while (L && AddRec->
getLoop() != L)
1369 L =
L->getParentLoop();
1375 if (!isLoopInvariant(Step, LoopNest))
1381 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1386bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1388 return checkSubscript(Src, LoopNest,
Loops,
true);
1393bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1395 return checkSubscript(Dst, LoopNest,
Loops,
false);
1401DependenceInfo::Subscript::ClassificationKind
1402DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1403 const SCEV *Dst,
const Loop *DstLoopNest,
1405 SmallBitVector SrcLoops(MaxLevels + 1);
1406 SmallBitVector DstLoops(MaxLevels + 1);
1407 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1408 return Subscript::NonLinear;
1409 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1410 return Subscript::NonLinear;
1413 unsigned N =
Loops.count();
1415 return Subscript::ZIV;
1417 return Subscript::SIV;
1418 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1419 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1420 return Subscript::RDIV;
1421 return Subscript::MIV;
1435 const SCEV *
Y)
const {
1449 if (SE->isKnownPredicate(Pred,
X,
Y))
1456 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1461 return SE->isKnownNonZero(Delta);
1463 return SE->isKnownNonNegative(Delta);
1465 return SE->isKnownNonPositive(Delta);
1467 return SE->isKnownPositive(Delta);
1469 return SE->isKnownNegative(Delta);
1481bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1485 if (!SType || !SizeType)
1488 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1489 S = SE->getTruncateOrZeroExtend(S, MaxType);
1490 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1492 auto CheckAddRecBECount = [&]() {
1496 const SCEV *BECount = collectUpperBound(AddRec->
getLoop(), MaxType);
1503 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1504 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1509 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1514 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1519 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1525 if (CheckAddRecBECount())
1529 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1530 return SE->isKnownNegative(LimitedBound);
1533bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1534 bool Inbounds =
false;
1536 Inbounds = SrcGEP->isInBounds();
1542 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1543 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1549 return SE->isKnownNonNegative(S);
1559const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1560 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1561 const SCEV *UB = SE->getBackedgeTakenCount(L);
1562 return SE->getTruncateOrZeroExtend(UB,
T);
1569const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1571 if (
const SCEV *UB = collectUpperBound(L,
T))
1619bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1634 Result.Consistent =
false;
1665bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1666 const SCEV *DstConst,
const Loop *CurSrcLoop,
1667 const Loop *CurDstLoop,
unsigned Level,
1669 Constraint &NewConstraint)
const {
1680 ++StrongSIVapplications;
1681 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1684 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1689 bool IsDeltaLarge = [&] {
1690 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1698 if (!AbsDelta || !AbsCoeff)
1700 const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
1705 ++StrongSIVindependence;
1706 ++StrongSIVsuccesses;
1714 APInt Distance = ConstDelta;
1715 APInt Remainder = ConstDelta;
1720 if (Remainder != 0) {
1722 ++StrongSIVindependence;
1723 ++StrongSIVsuccesses;
1726 Result.DV[
Level].Distance = SE->getConstant(Distance);
1727 NewConstraint.setDistance(SE->getConstant(Distance), CurSrcLoop,
1729 if (Distance.
sgt(0))
1731 else if (Distance.
slt(0))
1735 ++StrongSIVsuccesses;
1736 }
else if (Delta->
isZero()) {
1739 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1741 ++StrongSIVsuccesses;
1743 if (Coeff->
isOne()) {
1746 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1748 Result.Consistent =
false;
1749 NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
1750 SE->getNegativeSCEV(Delta), CurSrcLoop, CurDstLoop);
1754 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1755 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1756 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1757 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1758 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1763 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1764 (DeltaMaybeNegative && CoeffMaybeNegative))
1768 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1769 (DeltaMaybePositive && CoeffMaybeNegative))
1771 if (NewDirection <
Result.DV[Level].Direction)
1772 ++StrongSIVsuccesses;
1806bool DependenceInfo::weakCrossingSIVtest(
1807 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1808 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
1810 const SCEV *&SplitIter)
const {
1818 ++WeakCrossingSIVapplications;
1819 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1821 Result.Consistent =
false;
1822 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1824 NewConstraint.setLine(Coeff, Coeff, Delta, CurSrcLoop, CurDstLoop);
1826 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1827 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1828 ++WeakCrossingSIVsuccesses;
1829 if (!
Result.DV[Level].Direction) {
1830 ++WeakCrossingSIVindependence;
1841 if (SE->isKnownNegative(ConstCoeff)) {
1844 "dynamic cast of negative of ConstCoeff should yield constant");
1845 Delta = SE->getNegativeSCEV(Delta);
1847 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1850 SplitIter = SE->getUDivExpr(
1851 SE->getSMaxExpr(SE->getZero(Delta->
getType()), Delta),
1852 SE->getMulExpr(SE->getConstant(Delta->
getType(), 2), ConstCoeff));
1863 if (SE->isKnownNegative(Delta)) {
1865 ++WeakCrossingSIVindependence;
1866 ++WeakCrossingSIVsuccesses;
1872 if (
const SCEV *UpperBound =
1873 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1875 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1877 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1881 ++WeakCrossingSIVindependence;
1882 ++WeakCrossingSIVsuccesses;
1887 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1888 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1889 ++WeakCrossingSIVsuccesses;
1890 if (!
Result.DV[Level].Direction) {
1891 ++WeakCrossingSIVindependence;
1901 APInt APDelta = ConstDelta->
getAPInt();
1902 APInt APCoeff = ConstCoeff->
getAPInt();
1903 APInt Distance = APDelta;
1904 APInt Remainder = APDelta;
1907 if (Remainder != 0) {
1909 ++WeakCrossingSIVindependence;
1910 ++WeakCrossingSIVsuccesses;
1916 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1917 Remainder = Distance.
srem(Two);
1919 if (Remainder != 0) {
1921 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1922 ++WeakCrossingSIVsuccesses;
1939 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1940 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1948 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1949 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1956 X = AM.
slt(0) ? -A1 : A1;
1957 Y = BM.
slt(0) ? B1 : -B1;
1973 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1985 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
2020static std::pair<std::optional<APInt>, std::optional<APInt>>
2022 const std::optional<APInt> &UB) {
2023 assert(
A != 0 &&
"A must be non-zero");
2024 std::optional<APInt> TL, TU;
2044 return std::make_pair(TL, TU);
2066bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2067 const SCEV *SrcConst,
const SCEV *DstConst,
2068 const Loop *CurSrcLoop,
2069 const Loop *CurDstLoop,
unsigned Level,
2071 Constraint &NewConstraint)
const {
2076 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2077 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2080 ++ExactSIVapplications;
2081 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
2083 Result.Consistent =
false;
2088 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
2089 CurSrcLoop, CurDstLoop);
2093 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2098 APInt AM = ConstSrcCoeff->
getAPInt();
2099 APInt BM = ConstDstCoeff->
getAPInt();
2104 ++ExactSIVindependence;
2105 ++ExactSIVsuccesses;
2112 std::optional<APInt> UM;
2114 if (
const SCEVConstant *CUB =
2115 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
2116 UM = CUB->getAPInt();
2122 APInt TC = CM.
sdiv(
G);
2144 auto CreateVec = [](
const std::optional<APInt> &V0,
2145 const std::optional<APInt> &V1) {
2168 ++ExactSIVindependence;
2169 ++ExactSIVsuccesses;
2175 APInt LowerDistance, UpperDistance;
2178 LowerDistance = (TY - TX) + (TA - TB) * TL;
2179 UpperDistance = (TY - TX) + (TA - TB) * TU;
2181 LowerDistance = (TY - TX) + (TA - TB) * TU;
2182 UpperDistance = (TY - TX) + (TA - TB) * TL;
2185 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
2186 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
2188 APInt
Zero(Bits, 0,
true);
2189 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
2191 ++ExactSIVsuccesses;
2193 if (LowerDistance.
slt(0)) {
2195 ++ExactSIVsuccesses;
2197 if (UpperDistance.
sgt(0)) {
2199 ++ExactSIVsuccesses;
2205 ++ExactSIVindependence;
2216 return ConstDividend.
srem(ConstDivisor) == 0;
2250bool DependenceInfo::weakZeroSrcSIVtest(
2251 const SCEV *DstCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2252 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2264 ++WeakZeroSIVapplications;
2265 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
2267 Result.Consistent =
false;
2268 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
2269 NewConstraint.setLine(SE->getZero(Delta->
getType()), DstCoeff, Delta,
2270 CurSrcLoop, CurDstLoop);
2273 if (Level < CommonLevels) {
2276 ++WeakZeroSIVsuccesses;
2286 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2287 ? SE->getNegativeSCEV(ConstCoeff)
2289 const SCEV *NewDelta =
2290 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2294 if (
const SCEV *UpperBound =
2295 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2297 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2299 ++WeakZeroSIVindependence;
2300 ++WeakZeroSIVsuccesses;
2305 if (Level < CommonLevels) {
2308 ++WeakZeroSIVsuccesses;
2316 if (SE->isKnownNegative(NewDelta)) {
2318 ++WeakZeroSIVindependence;
2319 ++WeakZeroSIVsuccesses;
2326 ++WeakZeroSIVindependence;
2327 ++WeakZeroSIVsuccesses;
2364bool DependenceInfo::weakZeroDstSIVtest(
2365 const SCEV *SrcCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2366 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2377 ++WeakZeroSIVapplications;
2378 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2380 Result.Consistent =
false;
2381 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2382 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->
getType()), Delta,
2383 CurSrcLoop, CurDstLoop);
2386 if (Level < CommonLevels) {
2389 ++WeakZeroSIVsuccesses;
2399 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2400 ? SE->getNegativeSCEV(ConstCoeff)
2402 const SCEV *NewDelta =
2403 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2407 if (
const SCEV *UpperBound =
2408 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2410 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2412 ++WeakZeroSIVindependence;
2413 ++WeakZeroSIVsuccesses;
2418 if (Level < CommonLevels) {
2421 ++WeakZeroSIVsuccesses;
2429 if (SE->isKnownNegative(NewDelta)) {
2431 ++WeakZeroSIVindependence;
2432 ++WeakZeroSIVsuccesses;
2439 ++WeakZeroSIVindependence;
2440 ++WeakZeroSIVsuccesses;
2453bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2454 const SCEV *SrcConst,
const SCEV *DstConst,
2455 const Loop *SrcLoop,
const Loop *DstLoop,
2461 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2462 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2465 ++ExactRDIVapplications;
2466 Result.Consistent =
false;
2467 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2472 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2477 APInt AM = ConstSrcCoeff->
getAPInt();
2478 APInt BM = ConstDstCoeff->
getAPInt();
2483 ++ExactRDIVindependence;
2490 std::optional<APInt> SrcUM;
2492 if (
const SCEVConstant *UpperBound =
2493 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2494 SrcUM = UpperBound->getAPInt();
2498 std::optional<APInt> DstUM;
2500 if (
const SCEVConstant *UpperBound =
2501 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2502 DstUM = UpperBound->getAPInt();
2508 APInt TC = CM.
sdiv(
G);
2533 auto CreateVec = [](
const std::optional<APInt> &V0,
2534 const std::optional<APInt> &V1) {
2554 ++ExactRDIVindependence;
2600bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2603 const Loop *Loop2)
const {
2607 ++SymbolicRDIVapplications;
2614 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2615 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2618 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2619 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2622 if (SE->isKnownNonNegative(A1)) {
2623 if (SE->isKnownNonNegative(A2)) {
2627 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2630 ++SymbolicRDIVindependence;
2636 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2639 ++SymbolicRDIVindependence;
2643 }
else if (SE->isKnownNonPositive(A2)) {
2647 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2648 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2649 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2650 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2652 ++SymbolicRDIVindependence;
2657 if (SE->isKnownNegative(C2_C1)) {
2658 ++SymbolicRDIVindependence;
2662 }
else if (SE->isKnownNonPositive(A1)) {
2663 if (SE->isKnownNonNegative(A2)) {
2667 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2668 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2669 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2670 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2672 ++SymbolicRDIVindependence;
2677 if (SE->isKnownPositive(C2_C1)) {
2678 ++SymbolicRDIVindependence;
2681 }
else if (SE->isKnownNonPositive(A2)) {
2685 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2688 ++SymbolicRDIVindependence;
2694 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2697 ++SymbolicRDIVindependence;
2714bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2716 const SCEV *&SplitIter)
const {
2721 if (SrcAddRec && DstAddRec) {
2722 const SCEV *SrcConst = SrcAddRec->
getStart();
2723 const SCEV *DstConst = DstAddRec->
getStart();
2726 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2727 const Loop *CurDstLoop = DstAddRec->
getLoop();
2728 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2729 "Loops in the SIV test should have the same iteration space and "
2731 Level = mapSrcLoop(CurSrcLoop);
2733 if (SrcCoeff == DstCoeff)
2734 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2735 CurDstLoop, Level, Result, NewConstraint);
2736 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2737 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2738 CurDstLoop, Level, Result, NewConstraint,
2742 exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2743 CurDstLoop, Level, Result, NewConstraint);
2744 return disproven || gcdMIVtest(Src, Dst, Result) ||
2745 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2749 const SCEV *SrcConst = SrcAddRec->
getStart();
2751 const SCEV *DstConst = Dst;
2752 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2753 Level = mapSrcLoop(CurSrcLoop);
2754 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2755 CurSrcLoop, Level, Result, NewConstraint) ||
2756 gcdMIVtest(Src, Dst, Result);
2759 const SCEV *DstConst = DstAddRec->
getStart();
2761 const SCEV *SrcConst = Src;
2762 const Loop *CurDstLoop = DstAddRec->
getLoop();
2763 Level = mapDstLoop(CurDstLoop);
2764 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2765 CurDstLoop, Level, Result, NewConstraint) ||
2766 gcdMIVtest(Src, Dst, Result);
2785bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2793 const SCEV *SrcConst, *DstConst;
2794 const SCEV *SrcCoeff, *DstCoeff;
2795 const Loop *SrcLoop, *DstLoop;
2801 if (SrcAddRec && DstAddRec) {
2804 SrcLoop = SrcAddRec->
getLoop();
2807 DstLoop = DstAddRec->
getLoop();
2808 }
else if (SrcAddRec) {
2809 if (
const SCEVAddRecExpr *tmpAddRec =
2811 SrcConst = tmpAddRec->getStart();
2812 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2813 SrcLoop = tmpAddRec->getLoop();
2816 DstLoop = SrcAddRec->
getLoop();
2819 }
else if (DstAddRec) {
2820 if (
const SCEVAddRecExpr *tmpAddRec =
2822 DstConst = tmpAddRec->getStart();
2823 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2824 DstLoop = tmpAddRec->getLoop();
2827 SrcLoop = DstAddRec->
getLoop();
2832 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2834 gcdMIVtest(Src, Dst, Result) ||
2835 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2842bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2847 Result.Consistent =
false;
2848 return gcdMIVtest(Src, Dst, Result) ||
2849 banerjeeMIVtest(Src, Dst,
Loops, Result);
2860 return std::nullopt;
2863bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2864 const Loop *CurLoop,
2865 const SCEV *&CurLoopCoeff,
2866 APInt &RunningGCD)
const {
2869 if (RunningGCD == 1)
2874 assert(isLoopInvariant(Expr, CurLoop) &&
2875 "Expected loop invariant expression");
2882 if (AddRec->
getLoop() == CurLoop) {
2883 CurLoopCoeff = Step;
2897 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2918bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2925 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2932 const SCEV *Coefficients = Src;
2933 while (
const SCEVAddRecExpr *AddRec =
2944 const SCEV *SrcConst = Coefficients;
2951 while (
const SCEVAddRecExpr *AddRec =
2962 const SCEV *DstConst = Coefficients;
2965 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2970 for (
const SCEV *Operand : Sum->
operands()) {
2972 assert(!Constant &&
"Surprised to find multiple constants");
2989 if (ConstDelta == 0)
2993 APInt Remainder = ConstDelta.
srem(RunningGCD);
2994 if (Remainder != 0) {
3013 bool Improved =
false;
3015 while (
const SCEVAddRecExpr *AddRec =
3018 const Loop *CurLoop = AddRec->
getLoop();
3019 RunningGCD = ExtraGCD;
3021 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
3023 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
3024 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
3027 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
3037 if (RunningGCD != 0) {
3038 Remainder = ConstDelta.
srem(RunningGCD);
3040 if (Remainder != 0) {
3041 unsigned Level = mapSrcLoop(CurLoop);
3042 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
3086bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
3093 ++BanerjeeApplications;
3096 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
3099 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
3100 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
3101 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
3106 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3107 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
3110 findBoundsALL(
A,
B, Bound, K);
3125 bool Disproved =
false;
3128 unsigned DepthExpanded = 0;
3130 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
3132 bool Improved =
false;
3133 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3135 unsigned Old =
Result.DV[
K - 1].Direction;
3136 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
3137 Improved |= Old !=
Result.DV[
K - 1].Direction;
3138 if (!
Result.DV[K - 1].Direction) {
3146 ++BanerjeeSuccesses;
3148 ++BanerjeeIndependence;
3152 ++BanerjeeIndependence;
3166unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
3167 CoefficientInfo *
B, BoundInfo *Bound,
3169 unsigned &DepthExpanded,
3170 const SCEV *Delta)
const {
3176 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
3177 "direction exploration is terminated.\n");
3178 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
3184 if (Level > CommonLevels) {
3187 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3189 Bound[
K].DirSet |= Bound[
K].Direction;
3214 if (Level > DepthExpanded) {
3215 DepthExpanded =
Level;
3217 findBoundsLT(
A,
B, Bound, Level);
3218 findBoundsGT(
A,
B, Bound, Level);
3219 findBoundsEQ(
A,
B, Bound, Level);
3258 unsigned NewDeps = 0;
3262 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3267 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3272 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3278 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3283bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
3284 BoundInfo *Bound,
const SCEV *Delta)
const {
3285 Bound[
Level].Direction = DirKind;
3286 if (
const SCEV *LowerBound = getLowerBound(Bound))
3289 if (
const SCEV *UpperBound = getUpperBound(Bound))
3310void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
3311 BoundInfo *Bound,
unsigned K)
const {
3316 if (Bound[K].Iterations) {
3318 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3320 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3325 SE->getZero(
A[K].Coeff->
getType());
3328 SE->getZero(
A[K].Coeff->
getType());
3347void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3348 BoundInfo *Bound,
unsigned K)
const {
3353 if (Bound[K].Iterations) {
3354 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3355 const SCEV *NegativePart = getNegativePart(Delta);
3357 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3358 const SCEV *PositivePart = getPositivePart(Delta);
3360 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3364 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3365 const SCEV *NegativePart = getNegativePart(Delta);
3366 if (NegativePart->
isZero())
3368 const SCEV *PositivePart = getPositivePart(Delta);
3369 if (PositivePart->
isZero())
3387void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3388 BoundInfo *Bound,
unsigned K)
const {
3393 if (Bound[K].Iterations) {
3394 const SCEV *Iter_1 = SE->getMinusSCEV(
3395 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3396 const SCEV *NegPart =
3397 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3399 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3400 const SCEV *PosPart =
3401 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3403 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3407 const SCEV *NegPart =
3408 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3411 const SCEV *PosPart =
3412 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3431void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3432 BoundInfo *Bound,
unsigned K)
const {
3437 if (Bound[K].Iterations) {
3438 const SCEV *Iter_1 = SE->getMinusSCEV(
3439 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3440 const SCEV *NegPart =
3441 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3443 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3444 const SCEV *PosPart =
3445 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3447 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3451 const SCEV *NegPart =
3452 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3455 const SCEV *PosPart =
3456 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3463const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3464 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3468const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3469 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3475DependenceInfo::CoefficientInfo *
3476DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3478 const SCEV *
Zero = SE->getZero(Subscript->getType());
3479 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3480 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3482 CI[
K].PosPart =
Zero;
3483 CI[
K].NegPart =
Zero;
3484 CI[
K].Iterations =
nullptr;
3488 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3490 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3491 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3492 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3498 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3505 if (CI[K].Iterations)
3520const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3521 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3522 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3535const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3536 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3537 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3555const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3556 const Loop *TargetLoop)
const {
3559 return SE->getZero(Expr->
getType());
3560 if (AddRec->
getLoop() == TargetLoop)
3562 return findCoefficient(AddRec->
getStart(), TargetLoop);
3570const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3571 const Loop *TargetLoop)
const {
3575 if (AddRec->
getLoop() == TargetLoop)
3577 return SE->getAddRecExpr(zeroCoefficient(AddRec->
getStart(), TargetLoop),
3587const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3588 const Loop *TargetLoop,
3592 return SE->getAddRecExpr(Expr,
Value, TargetLoop,
3594 if (AddRec->
getLoop() == TargetLoop) {
3601 if (SE->isLoopInvariant(AddRec, TargetLoop))
3603 return SE->getAddRecExpr(
3619bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3624 for (
unsigned LI :
Loops.set_bits()) {
3627 if (Constraints[LI].isDistance())
3628 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3629 else if (Constraints[LI].isLine())
3630 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3631 else if (Constraints[LI].isPoint())
3632 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3642bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3643 Constraint &CurConstraint,
3645 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3646 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3648 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3651 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3652 Src = SE->getMinusSCEV(Src, DA_K);
3653 Src = zeroCoefficient(Src, CurSrcLoop);
3656 Dst = addToCoefficient(Dst, CurDstLoop, SE->getNegativeSCEV(A_K));
3658 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3668bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3669 Constraint &CurConstraint,
3671 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3672 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3673 const SCEV *
A = CurConstraint.getA();
3674 const SCEV *
B = CurConstraint.getB();
3675 const SCEV *
C = CurConstraint.getC();
3683 if (!Bconst || !Cconst)
3686 APInt Charlie = Cconst->
getAPInt();
3687 APInt CdivB = Charlie.
sdiv(Beta);
3688 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3689 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3690 Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
3691 Dst = zeroCoefficient(Dst, CurDstLoop);
3692 if (!findCoefficient(Src, CurSrcLoop)->
isZero())
3694 }
else if (
B->isZero()) {
3697 if (!Aconst || !Cconst)
3700 APInt Charlie = Cconst->
getAPInt();
3701 APInt CdivA = Charlie.
sdiv(Alpha);
3702 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3703 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3704 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3705 Src = zeroCoefficient(Src, CurSrcLoop);
3706 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3711 if (!Aconst || !Cconst)
3714 APInt Charlie = Cconst->
getAPInt();
3715 APInt CdivA = Charlie.
sdiv(Alpha);
3716 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3717 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3718 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3719 Src = zeroCoefficient(Src, CurSrcLoop);
3720 Dst = addToCoefficient(Dst, CurDstLoop, A_K);
3721 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3725 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3726 Src = SE->getMulExpr(Src,
A);
3727 Dst = SE->getMulExpr(Dst,
A);
3728 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K,
C));
3729 Src = zeroCoefficient(Src, CurSrcLoop);
3730 Dst = addToCoefficient(Dst, CurDstLoop, SE->getMulExpr(A_K,
B));
3731 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3742bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3743 Constraint &CurConstraint) {
3744 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3745 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3746 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3747 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3748 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3749 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3751 Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
3752 Src = zeroCoefficient(Src, CurSrcLoop);
3755 Dst = zeroCoefficient(Dst, CurDstLoop);
3762 const Constraint &CurConstraint)
const {
3765 if (CurConstraint.isAny())
3767 else if (CurConstraint.isDistance()) {
3769 Level.Scalar =
false;
3770 Level.Distance = CurConstraint.getD();
3772 if (!SE->isKnownNonZero(
Level.Distance))
3774 if (!SE->isKnownNonPositive(
Level.Distance))
3776 if (!SE->isKnownNonNegative(
Level.Distance))
3778 Level.Direction &= NewDirection;
3779 }
else if (CurConstraint.isLine()) {
3780 Level.Scalar =
false;
3781 Level.Distance =
nullptr;
3783 }
else if (CurConstraint.isPoint()) {
3784 Level.Scalar =
false;
3785 Level.Distance =
nullptr;
3788 CurConstraint.getX()))
3792 CurConstraint.getX()))
3796 CurConstraint.getX()))
3799 Level.Direction &= NewDirection;
3814 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3815 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3816 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3817 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3818 const SCEVUnknown *SrcBase =
3820 const SCEVUnknown *DstBase =
3823 if (!SrcBase || !DstBase || SrcBase != DstBase)
3828 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3829 SrcSubscripts, DstSubscripts) &&
3830 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3831 SrcSubscripts, DstSubscripts))
3834 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3835 isLoopInvariant(DstBase, DstLoop) &&
3836 "Expected SrcBase and DstBase to be loop invariant");
3840 dbgs() <<
"\nSrcSubscripts: ";
3841 for (
int I = 0;
I <
Size;
I++)
3842 dbgs() << *SrcSubscripts[
I];
3843 dbgs() <<
"\nDstSubscripts: ";
3844 for (
int I = 0;
I <
Size;
I++)
3845 dbgs() << *DstSubscripts[
I];
3853 SCEVMonotonicityChecker MonChecker(SE);
3854 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3855 for (
int I = 0;
I <
Size; ++
I) {
3856 Pair[
I].Src = SrcSubscripts[
I];
3857 Pair[
I].Dst = DstSubscripts[
I];
3858 unifySubscriptType(&Pair[
I]);
3861 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3863 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3874bool DependenceInfo::tryDelinearizeFixedSize(
3879 const SCEVUnknown *SrcBase =
3881 const SCEVUnknown *DstBase =
3883 assert(SrcBase && DstBase && SrcBase == DstBase &&
3884 "expected src and dst scev unknowns to be equal");
3887 SmallVector<int, 4> SrcSizes;
3888 SmallVector<int, 4> DstSizes;
3897 if (SrcSizes.size() != DstSizes.
size() ||
3898 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3899 SrcSubscripts.
clear();
3900 DstSubscripts.
clear();
3905 "Expected equal number of entries in the list of SrcSubscripts and "
3918 auto AllIndicesInRange = [&](SmallVector<int, 4> &DimensionSizes,
3919 SmallVectorImpl<const SCEV *> &Subscripts,
3921 size_t SSize = Subscripts.
size();
3922 for (
size_t I = 1;
I < SSize; ++
I) {
3923 const SCEV *S = Subscripts[
I];
3926 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3927 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *
Ptr <<
"\n";
3932 const SCEV *
Range = SE->getConstant(
3933 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3934 if (!isKnownLessThan(S,
Range)) {
3936 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3937 dbgs() <<
" S: " << *S <<
"\n"
3938 <<
" Range: " << *
Range <<
"\n";
3947 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3948 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3950 SrcSubscripts.
clear();
3951 DstSubscripts.
clear();
3956 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3957 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3958 <<
"DstGEP:" << *DstPtr <<
"\n";
3963bool DependenceInfo::tryDelinearizeParametricSize(
3970 const SCEVUnknown *SrcBase =
3972 const SCEVUnknown *DstBase =
3974 assert(SrcBase && DstBase && SrcBase == DstBase &&
3975 "expected src and dst scev unknowns to be equal");
3977 const SCEV *ElementSize = SE->getElementSize(Src);
3978 if (ElementSize != SE->getElementSize(Dst))
3981 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3982 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
4003 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
4004 SrcSubscripts.
size() != DstSubscripts.
size())
4007 size_t Size = SrcSubscripts.
size();
4016 for (
size_t I = 1;
I <
Size; ++
I) {
4019 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
4020 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
4021 if (SNN && DNN && SLT && DLT)
4025 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
4027 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
4029 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
4031 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
4032 << *
Sizes[
I - 1] <<
")\n";
4034 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
4035 << *
Sizes[
I - 1] <<
")\n";
4049 for (
unsigned VI : BV.
set_bits()) {
4059 FunctionAnalysisManager::Invalidator &Inv) {
4066 return Inv.invalidate<
AAManager>(F, PA) ||
4086std::unique_ptr<Dependence>
4088 bool UnderRuntimeAssumptions) {
4090 bool PossiblyLoopIndependent =
true;
4092 PossiblyLoopIndependent =
false;
4094 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
4100 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
4101 return std::make_unique<Dependence>(Src, Dst,
4113 return std::make_unique<Dependence>(Src, Dst,
4127 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
4128 return std::make_unique<Dependence>(Src, Dst,
4134 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4135 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4138 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
4139 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
4140 if (SrcBase != DstBase) {
4147 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
4148 return std::make_unique<Dependence>(Src, Dst,
4156 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
4157 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
4158 if (!isLoopInvariant(SrcBase, SrcLoop) ||
4159 !isLoopInvariant(DstBase, DstLoop)) {
4160 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
4161 return std::make_unique<Dependence>(Src, Dst,
4166 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
4167 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
4170 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
4171 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
4172 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
4173 return std::make_unique<Dependence>(Src, Dst,
4177 if (!Assume.empty()) {
4178 if (!UnderRuntimeAssumptions)
4179 return std::make_unique<Dependence>(Src, Dst,
4182 unsigned N = Assumptions.size();
4184 bool Implied =
false;
4185 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
4186 if (Assumptions[
I]->implies(
P, *SE))
4189 Assumptions.push_back(
P);
4195 Pair[0].Src = SrcEv;
4196 Pair[0].Dst = DstEv;
4198 SCEVMonotonicityChecker MonChecker(SE);
4201 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
4202 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
4203 return std::make_unique<Dependence>(Src, Dst,
4207 if (tryDelinearize(Src, Dst, Pair)) {
4209 Pairs = Pair.
size();
4214 establishNestingLevels(Src, Dst);
4216 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
4217 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
4218 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
4221 CommonLevels += SameSDLevels;
4222 MaxLevels -= SameSDLevels;
4223 if (SameSDLevels > 0) {
4226 for (
unsigned P = 0;
P < Pairs; ++
P) {
4228 Subscript::ClassificationKind TestClass =
4229 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
4230 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
4232 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
4233 TestClass != Subscript::RDIV) {
4235 CommonLevels -= SameSDLevels;
4236 MaxLevels += SameSDLevels;
4243 if (SameSDLevels > 0)
4247 PossiblyLoopIndependent, CommonLevels);
4250 for (
unsigned P = 0;
P < Pairs; ++
P) {
4251 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4252 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4253 Pair[
P].Loops.
resize(MaxLevels + 1);
4254 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4256 removeMatchingExtensions(&Pair[
P]);
4257 Pair[
P].Classification =
4258 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4259 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4260 Pair[
P].GroupLoops = Pair[
P].Loops;
4261 Pair[
P].Group.set(
P);
4330 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4331 if (Pair[
SI].Classification == Subscript::NonLinear) {
4333 ++NonlinearSubscriptPairs;
4334 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4336 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4338 Result.Consistent =
false;
4339 }
else if (Pair[
SI].Classification == Subscript::ZIV) {
4345 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4347 Intersection &= Pair[SJ].GroupLoops;
4348 if (Intersection.
any()) {
4350 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4352 Pair[SJ].Group |= Pair[
SI].Group;
4357 if (Pair[
SI].Group.count() == 1) {
4359 ++SeparableSubscriptPairs;
4362 ++CoupledSubscriptPairs;
4373 Constraint NewConstraint;
4374 NewConstraint.setAny(SE);
4379 switch (Pair[
SI].Classification) {
4380 case Subscript::ZIV:
4382 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4385 case Subscript::SIV: {
4388 const SCEV *SplitIter =
nullptr;
4389 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4394 case Subscript::RDIV:
4396 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4399 case Subscript::MIV:
4401 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
4409 if (Coupled.
count()) {
4412 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
4414 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4415 Constraints[
II].setAny(SE);
4423 for (
unsigned SJ : Group.set_bits()) {
4425 if (Pair[SJ].Classification == Subscript::SIV)
4431 unifySubscriptType(PairsInGroup);
4433 while (Sivs.
any()) {
4435 for (
unsigned SJ : Sivs.
set_bits()) {
4439 const SCEV *SplitIter =
nullptr;
4441 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4444 ConstrainedLevels.
set(Level);
4445 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
4446 if (Constraints[Level].isEmpty()) {
4447 ++DeltaIndependence;
4459 for (
unsigned SJ : Mivs.
set_bits()) {
4462 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
4463 Constraints, Result.Consistent)) {
4465 ++DeltaPropagations;
4466 Pair[SJ].Classification = classifyPair(
4467 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4468 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4469 switch (Pair[SJ].Classification) {
4470 case Subscript::ZIV:
4472 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4476 case Subscript::SIV:
4480 case Subscript::RDIV:
4481 case Subscript::MIV:
4492 for (
unsigned SJ : Mivs.
set_bits()) {
4493 if (Pair[SJ].Classification == Subscript::RDIV) {
4495 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4505 for (
unsigned SJ : Mivs.
set_bits()) {
4506 if (Pair[SJ].Classification == Subscript::MIV) {
4508 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
4516 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
4517 if (SJ > CommonLevels)
4519 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
4528 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
4529 CompleteLoops |= Pair[
SI].
Loops;
4530 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
4531 if (CompleteLoops[
II])
4532 Result.DV[
II - 1].Scalar =
false;
4537 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
4539 if (Result.DV[
II - 1].Distance ==
nullptr)
4540 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
4542 assert(Result.DV[
II - 1].Distance->isZero() &&
4543 "Inconsistency between distance and direction");
4549 const SCEV *Distance = Result.getDistance(
II);
4550 if (Distance && Distance->
isZero())
4552 "Distance is zero, but direction is not EQ");
4556 if (SameSDLevels > 0) {
4559 assert(CommonLevels >= SameSDLevels);
4560 CommonLevels -= SameSDLevels;
4561 MaxLevels += SameSDLevels;
4562 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
4563 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
4564 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
4565 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
4566 DV[Level] = Result.DV[Level];
4567 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
4568 DVSameSD[Level] = Result.DV[CommonLevels + Level];
4569 Result.DV = std::move(DV);
4570 Result.DVSameSD = std::move(DVSameSD);
4571 Result.Levels = CommonLevels;
4572 Result.SameSDLevels = SameSDLevels;
4574 Result.Consistent =
false;
4577 if (PossiblyLoopIndependent) {
4581 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4583 Result.LoopIndependent =
false;
4590 bool AllEqual =
true;
4591 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4601 return std::make_unique<FullDependence>(std::move(Result));
4652 unsigned SplitLevel) {
4654 "Dep should be splitable at SplitLevel");
4657 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4658 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4668 establishNestingLevels(Src, Dst);
4670 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4674 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4675 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4676 Pair[0].Src = SE->removePointerBase(SrcSCEV);
4677 Pair[0].Dst = SE->removePointerBase(DstSCEV);
4680 if (tryDelinearize(Src, Dst, Pair)) {
4682 Pairs = Pair.
size();
4686 for (
unsigned P = 0;
P < Pairs; ++
P) {
4687 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4688 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4689 Pair[
P].Loops.
resize(MaxLevels + 1);
4690 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4692 removeMatchingExtensions(&Pair[
P]);
4693 Pair[
P].Classification =
4694 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4695 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4696 Pair[
P].GroupLoops = Pair[
P].Loops;
4697 Pair[
P].Group.set(
P);
4704 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4705 if (Pair[
SI].Classification == Subscript::NonLinear) {
4707 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4709 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4711 Result.Consistent =
false;
4712 }
else if (Pair[
SI].Classification == Subscript::ZIV)
4717 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4719 Intersection &= Pair[SJ].GroupLoops;
4720 if (Intersection.
any()) {
4722 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4724 Pair[SJ].Group |= Pair[
SI].Group;
4729 if (Pair[
SI].Group.count() == 1)
4737 Constraint NewConstraint;
4738 NewConstraint.setAny(SE);
4742 switch (Pair[
SI].Classification) {
4743 case Subscript::SIV: {
4745 const SCEV *SplitIter =
nullptr;
4746 (void)testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4748 if (Level == SplitLevel) {
4749 assert(SplitIter !=
nullptr);
4754 case Subscript::ZIV:
4755 case Subscript::RDIV:
4756 case Subscript::MIV:
4763 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4767 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4768 Constraints[
II].setAny(SE);
4774 for (
unsigned SJ : Group.set_bits()) {
4775 if (Pair[SJ].Classification == Subscript::SIV)
4780 while (Sivs.
any()) {
4782 for (
unsigned SJ : Sivs.
set_bits()) {
4785 const SCEV *SplitIter =
nullptr;
4786 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4788 if (Level == SplitLevel && SplitIter)
4790 ConstrainedLevels.
set(Level);
4791 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4798 for (
unsigned SJ : Mivs.
set_bits()) {
4800 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4803 Pair[SJ].Classification = classifyPair(
4804 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4805 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4806 switch (Pair[SJ].Classification) {
4807 case Subscript::ZIV:
4810 case Subscript::SIV:
4814 case Subscript::RDIV:
4815 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::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 std::optional< APInt > getConstantPart(const SCEV *Expr)
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.