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";
410 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
413 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
414 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
415 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
423 if (SrcI->mayReadOrWriteMemory()) {
426 if (DstI->mayReadOrWriteMemory()) {
427 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
428 OS <<
" da analyze - ";
429 if (
auto D = DA->depends(&*SrcI, &*DstI,
435 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
436 const SCEV *Distance =
D->getDistance(Level);
437 bool IsDistanceZero = Distance && Distance->
isZero();
440 assert(IsDistanceZero == IsDirectionEQ &&
441 "Inconsistent distance and direction.");
446 if (NormalizeResults &&
D->normalize(&SE))
447 OS <<
"normalized - ";
449 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
450 if (
D->isSplitable(Level)) {
451 OS <<
" da analyze - split level = " << Level;
452 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
464 OS <<
"Runtime Assumptions:\n";
465 Assumptions.
print(OS, 0);
478 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
491 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
496 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
501 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
506 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
520 bool PossiblyLoopIndependent,
521 unsigned CommonLevels)
522 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
523 LoopIndependent(PossiblyLoopIndependent) {
527 DV = std::make_unique<
DVEntry[]>(CommonLevels);
546 for (
unsigned Level = 1; Level <= Levels; ++Level) {
547 unsigned char Direction = DV[Level - 1].Direction;
562 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
565 for (
unsigned Level = 1; Level <= Levels; ++Level) {
566 unsigned char Direction = DV[Level - 1].Direction;
574 DV[Level - 1].Direction = RevDirection;
576 if (DV[Level - 1].Distance !=
nullptr)
580 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
627 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
628 "Level out of range");
629 return Level > Levels;
637const SCEV *DependenceInfo::Constraint::getX()
const {
638 assert(Kind == Point &&
"Kind should be Point");
644const SCEV *DependenceInfo::Constraint::getY()
const {
645 assert(Kind == Point &&
"Kind should be Point");
651const SCEV *DependenceInfo::Constraint::getA()
const {
652 assert((Kind == Line || Kind == Distance) &&
653 "Kind should be Line (or Distance)");
659const SCEV *DependenceInfo::Constraint::getB()
const {
660 assert((Kind == Line || Kind == Distance) &&
661 "Kind should be Line (or Distance)");
667const SCEV *DependenceInfo::Constraint::getC()
const {
668 assert((Kind == Line || Kind == Distance) &&
669 "Kind should be Line (or Distance)");
675const SCEV *DependenceInfo::Constraint::getD()
const {
676 assert(Kind == Distance &&
"Kind should be Distance");
677 return SE->getNegativeSCEV(
C);
681const Loop *DependenceInfo::Constraint::getAssociatedSrcLoop()
const {
682 assert((Kind == Distance || Kind == Line || Kind == Point) &&
683 "Kind should be Distance, Line, or Point");
684 return AssociatedSrcLoop;
688const Loop *DependenceInfo::Constraint::getAssociatedDstLoop()
const {
689 assert((Kind == Distance || Kind == Line || Kind == Point) &&
690 "Kind should be Distance, Line, or Point");
691 return AssociatedDstLoop;
694void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
695 const Loop *CurSrcLoop,
696 const Loop *CurDstLoop) {
700 AssociatedSrcLoop = CurSrcLoop;
701 AssociatedDstLoop = CurDstLoop;
704void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
705 const SCEV *CC,
const Loop *CurSrcLoop,
706 const Loop *CurDstLoop) {
711 AssociatedSrcLoop = CurSrcLoop;
712 AssociatedDstLoop = CurDstLoop;
715void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
716 const Loop *CurSrcLoop,
717 const Loop *CurDstLoop) {
719 A = SE->getOne(
D->getType());
720 B = SE->getNegativeSCEV(
A);
721 C = SE->getNegativeSCEV(
D);
722 AssociatedSrcLoop = CurSrcLoop;
723 AssociatedDstLoop = CurDstLoop;
726void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
728void DependenceInfo::Constraint::setAny(ScalarEvolution *NewSE) {
733#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
735LLVM_DUMP_METHOD void DependenceInfo::Constraint::dump(raw_ostream &OS)
const {
741 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
742 else if (isDistance())
743 OS <<
" Distance is " << *getD() <<
" (" << *getA() <<
"*X + " << *getB()
744 <<
"*Y = " << *getC() <<
")\n";
746 OS <<
" Line is " << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC()
760bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
765 assert(!
Y->isPoint() &&
"Y must not be a Point");
779 if (
X->isDistance() &&
Y->isDistance()) {
803 assert(!(
X->isPoint() &&
Y->isPoint()) &&
804 "We shouldn't ever see X->isPoint() && Y->isPoint()");
806 if (
X->isLine() &&
Y->isLine()) {
808 const SCEV *Prod1 = SE->getMulExpr(
X->getA(),
Y->getB());
809 const SCEV *Prod2 = SE->getMulExpr(
X->getB(),
Y->getA());
813 Prod1 = SE->getMulExpr(
X->getC(),
Y->getB());
814 Prod2 = SE->getMulExpr(
X->getB(),
Y->getC());
827 const SCEV *C1B2 = SE->getMulExpr(
X->getC(),
Y->getB());
828 const SCEV *C1A2 = SE->getMulExpr(
X->getC(),
Y->getA());
829 const SCEV *C2B1 = SE->getMulExpr(
Y->getC(),
X->getB());
830 const SCEV *C2A1 = SE->getMulExpr(
Y->getC(),
X->getA());
831 const SCEV *A1B2 = SE->getMulExpr(
X->getA(),
Y->getB());
832 const SCEV *A2B1 = SE->getMulExpr(
Y->getA(),
X->getB());
833 const SCEVConstant *C1A2_C2A1 =
835 const SCEVConstant *C1B2_C2B1 =
837 const SCEVConstant *A1B2_A2B1 =
839 const SCEVConstant *A2B1_A1B2 =
841 if (!C1B2_C2B1 || !C1A2_C2A1 || !A1B2_A2B1 || !A2B1_A1B2)
857 if (Xr != 0 || Yr != 0) {
863 if (Xq.
slt(0) || Yq.
slt(0)) {
868 if (
const SCEVConstant *CUB = collectConstantUpperBound(
869 X->getAssociatedSrcLoop(), Prod1->
getType())) {
870 const APInt &UpperBound = CUB->getAPInt();
872 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
878 X->setPoint(SE->getConstant(Xq), SE->getConstant(Yq),
879 X->getAssociatedSrcLoop(),
X->getAssociatedDstLoop());
887 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
889 if (
X->isPoint() &&
Y->isLine()) {
891 const SCEV *A1X1 = SE->getMulExpr(
Y->getA(),
X->getX());
892 const SCEV *B1Y1 = SE->getMulExpr(
Y->getB(),
X->getY());
893 const SCEV *Sum = SE->getAddExpr(A1X1, B1Y1);
911SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
912 const SCEV *FailurePoint)
913 :
Type(
Type), FailurePoint(FailurePoint) {
915 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
916 "FailurePoint must be provided iff Type is Unknown");
922 case SCEVMonotonicityType::Unknown:
923 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
925 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
927 case SCEVMonotonicityType::Invariant:
930 case SCEVMonotonicityType::MultivariateSignedMonotonic:
931 OS <<
"MultivariateSignedMonotonic\n";
936bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
937 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
940SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
941 if (isLoopInvariant(Expr))
942 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
943 return createUnknown(Expr);
947SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
948 const Loop *OutermostLoop) {
950 "OutermostLoop must be outermost");
952 this->OutermostLoop = OutermostLoop;
968SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
970 return createUnknown(Expr);
975 SCEVMonotonicity StartMon =
visit(Start);
976 if (StartMon.isUnknown())
979 if (!isLoopInvariant(Step))
980 return createUnknown(Expr);
982 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
1005 if (SameSDLevels > 0) {
1006 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
1013 if (!Assumptions.isAlwaysTrue()) {
1014 OS <<
" Runtime Assumptions:\n";
1015 Assumptions.print(OS, 2);
1022 bool Splitable =
false;
1025 bool OnSameSD =
false;
1026 unsigned LevelNum = Levels;
1028 LevelNum += SameSDLevels;
1030 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
1109 return LI->isUnordered();
1111 return SI->isUnordered();
1119bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
1120 const Loop *DstLoop)
const {
1121 if (SrcLoop == DstLoop)
1127 if (!SrcLoop || !SrcLoop->
getLoopLatch() || !DstLoop ||
1131 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
1132 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
1133 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
1134 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
1135 DstUP = SE->getBackedgeTakenCount(DstLoop);
1137 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
1138 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
1139 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
1140 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
1211void DependenceInfo::establishNestingLevels(
const Instruction *Src,
1213 const BasicBlock *SrcBlock = Src->getParent();
1214 const BasicBlock *DstBlock = Dst->getParent();
1215 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
1216 unsigned DstLevel = LI->getLoopDepth(DstBlock);
1217 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
1218 const Loop *DstLoop = LI->getLoopFor(DstBlock);
1219 SrcLevels = SrcLevel;
1220 MaxLevels = SrcLevel + DstLevel;
1222 while (SrcLevel > DstLevel) {
1226 while (DstLevel > SrcLevel) {
1232 while (SrcLoop != DstLoop) {
1234 if (!haveSameSD(SrcLoop, DstLoop))
1240 CommonLevels = SrcLevel;
1241 MaxLevels -= CommonLevels;
1246unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
1252unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
1254 if (
D > CommonLevels)
1257 return D - CommonLevels + SrcLevels;
1284 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
1292 unsigned widestWidthSeen = 0;
1297 for (Subscript *Pair : Pairs) {
1298 const SCEV *Src = Pair->Src;
1299 const SCEV *Dst = Pair->Dst;
1302 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1304 "This function only unify integer types and "
1305 "expect Src and Dst share the same type otherwise.");
1318 assert(widestWidthSeen > 0);
1321 for (Subscript *Pair : Pairs) {
1322 const SCEV *Src = Pair->Src;
1323 const SCEV *Dst = Pair->Dst;
1326 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1328 "This function only unify integer types and "
1329 "expect Src and Dst share the same type otherwise.");
1334 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1337 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1346void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1347 const SCEV *Src = Pair->Src;
1348 const SCEV *Dst = Pair->Dst;
1353 const SCEV *SrcCastOp = SrcCast->
getOperand();
1354 const SCEV *DstCastOp = DstCast->
getOperand();
1356 Pair->Src = SrcCastOp;
1357 Pair->Dst = DstCastOp;
1368 return isLoopInvariant(Expr, LoopNest);
1375 const Loop *
L = LoopNest;
1376 while (L && AddRec->
getLoop() != L)
1377 L =
L->getParentLoop();
1383 if (!isLoopInvariant(Step, LoopNest))
1389 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1394bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1396 return checkSubscript(Src, LoopNest,
Loops,
true);
1401bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1403 return checkSubscript(Dst, LoopNest,
Loops,
false);
1409DependenceInfo::Subscript::ClassificationKind
1410DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1411 const SCEV *Dst,
const Loop *DstLoopNest,
1413 SmallBitVector SrcLoops(MaxLevels + 1);
1414 SmallBitVector DstLoops(MaxLevels + 1);
1415 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1416 return Subscript::NonLinear;
1417 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1418 return Subscript::NonLinear;
1421 unsigned N =
Loops.count();
1423 return Subscript::ZIV;
1425 return Subscript::SIV;
1426 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1427 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1428 return Subscript::RDIV;
1429 return Subscript::MIV;
1443 const SCEV *
Y)
const {
1457 if (SE->isKnownPredicate(Pred,
X,
Y))
1464 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1469 return SE->isKnownNonZero(Delta);
1471 return SE->isKnownNonNegative(Delta);
1473 return SE->isKnownNonPositive(Delta);
1475 return SE->isKnownPositive(Delta);
1477 return SE->isKnownNegative(Delta);
1489bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1493 if (!SType || !SizeType)
1496 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1497 S = SE->getTruncateOrZeroExtend(S, MaxType);
1498 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1500 auto CheckAddRecBECount = [&]() {
1504 const SCEV *BECount = collectUpperBound(AddRec->
getLoop(), MaxType);
1511 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1512 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1517 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1522 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1527 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1533 if (CheckAddRecBECount())
1537 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1538 return SE->isKnownNegative(LimitedBound);
1541bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1542 bool Inbounds =
false;
1544 Inbounds = SrcGEP->isInBounds();
1550 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1551 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1557 return SE->isKnownNonNegative(S);
1567const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1568 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1569 const SCEV *UB = SE->getBackedgeTakenCount(L);
1570 return SE->getTruncateOrZeroExtend(UB,
T);
1577const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1579 if (
const SCEV *UB = collectUpperBound(L,
T))
1636bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1651 Result.Consistent =
false;
1682bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1683 const SCEV *DstConst,
const Loop *CurSrcLoop,
1684 const Loop *CurDstLoop,
unsigned Level,
1686 Constraint &NewConstraint)
const {
1697 ++StrongSIVapplications;
1698 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1703 Result.Consistent =
false;
1710 bool IsDeltaLarge = [&] {
1711 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1719 if (!AbsDelta || !AbsCoeff)
1728 ++StrongSIVindependence;
1729 ++StrongSIVsuccesses;
1737 APInt Distance = ConstDelta;
1738 APInt Remainder = ConstDelta;
1743 if (Remainder != 0) {
1745 ++StrongSIVindependence;
1746 ++StrongSIVsuccesses;
1749 Result.DV[
Level].Distance = SE->getConstant(Distance);
1750 NewConstraint.setDistance(SE->getConstant(Distance), CurSrcLoop,
1752 if (Distance.
sgt(0))
1754 else if (Distance.
slt(0))
1758 ++StrongSIVsuccesses;
1759 }
else if (Delta->
isZero()) {
1762 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1764 ++StrongSIVsuccesses;
1766 if (Coeff->
isOne()) {
1769 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1771 Result.Consistent =
false;
1772 NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
1773 SE->getNegativeSCEV(Delta), CurSrcLoop, CurDstLoop);
1777 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1778 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1779 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1780 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1781 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1786 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1787 (DeltaMaybeNegative && CoeffMaybeNegative))
1791 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1792 (DeltaMaybePositive && CoeffMaybeNegative))
1794 if (NewDirection <
Result.DV[Level].Direction)
1795 ++StrongSIVsuccesses;
1829bool DependenceInfo::weakCrossingSIVtest(
1830 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1831 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
1833 const SCEV *&SplitIter)
const {
1841 ++WeakCrossingSIVapplications;
1842 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1844 Result.Consistent =
false;
1845 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1847 NewConstraint.setLine(Coeff, Coeff, Delta, CurSrcLoop, CurDstLoop);
1849 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1850 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1851 ++WeakCrossingSIVsuccesses;
1852 if (!
Result.DV[Level].Direction) {
1853 ++WeakCrossingSIVindependence;
1864 if (SE->isKnownNegative(ConstCoeff)) {
1867 "dynamic cast of negative of ConstCoeff should yield constant");
1868 Delta = SE->getNegativeSCEV(Delta);
1870 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1873 SplitIter = SE->getUDivExpr(
1874 SE->getSMaxExpr(SE->getZero(Delta->
getType()), Delta),
1875 SE->getMulExpr(SE->getConstant(Delta->
getType(), 2), ConstCoeff));
1886 if (SE->isKnownNegative(Delta)) {
1888 ++WeakCrossingSIVindependence;
1889 ++WeakCrossingSIVsuccesses;
1895 if (
const SCEV *UpperBound =
1896 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1898 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1900 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1904 ++WeakCrossingSIVindependence;
1905 ++WeakCrossingSIVsuccesses;
1910 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1911 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1912 ++WeakCrossingSIVsuccesses;
1913 if (!
Result.DV[Level].Direction) {
1914 ++WeakCrossingSIVindependence;
1924 APInt APDelta = ConstDelta->
getAPInt();
1925 APInt APCoeff = ConstCoeff->
getAPInt();
1926 APInt Distance = APDelta;
1927 APInt Remainder = APDelta;
1930 if (Remainder != 0) {
1932 ++WeakCrossingSIVindependence;
1933 ++WeakCrossingSIVsuccesses;
1939 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1940 Remainder = Distance.
srem(Two);
1942 if (Remainder != 0) {
1944 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1945 ++WeakCrossingSIVsuccesses;
1962 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1963 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1971 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1972 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1979 X = AM.
slt(0) ? -A1 : A1;
1980 Y = BM.
slt(0) ? B1 : -B1;
1996 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
2008 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
2043static std::pair<std::optional<APInt>, std::optional<APInt>>
2045 const std::optional<APInt> &UB) {
2046 assert(
A != 0 &&
"A must be non-zero");
2047 std::optional<APInt> TL, TU;
2067 return std::make_pair(TL, TU);
2089bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2090 const SCEV *SrcConst,
const SCEV *DstConst,
2091 const Loop *CurSrcLoop,
2092 const Loop *CurDstLoop,
unsigned Level,
2094 Constraint &NewConstraint)
const {
2099 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2100 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2103 ++ExactSIVapplications;
2104 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
2106 Result.Consistent =
false;
2111 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
2112 CurSrcLoop, CurDstLoop);
2116 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2121 APInt AM = ConstSrcCoeff->
getAPInt();
2122 APInt BM = ConstDstCoeff->
getAPInt();
2127 ++ExactSIVindependence;
2128 ++ExactSIVsuccesses;
2135 std::optional<APInt> UM;
2137 if (
const SCEVConstant *CUB =
2138 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
2139 UM = CUB->getAPInt();
2145 APInt TC = CM.
sdiv(
G);
2167 auto CreateVec = [](
const std::optional<APInt> &V0,
2168 const std::optional<APInt> &V1) {
2191 ++ExactSIVindependence;
2192 ++ExactSIVsuccesses;
2198 APInt LowerDistance, UpperDistance;
2201 LowerDistance = (TY - TX) + (TA - TB) * TL;
2202 UpperDistance = (TY - TX) + (TA - TB) * TU;
2204 LowerDistance = (TY - TX) + (TA - TB) * TU;
2205 UpperDistance = (TY - TX) + (TA - TB) * TL;
2208 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
2209 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
2211 APInt
Zero(Bits, 0,
true);
2212 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
2214 ++ExactSIVsuccesses;
2216 if (LowerDistance.
slt(0)) {
2218 ++ExactSIVsuccesses;
2220 if (UpperDistance.
sgt(0)) {
2222 ++ExactSIVsuccesses;
2228 ++ExactSIVindependence;
2239 return ConstDividend.
srem(ConstDivisor) == 0;
2273bool DependenceInfo::weakZeroSrcSIVtest(
2274 const SCEV *DstCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2275 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2287 ++WeakZeroSIVapplications;
2288 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
2290 Result.Consistent =
false;
2291 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
2292 NewConstraint.setLine(SE->getZero(Delta->
getType()), DstCoeff, Delta,
2293 CurSrcLoop, CurDstLoop);
2296 if (Level < CommonLevels) {
2299 ++WeakZeroSIVsuccesses;
2309 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2310 ? SE->getNegativeSCEV(ConstCoeff)
2312 const SCEV *NewDelta =
2313 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2317 if (
const SCEV *UpperBound =
2318 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2320 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2322 ++WeakZeroSIVindependence;
2323 ++WeakZeroSIVsuccesses;
2328 if (Level < CommonLevels) {
2331 ++WeakZeroSIVsuccesses;
2339 if (SE->isKnownNegative(NewDelta)) {
2341 ++WeakZeroSIVindependence;
2342 ++WeakZeroSIVsuccesses;
2349 ++WeakZeroSIVindependence;
2350 ++WeakZeroSIVsuccesses;
2387bool DependenceInfo::weakZeroDstSIVtest(
2388 const SCEV *SrcCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2389 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2400 ++WeakZeroSIVapplications;
2401 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2403 Result.Consistent =
false;
2404 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2405 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->
getType()), Delta,
2406 CurSrcLoop, CurDstLoop);
2409 if (Level < CommonLevels) {
2412 ++WeakZeroSIVsuccesses;
2422 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2423 ? SE->getNegativeSCEV(ConstCoeff)
2425 const SCEV *NewDelta =
2426 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2430 if (
const SCEV *UpperBound =
2431 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2433 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2435 ++WeakZeroSIVindependence;
2436 ++WeakZeroSIVsuccesses;
2441 if (Level < CommonLevels) {
2444 ++WeakZeroSIVsuccesses;
2452 if (SE->isKnownNegative(NewDelta)) {
2454 ++WeakZeroSIVindependence;
2455 ++WeakZeroSIVsuccesses;
2462 ++WeakZeroSIVindependence;
2463 ++WeakZeroSIVsuccesses;
2476bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2477 const SCEV *SrcConst,
const SCEV *DstConst,
2478 const Loop *SrcLoop,
const Loop *DstLoop,
2484 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2485 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2488 ++ExactRDIVapplications;
2489 Result.Consistent =
false;
2490 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2495 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2500 APInt AM = ConstSrcCoeff->
getAPInt();
2501 APInt BM = ConstDstCoeff->
getAPInt();
2506 ++ExactRDIVindependence;
2513 std::optional<APInt> SrcUM;
2515 if (
const SCEVConstant *UpperBound =
2516 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2517 SrcUM = UpperBound->getAPInt();
2521 std::optional<APInt> DstUM;
2523 if (
const SCEVConstant *UpperBound =
2524 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2525 DstUM = UpperBound->getAPInt();
2531 APInt TC = CM.
sdiv(
G);
2556 auto CreateVec = [](
const std::optional<APInt> &V0,
2557 const std::optional<APInt> &V1) {
2577 ++ExactRDIVindependence;
2623bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2626 const Loop *Loop2)
const {
2630 ++SymbolicRDIVapplications;
2637 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2638 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2641 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2642 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2645 if (SE->isKnownNonNegative(A1)) {
2646 if (SE->isKnownNonNegative(A2)) {
2650 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2653 ++SymbolicRDIVindependence;
2659 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2662 ++SymbolicRDIVindependence;
2666 }
else if (SE->isKnownNonPositive(A2)) {
2670 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2671 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2672 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2673 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2675 ++SymbolicRDIVindependence;
2680 if (SE->isKnownNegative(C2_C1)) {
2681 ++SymbolicRDIVindependence;
2685 }
else if (SE->isKnownNonPositive(A1)) {
2686 if (SE->isKnownNonNegative(A2)) {
2690 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2691 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2692 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2693 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2695 ++SymbolicRDIVindependence;
2700 if (SE->isKnownPositive(C2_C1)) {
2701 ++SymbolicRDIVindependence;
2704 }
else if (SE->isKnownNonPositive(A2)) {
2708 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2711 ++SymbolicRDIVindependence;
2717 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2720 ++SymbolicRDIVindependence;
2737bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2739 const SCEV *&SplitIter)
const {
2744 if (SrcAddRec && DstAddRec) {
2745 const SCEV *SrcConst = SrcAddRec->
getStart();
2746 const SCEV *DstConst = DstAddRec->
getStart();
2749 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2750 const Loop *CurDstLoop = DstAddRec->
getLoop();
2751 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2752 "Loops in the SIV test should have the same iteration space and "
2754 Level = mapSrcLoop(CurSrcLoop);
2756 if (SrcCoeff == DstCoeff)
2757 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2758 CurDstLoop, Level, Result, NewConstraint);
2759 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2760 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2761 CurDstLoop, Level, Result, NewConstraint,
2765 exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2766 CurDstLoop, Level, Result, NewConstraint);
2767 return disproven || gcdMIVtest(Src, Dst, Result) ||
2768 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2772 const SCEV *SrcConst = SrcAddRec->
getStart();
2774 const SCEV *DstConst = Dst;
2775 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2776 Level = mapSrcLoop(CurSrcLoop);
2777 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2778 CurSrcLoop, Level, Result, NewConstraint) ||
2779 gcdMIVtest(Src, Dst, Result);
2782 const SCEV *DstConst = DstAddRec->
getStart();
2784 const SCEV *SrcConst = Src;
2785 const Loop *CurDstLoop = DstAddRec->
getLoop();
2786 Level = mapDstLoop(CurDstLoop);
2787 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2788 CurDstLoop, Level, Result, NewConstraint) ||
2789 gcdMIVtest(Src, Dst, Result);
2808bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2816 const SCEV *SrcConst, *DstConst;
2817 const SCEV *SrcCoeff, *DstCoeff;
2818 const Loop *SrcLoop, *DstLoop;
2824 if (SrcAddRec && DstAddRec) {
2827 SrcLoop = SrcAddRec->
getLoop();
2830 DstLoop = DstAddRec->
getLoop();
2831 }
else if (SrcAddRec) {
2832 if (
const SCEVAddRecExpr *tmpAddRec =
2834 SrcConst = tmpAddRec->getStart();
2835 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2836 SrcLoop = tmpAddRec->getLoop();
2839 DstLoop = SrcAddRec->
getLoop();
2842 }
else if (DstAddRec) {
2843 if (
const SCEVAddRecExpr *tmpAddRec =
2845 DstConst = tmpAddRec->getStart();
2846 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2847 DstLoop = tmpAddRec->getLoop();
2850 SrcLoop = DstAddRec->
getLoop();
2855 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2857 gcdMIVtest(Src, Dst, Result) ||
2858 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2865bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2870 Result.Consistent =
false;
2871 return gcdMIVtest(Src, Dst, Result) ||
2872 banerjeeMIVtest(Src, Dst,
Loops, Result);
2885 if (Product->hasNoSignedWrap())
2887 return std::nullopt;
2890bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2891 const Loop *CurLoop,
2892 const SCEV *&CurLoopCoeff,
2893 APInt &RunningGCD)
const {
2896 if (RunningGCD == 1)
2901 assert(isLoopInvariant(Expr, CurLoop) &&
2902 "Expected loop invariant expression");
2909 if (AddRec->
getLoop() == CurLoop) {
2910 CurLoopCoeff = Step;
2924 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2945bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2952 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2959 const SCEV *Coefficients = Src;
2960 while (
const SCEVAddRecExpr *AddRec =
2971 const SCEV *SrcConst = Coefficients;
2978 while (
const SCEVAddRecExpr *AddRec =
2989 const SCEV *DstConst = Coefficients;
2992 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2997 for (
const SCEV *Operand : Sum->
operands()) {
2999 assert(!Constant &&
"Surprised to find multiple constants");
3016 if (ConstDelta == 0)
3020 APInt Remainder = ConstDelta.
srem(RunningGCD);
3021 if (Remainder != 0) {
3040 bool Improved =
false;
3042 while (
const SCEVAddRecExpr *AddRec =
3045 const Loop *CurLoop = AddRec->
getLoop();
3046 RunningGCD = ExtraGCD;
3048 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
3050 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
3051 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
3054 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
3064 if (RunningGCD != 0) {
3065 Remainder = ConstDelta.
srem(RunningGCD);
3067 if (Remainder != 0) {
3068 unsigned Level = mapSrcLoop(CurLoop);
3069 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
3113bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
3120 ++BanerjeeApplications;
3123 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
3126 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
3127 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
3128 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
3133 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3134 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
3137 findBoundsALL(
A,
B, Bound, K);
3152 bool Disproved =
false;
3155 unsigned DepthExpanded = 0;
3157 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
3159 bool Improved =
false;
3160 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3162 unsigned Old =
Result.DV[
K - 1].Direction;
3163 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
3164 Improved |= Old !=
Result.DV[
K - 1].Direction;
3165 if (!
Result.DV[K - 1].Direction) {
3173 ++BanerjeeSuccesses;
3175 ++BanerjeeIndependence;
3179 ++BanerjeeIndependence;
3193unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
3194 CoefficientInfo *
B, BoundInfo *Bound,
3196 unsigned &DepthExpanded,
3197 const SCEV *Delta)
const {
3203 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
3204 "direction exploration is terminated.\n");
3205 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
3211 if (Level > CommonLevels) {
3214 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
3216 Bound[
K].DirSet |= Bound[
K].Direction;
3241 if (Level > DepthExpanded) {
3242 DepthExpanded =
Level;
3244 findBoundsLT(
A,
B, Bound, Level);
3245 findBoundsGT(
A,
B, Bound, Level);
3246 findBoundsEQ(
A,
B, Bound, Level);
3285 unsigned NewDeps = 0;
3289 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3294 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3299 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3305 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
3310bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
3311 BoundInfo *Bound,
const SCEV *Delta)
const {
3312 Bound[
Level].Direction = DirKind;
3313 if (
const SCEV *LowerBound = getLowerBound(Bound))
3316 if (
const SCEV *UpperBound = getUpperBound(Bound))
3337void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
3338 BoundInfo *Bound,
unsigned K)
const {
3343 if (Bound[K].Iterations) {
3345 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3347 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3352 SE->getZero(
A[K].Coeff->
getType());
3355 SE->getZero(
A[K].Coeff->
getType());
3374void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3375 BoundInfo *Bound,
unsigned K)
const {
3380 if (Bound[K].Iterations) {
3381 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3382 const SCEV *NegativePart = getNegativePart(Delta);
3384 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3385 const SCEV *PositivePart = getPositivePart(Delta);
3387 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3391 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3392 const SCEV *NegativePart = getNegativePart(Delta);
3393 if (NegativePart->
isZero())
3395 const SCEV *PositivePart = getPositivePart(Delta);
3396 if (PositivePart->
isZero())
3414void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3415 BoundInfo *Bound,
unsigned K)
const {
3420 if (Bound[K].Iterations) {
3421 const SCEV *Iter_1 = SE->getMinusSCEV(
3422 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3423 const SCEV *NegPart =
3424 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3426 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3427 const SCEV *PosPart =
3428 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3430 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3434 const SCEV *NegPart =
3435 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3438 const SCEV *PosPart =
3439 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3458void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3459 BoundInfo *Bound,
unsigned K)
const {
3464 if (Bound[K].Iterations) {
3465 const SCEV *Iter_1 = SE->getMinusSCEV(
3466 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3467 const SCEV *NegPart =
3468 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3470 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3471 const SCEV *PosPart =
3472 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3474 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3478 const SCEV *NegPart =
3479 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3482 const SCEV *PosPart =
3483 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3490const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3491 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3495const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3496 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3502DependenceInfo::CoefficientInfo *
3503DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3505 const SCEV *
Zero = SE->getZero(Subscript->getType());
3506 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3507 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3509 CI[
K].PosPart =
Zero;
3510 CI[
K].NegPart =
Zero;
3511 CI[
K].Iterations =
nullptr;
3515 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3517 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3518 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3519 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3525 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3532 if (CI[K].Iterations)
3547const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3548 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3549 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3562const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3563 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3564 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3582const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3583 const Loop *TargetLoop)
const {
3586 return SE->getZero(Expr->
getType());
3587 if (AddRec->
getLoop() == TargetLoop)
3589 return findCoefficient(AddRec->
getStart(), TargetLoop);
3597const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3598 const Loop *TargetLoop)
const {
3602 if (AddRec->
getLoop() == TargetLoop)
3604 return SE->getAddRecExpr(zeroCoefficient(AddRec->
getStart(), TargetLoop),
3614const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3615 const Loop *TargetLoop,
3619 return SE->getAddRecExpr(Expr,
Value, TargetLoop,
3621 if (AddRec->
getLoop() == TargetLoop) {
3628 if (SE->isLoopInvariant(AddRec, TargetLoop))
3630 return SE->getAddRecExpr(
3646bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3651 for (
unsigned LI :
Loops.set_bits()) {
3654 if (Constraints[LI].isDistance())
3655 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3656 else if (Constraints[LI].isLine())
3657 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3658 else if (Constraints[LI].isPoint())
3659 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3669bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3670 Constraint &CurConstraint,
3672 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3673 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3675 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3678 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3679 Src = SE->getMinusSCEV(Src, DA_K);
3680 Src = zeroCoefficient(Src, CurSrcLoop);
3683 Dst = addToCoefficient(Dst, CurDstLoop, SE->getNegativeSCEV(A_K));
3685 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3695bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3696 Constraint &CurConstraint,
3698 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3699 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3700 const SCEV *
A = CurConstraint.getA();
3701 const SCEV *
B = CurConstraint.getB();
3702 const SCEV *
C = CurConstraint.getC();
3710 if (!Bconst || !Cconst)
3713 APInt Charlie = Cconst->
getAPInt();
3714 APInt CdivB = Charlie.
sdiv(Beta);
3715 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3716 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3717 Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
3718 Dst = zeroCoefficient(Dst, CurDstLoop);
3719 if (!findCoefficient(Src, CurSrcLoop)->
isZero())
3721 }
else if (
B->isZero()) {
3724 if (!Aconst || !Cconst)
3727 APInt Charlie = Cconst->
getAPInt();
3728 APInt CdivA = Charlie.
sdiv(Alpha);
3729 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3730 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3731 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3732 Src = zeroCoefficient(Src, CurSrcLoop);
3733 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3738 if (!Aconst || !Cconst)
3741 APInt Charlie = Cconst->
getAPInt();
3742 APInt CdivA = Charlie.
sdiv(Alpha);
3743 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3744 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3745 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3746 Src = zeroCoefficient(Src, CurSrcLoop);
3747 Dst = addToCoefficient(Dst, CurDstLoop, A_K);
3748 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3752 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3753 Src = SE->getMulExpr(Src,
A);
3754 Dst = SE->getMulExpr(Dst,
A);
3755 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K,
C));
3756 Src = zeroCoefficient(Src, CurSrcLoop);
3757 Dst = addToCoefficient(Dst, CurDstLoop, SE->getMulExpr(A_K,
B));
3758 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3769bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3770 Constraint &CurConstraint) {
3771 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3772 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3773 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3774 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3775 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3776 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3778 Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
3779 Src = zeroCoefficient(Src, CurSrcLoop);
3782 Dst = zeroCoefficient(Dst, CurDstLoop);
3789 const Constraint &CurConstraint)
const {
3792 if (CurConstraint.isAny())
3794 else if (CurConstraint.isDistance()) {
3796 Level.Scalar =
false;
3797 Level.Distance = CurConstraint.getD();
3799 if (!SE->isKnownNonZero(
Level.Distance))
3801 if (!SE->isKnownNonPositive(
Level.Distance))
3803 if (!SE->isKnownNonNegative(
Level.Distance))
3805 Level.Direction &= NewDirection;
3806 }
else if (CurConstraint.isLine()) {
3807 Level.Scalar =
false;
3808 Level.Distance =
nullptr;
3810 }
else if (CurConstraint.isPoint()) {
3811 Level.Scalar =
false;
3812 Level.Distance =
nullptr;
3815 CurConstraint.getX()))
3819 CurConstraint.getX()))
3823 CurConstraint.getX()))
3826 Level.Direction &= NewDirection;
3841 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3842 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3843 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3844 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3845 const SCEVUnknown *SrcBase =
3847 const SCEVUnknown *DstBase =
3850 if (!SrcBase || !DstBase || SrcBase != DstBase)
3855 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3856 SrcSubscripts, DstSubscripts) &&
3857 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3858 SrcSubscripts, DstSubscripts))
3861 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3862 isLoopInvariant(DstBase, DstLoop) &&
3863 "Expected SrcBase and DstBase to be loop invariant");
3867 dbgs() <<
"\nSrcSubscripts: ";
3868 for (
int I = 0;
I <
Size;
I++)
3869 dbgs() << *SrcSubscripts[
I];
3870 dbgs() <<
"\nDstSubscripts: ";
3871 for (
int I = 0;
I <
Size;
I++)
3872 dbgs() << *DstSubscripts[
I];
3880 SCEVMonotonicityChecker MonChecker(SE);
3881 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3882 for (
int I = 0;
I <
Size; ++
I) {
3883 Pair[
I].Src = SrcSubscripts[
I];
3884 Pair[
I].Dst = DstSubscripts[
I];
3885 unifySubscriptType(&Pair[
I]);
3888 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3890 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3901bool DependenceInfo::tryDelinearizeFixedSize(
3906 const SCEVUnknown *SrcBase =
3908 const SCEVUnknown *DstBase =
3910 assert(SrcBase && DstBase && SrcBase == DstBase &&
3911 "expected src and dst scev unknowns to be equal");
3914 SmallVector<int, 4> SrcSizes;
3915 SmallVector<int, 4> DstSizes;
3924 if (SrcSizes.size() != DstSizes.
size() ||
3925 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3926 SrcSubscripts.
clear();
3927 DstSubscripts.
clear();
3932 "Expected equal number of entries in the list of SrcSubscripts and "
3945 auto AllIndicesInRange = [&](SmallVector<int, 4> &DimensionSizes,
3946 SmallVectorImpl<const SCEV *> &Subscripts,
3948 size_t SSize = Subscripts.
size();
3949 for (
size_t I = 1;
I < SSize; ++
I) {
3950 const SCEV *S = Subscripts[
I];
3953 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3954 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *
Ptr <<
"\n";
3959 const SCEV *
Range = SE->getConstant(
3960 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3961 if (!isKnownLessThan(S,
Range)) {
3963 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3964 dbgs() <<
" S: " << *S <<
"\n"
3965 <<
" Range: " << *
Range <<
"\n";
3974 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3975 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3977 SrcSubscripts.
clear();
3978 DstSubscripts.
clear();
3983 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3984 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3985 <<
"DstGEP:" << *DstPtr <<
"\n";
3990bool DependenceInfo::tryDelinearizeParametricSize(
3997 const SCEVUnknown *SrcBase =
3999 const SCEVUnknown *DstBase =
4001 assert(SrcBase && DstBase && SrcBase == DstBase &&
4002 "expected src and dst scev unknowns to be equal");
4004 const SCEV *ElementSize = SE->getElementSize(Src);
4005 if (ElementSize != SE->getElementSize(Dst))
4008 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
4009 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
4030 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
4031 SrcSubscripts.
size() != DstSubscripts.
size())
4034 size_t Size = SrcSubscripts.
size();
4043 for (
size_t I = 1;
I <
Size; ++
I) {
4046 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
4047 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
4048 if (SNN && DNN && SLT && DLT)
4052 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
4054 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
4056 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
4058 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
4059 << *
Sizes[
I - 1] <<
")\n";
4061 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
4062 << *
Sizes[
I - 1] <<
")\n";
4076 for (
unsigned VI : BV.
set_bits()) {
4086 FunctionAnalysisManager::Invalidator &Inv) {
4093 return Inv.invalidate<
AAManager>(F, PA) ||
4113std::unique_ptr<Dependence>
4115 bool UnderRuntimeAssumptions) {
4117 bool PossiblyLoopIndependent =
true;
4119 PossiblyLoopIndependent =
false;
4121 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
4127 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
4128 return std::make_unique<Dependence>(Src, Dst,
4140 return std::make_unique<Dependence>(Src, Dst,
4154 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
4155 return std::make_unique<Dependence>(Src, Dst,
4161 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4162 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4165 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
4166 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
4167 if (SrcBase != DstBase) {
4174 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
4175 return std::make_unique<Dependence>(Src, Dst,
4183 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
4184 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
4185 if (!isLoopInvariant(SrcBase, SrcLoop) ||
4186 !isLoopInvariant(DstBase, DstLoop)) {
4187 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
4188 return std::make_unique<Dependence>(Src, Dst,
4193 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
4194 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
4197 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
4198 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
4199 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
4200 return std::make_unique<Dependence>(Src, Dst,
4204 if (!Assume.empty()) {
4205 if (!UnderRuntimeAssumptions)
4206 return std::make_unique<Dependence>(Src, Dst,
4209 unsigned N = Assumptions.size();
4211 bool Implied =
false;
4212 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
4213 if (Assumptions[
I]->implies(
P, *SE))
4216 Assumptions.push_back(
P);
4222 Pair[0].Src = SrcEv;
4223 Pair[0].Dst = DstEv;
4225 SCEVMonotonicityChecker MonChecker(SE);
4228 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
4229 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
4230 return std::make_unique<Dependence>(Src, Dst,
4234 if (tryDelinearize(Src, Dst, Pair)) {
4236 Pairs = Pair.
size();
4241 establishNestingLevels(Src, Dst);
4243 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
4244 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
4245 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
4248 CommonLevels += SameSDLevels;
4249 MaxLevels -= SameSDLevels;
4250 if (SameSDLevels > 0) {
4253 for (
unsigned P = 0;
P < Pairs; ++
P) {
4255 Subscript::ClassificationKind TestClass =
4256 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
4257 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
4259 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
4260 TestClass != Subscript::RDIV) {
4262 CommonLevels -= SameSDLevels;
4263 MaxLevels += SameSDLevels;
4270 if (SameSDLevels > 0)
4274 PossiblyLoopIndependent, CommonLevels);
4277 for (
unsigned P = 0;
P < Pairs; ++
P) {
4278 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4279 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4280 Pair[
P].Loops.
resize(MaxLevels + 1);
4281 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4283 removeMatchingExtensions(&Pair[
P]);
4284 Pair[
P].Classification =
4285 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4286 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4287 Pair[
P].GroupLoops = Pair[
P].Loops;
4288 Pair[
P].Group.set(
P);
4357 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4358 if (Pair[
SI].Classification == Subscript::NonLinear) {
4360 ++NonlinearSubscriptPairs;
4361 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4363 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4365 Result.Consistent =
false;
4366 }
else if (Pair[
SI].Classification == Subscript::ZIV) {
4372 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4374 Intersection &= Pair[SJ].GroupLoops;
4375 if (Intersection.
any()) {
4377 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4379 Pair[SJ].Group |= Pair[
SI].Group;
4384 if (Pair[
SI].Group.count() == 1) {
4386 ++SeparableSubscriptPairs;
4389 ++CoupledSubscriptPairs;
4400 Constraint NewConstraint;
4401 NewConstraint.setAny(SE);
4406 switch (Pair[
SI].Classification) {
4407 case Subscript::ZIV:
4409 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4412 case Subscript::SIV: {
4415 const SCEV *SplitIter =
nullptr;
4416 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4421 case Subscript::RDIV:
4423 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4426 case Subscript::MIV:
4428 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
4436 if (Coupled.
count()) {
4439 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
4441 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4442 Constraints[
II].setAny(SE);
4450 for (
unsigned SJ : Group.set_bits()) {
4452 if (Pair[SJ].Classification == Subscript::SIV)
4458 unifySubscriptType(PairsInGroup);
4460 while (Sivs.
any()) {
4462 for (
unsigned SJ : Sivs.
set_bits()) {
4466 const SCEV *SplitIter =
nullptr;
4468 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4471 ConstrainedLevels.
set(Level);
4472 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
4473 if (Constraints[Level].isEmpty()) {
4474 ++DeltaIndependence;
4486 for (
unsigned SJ : Mivs.
set_bits()) {
4489 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
4490 Constraints, Result.Consistent)) {
4492 ++DeltaPropagations;
4493 Pair[SJ].Classification = classifyPair(
4494 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4495 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4496 switch (Pair[SJ].Classification) {
4497 case Subscript::ZIV:
4499 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4503 case Subscript::SIV:
4507 case Subscript::RDIV:
4508 case Subscript::MIV:
4519 for (
unsigned SJ : Mivs.
set_bits()) {
4520 if (Pair[SJ].Classification == Subscript::RDIV) {
4522 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4532 for (
unsigned SJ : Mivs.
set_bits()) {
4533 if (Pair[SJ].Classification == Subscript::MIV) {
4535 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
4543 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
4544 if (SJ > CommonLevels)
4546 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
4555 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
4556 CompleteLoops |= Pair[
SI].
Loops;
4557 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
4558 if (CompleteLoops[
II])
4559 Result.DV[
II - 1].Scalar =
false;
4564 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
4566 if (Result.DV[
II - 1].Distance ==
nullptr)
4567 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
4569 assert(Result.DV[
II - 1].Distance->isZero() &&
4570 "Inconsistency between distance and direction");
4576 const SCEV *Distance = Result.getDistance(
II);
4577 if (Distance && Distance->
isZero())
4579 "Distance is zero, but direction is not EQ");
4583 if (SameSDLevels > 0) {
4586 assert(CommonLevels >= SameSDLevels);
4587 CommonLevels -= SameSDLevels;
4588 MaxLevels += SameSDLevels;
4589 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
4590 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
4591 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
4592 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
4593 DV[Level] = Result.DV[Level];
4594 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
4595 DVSameSD[Level] = Result.DV[CommonLevels + Level];
4596 Result.DV = std::move(DV);
4597 Result.DVSameSD = std::move(DVSameSD);
4598 Result.Levels = CommonLevels;
4599 Result.SameSDLevels = SameSDLevels;
4601 Result.Consistent =
false;
4604 if (PossiblyLoopIndependent) {
4608 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4610 Result.LoopIndependent =
false;
4617 bool AllEqual =
true;
4618 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4628 return std::make_unique<FullDependence>(std::move(Result));
4679 unsigned SplitLevel) {
4681 "Dep should be splitable at SplitLevel");
4684 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4685 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4695 establishNestingLevels(Src, Dst);
4697 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4701 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4702 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4703 Pair[0].Src = SE->removePointerBase(SrcSCEV);
4704 Pair[0].Dst = SE->removePointerBase(DstSCEV);
4707 if (tryDelinearize(Src, Dst, Pair)) {
4709 Pairs = Pair.
size();
4713 for (
unsigned P = 0;
P < Pairs; ++
P) {
4714 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4715 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4716 Pair[
P].Loops.
resize(MaxLevels + 1);
4717 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4719 removeMatchingExtensions(&Pair[
P]);
4720 Pair[
P].Classification =
4721 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4722 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4723 Pair[
P].GroupLoops = Pair[
P].Loops;
4724 Pair[
P].Group.set(
P);
4731 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4732 if (Pair[
SI].Classification == Subscript::NonLinear) {
4734 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4736 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4738 Result.Consistent =
false;
4739 }
else if (Pair[
SI].Classification == Subscript::ZIV)
4744 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4746 Intersection &= Pair[SJ].GroupLoops;
4747 if (Intersection.
any()) {
4749 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4751 Pair[SJ].Group |= Pair[
SI].Group;
4756 if (Pair[
SI].Group.count() == 1)
4764 Constraint NewConstraint;
4765 NewConstraint.setAny(SE);
4769 switch (Pair[
SI].Classification) {
4770 case Subscript::SIV: {
4772 const SCEV *SplitIter =
nullptr;
4773 (void)testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4775 if (Level == SplitLevel) {
4776 assert(SplitIter !=
nullptr);
4781 case Subscript::ZIV:
4782 case Subscript::RDIV:
4783 case Subscript::MIV:
4790 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4794 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4795 Constraints[
II].setAny(SE);
4801 for (
unsigned SJ : Group.set_bits()) {
4802 if (Pair[SJ].Classification == Subscript::SIV)
4807 while (Sivs.
any()) {
4809 for (
unsigned SJ : Sivs.
set_bits()) {
4812 const SCEV *SplitIter =
nullptr;
4813 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4815 if (Level == SplitLevel && SplitIter)
4817 ConstrainedLevels.
set(Level);
4818 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4825 for (
unsigned SJ : Mivs.
set_bits()) {
4827 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4830 Pair[SJ].Classification = classifyPair(
4831 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4832 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4833 switch (Pair[SJ].Classification) {
4834 case Subscript::ZIV:
4837 case Subscript::SIV:
4841 case Subscript::RDIV:
4842 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 const SCEV * mulSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A * B if it guaranteed not to signed wrap.
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static cl::opt< bool > EnableMonotonicityCheck("da-enable-monotonicity-check", cl::init(false), cl::Hidden, cl::desc("Check if the subscripts are monotonic. If it's not, dependence " "is reported as unknown."))
static cl::opt< bool > DumpMonotonicityReport("da-dump-monotonicity-report", cl::init(false), cl::Hidden, cl::desc("When printing analysis, dump the results of monotonicity checks."))
static cl::opt< unsigned > MIVMaxLevelThreshold("da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors."))
static cl::opt< bool > DisableDelinearizationChecks("da-disable-delinearization-checks", cl::Hidden, cl::desc("Disable checks that try to statically verify validity of " "delinearized subscripts. Enabling this option may result in incorrect " "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension."))
Module.h This file contains the declarations for the Module class.
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.
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStart() const
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 const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
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.