65#define DEBUG_TYPE "da"
71STATISTIC(NonlinearSubscriptPairs,
"Nonlinear subscript pairs");
74STATISTIC(StrongSIVapplications,
"Strong SIV applications");
75STATISTIC(StrongSIVsuccesses,
"Strong SIV successes");
76STATISTIC(StrongSIVindependence,
"Strong SIV independence");
77STATISTIC(WeakCrossingSIVapplications,
"Weak-Crossing SIV applications");
78STATISTIC(WeakCrossingSIVsuccesses,
"Weak-Crossing SIV successes");
79STATISTIC(WeakCrossingSIVindependence,
"Weak-Crossing SIV independence");
80STATISTIC(ExactSIVapplications,
"Exact SIV applications");
82STATISTIC(ExactSIVindependence,
"Exact SIV independence");
83STATISTIC(WeakZeroSIVapplications,
"Weak-Zero SIV applications");
84STATISTIC(WeakZeroSIVsuccesses,
"Weak-Zero SIV successes");
85STATISTIC(WeakZeroSIVindependence,
"Weak-Zero SIV independence");
86STATISTIC(ExactRDIVapplications,
"Exact RDIV applications");
87STATISTIC(ExactRDIVindependence,
"Exact RDIV independence");
88STATISTIC(SymbolicRDIVapplications,
"Symbolic RDIV applications");
89STATISTIC(SymbolicRDIVindependence,
"Symbolic RDIV independence");
93STATISTIC(BanerjeeApplications,
"Banerjee applications");
94STATISTIC(BanerjeeIndependence,
"Banerjee independence");
96STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
100 cl::desc(
"Try to delinearize array references."));
102 "da-disable-delinearization-checks",
cl::Hidden,
104 "Disable checks that try to statically verify validity of "
105 "delinearized subscripts. Enabling this option may result in incorrect "
106 "dependence vectors for languages that allow the subscript of one "
107 "dimension to underflow or overflow into another dimension."));
111 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
112 "explore MIV direction vectors."));
117enum class DependenceTestType {
132 "da-enable-dependence-test",
cl::init(DependenceTestType::All),
134 cl::desc(
"Run only specified dependence test routine and disable others. "
135 "The purpose is mainly to exclude the influence of other "
136 "dependence test routines in regression tests. If set to All, all "
137 "dependence test routines are enabled."),
139 "Enable all dependence test routines."),
140 clEnumValN(DependenceTestType::StrongSIV,
"strong-siv",
141 "Enable only Strong SIV test."),
142 clEnumValN(DependenceTestType::WeakCrossingSIV,
144 "Enable only Weak-Crossing SIV test."),
145 clEnumValN(DependenceTestType::ExactSIV,
"exact-siv",
146 "Enable only Exact SIV test."),
147 clEnumValN(DependenceTestType::WeakZeroSIV,
"weak-zero-siv",
148 "Enable only Weak-Zero SIV test."),
149 clEnumValN(DependenceTestType::ExactRDIV,
"exact-rdiv",
150 "Enable only Exact RDIV test."),
151 clEnumValN(DependenceTestType::SymbolicRDIV,
"symbolic-rdiv",
152 "Enable only Symbolic RDIV test."),
153 clEnumValN(DependenceTestType::GCDMIV,
"gcd-miv",
154 "Enable only GCD MIV test."),
155 clEnumValN(DependenceTestType::BanerjeeMIV,
"banerjee-miv",
156 "Enable only Banerjee MIV test.")));
162 cl::desc(
"Check if the subscripts are monotonic. If it's not, dependence "
163 "is reported as unknown."));
168 "When printing analysis, dump the results of monotonicity checks."));
184 "Dependence Analysis",
true,
true)
257enum class SCEVMonotonicityType {
269 MultivariateSignedMonotonic,
272struct SCEVMonotonicity {
273 SCEVMonotonicity(SCEVMonotonicityType
Type,
274 const SCEV *FailurePoint =
nullptr);
276 SCEVMonotonicityType
getType()
const {
return Type; }
278 const SCEV *getFailurePoint()
const {
return FailurePoint; }
280 bool isUnknown()
const {
return Type == SCEVMonotonicityType::Unknown; }
282 void print(raw_ostream &OS,
unsigned Depth)
const;
285 SCEVMonotonicityType
Type;
288 const SCEV *FailurePoint;
295struct SCEVMonotonicityChecker
296 :
public SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity> {
298 SCEVMonotonicityChecker(ScalarEvolution *SE) : SE(SE) {}
303 SCEVMonotonicity checkMonotonicity(
const SCEV *Expr,
304 const Loop *OutermostLoop);
310 const Loop *OutermostLoop;
313 SCEVMonotonicity invariantOrUnknown(
const SCEV *Expr);
317 bool isLoopInvariant(
const SCEV *Expr)
const;
320 SCEVMonotonicity createUnknown(
const SCEV *FailurePoint) {
321 return SCEVMonotonicity(SCEVMonotonicityType::Unknown, FailurePoint);
324 SCEVMonotonicity visitAddRecExpr(
const SCEVAddRecExpr *Expr);
326 SCEVMonotonicity visitConstant(
const SCEVConstant *) {
327 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
329 SCEVMonotonicity visitVScale(
const SCEVVScale *) {
330 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
334 SCEVMonotonicity visitZeroExtendExpr(
const SCEVZeroExtendExpr *Expr) {
335 return invariantOrUnknown(Expr);
337 SCEVMonotonicity visitSignExtendExpr(
const SCEVSignExtendExpr *Expr) {
338 return invariantOrUnknown(Expr);
340 SCEVMonotonicity visitAddExpr(
const SCEVAddExpr *Expr) {
341 return invariantOrUnknown(Expr);
343 SCEVMonotonicity visitMulExpr(
const SCEVMulExpr *Expr) {
344 return invariantOrUnknown(Expr);
346 SCEVMonotonicity visitPtrToIntExpr(
const SCEVPtrToIntExpr *Expr) {
347 return invariantOrUnknown(Expr);
349 SCEVMonotonicity visitTruncateExpr(
const SCEVTruncateExpr *Expr) {
350 return invariantOrUnknown(Expr);
352 SCEVMonotonicity visitUDivExpr(
const SCEVUDivExpr *Expr) {
353 return invariantOrUnknown(Expr);
355 SCEVMonotonicity visitSMaxExpr(
const SCEVSMaxExpr *Expr) {
356 return invariantOrUnknown(Expr);
358 SCEVMonotonicity visitUMaxExpr(
const SCEVUMaxExpr *Expr) {
359 return invariantOrUnknown(Expr);
361 SCEVMonotonicity visitSMinExpr(
const SCEVSMinExpr *Expr) {
362 return invariantOrUnknown(Expr);
364 SCEVMonotonicity visitUMinExpr(
const SCEVUMinExpr *Expr) {
365 return invariantOrUnknown(Expr);
367 SCEVMonotonicity visitSequentialUMinExpr(
const SCEVSequentialUMinExpr *Expr) {
368 return invariantOrUnknown(Expr);
370 SCEVMonotonicity visitUnknown(
const SCEVUnknown *Expr) {
371 return invariantOrUnknown(Expr);
373 SCEVMonotonicity visitCouldNotCompute(
const SCEVCouldNotCompute *Expr) {
374 return invariantOrUnknown(Expr);
377 friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
388 bool NormalizeResults) {
389 auto *
F = DA->getFunction();
392 SCEVMonotonicityChecker Checker(&SE);
393 OS <<
"Monotonicity check:\n";
399 const Loop *OutermostLoop = L ? L->getOutermostLoop() :
nullptr;
402 SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
403 OS.
indent(2) <<
"Inst: " << Inst <<
"\n";
404 OS.
indent(4) <<
"Expr: " << *AccessFn <<
"\n";
412 if (SrcI->mayReadOrWriteMemory()) {
415 if (DstI->mayReadOrWriteMemory()) {
416 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
417 OS <<
" da analyze - ";
418 if (
auto D = DA->depends(&*SrcI, &*DstI,
424 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
425 const SCEV *Distance =
D->getDistance(Level);
426 bool IsDistanceZero = Distance && Distance->
isZero();
429 assert(IsDistanceZero == IsDirectionEQ &&
430 "Inconsistent distance and direction.");
435 if (NormalizeResults &&
D->normalize(&SE))
436 OS <<
"normalized - ";
446 OS <<
"Runtime Assumptions:\n";
447 Assumptions.
print(OS, 0);
460 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
473 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
478 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
483 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
488 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
502 bool PossiblyLoopIndependent,
503 unsigned CommonLevels)
504 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
505 LoopIndependent(PossiblyLoopIndependent) {
509 DV = std::make_unique<
DVEntry[]>(CommonLevels);
528 for (
unsigned Level = 1; Level <= Levels; ++Level) {
529 unsigned char Direction = DV[Level - 1].Direction;
544 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
547 for (
unsigned Level = 1; Level <= Levels; ++Level) {
548 unsigned char Direction = DV[Level - 1].Direction;
556 DV[Level - 1].Direction = RevDirection;
558 if (DV[Level - 1].Distance !=
nullptr)
562 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
604 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
605 "Level out of range");
606 return Level > Levels;
612SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType
Type,
613 const SCEV *FailurePoint)
614 :
Type(
Type), FailurePoint(FailurePoint) {
616 ((
Type == SCEVMonotonicityType::Unknown) == (FailurePoint !=
nullptr)) &&
617 "FailurePoint must be provided iff Type is Unknown");
623 case SCEVMonotonicityType::Unknown:
624 assert(FailurePoint &&
"FailurePoint must be provided for Unknown");
626 OS.
indent(
Depth) <<
"Reason: " << *FailurePoint <<
"\n";
628 case SCEVMonotonicityType::Invariant:
631 case SCEVMonotonicityType::MultivariateSignedMonotonic:
632 OS <<
"MultivariateSignedMonotonic\n";
637bool SCEVMonotonicityChecker::isLoopInvariant(
const SCEV *Expr)
const {
638 return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
641SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(
const SCEV *Expr) {
642 if (isLoopInvariant(Expr))
643 return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
644 return createUnknown(Expr);
648SCEVMonotonicityChecker::checkMonotonicity(
const SCEV *Expr,
649 const Loop *OutermostLoop) {
651 "OutermostLoop must be outermost");
653 this->OutermostLoop = OutermostLoop;
669SCEVMonotonicityChecker::visitAddRecExpr(
const SCEVAddRecExpr *Expr) {
671 return createUnknown(Expr);
676 SCEVMonotonicity StartMon =
visit(Start);
677 if (StartMon.isUnknown())
680 if (!isLoopInvariant(Step))
681 return createUnknown(Expr);
683 return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
706 if (SameSDLevels > 0) {
707 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
714 if (!Assumptions.isAlwaysTrue()) {
715 OS <<
" Runtime Assumptions:\n";
716 Assumptions.print(OS, 2);
725 bool OnSameSD =
false;
726 unsigned LevelNum = Levels;
728 LevelNum += SameSDLevels;
730 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
805 return LI->isUnordered();
807 return SI->isUnordered();
815bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
816 const Loop *DstLoop)
const {
817 if (SrcLoop == DstLoop)
827 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
828 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
829 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
830 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
831 DstUP = SE->getBackedgeTakenCount(DstLoop);
833 if (SrcUB !=
nullptr && DstUP !=
nullptr) {
834 Type *WiderType = SE->getWiderType(SrcUB->
getType(), DstUP->getType());
835 SrcUB = SE->getNoopOrZeroExtend(SrcUB, WiderType);
836 DstUP = SE->getNoopOrZeroExtend(DstUP, WiderType);
907void DependenceInfo::establishNestingLevels(
const Instruction *Src,
909 const BasicBlock *SrcBlock = Src->getParent();
910 const BasicBlock *DstBlock = Dst->getParent();
911 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
912 unsigned DstLevel = LI->getLoopDepth(DstBlock);
913 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
914 const Loop *DstLoop = LI->getLoopFor(DstBlock);
915 SrcLevels = SrcLevel;
916 MaxLevels = SrcLevel + DstLevel;
918 while (SrcLevel > DstLevel) {
922 while (DstLevel > SrcLevel) {
928 while (SrcLoop != DstLoop) {
930 if (!haveSameSD(SrcLoop, DstLoop))
936 CommonLevels = SrcLevel;
937 MaxLevels -= CommonLevels;
942unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
948unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
950 if (
D > CommonLevels)
953 return D - CommonLevels + SrcLevels;
980 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
988 unsigned widestWidthSeen = 0;
993 for (Subscript *Pair : Pairs) {
994 const SCEV *Src = Pair->Src;
995 const SCEV *Dst = Pair->Dst;
998 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1000 "This function only unify integer types and "
1001 "expect Src and Dst share the same type otherwise.");
1014 assert(widestWidthSeen > 0);
1017 for (Subscript *Pair : Pairs) {
1018 const SCEV *Src = Pair->Src;
1019 const SCEV *Dst = Pair->Dst;
1022 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1024 "This function only unify integer types and "
1025 "expect Src and Dst share the same type otherwise.");
1030 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1033 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1042void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1043 const SCEV *Src = Pair->Src;
1044 const SCEV *Dst = Pair->Dst;
1049 const SCEV *SrcCastOp = SrcCast->
getOperand();
1050 const SCEV *DstCastOp = DstCast->
getOperand();
1052 Pair->Src = SrcCastOp;
1053 Pair->Dst = DstCastOp;
1064 return isLoopInvariant(Expr, LoopNest);
1071 const Loop *
L = LoopNest;
1072 while (L && AddRec->
getLoop() != L)
1073 L =
L->getParentLoop();
1079 if (!isLoopInvariant(Step, LoopNest))
1085 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1090bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1092 return checkSubscript(Src, LoopNest,
Loops,
true);
1097bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1099 return checkSubscript(Dst, LoopNest,
Loops,
false);
1105DependenceInfo::Subscript::ClassificationKind
1106DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1107 const SCEV *Dst,
const Loop *DstLoopNest,
1109 SmallBitVector SrcLoops(MaxLevels + 1);
1110 SmallBitVector DstLoops(MaxLevels + 1);
1111 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1112 return Subscript::NonLinear;
1113 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1114 return Subscript::NonLinear;
1117 unsigned N =
Loops.count();
1119 return Subscript::ZIV;
1121 return Subscript::SIV;
1122 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1123 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1124 return Subscript::RDIV;
1125 return Subscript::MIV;
1139 const SCEV *
Y)
const {
1153 if (SE->isKnownPredicate(Pred,
X,
Y))
1160 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1165 return SE->isKnownNonZero(Delta);
1167 return SE->isKnownNonNegative(Delta);
1169 return SE->isKnownNonPositive(Delta);
1171 return SE->isKnownPositive(Delta);
1173 return SE->isKnownNegative(Delta);
1185bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1189 if (!SType || !SizeType)
1192 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1193 S = SE->getTruncateOrZeroExtend(S, MaxType);
1194 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1196 auto CheckAddRecBECount = [&]() {
1200 const SCEV *BECount = collectUpperBound(AddRec->
getLoop(), MaxType);
1207 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1208 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1213 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1218 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1223 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1229 if (CheckAddRecBECount())
1233 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1234 return SE->isKnownNegative(LimitedBound);
1237bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *Ptr)
const {
1238 bool Inbounds =
false;
1240 Inbounds = SrcGEP->isInBounds();
1246 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1247 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1253 return SE->isKnownNonNegative(S);
1263const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1264 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1265 const SCEV *UB = SE->getBackedgeTakenCount(L);
1266 return SE->getTruncateOrZeroExtend(UB,
T);
1273const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1275 if (
const SCEV *UB = collectUpperBound(L,
T))
1332bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1347 Result.Consistent =
false;
1378bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1379 const SCEV *DstConst,
const Loop *CurSrcLoop,
1380 const Loop *CurDstLoop,
unsigned Level,
1392 ++StrongSIVapplications;
1393 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1398 Result.Consistent =
false;
1405 bool IsDeltaLarge = [&] {
1406 const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->
getType());
1414 if (!AbsDelta || !AbsCoeff)
1423 ++StrongSIVindependence;
1424 ++StrongSIVsuccesses;
1432 APInt Distance = ConstDelta;
1433 APInt Remainder = ConstDelta;
1438 if (Remainder != 0) {
1440 ++StrongSIVindependence;
1441 ++StrongSIVsuccesses;
1444 Result.DV[
Level].Distance = SE->getConstant(Distance);
1445 if (Distance.
sgt(0))
1447 else if (Distance.
slt(0))
1451 ++StrongSIVsuccesses;
1452 }
else if (Delta->
isZero()) {
1456 ++StrongSIVsuccesses;
1458 if (Coeff->
isOne()) {
1462 Result.Consistent =
false;
1466 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1467 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1468 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1469 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1470 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1475 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1476 (DeltaMaybeNegative && CoeffMaybeNegative))
1480 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1481 (DeltaMaybePositive && CoeffMaybeNegative))
1483 if (NewDirection <
Result.DV[Level].Direction)
1484 ++StrongSIVsuccesses;
1518bool DependenceInfo::weakCrossingSIVtest(
const SCEV *Coeff,
1519 const SCEV *SrcConst,
1520 const SCEV *DstConst,
1521 const Loop *CurSrcLoop,
1522 const Loop *CurDstLoop,
unsigned Level,
1531 ++WeakCrossingSIVapplications;
1532 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1534 Result.Consistent =
false;
1535 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1538 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1539 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1540 ++WeakCrossingSIVsuccesses;
1541 if (!
Result.DV[Level].Direction) {
1542 ++WeakCrossingSIVindependence;
1552 if (SE->isKnownNegative(ConstCoeff)) {
1555 "dynamic cast of negative of ConstCoeff should yield constant");
1556 Delta = SE->getNegativeSCEV(Delta);
1558 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1568 if (SE->isKnownNegative(Delta)) {
1570 ++WeakCrossingSIVindependence;
1571 ++WeakCrossingSIVsuccesses;
1577 if (
const SCEV *UpperBound =
1578 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1580 const SCEV *ConstantTwo = SE->getConstant(UpperBound->
getType(), 2);
1582 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1586 ++WeakCrossingSIVindependence;
1587 ++WeakCrossingSIVsuccesses;
1592 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1593 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1594 ++WeakCrossingSIVsuccesses;
1595 if (!
Result.DV[Level].Direction) {
1596 ++WeakCrossingSIVindependence;
1605 APInt APDelta = ConstDelta->
getAPInt();
1606 APInt APCoeff = ConstCoeff->
getAPInt();
1607 APInt Distance = APDelta;
1608 APInt Remainder = APDelta;
1611 if (Remainder != 0) {
1613 ++WeakCrossingSIVindependence;
1614 ++WeakCrossingSIVsuccesses;
1620 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1621 Remainder = Distance.
srem(Two);
1623 if (Remainder != 0) {
1625 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1626 ++WeakCrossingSIVsuccesses;
1643 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1644 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1652 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1653 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1660 X = AM.
slt(0) ? -A1 : A1;
1661 Y = BM.
slt(0) ? B1 : -B1;
1677 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1689 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1724static std::pair<std::optional<APInt>, std::optional<APInt>>
1726 const std::optional<APInt> &UB) {
1727 assert(
A != 0 &&
"A must be non-zero");
1728 std::optional<APInt> TL, TU;
1748 return std::make_pair(TL, TU);
1770bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1771 const SCEV *SrcConst,
const SCEV *DstConst,
1772 const Loop *CurSrcLoop,
1773 const Loop *CurDstLoop,
unsigned Level,
1779 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1780 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1783 ++ExactSIVapplications;
1784 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1786 Result.Consistent =
false;
1794 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1799 APInt AM = ConstSrcCoeff->
getAPInt();
1800 APInt BM = ConstDstCoeff->
getAPInt();
1805 ++ExactSIVindependence;
1806 ++ExactSIVsuccesses;
1813 std::optional<APInt> UM;
1815 if (
const SCEVConstant *CUB =
1816 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1817 UM = CUB->getAPInt();
1823 APInt TC = CM.
sdiv(
G);
1845 auto CreateVec = [](
const std::optional<APInt> &V0,
1846 const std::optional<APInt> &V1) {
1869 ++ExactSIVindependence;
1870 ++ExactSIVsuccesses;
1876 APInt LowerDistance, UpperDistance;
1879 LowerDistance = (TY - TX) + (TA - TB) * TL;
1880 UpperDistance = (TY - TX) + (TA - TB) * TU;
1882 LowerDistance = (TY - TX) + (TA - TB) * TU;
1883 UpperDistance = (TY - TX) + (TA - TB) * TL;
1886 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1887 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1889 APInt
Zero(Bits, 0,
true);
1890 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1892 ++ExactSIVsuccesses;
1894 if (LowerDistance.
slt(0)) {
1896 ++ExactSIVsuccesses;
1898 if (UpperDistance.
sgt(0)) {
1900 ++ExactSIVsuccesses;
1906 ++ExactSIVindependence;
1917 return ConstDividend.
srem(ConstDivisor) == 0;
1951bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1952 const SCEV *SrcConst,
1953 const SCEV *DstConst,
1954 const Loop *CurSrcLoop,
1955 const Loop *CurDstLoop,
unsigned Level,
1967 ++WeakZeroSIVapplications;
1968 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1970 Result.Consistent =
false;
1971 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1974 if (Level < CommonLevels) {
1977 ++WeakZeroSIVsuccesses;
1987 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1988 ? SE->getNegativeSCEV(ConstCoeff)
1990 const SCEV *NewDelta =
1991 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1995 if (
const SCEV *UpperBound =
1996 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1998 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2000 ++WeakZeroSIVindependence;
2001 ++WeakZeroSIVsuccesses;
2006 if (Level < CommonLevels) {
2009 ++WeakZeroSIVsuccesses;
2017 if (SE->isKnownNegative(NewDelta)) {
2019 ++WeakZeroSIVindependence;
2020 ++WeakZeroSIVsuccesses;
2027 ++WeakZeroSIVindependence;
2028 ++WeakZeroSIVsuccesses;
2065bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
2066 const SCEV *SrcConst,
2067 const SCEV *DstConst,
2068 const Loop *CurSrcLoop,
2069 const Loop *CurDstLoop,
unsigned Level,
2080 ++WeakZeroSIVapplications;
2081 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2083 Result.Consistent =
false;
2084 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2087 if (Level < CommonLevels) {
2090 ++WeakZeroSIVsuccesses;
2100 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2101 ? SE->getNegativeSCEV(ConstCoeff)
2103 const SCEV *NewDelta =
2104 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2108 if (
const SCEV *UpperBound =
2109 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2111 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2113 ++WeakZeroSIVindependence;
2114 ++WeakZeroSIVsuccesses;
2119 if (Level < CommonLevels) {
2122 ++WeakZeroSIVsuccesses;
2130 if (SE->isKnownNegative(NewDelta)) {
2132 ++WeakZeroSIVindependence;
2133 ++WeakZeroSIVsuccesses;
2140 ++WeakZeroSIVindependence;
2141 ++WeakZeroSIVsuccesses;
2154bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2155 const SCEV *SrcConst,
const SCEV *DstConst,
2156 const Loop *SrcLoop,
const Loop *DstLoop,
2162 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2163 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2166 ++ExactRDIVapplications;
2167 Result.Consistent =
false;
2168 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2173 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2178 APInt AM = ConstSrcCoeff->
getAPInt();
2179 APInt BM = ConstDstCoeff->
getAPInt();
2184 ++ExactRDIVindependence;
2191 std::optional<APInt> SrcUM;
2193 if (
const SCEVConstant *UpperBound =
2194 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2195 SrcUM = UpperBound->getAPInt();
2199 std::optional<APInt> DstUM;
2201 if (
const SCEVConstant *UpperBound =
2202 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2203 DstUM = UpperBound->getAPInt();
2209 APInt TC = CM.
sdiv(
G);
2234 auto CreateVec = [](
const std::optional<APInt> &V0,
2235 const std::optional<APInt> &V1) {
2255 ++ExactRDIVindependence;
2301bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2304 const Loop *Loop2)
const {
2308 ++SymbolicRDIVapplications;
2315 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2316 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2319 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2320 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2323 if (SE->isKnownNonNegative(A1)) {
2324 if (SE->isKnownNonNegative(A2)) {
2328 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2331 ++SymbolicRDIVindependence;
2337 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2340 ++SymbolicRDIVindependence;
2344 }
else if (SE->isKnownNonPositive(A2)) {
2348 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2349 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2350 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2351 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2353 ++SymbolicRDIVindependence;
2358 if (SE->isKnownNegative(C2_C1)) {
2359 ++SymbolicRDIVindependence;
2363 }
else if (SE->isKnownNonPositive(A1)) {
2364 if (SE->isKnownNonNegative(A2)) {
2368 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2369 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2370 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2371 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2373 ++SymbolicRDIVindependence;
2378 if (SE->isKnownPositive(C2_C1)) {
2379 ++SymbolicRDIVindependence;
2382 }
else if (SE->isKnownNonPositive(A2)) {
2386 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2389 ++SymbolicRDIVindependence;
2395 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2398 ++SymbolicRDIVindependence;
2415bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2421 if (SrcAddRec && DstAddRec) {
2422 const SCEV *SrcConst = SrcAddRec->
getStart();
2423 const SCEV *DstConst = DstAddRec->
getStart();
2426 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2427 const Loop *CurDstLoop = DstAddRec->
getLoop();
2428 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2429 "Loops in the SIV test should have the same iteration space and "
2431 Level = mapSrcLoop(CurSrcLoop);
2433 if (SrcCoeff == DstCoeff)
2434 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2435 CurDstLoop, Level, Result);
2436 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2437 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2438 CurDstLoop, Level, Result);
2440 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst,
2441 CurSrcLoop, CurDstLoop, Level, Result);
2442 return disproven || gcdMIVtest(Src, Dst, Result) ||
2443 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2447 const SCEV *SrcConst = SrcAddRec->
getStart();
2449 const SCEV *DstConst = Dst;
2450 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2451 Level = mapSrcLoop(CurSrcLoop);
2452 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2453 CurSrcLoop, Level, Result) ||
2454 gcdMIVtest(Src, Dst, Result);
2457 const SCEV *DstConst = DstAddRec->
getStart();
2459 const SCEV *SrcConst = Src;
2460 const Loop *CurDstLoop = DstAddRec->
getLoop();
2461 Level = mapDstLoop(CurDstLoop);
2462 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2463 CurDstLoop, Level, Result) ||
2464 gcdMIVtest(Src, Dst, Result);
2483bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2491 const SCEV *SrcConst, *DstConst;
2492 const SCEV *SrcCoeff, *DstCoeff;
2493 const Loop *SrcLoop, *DstLoop;
2499 if (SrcAddRec && DstAddRec) {
2502 SrcLoop = SrcAddRec->
getLoop();
2505 DstLoop = DstAddRec->
getLoop();
2506 }
else if (SrcAddRec) {
2507 if (
const SCEVAddRecExpr *tmpAddRec =
2509 SrcConst = tmpAddRec->getStart();
2510 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2511 SrcLoop = tmpAddRec->getLoop();
2514 DstLoop = SrcAddRec->
getLoop();
2517 }
else if (DstAddRec) {
2518 if (
const SCEVAddRecExpr *tmpAddRec =
2520 DstConst = tmpAddRec->getStart();
2521 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2522 DstLoop = tmpAddRec->getLoop();
2525 SrcLoop = DstAddRec->
getLoop();
2530 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2532 gcdMIVtest(Src, Dst, Result) ||
2533 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2540bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2545 Result.Consistent =
false;
2546 return gcdMIVtest(Src, Dst, Result) ||
2547 banerjeeMIVtest(Src, Dst,
Loops, Result);
2560 if (Product->hasNoSignedWrap())
2562 return std::nullopt;
2565bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2566 const Loop *CurLoop,
2567 const SCEV *&CurLoopCoeff,
2568 APInt &RunningGCD)
const {
2571 if (RunningGCD == 1)
2576 assert(isLoopInvariant(Expr, CurLoop) &&
2577 "Expected loop invariant expression");
2584 if (AddRec->
getLoop() == CurLoop) {
2585 CurLoopCoeff = Step;
2599 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2620bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2627 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2634 const SCEV *Coefficients = Src;
2635 while (
const SCEVAddRecExpr *AddRec =
2646 const SCEV *SrcConst = Coefficients;
2653 while (
const SCEVAddRecExpr *AddRec =
2664 const SCEV *DstConst = Coefficients;
2667 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2672 for (
const SCEV *Operand : Sum->operands()) {
2674 assert(!Constant &&
"Surprised to find multiple constants");
2691 if (ConstDelta == 0)
2695 APInt Remainder = ConstDelta.
srem(RunningGCD);
2696 if (Remainder != 0) {
2715 bool Improved =
false;
2717 while (
const SCEVAddRecExpr *AddRec =
2720 const Loop *CurLoop = AddRec->
getLoop();
2721 RunningGCD = ExtraGCD;
2723 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2725 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2726 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2729 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2739 if (RunningGCD != 0) {
2740 Remainder = ConstDelta.
srem(RunningGCD);
2742 if (Remainder != 0) {
2743 unsigned Level = mapSrcLoop(CurLoop);
2744 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2788bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2795 ++BanerjeeApplications;
2798 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2801 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2802 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2803 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2808 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2809 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2812 findBoundsALL(
A,
B, Bound, K);
2827 bool Disproved =
false;
2830 unsigned DepthExpanded = 0;
2832 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2834 bool Improved =
false;
2835 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2837 unsigned Old =
Result.DV[
K - 1].Direction;
2838 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2839 Improved |= Old !=
Result.DV[
K - 1].Direction;
2840 if (!
Result.DV[K - 1].Direction) {
2848 ++BanerjeeSuccesses;
2850 ++BanerjeeIndependence;
2854 ++BanerjeeIndependence;
2868unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2869 CoefficientInfo *
B, BoundInfo *Bound,
2871 unsigned &DepthExpanded,
2872 const SCEV *Delta)
const {
2878 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2879 "direction exploration is terminated.\n");
2880 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2886 if (Level > CommonLevels) {
2889 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2891 Bound[
K].DirSet |= Bound[
K].Direction;
2916 if (Level > DepthExpanded) {
2917 DepthExpanded =
Level;
2919 findBoundsLT(
A,
B, Bound, Level);
2920 findBoundsGT(
A,
B, Bound, Level);
2921 findBoundsEQ(
A,
B, Bound, Level);
2960 unsigned NewDeps = 0;
2964 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2969 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2974 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2980 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2985bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2986 BoundInfo *Bound,
const SCEV *Delta)
const {
2987 Bound[
Level].Direction = DirKind;
2988 if (
const SCEV *LowerBound = getLowerBound(Bound))
2991 if (
const SCEV *UpperBound = getUpperBound(Bound))
3012void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
3013 BoundInfo *Bound,
unsigned K)
const {
3018 if (Bound[K].Iterations) {
3020 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
3022 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
3027 SE->getZero(
A[K].Coeff->
getType());
3030 SE->getZero(
A[K].Coeff->
getType());
3049void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
3050 BoundInfo *Bound,
unsigned K)
const {
3055 if (Bound[K].Iterations) {
3056 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3057 const SCEV *NegativePart = getNegativePart(Delta);
3059 SE->getMulExpr(NegativePart, Bound[K].Iterations);
3060 const SCEV *PositivePart = getPositivePart(Delta);
3062 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3066 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3067 const SCEV *NegativePart = getNegativePart(Delta);
3068 if (NegativePart->
isZero())
3070 const SCEV *PositivePart = getPositivePart(Delta);
3071 if (PositivePart->
isZero())
3089void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3090 BoundInfo *Bound,
unsigned K)
const {
3095 if (Bound[K].Iterations) {
3096 const SCEV *Iter_1 = SE->getMinusSCEV(
3097 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3098 const SCEV *NegPart =
3099 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3101 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3102 const SCEV *PosPart =
3103 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3105 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3109 const SCEV *NegPart =
3110 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3113 const SCEV *PosPart =
3114 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3133void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3134 BoundInfo *Bound,
unsigned K)
const {
3139 if (Bound[K].Iterations) {
3140 const SCEV *Iter_1 = SE->getMinusSCEV(
3141 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3142 const SCEV *NegPart =
3143 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3145 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3146 const SCEV *PosPart =
3147 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3149 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3153 const SCEV *NegPart =
3154 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3157 const SCEV *PosPart =
3158 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3165const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3166 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3170const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3171 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3177DependenceInfo::CoefficientInfo *
3178DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3180 const SCEV *
Zero = SE->getZero(Subscript->getType());
3181 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3182 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3184 CI[
K].PosPart =
Zero;
3185 CI[
K].NegPart =
Zero;
3186 CI[
K].Iterations =
nullptr;
3190 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3192 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3193 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3194 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3200 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3207 if (CI[K].Iterations)
3222const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3223 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3224 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3237const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3238 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3239 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3258 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3259 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3260 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3261 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3262 const SCEVUnknown *SrcBase =
3264 const SCEVUnknown *DstBase =
3267 if (!SrcBase || !DstBase || SrcBase != DstBase)
3272 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3273 SrcSubscripts, DstSubscripts) &&
3274 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3275 SrcSubscripts, DstSubscripts))
3278 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3279 isLoopInvariant(DstBase, DstLoop) &&
3280 "Expected SrcBase and DstBase to be loop invariant");
3284 dbgs() <<
"\nSrcSubscripts: ";
3285 for (
int I = 0;
I <
Size;
I++)
3286 dbgs() << *SrcSubscripts[
I];
3287 dbgs() <<
"\nDstSubscripts: ";
3288 for (
int I = 0;
I <
Size;
I++)
3289 dbgs() << *DstSubscripts[
I];
3297 SCEVMonotonicityChecker MonChecker(SE);
3298 const Loop *OutermostLoop = SrcLoop ? SrcLoop->
getOutermostLoop() :
nullptr;
3299 for (
int I = 0;
I <
Size; ++
I) {
3300 Pair[
I].Src = SrcSubscripts[
I];
3301 Pair[
I].Dst = DstSubscripts[
I];
3302 unifySubscriptType(&Pair[
I]);
3305 if (MonChecker.checkMonotonicity(Pair[
I].Src, OutermostLoop).isUnknown())
3307 if (MonChecker.checkMonotonicity(Pair[
I].Dst, OutermostLoop).isUnknown())
3318bool DependenceInfo::tryDelinearizeFixedSize(
3323 const SCEVUnknown *SrcBase =
3325 const SCEVUnknown *DstBase =
3327 assert(SrcBase && DstBase && SrcBase == DstBase &&
3328 "expected src and dst scev unknowns to be equal");
3331 const SCEV *ElemSize = SE->getElementSize(Src);
3332 assert(ElemSize == SE->getElementSize(Dst) &&
"Different element sizes");
3335 SrcSubscripts, SrcSizes, ElemSize) ||
3337 DstSubscripts, DstSizes, ElemSize))
3342 if (SrcSizes.
size() != DstSizes.
size() ||
3343 !std::equal(SrcSizes.
begin(), SrcSizes.
end(), DstSizes.
begin())) {
3344 SrcSubscripts.
clear();
3345 DstSubscripts.
clear();
3350 "Expected equal number of entries in the list of SrcSubscripts and "
3364 SmallVectorImpl<const SCEV *> &Subscripts,
3366 size_t SSize = Subscripts.
size();
3367 for (
size_t I = 1;
I < SSize; ++
I) {
3368 const SCEV *S = Subscripts[
I];
3371 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3372 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *Ptr <<
"\n";
3376 const SCEV *
Range = DimensionSizes[
I - 1];
3377 if (!isKnownLessThan(S,
Range)) {
3379 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3380 dbgs() <<
" S: " << *S <<
"\n"
3381 <<
" Range: " << *
Range <<
"\n";
3389 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3390 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3392 SrcSubscripts.
clear();
3393 DstSubscripts.
clear();
3398 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3399 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3400 <<
"DstGEP:" << *DstPtr <<
"\n";
3405bool DependenceInfo::tryDelinearizeParametricSize(
3412 const SCEVUnknown *SrcBase =
3414 const SCEVUnknown *DstBase =
3416 assert(SrcBase && DstBase && SrcBase == DstBase &&
3417 "expected src and dst scev unknowns to be equal");
3419 const SCEV *ElementSize = SE->getElementSize(Src);
3420 if (ElementSize != SE->getElementSize(Dst))
3423 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3424 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3445 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3446 SrcSubscripts.
size() != DstSubscripts.
size())
3449 size_t Size = SrcSubscripts.
size();
3458 for (
size_t I = 1;
I <
Size; ++
I) {
3461 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
3462 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
3463 if (SNN && DNN && SLT && DLT)
3467 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
3469 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
3471 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
3473 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
3474 << *
Sizes[
I - 1] <<
")\n";
3476 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
3477 << *
Sizes[
I - 1] <<
")\n";
3491 for (
unsigned VI : BV.
set_bits()) {
3501 FunctionAnalysisManager::Invalidator &Inv) {
3508 return Inv.invalidate<
AAManager>(F, PA) ||
3526std::unique_ptr<Dependence>
3528 bool UnderRuntimeAssumptions) {
3530 bool PossiblyLoopIndependent =
true;
3532 PossiblyLoopIndependent =
false;
3534 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3540 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3541 return std::make_unique<Dependence>(Src, Dst,
3553 return std::make_unique<Dependence>(Src, Dst,
3567 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3568 return std::make_unique<Dependence>(Src, Dst,
3574 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3575 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3578 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3579 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3580 if (SrcBase != DstBase) {
3587 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3588 return std::make_unique<Dependence>(Src, Dst,
3596 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3597 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3598 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3599 !isLoopInvariant(DstBase, DstLoop)) {
3600 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3601 return std::make_unique<Dependence>(Src, Dst,
3606 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3607 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3610 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3611 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3612 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3613 return std::make_unique<Dependence>(Src, Dst,
3617 if (!Assume.empty()) {
3618 if (!UnderRuntimeAssumptions)
3619 return std::make_unique<Dependence>(Src, Dst,
3622 unsigned N = Assumptions.size();
3624 bool Implied =
false;
3625 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
3626 if (Assumptions[
I]->implies(
P, *SE))
3629 Assumptions.push_back(
P);
3635 Pair[0].Src = SrcEv;
3636 Pair[0].Dst = DstEv;
3638 SCEVMonotonicityChecker MonChecker(SE);
3641 if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
3642 MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
3643 return std::make_unique<Dependence>(Src, Dst,
3647 if (tryDelinearize(Src, Dst, Pair)) {
3649 Pairs = Pair.
size();
3654 establishNestingLevels(Src, Dst);
3656 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3657 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3658 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3661 CommonLevels += SameSDLevels;
3662 MaxLevels -= SameSDLevels;
3663 if (SameSDLevels > 0) {
3666 for (
unsigned P = 0;
P < Pairs; ++
P) {
3668 Subscript::ClassificationKind TestClass =
3669 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3670 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3672 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3673 TestClass != Subscript::RDIV) {
3675 CommonLevels -= SameSDLevels;
3676 MaxLevels += SameSDLevels;
3683 if (SameSDLevels > 0)
3687 PossiblyLoopIndependent, CommonLevels);
3690 for (
unsigned P = 0;
P < Pairs; ++
P) {
3691 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3692 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3693 Pair[
P].Loops.
resize(MaxLevels + 1);
3694 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3696 removeMatchingExtensions(&Pair[
P]);
3697 Pair[
P].Classification =
3698 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3699 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3700 Pair[
P].GroupLoops = Pair[
P].Loops;
3701 Pair[
P].Group.set(
P);
3711 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3713 switch (Pair[
SI].Classification) {
3714 case Subscript::NonLinear:
3716 ++NonlinearSubscriptPairs;
3717 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3719 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3721 Result.Consistent =
false;
3723 case Subscript::ZIV:
3725 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3728 case Subscript::SIV: {
3731 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result))
3735 case Subscript::RDIV:
3737 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3740 case Subscript::MIV:
3742 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3750 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
3751 CompleteLoops |= Pair[
SI].
Loops;
3752 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3753 if (CompleteLoops[
II])
3754 Result.DV[
II - 1].Scalar =
false;
3759 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3761 if (Result.DV[
II - 1].Distance ==
nullptr)
3762 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
3764 assert(Result.DV[
II - 1].Distance->isZero() &&
3765 "Inconsistency between distance and direction");
3771 const SCEV *Distance = Result.getDistance(
II);
3772 if (Distance && Distance->
isZero())
3774 "Distance is zero, but direction is not EQ");
3778 if (SameSDLevels > 0) {
3781 assert(CommonLevels >= SameSDLevels);
3782 CommonLevels -= SameSDLevels;
3783 MaxLevels += SameSDLevels;
3784 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
3785 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
3786 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
3787 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
3788 DV[Level] = Result.DV[Level];
3789 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
3790 DVSameSD[Level] = Result.DV[CommonLevels + Level];
3791 Result.DV = std::move(DV);
3792 Result.DVSameSD = std::move(DVSameSD);
3793 Result.Levels = CommonLevels;
3794 Result.SameSDLevels = SameSDLevels;
3796 Result.Consistent =
false;
3799 if (PossiblyLoopIndependent) {
3803 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3805 Result.LoopIndependent =
false;
3812 bool AllEqual =
true;
3813 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3823 return std::make_unique<FullDependence>(std::move(Result));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static cl::opt< DependenceTestType > EnableDependenceTest("da-enable-dependence-test", cl::init(DependenceTestType::All), cl::ReallyHidden, cl::desc("Run only specified dependence test routine and disable others. " "The purpose is mainly to exclude the influence of other " "dependence test routines in regression tests. If set to All, all " "dependence test routines are enabled."), cl::values(clEnumValN(DependenceTestType::All, "all", "Enable all dependence test routines."), clEnumValN(DependenceTestType::StrongSIV, "strong-siv", "Enable only Strong SIV test."), clEnumValN(DependenceTestType::WeakCrossingSIV, "weak-crossing-siv", "Enable only Weak-Crossing SIV test."), clEnumValN(DependenceTestType::ExactSIV, "exact-siv", "Enable only Exact SIV test."), clEnumValN(DependenceTestType::WeakZeroSIV, "weak-zero-siv", "Enable only Weak-Zero SIV test."), clEnumValN(DependenceTestType::ExactRDIV, "exact-rdiv", "Enable only Exact RDIV test."), clEnumValN(DependenceTestType::SymbolicRDIV, "symbolic-rdiv", "Enable only Symbolic RDIV test."), clEnumValN(DependenceTestType::GCDMIV, "gcd-miv", "Enable only GCD MIV test."), clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv", "Enable only Banerjee MIV test.")))
static bool isLoadOrStore(const Instruction *I)
static 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.
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)
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),...
size_t size() const
size - Get the array size.
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 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.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns the runtime assumptions under which this Dependence relation is valid...
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual bool isPeelLast(unsigned Level, bool SameSD=false) const
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
virtual unsigned getDirection(unsigned Level, bool SameSD=false) const
getDirection - Returns the direction associated with a particular common or SameSD level.
virtual bool isScalar(unsigned Level, bool SameSD=false) const
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
virtual bool isPeelFirst(unsigned Level, bool SameSD=false) const
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
virtual bool inSameSDLoops(unsigned Level) const
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
unsigned getDirection(unsigned Level, bool SameSD=false) const override
getDirection - Returns the direction associated with a particular common or SameSD level.
bool isScalar(unsigned Level, bool SameSD=false) const override
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isDirectionNegative() const override
Check if the direction vector is negative.
const SCEV * getDistance(unsigned Level, bool SameSD=false) const override
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
DVEntry getDVEntry(unsigned Level, bool IsSameSD) const
getDVEntry - Returns the DV entry associated with a regular or a SameSD level.
bool isPeelLast(unsigned Level, bool SameSD=false) const override
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
bool isPeelFirst(unsigned Level, bool SameSD=false) const override
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStart() const
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
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 bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI const SCEV * getAbsExpr(const SCEV *Op, bool IsNSW)
LLVM_ABI const SCEV * removePointerBase(const SCEV *S)
Compute an expression equivalent to S - getPointerBase(S).
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM Value Representation.
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.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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)...
bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an acces...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
@ SMin
Signed integer min implemented in terms of select(cmp()).
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.