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)
157 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
158 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
159 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
181 auto *
F = DA->getFunction();
184 if (SrcI->mayReadOrWriteMemory()) {
186 DstI != DstE; ++DstI) {
187 if (DstI->mayReadOrWriteMemory()) {
188 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
189 OS <<
" da analyze - ";
190 if (
auto D = DA->depends(&*SrcI, &*DstI)) {
192 if (NormalizeResults &&
D->normalize(&SE))
193 OS <<
"normalized - ";
195 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
196 if (
D->isSplitable(Level)) {
197 OS <<
" da analyze - split level = " << Level;
198 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
214 getAnalysis<ScalarEvolutionWrapperPass>().getSE(),
false);
219 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
267 bool PossiblyLoopIndependent,
268 unsigned CommonLevels)
269 :
Dependence(Source, Destination), Levels(CommonLevels),
270 LoopIndependent(PossiblyLoopIndependent) {
273 DV = std::make_unique<DVEntry[]>(CommonLevels);
292 for (
unsigned Level = 1; Level <= Levels; ++Level) {
293 unsigned char Direction = DV[Level - 1].Direction;
308 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
311 for (
unsigned Level = 1; Level <= Levels; ++Level) {
312 unsigned char Direction = DV[Level - 1].Direction;
320 DV[Level - 1].Direction = RevDirection;
322 if (DV[Level - 1].Distance !=
nullptr)
323 DV[Level - 1].Distance =
327 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
336 assert(0 < Level && Level <= Levels &&
"Level out of range");
337 return DV[Level - 1].Direction;
343 assert(0 < Level && Level <= Levels &&
"Level out of range");
344 return DV[Level - 1].Distance;
352 assert(0 < Level && Level <= Levels &&
"Level out of range");
353 return DV[Level - 1].Scalar;
360 assert(0 < Level && Level <= Levels &&
"Level out of range");
361 return DV[Level - 1].PeelFirst;
368 assert(0 < Level && Level <= Levels &&
"Level out of range");
369 return DV[Level - 1].PeelLast;
375 assert(0 < Level && Level <= Levels &&
"Level out of range");
376 return DV[Level - 1].Splitable;
385const SCEV *DependenceInfo::Constraint::getX()
const {
386 assert(Kind == Point &&
"Kind should be Point");
393const SCEV *DependenceInfo::Constraint::getY()
const {
394 assert(Kind == Point &&
"Kind should be Point");
401const SCEV *DependenceInfo::Constraint::getA()
const {
402 assert((Kind == Line || Kind == Distance) &&
403 "Kind should be Line (or Distance)");
410const SCEV *DependenceInfo::Constraint::getB()
const {
411 assert((Kind == Line || Kind == Distance) &&
412 "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)");
428const SCEV *DependenceInfo::Constraint::getD()
const {
429 assert(Kind == Distance &&
"Kind should be Distance");
430 return SE->getNegativeSCEV(
C);
435const Loop *DependenceInfo::Constraint::getAssociatedLoop()
const {
436 assert((Kind == Distance || Kind == Line || Kind == Point) &&
437 "Kind should be Distance, Line, or Point");
438 return AssociatedLoop;
441void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
442 const Loop *CurLoop) {
446 AssociatedLoop = CurLoop;
449void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
455 AssociatedLoop = CurLoop;
458void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
459 const Loop *CurLoop) {
461 A = SE->getOne(
D->getType());
462 B = SE->getNegativeSCEV(
A);
463 C = SE->getNegativeSCEV(
D);
464 AssociatedLoop = CurLoop;
467void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
474#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
482 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
483 else if (isDistance())
484 OS <<
" Distance is " << *getD() <<
485 " (" << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC() <<
")\n";
487 OS <<
" Line is " << *getA() <<
"*X + " <<
488 *getB() <<
"*Y = " << *getC() <<
"\n";
502bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
507 assert(!
Y->isPoint() &&
"Y must not be a Point");
521 if (
X->isDistance() &&
Y->isDistance()) {
532 if (isa<SCEVConstant>(
Y->getD())) {
545 assert(!(
X->isPoint() &&
Y->isPoint()) &&
546 "We shouldn't ever see X->isPoint() && Y->isPoint()");
548 if (
X->isLine() &&
Y->isLine()) {
583 if (!C1B2_C2B1 || !C1A2_C2A1 ||
584 !A1B2_A2B1 || !A2B1_A1B2)
600 if (Xr != 0 || Yr != 0) {
606 if (Xq.
slt(0) || Yq.
slt(0)) {
612 collectConstantUpperBound(
X->getAssociatedLoop(), Prod1->
getType())) {
613 const APInt &UpperBound = CUB->getAPInt();
615 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
623 X->getAssociatedLoop());
631 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
633 if (
X->isPoint() &&
Y->isLine()) {
658 bool Splitable =
false;
674 for (
unsigned II = 1;
II <= Levels; ++
II) {
754 if (
const LoadInst *LI = dyn_cast<LoadInst>(
I))
755 return LI->isUnordered();
756 else if (
const StoreInst *SI = dyn_cast<StoreInst>(
I))
757 return SI->isUnordered();
812void DependenceInfo::establishNestingLevels(
const Instruction *Src,
814 const BasicBlock *SrcBlock = Src->getParent();
815 const BasicBlock *DstBlock = Dst->getParent();
820 SrcLevels = SrcLevel;
821 MaxLevels = SrcLevel + DstLevel;
822 while (SrcLevel > DstLevel) {
826 while (DstLevel > SrcLevel) {
830 while (SrcLoop != DstLoop) {
835 CommonLevels = SrcLevel;
836 MaxLevels -= CommonLevels;
842unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
849unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
851 if (
D > CommonLevels)
854 return D - CommonLevels + SrcLevels;
883 unsigned Level =
LoopNest->getLoopDepth();
892 unsigned widestWidthSeen = 0;
897 for (Subscript *Pair : Pairs) {
898 const SCEV *Src = Pair->Src;
899 const SCEV *Dst = Pair->Dst;
900 IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
901 IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
902 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
903 assert(SrcTy == DstTy &&
"This function only unify integer types and "
904 "expect Src and Dst share the same type "
919 assert(widestWidthSeen > 0);
922 for (Subscript *Pair : Pairs) {
923 const SCEV *Src = Pair->Src;
924 const SCEV *Dst = Pair->Dst;
925 IntegerType *SrcTy = dyn_cast<IntegerType>(Src->getType());
926 IntegerType *DstTy = dyn_cast<IntegerType>(Dst->getType());
927 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
928 assert(SrcTy == DstTy &&
"This function only unify integer types and "
929 "expect Src and Dst share the same type "
947void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
948 const SCEV *Src = Pair->Src;
949 const SCEV *Dst = Pair->Dst;
950 if ((isa<SCEVZeroExtendExpr>(Src) && isa<SCEVZeroExtendExpr>(Dst)) ||
951 (isa<SCEVSignExtendExpr>(Src) && isa<SCEVSignExtendExpr>(Dst))) {
957 Pair->Src = SrcCastOp;
958 Pair->Dst = DstCastOp;
969 return isLoopInvariant(Expr,
LoopNest);
977 while (L && AddRec->
getLoop() != L)
978 L =
L->getParentLoop();
985 if (!isa<SCEVCouldNotCompute>(UB)) {
992 if (!isLoopInvariant(Step,
LoopNest))
1003bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *
LoopNest,
1010bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *
LoopNest,
1019DependenceInfo::Subscript::ClassificationKind
1020DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1021 const SCEV *Dst,
const Loop *DstLoopNest,
1025 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1026 return Subscript::NonLinear;
1027 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1028 return Subscript::NonLinear;
1031 unsigned N =
Loops.count();
1033 return Subscript::ZIV;
1035 return Subscript::SIV;
1036 if (
N == 2 && (SrcLoops.count() == 0 ||
1037 DstLoops.count() == 0 ||
1038 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1039 return Subscript::RDIV;
1040 return Subscript::MIV;
1055 const SCEV *
Y)
const {
1058 if ((isa<SCEVSignExtendExpr>(
X) &&
1059 isa<SCEVSignExtendExpr>(
Y)) ||
1060 (isa<SCEVZeroExtendExpr>(
X) &&
1061 isa<SCEVZeroExtendExpr>(
Y))) {
1101bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1103 auto *SType = dyn_cast<IntegerType>(S->
getType());
1104 auto *SizeType = dyn_cast<IntegerType>(
Size->getType());
1105 if (!SType || !SizeType)
1108 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1114 if (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Bound)) {
1117 if (!isa<SCEVCouldNotCompute>(BECount)) {
1126 const SCEV *LimitedBound =
1131bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1132 bool Inbounds =
false;
1133 if (
auto *SrcGEP = dyn_cast<GetElementPtrInst>(
Ptr))
1134 Inbounds = SrcGEP->isInBounds();
1136 if (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
1157const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1168const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1170 if (
const SCEV *UB = collectUpperBound(L,
T))
1171 return dyn_cast<SCEVConstant>(UB);
1186bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1201 Result.Consistent =
false;
1233bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1234 const SCEV *DstConst,
const Loop *CurLoop,
1236 Constraint &NewConstraint)
const {
1244 ++StrongSIVapplications;
1245 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1253 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1256 const SCEV *AbsDelta =
1258 const SCEV *AbsCoeff =
1263 ++StrongSIVindependence;
1264 ++StrongSIVsuccesses;
1270 if (isa<SCEVConstant>(Delta) && isa<SCEVConstant>(Coeff)) {
1271 APInt ConstDelta = cast<SCEVConstant>(Delta)->getAPInt();
1272 APInt ConstCoeff = cast<SCEVConstant>(Coeff)->getAPInt();
1273 APInt Distance = ConstDelta;
1274 APInt Remainder = ConstDelta;
1279 if (Remainder != 0) {
1281 ++StrongSIVindependence;
1282 ++StrongSIVsuccesses;
1286 NewConstraint.setDistance(SE->
getConstant(Distance), CurLoop);
1287 if (Distance.
sgt(0))
1289 else if (Distance.
slt(0))
1293 ++StrongSIVsuccesses;
1295 else if (Delta->
isZero()) {
1297 Result.DV[Level].Distance = Delta;
1298 NewConstraint.setDistance(Delta, CurLoop);
1300 ++StrongSIVsuccesses;
1303 if (Coeff->
isOne()) {
1305 Result.DV[Level].Distance = Delta;
1306 NewConstraint.setDistance(Delta, CurLoop);
1309 Result.Consistent =
false;
1310 NewConstraint.setLine(Coeff,
1325 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1326 (DeltaMaybeNegative && CoeffMaybeNegative))
1330 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1331 (DeltaMaybePositive && CoeffMaybeNegative))
1333 if (NewDirection <
Result.DV[Level].Direction)
1334 ++StrongSIVsuccesses;
1335 Result.DV[Level].Direction &= NewDirection;
1369bool DependenceInfo::weakCrossingSIVtest(
1370 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1372 Constraint &NewConstraint,
const SCEV *&SplitIter)
const {
1377 ++WeakCrossingSIVapplications;
1378 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1380 Result.Consistent =
false;
1383 NewConstraint.setLine(Coeff, Coeff, Delta, CurLoop);
1387 ++WeakCrossingSIVsuccesses;
1388 if (!
Result.DV[Level].Direction) {
1389 ++WeakCrossingSIVindependence;
1392 Result.DV[Level].Distance = Delta;
1395 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(Coeff);
1399 Result.DV[Level].Splitable =
true;
1403 "dynamic cast of negative of ConstCoeff should yield constant");
1414 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1424 ++WeakCrossingSIVindependence;
1425 ++WeakCrossingSIVsuccesses;
1431 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1439 ++WeakCrossingSIVindependence;
1440 ++WeakCrossingSIVsuccesses;
1447 ++WeakCrossingSIVsuccesses;
1448 if (!
Result.DV[Level].Direction) {
1449 ++WeakCrossingSIVindependence;
1452 Result.DV[Level].Splitable =
false;
1461 APInt Distance = APDelta;
1462 APInt Remainder = APDelta;
1465 if (Remainder != 0) {
1467 ++WeakCrossingSIVindependence;
1468 ++WeakCrossingSIVsuccesses;
1475 Remainder = Distance.
srem(Two);
1477 if (Remainder != 0) {
1480 ++WeakCrossingSIVsuccesses;
1498 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1499 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1506 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1507 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1513 X = AM.
slt(0) ? -A1 : A1;
1514 Y = BM.
slt(0) ? B1 : -B1;
1530 if ((
A.sgt(0) &&
B.sgt(0)) ||
1531 (
A.slt(0) &&
B.slt(0)))
1543 if ((
A.sgt(0) &&
B.sgt(0)) ||
1544 (
A.slt(0) &&
B.slt(0)))
1569bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1570 const SCEV *SrcConst,
const SCEV *DstConst,
1571 const Loop *CurLoop,
unsigned Level,
1573 Constraint &NewConstraint)
const {
1575 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1576 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1579 ++ExactSIVapplications;
1580 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1582 Result.Consistent =
false;
1587 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1588 const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1589 const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1590 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1601 ++ExactSIVindependence;
1602 ++ExactSIVsuccesses;
1609 APInt UM(Bits, 1,
true);
1610 bool UMValid =
false;
1613 collectConstantUpperBound(CurLoop, Delta->
getType())) {
1614 UM = CUB->getAPInt();
1678 ++ExactSIVindependence;
1679 ++ExactSIVsuccesses;
1685 APInt LowerDistance, UpperDistance;
1687 LowerDistance = (TY - TX) + (TA - TB) * TL;
1688 UpperDistance = (TY - TX) + (TA - TB) * TU;
1690 LowerDistance = (TY - TX) + (TA - TB) * TU;
1691 UpperDistance = (TY - TX) + (TA - TB) * TL;
1694 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1695 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1698 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1700 ++ExactSIVsuccesses;
1702 if (LowerDistance.
slt(0)) {
1704 ++ExactSIVsuccesses;
1706 if (UpperDistance.
sgt(0)) {
1708 ++ExactSIVsuccesses;
1712 Result.DV[Level].Direction &= NewDirection;
1714 ++ExactSIVindependence;
1727 return ConstDividend.
srem(ConstDivisor) == 0;
1762bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1763 const SCEV *SrcConst,
1764 const SCEV *DstConst,
1765 const Loop *CurLoop,
unsigned Level,
1767 Constraint &NewConstraint)
const {
1775 ++WeakZeroSIVapplications;
1776 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1778 Result.Consistent =
false;
1780 NewConstraint.setLine(SE->
getZero(Delta->
getType()), DstCoeff, Delta,
1784 if (Level < CommonLevels) {
1786 Result.DV[Level].PeelFirst =
true;
1787 ++WeakZeroSIVsuccesses;
1791 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1794 const SCEV *AbsCoeff =
1797 const SCEV *NewDelta =
1802 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1806 ++WeakZeroSIVindependence;
1807 ++WeakZeroSIVsuccesses;
1812 if (Level < CommonLevels) {
1814 Result.DV[Level].PeelLast =
true;
1815 ++WeakZeroSIVsuccesses;
1825 ++WeakZeroSIVindependence;
1826 ++WeakZeroSIVsuccesses;
1831 if (isa<SCEVConstant>(Delta) &&
1833 ++WeakZeroSIVindependence;
1834 ++WeakZeroSIVsuccesses;
1872bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1873 const SCEV *SrcConst,
1874 const SCEV *DstConst,
1875 const Loop *CurLoop,
unsigned Level,
1877 Constraint &NewConstraint)
const {
1884 ++WeakZeroSIVapplications;
1885 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1887 Result.Consistent =
false;
1889 NewConstraint.setLine(SrcCoeff, SE->
getZero(Delta->
getType()), Delta,
1893 if (Level < CommonLevels) {
1895 Result.DV[Level].PeelFirst =
true;
1896 ++WeakZeroSIVsuccesses;
1900 const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1903 const SCEV *AbsCoeff =
1906 const SCEV *NewDelta =
1911 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1915 ++WeakZeroSIVindependence;
1916 ++WeakZeroSIVsuccesses;
1921 if (Level < CommonLevels) {
1923 Result.DV[Level].PeelLast =
true;
1924 ++WeakZeroSIVsuccesses;
1934 ++WeakZeroSIVindependence;
1935 ++WeakZeroSIVsuccesses;
1940 if (isa<SCEVConstant>(Delta) &&
1942 ++WeakZeroSIVindependence;
1943 ++WeakZeroSIVsuccesses;
1957bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1958 const SCEV *SrcConst,
const SCEV *DstConst,
1959 const Loop *SrcLoop,
const Loop *DstLoop,
1962 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1963 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1966 ++ExactRDIVapplications;
1967 Result.Consistent =
false;
1970 const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
1971 const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
1972 const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
1973 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1984 ++ExactRDIVindependence;
1991 APInt SrcUM(Bits, 1,
true);
1992 bool SrcUMvalid =
false;
1995 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
1996 SrcUM = UpperBound->getAPInt();
2001 APInt DstUM(Bits, 1,
true);
2002 bool DstUMvalid =
false;
2005 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2006 DstUM = UpperBound->getAPInt();
2067 ++ExactRDIVindependence;
2114bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2117 const Loop *Loop2)
const {
2118 ++SymbolicRDIVapplications;
2125 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2126 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2141 ++SymbolicRDIVindependence;
2150 ++SymbolicRDIVindependence;
2162 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2164 ++SymbolicRDIVindependence;
2170 ++SymbolicRDIVindependence;
2183 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2185 ++SymbolicRDIVindependence;
2191 ++SymbolicRDIVindependence;
2202 ++SymbolicRDIVindependence;
2211 ++SymbolicRDIVindependence;
2229bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2231 const SCEV *&SplitIter)
const {
2236 if (SrcAddRec && DstAddRec) {
2243 "both loops in SIV should be same");
2244 Level = mapSrcLoop(CurLoop);
2246 if (SrcCoeff == DstCoeff)
2247 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2248 Level, Result, NewConstraint);
2250 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2251 Level, Result, NewConstraint, SplitIter);
2253 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2254 Level, Result, NewConstraint);
2256 gcdMIVtest(Src, Dst, Result) ||
2257 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop, CurLoop);
2262 const SCEV *DstConst = Dst;
2264 Level = mapSrcLoop(CurLoop);
2265 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2266 Level, Result, NewConstraint) ||
2267 gcdMIVtest(Src, Dst, Result);
2272 const SCEV *SrcConst = Src;
2274 Level = mapDstLoop(CurLoop);
2275 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst,
2276 CurLoop, Level, Result, NewConstraint) ||
2277 gcdMIVtest(Src, Dst, Result);
2297bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2305 const SCEV *SrcConst, *DstConst;
2306 const SCEV *SrcCoeff, *DstCoeff;
2307 const Loop *SrcLoop, *DstLoop;
2313 if (SrcAddRec && DstAddRec) {
2316 SrcLoop = SrcAddRec->
getLoop();
2319 DstLoop = DstAddRec->
getLoop();
2321 else if (SrcAddRec) {
2323 dyn_cast<SCEVAddRecExpr>(SrcAddRec->
getStart())) {
2324 SrcConst = tmpAddRec->getStart();
2325 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2326 SrcLoop = tmpAddRec->getLoop();
2329 DstLoop = SrcAddRec->
getLoop();
2334 else if (DstAddRec) {
2336 dyn_cast<SCEVAddRecExpr>(DstAddRec->
getStart())) {
2337 DstConst = tmpAddRec->getStart();
2338 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2339 DstLoop = tmpAddRec->getLoop();
2342 SrcLoop = DstAddRec->
getLoop();
2349 return exactRDIVtest(SrcCoeff, DstCoeff,
2353 gcdMIVtest(Src, Dst, Result) ||
2354 symbolicRDIVtest(SrcCoeff, DstCoeff,
2363bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2368 Result.Consistent =
false;
2369 return gcdMIVtest(Src, Dst, Result) ||
2370 banerjeeMIVtest(Src, Dst,
Loops, Result);
2378 if (
const auto *
Constant = dyn_cast<SCEVConstant>(Expr))
2380 else if (
const auto *Product = dyn_cast<SCEVMulExpr>(Expr))
2381 if (
const auto *
Constant = dyn_cast<SCEVConstant>(Product->getOperand(0)))
2405bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2416 const SCEV *Coefficients = Src;
2418 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2429 const SCEV *SrcConst = Coefficients;
2437 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2448 const SCEV *DstConst = Coefficients;
2454 if (
const SCEVAddExpr *Sum = dyn_cast<SCEVAddExpr>(Delta)) {
2457 if (isa<SCEVConstant>(Operand)) {
2459 Constant = cast<SCEVConstant>(Operand);
2461 else if (
const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Operand)) {
2469 ConstOpValue.
abs());
2479 if (ConstDelta == 0)
2483 APInt Remainder = ConstDelta.
srem(RunningGCD);
2484 if (Remainder != 0) {
2503 bool Improved =
false;
2506 dyn_cast<SCEVAddRecExpr>(Coefficients)) {
2509 RunningGCD = ExtraGCD;
2512 const SCEV *Inner = Src;
2513 while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
2514 AddRec = cast<SCEVAddRecExpr>(Inner);
2516 if (CurLoop == AddRec->
getLoop())
2530 while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
2531 AddRec = cast<SCEVAddRecExpr>(Inner);
2533 if (CurLoop == AddRec->
getLoop())
2557 if (RunningGCD != 0) {
2558 Remainder = ConstDelta.
srem(RunningGCD);
2560 if (Remainder != 0) {
2561 unsigned Level = mapSrcLoop(CurLoop);
2607bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2611 ++BanerjeeApplications;
2614 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2617 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2618 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2624 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2625 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2628 findBoundsALL(
A,
B, Bound, K);
2643 bool Disproved =
false;
2646 unsigned DepthExpanded = 0;
2647 unsigned NewDeps = exploreDirections(1,
A,
B, Bound,
2648 Loops, DepthExpanded, Delta);
2650 bool Improved =
false;
2651 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2653 unsigned Old =
Result.DV[
K - 1].Direction;
2654 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2655 Improved |= Old !=
Result.DV[
K - 1].Direction;
2656 if (!
Result.DV[K - 1].Direction) {
2664 ++BanerjeeSuccesses;
2667 ++BanerjeeIndependence;
2672 ++BanerjeeIndependence;
2687unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2688 CoefficientInfo *
B, BoundInfo *Bound,
2690 unsigned &DepthExpanded,
2691 const SCEV *Delta)
const {
2697 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2698 "direction exploration is terminated.\n");
2699 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2705 if (Level > CommonLevels) {
2708 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2710 Bound[
K].DirSet |= Bound[
K].Direction;
2735 if (Level > DepthExpanded) {
2736 DepthExpanded = Level;
2738 findBoundsLT(
A,
B, Bound, Level);
2739 findBoundsGT(
A,
B, Bound, Level);
2740 findBoundsEQ(
A,
B, Bound, Level);
2779 unsigned NewDeps = 0;
2783 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
2784 Loops, DepthExpanded, Delta);
2788 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
2789 Loops, DepthExpanded, Delta);
2793 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
2794 Loops, DepthExpanded, Delta);
2800 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2805bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2806 BoundInfo *Bound,
const SCEV *Delta)
const {
2807 Bound[Level].Direction = DirKind;
2808 if (
const SCEV *LowerBound = getLowerBound(Bound))
2811 if (
const SCEV *UpperBound = getUpperBound(Bound))
2833void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2834 BoundInfo *Bound,
unsigned K)
const {
2837 if (Bound[K].Iterations) {
2840 Bound[K].Iterations);
2843 Bound[K].Iterations);
2872void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2873 BoundInfo *Bound,
unsigned K)
const {
2876 if (Bound[K].Iterations) {
2878 const SCEV *NegativePart = getNegativePart(Delta);
2880 SE->
getMulExpr(NegativePart, Bound[K].Iterations);
2881 const SCEV *PositivePart = getPositivePart(Delta);
2883 SE->
getMulExpr(PositivePart, Bound[K].Iterations);
2889 const SCEV *NegativePart = getNegativePart(Delta);
2890 if (NegativePart->
isZero())
2892 const SCEV *PositivePart = getPositivePart(Delta);
2893 if (PositivePart->
isZero())
2912void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2913 BoundInfo *Bound,
unsigned K)
const {
2916 if (Bound[K].Iterations) {
2918 Bound[K].Iterations, SE->
getOne(Bound[K].Iterations->getType()));
2919 const SCEV *NegPart =
2923 const SCEV *PosPart =
2931 const SCEV *NegPart =
2935 const SCEV *PosPart =
2956void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2957 BoundInfo *Bound,
unsigned K)
const {
2960 if (Bound[K].Iterations) {
2962 Bound[K].Iterations, SE->
getOne(Bound[K].Iterations->getType()));
2963 const SCEV *NegPart =
2967 const SCEV *PosPart =
2986const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2992const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3000DependenceInfo::CoefficientInfo *
3001DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3004 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3005 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3007 CI[
K].PosPart =
Zero;
3008 CI[
K].NegPart =
Zero;
3009 CI[
K].Iterations =
nullptr;
3011 while (
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Subscript)) {
3013 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3015 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3016 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3017 CI[
K].Iterations = collectUpperBound(L, Subscript->
getType());
3023 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3030 if (CI[K].Iterations)
3046const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3047 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3048 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3062const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3063 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3064 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3083const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3084 const Loop *TargetLoop)
const {
3088 if (AddRec->
getLoop() == TargetLoop)
3090 return findCoefficient(AddRec->
getStart(), TargetLoop);
3099const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3100 const Loop *TargetLoop)
const {
3104 if (AddRec->
getLoop() == TargetLoop)
3118const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3119 const Loop *TargetLoop,
3127 if (AddRec->
getLoop() == TargetLoop) {
3155bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3160 for (
unsigned LI :
Loops.set_bits()) {
3163 if (Constraints[LI].isDistance())
3164 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3165 else if (Constraints[LI].isLine())
3166 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3167 else if (Constraints[LI].isPoint())
3168 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3179bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3180 Constraint &CurConstraint,
3182 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3184 const SCEV *A_K = findCoefficient(Src, CurLoop);
3189 Src = zeroCoefficient(Src, CurLoop);
3194 if (!findCoefficient(Dst, CurLoop)->
isZero())
3205bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3206 Constraint &CurConstraint,
3208 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3209 const SCEV *
A = CurConstraint.getA();
3210 const SCEV *
B = CurConstraint.getB();
3211 const SCEV *
C = CurConstraint.getC();
3219 if (!Bconst || !Cconst)
return false;
3223 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3224 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3227 Dst = zeroCoefficient(Dst, CurLoop);
3228 if (!findCoefficient(Src, CurLoop)->
isZero())
3231 else if (
B->isZero()) {
3234 if (!Aconst || !Cconst)
return false;
3238 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3239 const SCEV *A_K = findCoefficient(Src, CurLoop);
3241 Src = zeroCoefficient(Src, CurLoop);
3242 if (!findCoefficient(Dst, CurLoop)->
isZero())
3248 if (!Aconst || !Cconst)
return false;
3252 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3253 const SCEV *A_K = findCoefficient(Src, CurLoop);
3255 Src = zeroCoefficient(Src, CurLoop);
3256 Dst = addToCoefficient(Dst, CurLoop, A_K);
3257 if (!findCoefficient(Dst, CurLoop)->
isZero())
3262 const SCEV *A_K = findCoefficient(Src, CurLoop);
3266 Src = zeroCoefficient(Src, CurLoop);
3267 Dst = addToCoefficient(Dst, CurLoop, SE->
getMulExpr(A_K,
B));
3268 if (!findCoefficient(Dst, CurLoop)->
isZero())
3280bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3281 Constraint &CurConstraint) {
3282 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3283 const SCEV *A_K = findCoefficient(Src, CurLoop);
3284 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3289 Src = zeroCoefficient(Src, CurLoop);
3292 Dst = zeroCoefficient(Dst, CurLoop);
3300 const Constraint &CurConstraint)
const {
3303 if (CurConstraint.isAny())
3305 else if (CurConstraint.isDistance()) {
3307 Level.Scalar =
false;
3308 Level.Distance = CurConstraint.getD();
3316 Level.Direction &= NewDirection;
3318 else if (CurConstraint.isLine()) {
3319 Level.Scalar =
false;
3320 Level.Distance =
nullptr;
3323 else if (CurConstraint.isPoint()) {
3324 Level.Scalar =
false;
3325 Level.Distance =
nullptr;
3328 CurConstraint.getY(),
3329 CurConstraint.getX()))
3333 CurConstraint.getY(),
3334 CurConstraint.getX()))
3338 CurConstraint.getY(),
3339 CurConstraint.getX()))
3342 Level.Direction &= NewDirection;
3367 if (!SrcBase || !DstBase || SrcBase != DstBase)
3372 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3373 SrcSubscripts, DstSubscripts) &&
3374 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3375 SrcSubscripts, DstSubscripts))
3380 dbgs() <<
"\nSrcSubscripts: ";
3381 for (
int I = 0;
I <
Size;
I++)
3382 dbgs() << *SrcSubscripts[
I];
3383 dbgs() <<
"\nDstSubscripts: ";
3384 for (
int I = 0;
I <
Size;
I++)
3385 dbgs() << *DstSubscripts[
I];
3393 for (
int I = 0;
I <
Size; ++
I) {
3394 Pair[
I].Src = SrcSubscripts[
I];
3395 Pair[
I].Dst = DstSubscripts[
I];
3396 unifySubscriptType(&Pair[
I]);
3405bool DependenceInfo::tryDelinearizeFixedSize(
3414 assert(SrcBase && DstBase && SrcBase == DstBase &&
3415 "expected src and dst scev unknowns to be equal");
3428 if (SrcSizes.size() != DstSizes.
size() ||
3429 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3430 SrcSubscripts.
clear();
3431 DstSubscripts.
clear();
3436 "Expected equal number of entries in the list of SrcSubscripts and "
3452 size_t SSize = Subscripts.
size();
3453 for (
size_t I = 1;
I < SSize; ++
I) {
3454 const SCEV *S = Subscripts[
I];
3455 if (!isKnownNonNegative(S,
Ptr))
3457 if (
auto *SType = dyn_cast<IntegerType>(S->
getType())) {
3459 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3460 if (!isKnownLessThan(S,
Range))
3467 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3468 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3469 SrcSubscripts.
clear();
3470 DstSubscripts.
clear();
3475 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3476 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3477 <<
"DstGEP:" << *DstPtr <<
"\n";
3482bool DependenceInfo::tryDelinearizeParametricSize(
3493 assert(SrcBase && DstBase && SrcBase == DstBase &&
3494 "expected src and dst scev unknowns to be equal");
3522 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3523 SrcSubscripts.
size() != DstSubscripts.
size())
3526 size_t Size = SrcSubscripts.
size();
3535 for (
size_t I = 1;
I <
Size; ++
I) {
3536 if (!isKnownNonNegative(SrcSubscripts[
I], SrcPtr))
3539 if (!isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]))
3542 if (!isKnownNonNegative(DstSubscripts[
I], DstPtr))
3545 if (!isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]))
3558 for (
unsigned VI : BV.
set_bits()) {
3591std::unique_ptr<Dependence>
3593 bool PossiblyLoopIndependent =
true;
3595 PossiblyLoopIndependent =
false;
3597 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3603 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3604 return std::make_unique<Dependence>(Src, Dst);
3619 return std::make_unique<Dependence>(Src, Dst);
3629 establishNestingLevels(Src, Dst);
3630 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3631 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3633 FullDependence Result(Src, Dst, PossiblyLoopIndependent, CommonLevels);
3649 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3650 return std::make_unique<Dependence>(Src, Dst);
3652 Pair[0].Src = SrcSCEV;
3653 Pair[0].Dst = DstSCEV;
3656 if (tryDelinearize(Src, Dst, Pair)) {
3658 Pairs = Pair.
size();
3662 for (
unsigned P = 0;
P < Pairs; ++
P) {
3663 Pair[
P].Loops.
resize(MaxLevels + 1);
3664 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3666 removeMatchingExtensions(&Pair[
P]);
3667 Pair[
P].Classification =
3668 classifyPair(Pair[
P].Src, LI->
getLoopFor(Src->getParent()),
3671 Pair[
P].GroupLoops = Pair[
P].Loops;
3672 Pair[
P].Group.set(
P);
3741 for (
unsigned SI = 0; SI < Pairs; ++SI) {
3742 if (Pair[SI].Classification == Subscript::NonLinear) {
3744 ++NonlinearSubscriptPairs;
3745 collectCommonLoops(Pair[SI].Src,
3748 collectCommonLoops(Pair[SI].Dst,
3751 Result.Consistent =
false;
3752 }
else if (Pair[SI].Classification == Subscript::ZIV) {
3759 for (
unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
3761 Intersection &= Pair[SJ].GroupLoops;
3762 if (Intersection.
any()) {
3764 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
3766 Pair[SJ].Group |= Pair[SI].Group;
3771 if (Pair[SI].Group.count() == 1) {
3773 ++SeparableSubscriptPairs;
3777 ++CoupledSubscriptPairs;
3788 Constraint NewConstraint;
3789 NewConstraint.setAny(SE);
3792 for (
unsigned SI : Separable.
set_bits()) {
3794 switch (Pair[SI].Classification) {
3795 case Subscript::ZIV:
3797 if (testZIV(Pair[SI].Src, Pair[SI].Dst, Result))
3800 case Subscript::SIV: {
3803 const SCEV *SplitIter =
nullptr;
3804 if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result, NewConstraint,
3809 case Subscript::RDIV:
3811 if (testRDIV(Pair[SI].Src, Pair[SI].Dst, Result))
3814 case Subscript::MIV:
3816 if (testMIV(Pair[SI].Src, Pair[SI].Dst, Pair[SI].
Loops, Result))
3824 if (Coupled.
count()) {
3827 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
3829 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
3830 Constraints[
II].setAny(SE);
3831 for (
unsigned SI : Coupled.
set_bits()) {
3838 for (
unsigned SJ : Group.set_bits()) {
3840 if (Pair[SJ].Classification == Subscript::SIV)
3846 unifySubscriptType(PairsInGroup);
3848 while (Sivs.
any()) {
3849 bool Changed =
false;
3850 for (
unsigned SJ : Sivs.
set_bits()) {
3854 const SCEV *SplitIter =
nullptr;
3856 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
3859 ConstrainedLevels.
set(Level);
3860 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
3861 if (Constraints[Level].isEmpty()) {
3862 ++DeltaIndependence;
3874 for (
unsigned SJ : Mivs.
set_bits()) {
3877 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
3878 Constraints, Result.Consistent)) {
3880 ++DeltaPropagations;
3881 Pair[SJ].Classification =
3882 classifyPair(Pair[SJ].Src, LI->
getLoopFor(Src->getParent()),
3883 Pair[SJ].Dst, LI->
getLoopFor(Dst->getParent()),
3885 switch (Pair[SJ].Classification) {
3886 case Subscript::ZIV:
3888 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3892 case Subscript::SIV:
3896 case Subscript::RDIV:
3897 case Subscript::MIV:
3908 for (
unsigned SJ : Mivs.
set_bits()) {
3909 if (Pair[SJ].Classification == Subscript::RDIV) {
3911 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3921 for (
unsigned SJ : Mivs.
set_bits()) {
3922 if (Pair[SJ].Classification == Subscript::MIV) {
3924 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
3933 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
3934 if (SJ > CommonLevels)
3936 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
3945 for (
unsigned SI = 0; SI < Pairs; ++SI)
3946 CompleteLoops |= Pair[SI].
Loops;
3947 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
3948 if (CompleteLoops[
II])
3949 Result.DV[
II - 1].Scalar =
false;
3951 if (PossiblyLoopIndependent) {
3955 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3957 Result.LoopIndependent =
false;
3965 bool AllEqual =
true;
3966 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
3976 return std::make_unique<FullDependence>(std::move(Result));
4027 unsigned SplitLevel) {
4029 "Dep should be splitable at SplitLevel");
4032 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4033 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4043 establishNestingLevels(Src, Dst);
4051 Pair[0].Src = SrcSCEV;
4052 Pair[0].Dst = DstSCEV;
4055 if (tryDelinearize(Src, Dst, Pair)) {
4057 Pairs = Pair.
size();
4061 for (
unsigned P = 0;
P < Pairs; ++
P) {
4062 Pair[
P].Loops.
resize(MaxLevels + 1);
4063 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4065 removeMatchingExtensions(&Pair[
P]);
4066 Pair[
P].Classification =
4067 classifyPair(Pair[
P].Src, LI->
getLoopFor(Src->getParent()),
4070 Pair[
P].GroupLoops = Pair[
P].Loops;
4071 Pair[
P].Group.set(
P);
4078 for (
unsigned SI = 0; SI < Pairs; ++SI) {
4079 if (Pair[SI].Classification == Subscript::NonLinear) {
4081 collectCommonLoops(Pair[SI].Src,
4084 collectCommonLoops(Pair[SI].Dst,
4087 Result.Consistent =
false;
4089 else if (Pair[SI].Classification == Subscript::ZIV)
4094 for (
unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
4096 Intersection &= Pair[SJ].GroupLoops;
4097 if (Intersection.
any()) {
4099 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
4101 Pair[SJ].Group |= Pair[SI].Group;
4106 if (Pair[SI].Group.count() == 1)
4114 Constraint NewConstraint;
4115 NewConstraint.setAny(SE);
4118 for (
unsigned SI : Separable.
set_bits()) {
4119 switch (Pair[SI].Classification) {
4120 case Subscript::SIV: {
4122 const SCEV *SplitIter =
nullptr;
4123 (void) testSIV(Pair[SI].Src, Pair[SI].Dst, Level,
4124 Result, NewConstraint, SplitIter);
4125 if (Level == SplitLevel) {
4126 assert(SplitIter !=
nullptr);
4131 case Subscript::ZIV:
4132 case Subscript::RDIV:
4133 case Subscript::MIV:
4140 if (Coupled.
count()) {
4143 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4144 Constraints[
II].setAny(SE);
4145 for (
unsigned SI : Coupled.
set_bits()) {
4150 for (
unsigned SJ : Group.set_bits()) {
4151 if (Pair[SJ].Classification == Subscript::SIV)
4156 while (Sivs.
any()) {
4157 bool Changed =
false;
4158 for (
unsigned SJ : Sivs.
set_bits()) {
4161 const SCEV *SplitIter =
nullptr;
4162 (void) testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level,
4163 Result, NewConstraint, SplitIter);
4164 if (Level == SplitLevel && SplitIter)
4166 ConstrainedLevels.
set(Level);
4167 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4173 for (
unsigned SJ : Mivs.
set_bits()) {
4175 if (propagate(Pair[SJ].Src, Pair[SJ].Dst,
4176 Pair[SJ].
Loops, Constraints, Result.Consistent)) {
4177 Pair[SJ].Classification =
4178 classifyPair(Pair[SJ].Src, LI->
getLoopFor(Src->getParent()),
4179 Pair[SJ].Dst, LI->
getLoopFor(Dst->getParent()),
4181 switch (Pair[SJ].Classification) {
4182 case Subscript::ZIV:
4185 case Subscript::SIV:
4189 case Subscript::RDIV:
4190 case Subscript::MIV:
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 const SCEVConstant * getConstantPart(const SCEV *Expr)
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 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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
Class for arbitrary precision integers.
static 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.
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.
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.
Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
const SCEV * getSplitIteration(const Dependence &Dep, unsigned Level)
getSplitIteration - Give a dependence that's splittable at some particular level, return the iteratio...
std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst)
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.
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.
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.
FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, unsigned Levels)
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.
bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
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 MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
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.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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
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.
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
const SCEV * getOperand(unsigned i) const
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.
ArrayRef< const SCEV * > operands() const
Return operands of this SCEV expression.
bool isOne() const
Return true if the expression is a constant one.
bool isZero() const
Return true if the expression is a constant zero.
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.
bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
const SCEV * getSMaxExpr(const SCEV *LHS, const SCEV *RHS)
bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
bool isKnownNonZero(const SCEV *S)
Test if the given expression is known to be non-zero.
const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
const SCEV * getSMinExpr(const SCEV *LHS, const SCEV *RHS)
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.
uint64_t getTypeSizeInBits(Type *Ty) const
Return the size in bits of the specified type, for which isSCEVable must return true.
const SCEV * getConstant(ConstantInt *V)
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.
bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
const SCEV * getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, SCEV::NoWrapFlags Flags)
Get an add recurrence expression for the specified loop.
const SCEV * getUDivExpr(const SCEV *LHS, const SCEV *RHS)
Get a canonical unsigned division expression, or something simpler if possible.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
bool hasLoopInvariantBackedgeTakenCount(const Loop *L)
Return true if the specified loop has an analyzable loop-invariant backedge-taken count.
const SCEV * getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
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.
const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
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.
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.
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.
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.
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...
void initializeDependenceAnalysisWrapperPassPass(PassRegistry &)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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)...
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
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
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...
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.