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");
110 cl::desc(
"Try to delinearize array references."));
112 "da-disable-delinearization-checks",
cl::Hidden,
114 "Disable checks that try to statically verify validity of "
115 "delinearized subscripts. Enabling this option may result in incorrect "
116 "dependence vectors for languages that allow the subscript of one "
117 "dimension to underflow or overflow into another dimension."));
121 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
122 "explore MIV direction vectors."));
138 "Dependence Analysis",
true,
true)
155 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
156 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
157 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
179 auto *
F = DA->getFunction();
182 if (SrcI->mayReadOrWriteMemory()) {
185 if (DstI->mayReadOrWriteMemory()) {
186 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
187 OS <<
" da analyze - ";
188 if (
auto D = DA->depends(&*SrcI, &*DstI,
194 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
195 const SCEV *Distance =
D->getDistance(Level);
196 bool IsDistanceZero = Distance && Distance->
isZero();
199 assert(IsDistanceZero == IsDirectionEQ &&
200 "Inconsistent distance and direction.");
205 if (NormalizeResults &&
D->normalize(&SE))
206 OS <<
"normalized - ";
208 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
209 if (
D->isSplitable(Level)) {
210 OS <<
" da analyze - split level = " << Level;
211 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
223 OS <<
"Runtime Assumptions:\n";
231 OS, info.get(), getAnalysis<ScalarEvolutionWrapperPass>().getSE(),
false);
236 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
278 bool PossiblyLoopIndependent,
279 unsigned CommonLevels)
280 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
281 LoopIndependent(PossiblyLoopIndependent) {
284 DV = std::make_unique<DVEntry[]>(CommonLevels);
303 for (
unsigned Level = 1; Level <= Levels; ++Level) {
304 unsigned char Direction = DV[Level - 1].Direction;
319 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
322 for (
unsigned Level = 1; Level <= Levels; ++Level) {
323 unsigned char Direction = DV[Level - 1].Direction;
331 DV[Level - 1].Direction = RevDirection;
333 if (DV[Level - 1].Distance !=
nullptr)
337 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
346 assert(0 < Level && Level <= Levels &&
"Level out of range");
347 return DV[Level - 1].Direction;
352 assert(0 < Level && Level <= Levels &&
"Level out of range");
353 return DV[Level - 1].Distance;
360 assert(0 < Level && Level <= Levels &&
"Level out of range");
361 return DV[Level - 1].Scalar;
367 assert(0 < Level && Level <= Levels &&
"Level out of range");
368 return DV[Level - 1].PeelFirst;
374 assert(0 < Level && Level <= Levels &&
"Level out of range");
375 return DV[Level - 1].PeelLast;
380 assert(0 < Level && Level <= Levels &&
"Level out of range");
381 return DV[Level - 1].Splitable;
389const SCEV *DependenceInfo::Constraint::getX()
const {
390 assert(Kind == Point &&
"Kind should be Point");
396const SCEV *DependenceInfo::Constraint::getY()
const {
397 assert(Kind == Point &&
"Kind should be Point");
403const SCEV *DependenceInfo::Constraint::getA()
const {
404 assert((Kind == Line || Kind == Distance) &&
405 "Kind should be Line (or Distance)");
411const SCEV *DependenceInfo::Constraint::getB()
const {
412 assert((Kind == Line || Kind == Distance) &&
413 "Kind should be Line (or Distance)");
419const SCEV *DependenceInfo::Constraint::getC()
const {
420 assert((Kind == Line || Kind == Distance) &&
421 "Kind should be Line (or Distance)");
427const SCEV *DependenceInfo::Constraint::getD()
const {
428 assert(Kind == Distance &&
"Kind should be Distance");
429 return SE->getNegativeSCEV(
C);
433const Loop *DependenceInfo::Constraint::getAssociatedLoop()
const {
434 assert((Kind == Distance || Kind == Line || Kind == Point) &&
435 "Kind should be Distance, Line, or Point");
436 return AssociatedLoop;
439void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
440 const Loop *CurLoop) {
444 AssociatedLoop = CurLoop;
447void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
448 const SCEV *CC,
const Loop *CurLoop) {
453 AssociatedLoop = CurLoop;
456void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
457 const Loop *CurLoop) {
459 A = SE->getOne(
D->getType());
460 B = SE->getNegativeSCEV(
A);
461 C = SE->getNegativeSCEV(
D);
462 AssociatedLoop = CurLoop;
465void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
472#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
480 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
481 else if (isDistance())
482 OS <<
" Distance is " << *getD() <<
" (" << *getA() <<
"*X + " << *getB()
483 <<
"*Y = " << *getC() <<
")\n";
485 OS <<
" Line is " << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC()
499bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
504 assert(!
Y->isPoint() &&
"Y must not be a Point");
518 if (
X->isDistance() &&
Y->isDistance()) {
529 if (isa<SCEVConstant>(
Y->getD())) {
542 assert(!(
X->isPoint() &&
Y->isPoint()) &&
543 "We shouldn't ever see X->isPoint() && Y->isPoint()");
545 if (
X->isLine() &&
Y->isLine()) {
580 if (!C1B2_C2B1 || !C1A2_C2A1 || !A1B2_A2B1 || !A2B1_A1B2)
596 if (Xr != 0 || Yr != 0) {
602 if (Xq.
slt(0) || Yq.
slt(0)) {
607 if (
const SCEVConstant *CUB = collectConstantUpperBound(
608 X->getAssociatedLoop(), Prod1->
getType())) {
609 const APInt &UpperBound = CUB->getAPInt();
611 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
618 X->getAssociatedLoop());
626 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
628 if (
X->isPoint() &&
Y->isLine()) {
652 bool Splitable =
false;
668 for (
unsigned II = 1;
II <= Levels; ++
II) {
706 OS <<
" Runtime Assumptions:\n";
752 if (
const LoadInst *LI = dyn_cast<LoadInst>(
I))
753 return LI->isUnordered();
754 else if (
const StoreInst *SI = dyn_cast<StoreInst>(
I))
755 return SI->isUnordered();
809void DependenceInfo::establishNestingLevels(
const Instruction *Src,
811 const BasicBlock *SrcBlock = Src->getParent();
812 const BasicBlock *DstBlock = Dst->getParent();
817 SrcLevels = SrcLevel;
818 MaxLevels = SrcLevel + DstLevel;
819 while (SrcLevel > DstLevel) {
823 while (DstLevel > SrcLevel) {
827 while (SrcLoop != DstLoop) {
832 CommonLevels = SrcLevel;
833 MaxLevels -= CommonLevels;
838unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
844unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
846 if (
D > CommonLevels)
849 return D - CommonLevels + SrcLevels;
875 unsigned Level =
LoopNest->getLoopDepth();
884 unsigned widestWidthSeen = 0;
889 for (Subscript *Pair : Pairs) {
890 const SCEV *Src = Pair->Src;
891 const SCEV *Dst = Pair->Dst;
892 IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
893 IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
894 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
896 "This function only unify integer types and "
897 "expect Src and Dst share the same type otherwise.");
910 assert(widestWidthSeen > 0);
913 for (Subscript *Pair : Pairs) {
914 const SCEV *Src = Pair->Src;
915 const SCEV *Dst = Pair->Dst;
916 IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
917 IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
918 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
920 "This function only unify integer types and "
921 "expect Src and Dst share the same type otherwise.");
938void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
939 const SCEV *Src = Pair->Src;
940 const SCEV *Dst = Pair->Dst;
941 if ((isa<SCEVZeroExtendExpr>(Src) && isa<SCEVZeroExtendExpr>(Dst)) ||
942 (isa<SCEVSignExtendExpr>(Src) && isa<SCEVSignExtendExpr>(Dst))) {
948 Pair->Src = SrcCastOp;
949 Pair->Dst = DstCastOp;
960 return isLoopInvariant(Expr,
LoopNest);
968 while (L && AddRec->
getLoop() != L)
969 L =
L->getParentLoop();
975 if (!isLoopInvariant(Step,
LoopNest))
986bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
993bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1001DependenceInfo::Subscript::ClassificationKind
1002DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1003 const SCEV *Dst,
const Loop *DstLoopNest,
1007 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1008 return Subscript::NonLinear;
1009 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1010 return Subscript::NonLinear;
1013 unsigned N =
Loops.count();
1015 return Subscript::ZIV;
1017 return Subscript::SIV;
1018 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1019 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1020 return Subscript::RDIV;
1021 return Subscript::MIV;
1035 const SCEV *
Y)
const {
1037 if ((isa<SCEVSignExtendExpr>(
X) && isa<SCEVSignExtendExpr>(
Y)) ||
1038 (isa<SCEVZeroExtendExpr>(
X) && isa<SCEVZeroExtendExpr>(
Y))) {
1081bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1083 auto *SType = dyn_cast<IntegerType>(S->
getType());
1084 auto *SizeType = dyn_cast<IntegerType>(
Size->getType());
1085 if (!SType || !SizeType)
1088 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1124bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1125 bool Inbounds =
false;
1126 if (
auto *SrcGEP = dyn_cast<GetElementPtrInst>(
Ptr))
1127 Inbounds = SrcGEP->isInBounds();
1129 if (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
1150const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1160const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1162 if (
const SCEV *UB = collectUpperBound(L,
T))
1163 return dyn_cast<SCEVConstant>(UB);
1177bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1192 Result.Consistent =
false;
1223bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1224 const SCEV *DstConst,
const Loop *CurLoop,
1226 Constraint &NewConstraint)
const {
1234 ++StrongSIVapplications;
1235 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1243 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1246 const SCEV *AbsDelta =
1248 const SCEV *AbsCoeff =
1253 ++StrongSIVindependence;
1254 ++StrongSIVsuccesses;
1260 if (isa<SCEVConstant>(Delta) && isa<SCEVConstant>(Coeff)) {
1261 APInt ConstDelta = cast<SCEVConstant>(Delta)->getAPInt();
1262 APInt ConstCoeff = cast<SCEVConstant>(Coeff)->getAPInt();
1263 APInt Distance = ConstDelta;
1264 APInt Remainder = ConstDelta;
1269 if (Remainder != 0) {
1271 ++StrongSIVindependence;
1272 ++StrongSIVsuccesses;
1276 NewConstraint.setDistance(SE->
getConstant(Distance), CurLoop);
1277 if (Distance.
sgt(0))
1279 else if (Distance.
slt(0))
1283 ++StrongSIVsuccesses;
1284 }
else if (Delta->
isZero()) {
1286 Result.DV[Level].Distance = Delta;
1287 NewConstraint.setDistance(Delta, CurLoop);
1289 ++StrongSIVsuccesses;
1291 if (Coeff->
isOne()) {
1293 Result.DV[Level].Distance = Delta;
1294 NewConstraint.setDistance(Delta, CurLoop);
1296 Result.Consistent =
false;
1311 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1312 (DeltaMaybeNegative && CoeffMaybeNegative))
1316 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1317 (DeltaMaybePositive && CoeffMaybeNegative))
1319 if (NewDirection <
Result.DV[Level].Direction)
1320 ++StrongSIVsuccesses;
1321 Result.DV[Level].Direction &= NewDirection;
1354bool DependenceInfo::weakCrossingSIVtest(
1355 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1357 Constraint &NewConstraint,
const SCEV *&SplitIter)
const {
1362 ++WeakCrossingSIVapplications;
1363 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1365 Result.Consistent =
false;
1368 NewConstraint.setLine(Coeff, Coeff, Delta, CurLoop);
1372 ++WeakCrossingSIVsuccesses;
1373 if (!
Result.DV[Level].Direction) {
1374 ++WeakCrossingSIVindependence;
1377 Result.DV[Level].Distance = Delta;
1380 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(Coeff);
1384 Result.DV[Level].Splitable =
true;
1388 "dynamic cast of negative of ConstCoeff should yield constant");
1399 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1409 ++WeakCrossingSIVindependence;
1410 ++WeakCrossingSIVsuccesses;
1416 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1424 ++WeakCrossingSIVindependence;
1425 ++WeakCrossingSIVsuccesses;
1432 ++WeakCrossingSIVsuccesses;
1433 if (!
Result.DV[Level].Direction) {
1434 ++WeakCrossingSIVindependence;
1437 Result.DV[Level].Splitable =
false;
1446 APInt Distance = APDelta;
1447 APInt Remainder = APDelta;
1450 if (Remainder != 0) {
1452 ++WeakCrossingSIVindependence;
1453 ++WeakCrossingSIVsuccesses;
1460 Remainder = Distance.
srem(Two);
1462 if (Remainder != 0) {
1465 ++WeakCrossingSIVsuccesses;
1482 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1483 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1491 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1492 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1499 X = AM.
slt(0) ? -A1 : A1;
1500 Y = BM.
slt(0) ? B1 : -B1;
1516 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1528 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1563static std::pair<std::optional<APInt>, std::optional<APInt>>
1565 const std::optional<APInt> &UB) {
1566 assert(
A != 0 &&
"A must be non-zero");
1567 std::optional<APInt> TL, TU;
1587 return std::make_pair(TL, TU);
1609bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1610 const SCEV *SrcConst,
const SCEV *DstConst,
1611 const Loop *CurLoop,
unsigned Level,
1613 Constraint &NewConstraint)
const {
1615 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1616 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1619 ++ExactSIVapplications;
1620 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1622 Result.Consistent =
false;
1627 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1628 const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1629 const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1630 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1641 ++ExactSIVindependence;
1642 ++ExactSIVsuccesses;
1649 std::optional<APInt> UM;
1652 collectConstantUpperBound(CurLoop, Delta->
getType())) {
1653 UM = CUB->getAPInt();
1681 auto CreateVec = [](
const std::optional<APInt> &V0,
1682 const std::optional<APInt> &V1) {
1705 ++ExactSIVindependence;
1706 ++ExactSIVsuccesses;
1712 APInt LowerDistance, UpperDistance;
1714 LowerDistance = (TY - TX) + (TA - TB) * TL;
1715 UpperDistance = (TY - TX) + (TA - TB) * TU;
1717 LowerDistance = (TY - TX) + (TA - TB) * TU;
1718 UpperDistance = (TY - TX) + (TA - TB) * TL;
1721 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1722 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1725 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1727 ++ExactSIVsuccesses;
1729 if (LowerDistance.
slt(0)) {
1731 ++ExactSIVsuccesses;
1733 if (UpperDistance.
sgt(0)) {
1735 ++ExactSIVsuccesses;
1739 Result.DV[Level].Direction &= NewDirection;
1741 ++ExactSIVindependence;
1752 return ConstDividend.
srem(ConstDivisor) == 0;
1786bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1787 const SCEV *SrcConst,
1788 const SCEV *DstConst,
1789 const Loop *CurLoop,
unsigned Level,
1791 Constraint &NewConstraint)
const {
1799 ++WeakZeroSIVapplications;
1800 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1802 Result.Consistent =
false;
1804 NewConstraint.setLine(SE->
getZero(Delta->
getType()), DstCoeff, Delta,
1808 if (Level < CommonLevels) {
1810 Result.DV[Level].PeelFirst =
true;
1811 ++WeakZeroSIVsuccesses;
1815 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1821 const SCEV *NewDelta =
1826 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1830 ++WeakZeroSIVindependence;
1831 ++WeakZeroSIVsuccesses;
1836 if (Level < CommonLevels) {
1838 Result.DV[Level].PeelLast =
true;
1839 ++WeakZeroSIVsuccesses;
1849 ++WeakZeroSIVindependence;
1850 ++WeakZeroSIVsuccesses;
1855 if (isa<SCEVConstant>(Delta) &&
1857 ++WeakZeroSIVindependence;
1858 ++WeakZeroSIVsuccesses;
1895bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1896 const SCEV *SrcConst,
1897 const SCEV *DstConst,
1898 const Loop *CurLoop,
unsigned Level,
1900 Constraint &NewConstraint)
const {
1907 ++WeakZeroSIVapplications;
1908 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1910 Result.Consistent =
false;
1912 NewConstraint.setLine(SrcCoeff, SE->
getZero(Delta->
getType()), Delta,
1916 if (Level < CommonLevels) {
1918 Result.DV[Level].PeelFirst =
true;
1919 ++WeakZeroSIVsuccesses;
1923 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1929 const SCEV *NewDelta =
1934 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1938 ++WeakZeroSIVindependence;
1939 ++WeakZeroSIVsuccesses;
1944 if (Level < CommonLevels) {
1946 Result.DV[Level].PeelLast =
true;
1947 ++WeakZeroSIVsuccesses;
1957 ++WeakZeroSIVindependence;
1958 ++WeakZeroSIVsuccesses;
1963 if (isa<SCEVConstant>(Delta) &&
1965 ++WeakZeroSIVindependence;
1966 ++WeakZeroSIVsuccesses;
1979bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1980 const SCEV *SrcConst,
const SCEV *DstConst,
1981 const Loop *SrcLoop,
const Loop *DstLoop,
1984 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1985 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1988 ++ExactRDIVapplications;
1989 Result.Consistent =
false;
1992 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1993 const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1994 const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1995 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2006 ++ExactRDIVindependence;
2013 std::optional<APInt> SrcUM;
2016 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2017 SrcUM = UpperBound->getAPInt();
2021 std::optional<APInt> DstUM;
2024 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2025 DstUM = UpperBound->getAPInt();
2056 auto CreateVec = [](
const std::optional<APInt> &V0,
2057 const std::optional<APInt> &V1) {
2077 ++ExactRDIVindependence;
2123bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2126 const Loop *Loop2)
const {
2127 ++SymbolicRDIVapplications;
2134 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2135 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2150 ++SymbolicRDIVindependence;
2159 ++SymbolicRDIVindependence;
2170 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2172 ++SymbolicRDIVindependence;
2178 ++SymbolicRDIVindependence;
2190 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2192 ++SymbolicRDIVindependence;
2198 ++SymbolicRDIVindependence;
2208 ++SymbolicRDIVindependence;
2217 ++SymbolicRDIVindependence;
2234bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2236 const SCEV *&SplitIter)
const {
2241 if (SrcAddRec && DstAddRec) {
2248 "both loops in SIV should be same");
2249 Level = mapSrcLoop(CurLoop);
2251 if (SrcCoeff == DstCoeff)
2252 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop, Level,
2253 Result, NewConstraint);
2255 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2256 Level, Result, NewConstraint, SplitIter);
2258 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2259 Level, Result, NewConstraint);
2260 return disproven || gcdMIVtest(Src, Dst, Result) ||
2261 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2267 const SCEV *DstConst = Dst;
2269 Level = mapSrcLoop(CurLoop);
2270 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop, Level,
2271 Result, NewConstraint) ||
2272 gcdMIVtest(Src, Dst, Result);
2277 const SCEV *SrcConst = Src;
2279 Level = mapDstLoop(CurLoop);
2280 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurLoop, Level,
2281 Result, NewConstraint) ||
2282 gcdMIVtest(Src, Dst, Result);
2301bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2309 const SCEV *SrcConst, *DstConst;
2310 const SCEV *SrcCoeff, *DstCoeff;
2311 const Loop *SrcLoop, *DstLoop;
2317 if (SrcAddRec && DstAddRec) {
2320 SrcLoop = SrcAddRec->
getLoop();
2323 DstLoop = DstAddRec->
getLoop();
2324 }
else if (SrcAddRec) {
2326 dyn_cast<SCEVAddRecExpr>(SrcAddRec->
getStart())) {
2327 SrcConst = tmpAddRec->getStart();
2328 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2329 SrcLoop = tmpAddRec->getLoop();
2332 DstLoop = SrcAddRec->
getLoop();
2335 }
else if (DstAddRec) {
2337 dyn_cast<SCEVAddRecExpr>(DstAddRec->
getStart())) {
2338 DstConst = tmpAddRec->getStart();
2339 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2340 DstLoop = tmpAddRec->getLoop();
2343 SrcLoop = DstAddRec->
getLoop();
2348 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2350 gcdMIVtest(Src, Dst, Result) ||
2351 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2358bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2363 Result.Consistent =
false;
2364 return gcdMIVtest(Src, Dst, Result) ||
2365 banerjeeMIVtest(Src, Dst,
Loops, Result);
2371 if (
const auto *
Constant = dyn_cast<SCEVConstant>(Expr))
2373 if (
const auto *Product = dyn_cast<SCEVMulExpr>(Expr))
2374 if (
const auto *
Constant = dyn_cast<SCEVConstant>(Product->getOperand(0)))
2376 return std::nullopt;
2379bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2380 const Loop *CurLoop,
2381 const SCEV *&CurLoopCoeff,
2382 APInt &RunningGCD)
const {
2385 if (RunningGCD == 1)
2390 assert(isLoopInvariant(Expr, CurLoop) &&
2391 "Expected loop invariant expression");
2398 if (AddRec->
getLoop() == CurLoop) {
2399 CurLoopCoeff = Step;
2413 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2434bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2445 const SCEV *Coefficients = Src;
2447 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2457 const SCEV *SrcConst = Coefficients;
2465 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2475 const SCEV *DstConst = Coefficients;
2481 if (
const SCEVAddExpr *Sum = dyn_cast<SCEVAddExpr>(Delta)) {
2484 if (isa<SCEVConstant>(Operand)) {
2486 Constant = cast<SCEVConstant>(Operand);
2487 }
else if (
const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Operand)) {
2502 if (ConstDelta == 0)
2506 APInt Remainder = ConstDelta.
srem(RunningGCD);
2507 if (Remainder != 0) {
2526 bool Improved =
false;
2529 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2532 RunningGCD = ExtraGCD;
2536 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2537 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2550 if (RunningGCD != 0) {
2551 Remainder = ConstDelta.
srem(RunningGCD);
2553 if (Remainder != 0) {
2554 unsigned Level = mapSrcLoop(CurLoop);
2599bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2603 ++BanerjeeApplications;
2606 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2609 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2610 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2616 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2617 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2620 findBoundsALL(
A,
B, Bound, K);
2635 bool Disproved =
false;
2638 unsigned DepthExpanded = 0;
2640 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2642 bool Improved =
false;
2643 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2645 unsigned Old =
Result.DV[
K - 1].Direction;
2646 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2647 Improved |= Old !=
Result.DV[
K - 1].Direction;
2648 if (!
Result.DV[K - 1].Direction) {
2656 ++BanerjeeSuccesses;
2658 ++BanerjeeIndependence;
2662 ++BanerjeeIndependence;
2676unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2677 CoefficientInfo *
B, BoundInfo *Bound,
2679 unsigned &DepthExpanded,
2680 const SCEV *Delta)
const {
2686 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2687 "direction exploration is terminated.\n");
2688 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2694 if (Level > CommonLevels) {
2697 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2699 Bound[
K].DirSet |= Bound[
K].Direction;
2724 if (Level > DepthExpanded) {
2725 DepthExpanded = Level;
2727 findBoundsLT(
A,
B, Bound, Level);
2728 findBoundsGT(
A,
B, Bound, Level);
2729 findBoundsEQ(
A,
B, Bound, Level);
2768 unsigned NewDeps = 0;
2772 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2777 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2782 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2788 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2793bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2794 BoundInfo *Bound,
const SCEV *Delta)
const {
2795 Bound[Level].Direction = DirKind;
2796 if (
const SCEV *LowerBound = getLowerBound(Bound))
2799 if (
const SCEV *UpperBound = getUpperBound(Bound))
2820void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2821 BoundInfo *Bound,
unsigned K)
const {
2826 if (Bound[K].Iterations) {
2828 SE->
getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2830 SE->
getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2857void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2858 BoundInfo *Bound,
unsigned K)
const {
2863 if (Bound[K].Iterations) {
2865 const SCEV *NegativePart = getNegativePart(Delta);
2867 SE->
getMulExpr(NegativePart, Bound[K].Iterations);
2868 const SCEV *PositivePart = getPositivePart(Delta);
2870 SE->
getMulExpr(PositivePart, Bound[K].Iterations);
2875 const SCEV *NegativePart = getNegativePart(Delta);
2876 if (NegativePart->
isZero())
2878 const SCEV *PositivePart = getPositivePart(Delta);
2879 if (PositivePart->
isZero())
2897void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2898 BoundInfo *Bound,
unsigned K)
const {
2903 if (Bound[K].Iterations) {
2905 Bound[K].Iterations, SE->
getOne(Bound[K].Iterations->getType()));
2906 const SCEV *NegPart =
2910 const SCEV *PosPart =
2917 const SCEV *NegPart =
2921 const SCEV *PosPart =
2941void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2942 BoundInfo *Bound,
unsigned K)
const {
2947 if (Bound[K].Iterations) {
2949 Bound[K].Iterations, SE->
getOne(Bound[K].Iterations->getType()));
2950 const SCEV *NegPart =
2954 const SCEV *PosPart =
2961 const SCEV *NegPart =
2965 const SCEV *PosPart =
2973const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2978const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2985DependenceInfo::CoefficientInfo *
2986DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
2989 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
2990 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2992 CI[
K].PosPart =
Zero;
2993 CI[
K].NegPart =
Zero;
2994 CI[
K].Iterations =
nullptr;
2996 while (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Subscript)) {
2998 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3000 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3001 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3002 CI[
K].Iterations = collectUpperBound(L, Subscript->
getType());
3008 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3015 if (CI[K].Iterations)
3030const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3031 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3032 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3045const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3046 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3047 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3065const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3066 const Loop *TargetLoop)
const {
3070 if (AddRec->
getLoop() == TargetLoop)
3072 return findCoefficient(AddRec->
getStart(), TargetLoop);
3080const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3081 const Loop *TargetLoop)
const {
3085 if (AddRec->
getLoop() == TargetLoop)
3097const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3098 const Loop *TargetLoop,
3104 if (AddRec->
getLoop() == TargetLoop) {
3129bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3134 for (
unsigned LI :
Loops.set_bits()) {
3137 if (Constraints[LI].isDistance())
3138 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3139 else if (Constraints[LI].isLine())
3140 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3141 else if (Constraints[LI].isPoint())
3142 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3152bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3153 Constraint &CurConstraint,
3155 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3157 const SCEV *A_K = findCoefficient(Src, CurLoop);
3162 Src = zeroCoefficient(Src, CurLoop);
3167 if (!findCoefficient(Dst, CurLoop)->
isZero())
3177bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3178 Constraint &CurConstraint,
3180 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3181 const SCEV *
A = CurConstraint.getA();
3182 const SCEV *
B = CurConstraint.getB();
3183 const SCEV *
C = CurConstraint.getC();
3191 if (!Bconst || !Cconst)
3196 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3197 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3199 Dst = zeroCoefficient(Dst, CurLoop);
3200 if (!findCoefficient(Src, CurLoop)->
isZero())
3202 }
else if (
B->isZero()) {
3205 if (!Aconst || !Cconst)
3210 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3211 const SCEV *A_K = findCoefficient(Src, CurLoop);
3213 Src = zeroCoefficient(Src, CurLoop);
3214 if (!findCoefficient(Dst, CurLoop)->
isZero())
3219 if (!Aconst || !Cconst)
3224 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3225 const SCEV *A_K = findCoefficient(Src, CurLoop);
3227 Src = zeroCoefficient(Src, CurLoop);
3228 Dst = addToCoefficient(Dst, CurLoop, A_K);
3229 if (!findCoefficient(Dst, CurLoop)->
isZero())
3233 const SCEV *A_K = findCoefficient(Src, CurLoop);
3237 Src = zeroCoefficient(Src, CurLoop);
3238 Dst = addToCoefficient(Dst, CurLoop, SE->
getMulExpr(A_K,
B));
3239 if (!findCoefficient(Dst, CurLoop)->
isZero())
3250bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3251 Constraint &CurConstraint) {
3252 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3253 const SCEV *A_K = findCoefficient(Src, CurLoop);
3254 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3259 Src = zeroCoefficient(Src, CurLoop);
3262 Dst = zeroCoefficient(Dst, CurLoop);
3269 const Constraint &CurConstraint)
const {
3272 if (CurConstraint.isAny())
3274 else if (CurConstraint.isDistance()) {
3276 Level.Scalar =
false;
3277 Level.Distance = CurConstraint.getD();
3285 Level.Direction &= NewDirection;
3286 }
else if (CurConstraint.isLine()) {
3287 Level.Scalar =
false;
3288 Level.Distance =
nullptr;
3290 }
else if (CurConstraint.isPoint()) {
3291 Level.Scalar =
false;
3292 Level.Distance =
nullptr;
3295 CurConstraint.getX()))
3299 CurConstraint.getX()))
3303 CurConstraint.getX()))
3306 Level.Direction &= NewDirection;
3330 if (!SrcBase || !DstBase || SrcBase != DstBase)
3335 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3336 SrcSubscripts, DstSubscripts) &&
3337 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3338 SrcSubscripts, DstSubscripts))
3341 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3342 isLoopInvariant(DstBase, DstLoop) &&
3343 "Expected SrcBase and DstBase to be loop invariant");
3347 dbgs() <<
"\nSrcSubscripts: ";
3348 for (
int I = 0;
I <
Size;
I++)
3349 dbgs() << *SrcSubscripts[
I];
3350 dbgs() <<
"\nDstSubscripts: ";
3351 for (
int I = 0;
I <
Size;
I++)
3352 dbgs() << *DstSubscripts[
I];
3360 for (
int I = 0;
I <
Size; ++
I) {
3361 Pair[
I].Src = SrcSubscripts[
I];
3362 Pair[
I].Dst = DstSubscripts[
I];
3363 unifySubscriptType(&Pair[
I]);
3372bool DependenceInfo::tryDelinearizeFixedSize(
3381 assert(SrcBase && DstBase && SrcBase == DstBase &&
3382 "expected src and dst scev unknowns to be equal");
3395 if (SrcSizes.size() != DstSizes.
size() ||
3396 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3397 SrcSubscripts.
clear();
3398 DstSubscripts.
clear();
3403 "Expected equal number of entries in the list of SrcSubscripts and "
3419 size_t SSize = Subscripts.
size();
3420 for (
size_t I = 1;
I < SSize; ++
I) {
3421 const SCEV *S = Subscripts[
I];
3422 if (!isKnownNonNegative(S,
Ptr))
3424 if (
auto *SType = dyn_cast<IntegerType>(S->
getType())) {
3426 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3427 if (!isKnownLessThan(S,
Range))
3434 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3435 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3436 SrcSubscripts.
clear();
3437 DstSubscripts.
clear();
3442 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3443 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3444 <<
"DstGEP:" << *DstPtr <<
"\n";
3449bool DependenceInfo::tryDelinearizeParametricSize(
3460 assert(SrcBase && DstBase && SrcBase == DstBase &&
3461 "expected src and dst scev unknowns to be equal");
3489 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3490 SrcSubscripts.
size() != DstSubscripts.
size())
3493 size_t Size = SrcSubscripts.
size();
3502 for (
size_t I = 1;
I <
Size; ++
I) {
3503 if (!isKnownNonNegative(SrcSubscripts[
I], SrcPtr))
3506 if (!isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]))
3509 if (!isKnownNonNegative(DstSubscripts[
I], DstPtr))
3512 if (!isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]))
3525 for (
unsigned VI : BV.
set_bits()) {
3562std::unique_ptr<Dependence>
3564 bool UnderRuntimeAssumptions) {
3566 bool PossiblyLoopIndependent =
true;
3568 PossiblyLoopIndependent =
false;
3570 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3576 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3577 return std::make_unique<Dependence>(Src, Dst,
3589 return std::make_unique<Dependence>(Src, Dst,
3603 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3604 return std::make_unique<Dependence>(Src, Dst,
3616 if (SrcBase != DstBase) {
3623 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3624 return std::make_unique<Dependence>(Src, Dst,
3634 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3635 !isLoopInvariant(DstBase, DstLoop)) {
3636 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3637 return std::make_unique<Dependence>(Src, Dst,
3648 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3649 return std::make_unique<Dependence>(Src, Dst,
3653 if (!Assume.empty()) {
3654 if (!UnderRuntimeAssumptions)
3655 return std::make_unique<Dependence>(Src, Dst,
3658 unsigned N = Assumptions.size();
3660 bool Implied =
false;
3661 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
3662 if (Assumptions[
I]->implies(
P, *SE))
3665 Assumptions.push_back(
P);
3669 establishNestingLevels(Src, Dst);
3670 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3671 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3674 PossiblyLoopIndependent, CommonLevels);
3679 Pair[0].Src = SrcSCEV;
3680 Pair[0].Dst = DstSCEV;
3683 if (tryDelinearize(Src, Dst, Pair)) {
3685 Pairs = Pair.
size();
3689 for (
unsigned P = 0;
P < Pairs; ++
P) {
3690 Pair[
P].Loops.
resize(MaxLevels + 1);
3691 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3693 removeMatchingExtensions(&Pair[
P]);
3694 Pair[
P].Classification =
3695 classifyPair(Pair[
P].Src, LI->
getLoopFor(Src->getParent()), Pair[
P].Dst,
3697 Pair[
P].GroupLoops = Pair[
P].Loops;
3698 Pair[
P].Group.set(
P);
3767 for (
unsigned SI = 0; SI < Pairs; ++SI) {
3768 if (Pair[SI].Classification == Subscript::NonLinear) {
3770 ++NonlinearSubscriptPairs;
3771 collectCommonLoops(Pair[SI].Src, LI->
getLoopFor(Src->getParent()),
3773 collectCommonLoops(Pair[SI].Dst, LI->
getLoopFor(Dst->getParent()),
3775 Result.Consistent =
false;
3776 }
else if (Pair[SI].Classification == Subscript::ZIV) {
3782 for (
unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
3784 Intersection &= Pair[SJ].GroupLoops;
3785 if (Intersection.
any()) {
3787 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
3789 Pair[SJ].Group |= Pair[SI].Group;
3794 if (Pair[SI].Group.count() == 1) {
3796 ++SeparableSubscriptPairs;
3799 ++CoupledSubscriptPairs;
3810 Constraint NewConstraint;
3811 NewConstraint.setAny(SE);
3814 for (
unsigned SI : Separable.
set_bits()) {
3816 switch (Pair[SI].Classification) {
3817 case Subscript::ZIV:
3819 if (testZIV(Pair[SI].Src, Pair[SI].Dst, Result))
3822 case Subscript::SIV: {
3825 const SCEV *SplitIter =
nullptr;
3826 if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result, NewConstraint,
3831 case Subscript::RDIV:
3833 if (testRDIV(Pair[SI].Src, Pair[SI].Dst, Result))
3836 case Subscript::MIV:
3838 if (testMIV(Pair[SI].Src, Pair[SI].Dst, Pair[SI].
Loops, Result))
3846 if (Coupled.
count()) {
3849 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
3851 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
3852 Constraints[
II].setAny(SE);
3853 for (
unsigned SI : Coupled.
set_bits()) {
3860 for (
unsigned SJ : Group.set_bits()) {
3862 if (Pair[SJ].Classification == Subscript::SIV)
3868 unifySubscriptType(PairsInGroup);
3870 while (Sivs.
any()) {
3871 bool Changed =
false;
3872 for (
unsigned SJ : Sivs.
set_bits()) {
3876 const SCEV *SplitIter =
nullptr;
3878 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
3881 ConstrainedLevels.
set(Level);
3882 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
3883 if (Constraints[Level].isEmpty()) {
3884 ++DeltaIndependence;
3896 for (
unsigned SJ : Mivs.
set_bits()) {
3899 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
3900 Constraints, Result.Consistent)) {
3902 ++DeltaPropagations;
3903 Pair[SJ].Classification = classifyPair(
3904 Pair[SJ].Src, LI->
getLoopFor(Src->getParent()), Pair[SJ].Dst,
3905 LI->
getLoopFor(Dst->getParent()), Pair[SJ].Loops);
3906 switch (Pair[SJ].Classification) {
3907 case Subscript::ZIV:
3909 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3913 case Subscript::SIV:
3917 case Subscript::RDIV:
3918 case Subscript::MIV:
3929 for (
unsigned SJ : Mivs.
set_bits()) {
3930 if (Pair[SJ].Classification == Subscript::RDIV) {
3932 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3942 for (
unsigned SJ : Mivs.
set_bits()) {
3943 if (Pair[SJ].Classification == Subscript::MIV) {
3945 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
3953 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
3954 if (SJ > CommonLevels)
3956 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
3965 for (
unsigned SI = 0; SI < Pairs; ++SI)
3966 CompleteLoops |= Pair[SI].
Loops;
3967 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3968 if (CompleteLoops[
II])
3969 Result.DV[
II - 1].Scalar =
false;
3974 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
3976 if (Result.DV[
II - 1].Distance ==
nullptr)
3979 assert(Result.DV[
II - 1].Distance->isZero() &&
3980 "Inconsistency between distance and direction");
3986 const SCEV *Distance = Result.getDistance(
II);
3987 if (Distance && Distance->
isZero())
3989 "Distance is zero, but direction is not EQ");
3993 if (PossiblyLoopIndependent) {
3997 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3999 Result.LoopIndependent =
false;
4006 bool AllEqual =
true;
4007 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4017 return std::make_unique<FullDependence>(std::move(Result));
4068 unsigned SplitLevel) {
4070 "Dep should be splitable at SplitLevel");
4073 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4074 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4084 establishNestingLevels(Src, Dst);
4086 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4092 Pair[0].Src = SrcSCEV;
4093 Pair[0].Dst = DstSCEV;
4096 if (tryDelinearize(Src, Dst, Pair)) {
4098 Pairs = Pair.
size();
4102 for (
unsigned P = 0;
P < Pairs; ++
P) {
4103 Pair[
P].Loops.
resize(MaxLevels + 1);
4104 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4106 removeMatchingExtensions(&Pair[
P]);
4107 Pair[
P].Classification =
4108 classifyPair(Pair[
P].Src, LI->
getLoopFor(Src->getParent()), Pair[
P].Dst,
4110 Pair[
P].GroupLoops = Pair[
P].Loops;
4111 Pair[
P].Group.set(
P);
4118 for (
unsigned SI = 0; SI < Pairs; ++SI) {
4119 if (Pair[SI].Classification == Subscript::NonLinear) {
4121 collectCommonLoops(Pair[SI].Src, LI->
getLoopFor(Src->getParent()),
4123 collectCommonLoops(Pair[SI].Dst, LI->
getLoopFor(Dst->getParent()),
4125 Result.Consistent =
false;
4126 }
else if (Pair[SI].Classification == Subscript::ZIV)
4131 for (
unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
4133 Intersection &= Pair[SJ].GroupLoops;
4134 if (Intersection.
any()) {
4136 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
4138 Pair[SJ].Group |= Pair[SI].Group;
4143 if (Pair[SI].Group.count() == 1)
4151 Constraint NewConstraint;
4152 NewConstraint.setAny(SE);
4155 for (
unsigned SI : Separable.
set_bits()) {
4156 switch (Pair[SI].Classification) {
4157 case Subscript::SIV: {
4159 const SCEV *SplitIter =
nullptr;
4160 (void)testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result, NewConstraint,
4162 if (Level == SplitLevel) {
4163 assert(SplitIter !=
nullptr);
4168 case Subscript::ZIV:
4169 case Subscript::RDIV:
4170 case Subscript::MIV:
4177 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4181 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4182 Constraints[
II].setAny(SE);
4183 for (
unsigned SI : Coupled.
set_bits()) {
4188 for (
unsigned SJ : Group.set_bits()) {
4189 if (Pair[SJ].Classification == Subscript::SIV)
4194 while (Sivs.
any()) {
4195 bool Changed =
false;
4196 for (
unsigned SJ : Sivs.
set_bits()) {
4199 const SCEV *SplitIter =
nullptr;
4200 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4202 if (Level == SplitLevel && SplitIter)
4204 ConstrainedLevels.
set(Level);
4205 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4212 for (
unsigned SJ : Mivs.
set_bits()) {
4214 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4217 Pair[SJ].Classification = classifyPair(
4218 Pair[SJ].Src, LI->
getLoopFor(Src->getParent()), Pair[SJ].Dst,
4219 LI->
getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4220 switch (Pair[SJ].Classification) {
4221 case Subscript::ZIV:
4224 case Subscript::SIV:
4228 case Subscript::RDIV:
4229 case Subscript::MIV:
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
block Block Frequency Analysis
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static bool isLoadOrStore(const Instruction *I)
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 AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static std::pair< std::optional< APInt >, std::optional< APInt > > inferDomainOfAffine(const APInt &A, const APInt &B, const std::optional< APInt > &UB)
Given an affine expression of the form A*k + B, where k is an arbitrary integer, infer the possible r...
static std::optional< APInt > getConstantPart(const SCEV *Expr)
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, bool NormalizeResults)
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."))
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
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)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
A private abstract base class describing the concept of an individual alias analysis implementation.
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 <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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),...
LLVM Basic Block Representation.
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
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.
virtual unsigned getDirection(unsigned Level) const
getDirection - Returns the direction associated with a particular level.
virtual bool isPeelFirst(unsigned Level) const
isPeelFirst - Returns true if peeling the first iteration from this loop will break this dependence.
Instruction * getDst() const
getDst - Returns the destination instruction for this dependence.
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 bool isSplitable(unsigned Level) const
isSplitable - Returns true if splitting this loop will break the dependence.
virtual const SCEV * getDistance(unsigned Level) const
getDistance - Returns the distance (or NULL) associated with a particular level.
virtual bool isScalar(unsigned Level) const
isScalar - Returns true if a particular level is scalar; that is, if no subscript in the source or de...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
virtual bool isPeelLast(unsigned Level) const
isPeelLast - Returns true if peeling the last iteration from this loop will break this dependence.
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti 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.
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
unsigned getDirection(unsigned Level) const override
getDirection - Returns the direction associated with a particular level.
const SCEV * getDistance(unsigned Level) const override
getDistance - Returns the distance (or NULL) associated with a particular level.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
bool isDirectionNegative() const override
Check if the direction vector is negative.
bool isSplitable(unsigned Level) const override
isSplitable - Returns true if splitting the loop will break the dependence.
bool isScalar(unsigned Level) const override
isScalar - Returns true if a particular level is scalar; that is, if no subscript in the source or de...
bool isPeelLast(unsigned Level) const override
isPeelLast - Returns true if peeling the last iteration from this loop will break this dependence.
bool isPeelFirst(unsigned Level) const override
isPeelFirst - Returns true if peeling the first iteration from this loop will break this dependence.
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
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.
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.
unsigned getLoopDepth(const BlockT *BB) const
Return the loop nesting level of the specified block.
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.
Loop & getOutermostLoop() const
Return the outermost loop in the loop nest.
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.
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 an addition of some number of SCEVs.
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
This is the base class for unary integral cast operator classes.
This node represents multiplication of some number of SCEVs.
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 means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
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 bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI const SCEV * getSMaxExpr(const SCEV *LHS, const SCEV *RHS)
LLVM_ABI bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
LLVM_ABI bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
LLVM_ABI bool isKnownNonZero(const SCEV *S)
Test if the given expression is known to be non-zero.
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 const SCEV * getSMinExpr(const SCEV *LHS, const SCEV *RHS)
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
LLVM_ABI uint64_t getTypeSizeInBits(Type *Ty) const
Return the size in bits of the specified type, for which isSCEVable must return true.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
LLVM_ABI const SCEV * getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, SCEV::NoWrapFlags Flags)
Get an add recurrence expression for the specified loop.
LLVM_ABI const SCEV * getUDivExpr(const SCEV *LHS, const SCEV *RHS)
Get a canonical unsigned division expression, or something simpler if possible.
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI bool hasLoopInvariantBackedgeTakenCount(const Loop *L)
Return true if the specified loop has an analyzable loop-invariant backedge-taken count.
LLVM_ABI bool isKnownMultipleOf(const SCEV *S, uint64_t M, SmallVectorImpl< const SCEVPredicate * > &Assumptions)
Check that S is a multiple of M.
LLVM_ABI const SCEV * getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
LLVM_ABI const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
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 const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
LLVM_ABI const SCEV * getTruncateOrZeroExtend(const SCEV *V, Type *Ty, unsigned Depth=0)
Return a SCEV corresponding to a conversion of the input value to the specified type.
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add 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.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ C
The default llvm calling convention, compatible with C.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
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)
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...
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.
inst_iterator inst_end(Function *F)
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
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...
Direction
An enum for the direction of the loop.