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."));
126 cl::desc(
"Run only SIV routines and disable others (ZIV, RDIV, and MIV). "
127 "The purpose is mainly to exclude the influence of those routines "
128 "in regression tests for SIV routines."));
144 "Dependence Analysis",
true,
true)
185 auto *
F = DA->getFunction();
188 if (SrcI->mayReadOrWriteMemory()) {
191 if (DstI->mayReadOrWriteMemory()) {
192 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
193 OS <<
" da analyze - ";
194 if (
auto D = DA->depends(&*SrcI, &*DstI,
200 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
201 const SCEV *Distance =
D->getDistance(Level);
202 bool IsDistanceZero = Distance && Distance->
isZero();
205 assert(IsDistanceZero == IsDirectionEQ &&
206 "Inconsistent distance and direction.");
211 if (NormalizeResults &&
D->normalize(&SE))
212 OS <<
"normalized - ";
214 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
215 if (
D->isSplitable(Level)) {
216 OS <<
" da analyze - split level = " << Level;
217 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
229 OS <<
"Runtime Assumptions:\n";
230 Assumptions.
print(OS, 0);
242 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
255 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
260 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
265 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
270 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
284 bool PossiblyLoopIndependent,
285 unsigned CommonLevels)
286 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
287 LoopIndependent(PossiblyLoopIndependent) {
290 DV = std::make_unique<
DVEntry[]>(CommonLevels);
309 for (
unsigned Level = 1; Level <= Levels; ++Level) {
310 unsigned char Direction = DV[Level - 1].Direction;
325 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
328 for (
unsigned Level = 1; Level <= Levels; ++Level) {
329 unsigned char Direction = DV[Level - 1].Direction;
337 DV[Level - 1].Direction = RevDirection;
339 if (DV[Level - 1].Distance !=
nullptr)
343 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
352 assert(0 < Level && Level <= Levels &&
"Level out of range");
353 return DV[Level - 1].Direction;
358 assert(0 < Level && Level <= Levels &&
"Level out of range");
359 return DV[Level - 1].Distance;
366 assert(0 < Level && Level <= Levels &&
"Level out of range");
367 return DV[Level - 1].Scalar;
373 assert(0 < Level && Level <= Levels &&
"Level out of range");
374 return DV[Level - 1].PeelFirst;
380 assert(0 < Level && Level <= Levels &&
"Level out of range");
381 return DV[Level - 1].PeelLast;
386 assert(0 < Level && Level <= Levels &&
"Level out of range");
387 return DV[Level - 1].Splitable;
395const SCEV *DependenceInfo::Constraint::getX()
const {
396 assert(Kind == Point &&
"Kind should be Point");
402const SCEV *DependenceInfo::Constraint::getY()
const {
403 assert(Kind == Point &&
"Kind should be Point");
409const SCEV *DependenceInfo::Constraint::getA()
const {
410 assert((Kind == Line || Kind == Distance) &&
411 "Kind should be Line (or Distance)");
417const SCEV *DependenceInfo::Constraint::getB()
const {
418 assert((Kind == Line || Kind == Distance) &&
419 "Kind should be Line (or Distance)");
425const SCEV *DependenceInfo::Constraint::getC()
const {
426 assert((Kind == Line || Kind == Distance) &&
427 "Kind should be Line (or Distance)");
433const SCEV *DependenceInfo::Constraint::getD()
const {
434 assert(Kind == Distance &&
"Kind should be Distance");
435 return SE->getNegativeSCEV(
C);
439const Loop *DependenceInfo::Constraint::getAssociatedLoop()
const {
440 assert((Kind == Distance || Kind == Line || Kind == Point) &&
441 "Kind should be Distance, Line, or Point");
442 return AssociatedLoop;
445void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
446 const Loop *CurLoop) {
450 AssociatedLoop = CurLoop;
453void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
454 const SCEV *CC,
const Loop *CurLoop) {
459 AssociatedLoop = CurLoop;
462void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
463 const Loop *CurLoop) {
465 A = SE->getOne(
D->getType());
466 B = SE->getNegativeSCEV(
A);
467 C = SE->getNegativeSCEV(
D);
468 AssociatedLoop = CurLoop;
471void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
473void DependenceInfo::Constraint::setAny(ScalarEvolution *NewSE) {
478#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
480LLVM_DUMP_METHOD void DependenceInfo::Constraint::dump(raw_ostream &OS)
const {
486 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
487 else if (isDistance())
488 OS <<
" Distance is " << *getD() <<
" (" << *getA() <<
"*X + " << *getB()
489 <<
"*Y = " << *getC() <<
")\n";
491 OS <<
" Line is " << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC()
505bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
510 assert(!
Y->isPoint() &&
"Y must not be a Point");
524 if (
X->isDistance() &&
Y->isDistance()) {
548 assert(!(
X->isPoint() &&
Y->isPoint()) &&
549 "We shouldn't ever see X->isPoint() && Y->isPoint()");
551 if (
X->isLine() &&
Y->isLine()) {
553 const SCEV *Prod1 = SE->getMulExpr(
X->getA(),
Y->getB());
554 const SCEV *Prod2 = SE->getMulExpr(
X->getB(),
Y->getA());
558 Prod1 = SE->getMulExpr(
X->getC(),
Y->getB());
559 Prod2 = SE->getMulExpr(
X->getB(),
Y->getC());
572 const SCEV *C1B2 = SE->getMulExpr(
X->getC(),
Y->getB());
573 const SCEV *C1A2 = SE->getMulExpr(
X->getC(),
Y->getA());
574 const SCEV *C2B1 = SE->getMulExpr(
Y->getC(),
X->getB());
575 const SCEV *C2A1 = SE->getMulExpr(
Y->getC(),
X->getA());
576 const SCEV *A1B2 = SE->getMulExpr(
X->getA(),
Y->getB());
577 const SCEV *A2B1 = SE->getMulExpr(
Y->getA(),
X->getB());
578 const SCEVConstant *C1A2_C2A1 =
580 const SCEVConstant *C1B2_C2B1 =
582 const SCEVConstant *A1B2_A2B1 =
584 const SCEVConstant *A2B1_A1B2 =
586 if (!C1B2_C2B1 || !C1A2_C2A1 || !A1B2_A2B1 || !A2B1_A1B2)
602 if (Xr != 0 || Yr != 0) {
608 if (Xq.
slt(0) || Yq.
slt(0)) {
613 if (
const SCEVConstant *CUB = collectConstantUpperBound(
614 X->getAssociatedLoop(), Prod1->
getType())) {
615 const APInt &UpperBound = CUB->getAPInt();
617 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
623 X->setPoint(SE->getConstant(Xq), SE->getConstant(Yq),
624 X->getAssociatedLoop());
632 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
634 if (
X->isPoint() &&
Y->isLine()) {
636 const SCEV *A1X1 = SE->getMulExpr(
Y->getA(),
X->getX());
637 const SCEV *B1Y1 = SE->getMulExpr(
Y->getB(),
X->getY());
638 const SCEV *Sum = SE->getAddExpr(A1X1, B1Y1);
658 bool Splitable =
false;
674 for (
unsigned II = 1;
II <= Levels; ++
II) {
711 if (!Assumptions.isAlwaysTrue()) {
712 OS <<
" Runtime Assumptions:\n";
713 Assumptions.print(OS, 2);
759 return LI->isUnordered();
761 return SI->isUnordered();
815void DependenceInfo::establishNestingLevels(
const Instruction *Src,
816 const Instruction *Dst) {
817 const BasicBlock *SrcBlock = Src->getParent();
818 const BasicBlock *DstBlock = Dst->getParent();
819 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
820 unsigned DstLevel = LI->getLoopDepth(DstBlock);
821 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
822 const Loop *DstLoop = LI->getLoopFor(DstBlock);
823 SrcLevels = SrcLevel;
824 MaxLevels = SrcLevel + DstLevel;
825 while (SrcLevel > DstLevel) {
829 while (DstLevel > SrcLevel) {
833 while (SrcLoop != DstLoop) {
838 CommonLevels = SrcLevel;
839 MaxLevels -= CommonLevels;
844unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
850unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
852 if (
D > CommonLevels)
855 return D - CommonLevels + SrcLevels;
861bool DependenceInfo::isLoopInvariant(
const SCEV *Expression,
862 const Loop *LoopNest)
const {
877void DependenceInfo::collectCommonLoops(
const SCEV *Expression,
878 const Loop *LoopNest,
879 SmallBitVector &
Loops)
const {
882 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
890 unsigned widestWidthSeen = 0;
895 for (Subscript *Pair : Pairs) {
896 const SCEV *Src = Pair->Src;
897 const SCEV *Dst = Pair->Dst;
900 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
902 "This function only unify integer types and "
903 "expect Src and Dst share the same type otherwise.");
916 assert(widestWidthSeen > 0);
919 for (Subscript *Pair : Pairs) {
920 const SCEV *Src = Pair->Src;
921 const SCEV *Dst = Pair->Dst;
924 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
926 "This function only unify integer types and "
927 "expect Src and Dst share the same type otherwise.");
932 Pair->Src = SE->getSignExtendExpr(Src, widestType);
935 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
944void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
945 const SCEV *Src = Pair->Src;
946 const SCEV *Dst = Pair->Dst;
951 const SCEV *SrcCastOp = SrcCast->
getOperand();
952 const SCEV *DstCastOp = DstCast->
getOperand();
954 Pair->Src = SrcCastOp;
955 Pair->Dst = DstCastOp;
962bool DependenceInfo::checkSubscript(
const SCEV *Expr,
const Loop *LoopNest,
963 SmallBitVector &
Loops,
bool IsSrc) {
966 return isLoopInvariant(Expr, LoopNest);
973 const Loop *
L = LoopNest;
974 while (L && AddRec->
getLoop() != L)
975 L =
L->getParentLoop();
981 if (!isLoopInvariant(Step, LoopNest))
987 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
992bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *LoopNest,
993 SmallBitVector &
Loops) {
994 return checkSubscript(Src, LoopNest,
Loops,
true);
999bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *LoopNest,
1000 SmallBitVector &
Loops) {
1001 return checkSubscript(Dst, LoopNest,
Loops,
false);
1007DependenceInfo::Subscript::ClassificationKind
1008DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1009 const SCEV *Dst,
const Loop *DstLoopNest,
1010 SmallBitVector &
Loops) {
1011 SmallBitVector SrcLoops(MaxLevels + 1);
1012 SmallBitVector DstLoops(MaxLevels + 1);
1013 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1014 return Subscript::NonLinear;
1015 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1016 return Subscript::NonLinear;
1019 unsigned N =
Loops.count();
1021 return Subscript::ZIV;
1023 return Subscript::SIV;
1024 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1025 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1026 return Subscript::RDIV;
1027 return Subscript::MIV;
1041 const SCEV *
Y)
const {
1055 if (SE->isKnownPredicate(Pred,
X,
Y))
1062 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1067 return SE->isKnownNonZero(Delta);
1069 return SE->isKnownNonNegative(Delta);
1071 return SE->isKnownNonPositive(Delta);
1073 return SE->isKnownPositive(Delta);
1075 return SE->isKnownNegative(Delta);
1087bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1091 if (!SType || !SizeType)
1094 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1095 S = SE->getTruncateOrZeroExtend(S, MaxType);
1096 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1101 const SCEV *BECount = SE->getBackedgeTakenCount(AddRec->
getLoop());
1105 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1106 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1111 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1116 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1121 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1126 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1127 return SE->isKnownNegative(LimitedBound);
1130bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1131 bool Inbounds =
false;
1133 Inbounds = SrcGEP->isInBounds();
1139 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1140 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1146 return SE->isKnownNonNegative(S);
1156const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1157 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1158 const SCEV *UB = SE->getBackedgeTakenCount(L);
1159 return SE->getTruncateOrZeroExtend(UB,
T);
1166const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1168 if (
const SCEV *UB = collectUpperBound(L,
T))
1183bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1184 FullDependence &Result)
const {
1198 Result.Consistent =
false;
1229bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1230 const SCEV *DstConst,
const Loop *CurLoop,
1231 unsigned Level, FullDependence &Result,
1232 Constraint &NewConstraint)
const {
1240 ++StrongSIVapplications;
1241 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1244 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1249 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1252 const SCEV *AbsDelta =
1253 SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
1254 const SCEV *AbsCoeff =
1255 SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
1256 const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
1259 ++StrongSIVindependence;
1260 ++StrongSIVsuccesses;
1269 APInt Distance = ConstDelta;
1270 APInt Remainder = ConstDelta;
1275 if (Remainder != 0) {
1277 ++StrongSIVindependence;
1278 ++StrongSIVsuccesses;
1281 Result.DV[
Level].Distance = SE->getConstant(Distance);
1282 NewConstraint.setDistance(SE->getConstant(Distance), CurLoop);
1283 if (Distance.
sgt(0))
1285 else if (Distance.
slt(0))
1289 ++StrongSIVsuccesses;
1290 }
else if (Delta->
isZero()) {
1293 NewConstraint.setDistance(Delta, CurLoop);
1295 ++StrongSIVsuccesses;
1297 if (Coeff->
isOne()) {
1300 NewConstraint.setDistance(Delta, CurLoop);
1302 Result.Consistent =
false;
1303 NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
1304 SE->getNegativeSCEV(Delta), CurLoop);
1308 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1309 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1310 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1311 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1312 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1317 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1318 (DeltaMaybeNegative && CoeffMaybeNegative))
1322 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1323 (DeltaMaybePositive && CoeffMaybeNegative))
1325 if (NewDirection <
Result.DV[Level].Direction)
1326 ++StrongSIVsuccesses;
1360bool DependenceInfo::weakCrossingSIVtest(
1361 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1362 const Loop *CurLoop,
unsigned Level, FullDependence &Result,
1363 Constraint &NewConstraint,
const SCEV *&SplitIter)
const {
1368 ++WeakCrossingSIVapplications;
1369 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1371 Result.Consistent =
false;
1372 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1374 NewConstraint.setLine(Coeff, Coeff, Delta, CurLoop);
1376 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1377 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1378 ++WeakCrossingSIVsuccesses;
1379 if (!
Result.DV[Level].Direction) {
1380 ++WeakCrossingSIVindependence;
1391 if (SE->isKnownNegative(ConstCoeff)) {
1394 "dynamic cast of negative of ConstCoeff should yield constant");
1395 Delta = SE->getNegativeSCEV(Delta);
1397 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1400 SplitIter = SE->getUDivExpr(
1401 SE->getSMaxExpr(SE->getZero(Delta->
getType()), Delta),
1402 SE->getMulExpr(SE->getConstant(Delta->
getType(), 2), ConstCoeff));
1413 if (SE->isKnownNegative(Delta)) {
1415 ++WeakCrossingSIVindependence;
1416 ++WeakCrossingSIVsuccesses;
1422 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1424 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1426 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1430 ++WeakCrossingSIVindependence;
1431 ++WeakCrossingSIVsuccesses;
1436 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1437 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1438 ++WeakCrossingSIVsuccesses;
1439 if (!
Result.DV[Level].Direction) {
1440 ++WeakCrossingSIVindependence;
1450 APInt APDelta = ConstDelta->
getAPInt();
1451 APInt APCoeff = ConstCoeff->
getAPInt();
1452 APInt Distance = APDelta;
1453 APInt Remainder = APDelta;
1456 if (Remainder != 0) {
1458 ++WeakCrossingSIVindependence;
1459 ++WeakCrossingSIVsuccesses;
1465 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1466 Remainder = Distance.
srem(Two);
1468 if (Remainder != 0) {
1470 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1471 ++WeakCrossingSIVsuccesses;
1488 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1489 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1497 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1498 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1505 X = AM.
slt(0) ? -A1 : A1;
1506 Y = BM.
slt(0) ? B1 : -B1;
1522 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1534 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1569static std::pair<std::optional<APInt>, std::optional<APInt>>
1571 const std::optional<APInt> &UB) {
1572 assert(
A != 0 &&
"A must be non-zero");
1573 std::optional<APInt> TL, TU;
1593 return std::make_pair(TL, TU);
1615bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1616 const SCEV *SrcConst,
const SCEV *DstConst,
1617 const Loop *CurLoop,
unsigned Level,
1618 FullDependence &Result,
1619 Constraint &NewConstraint)
const {
1621 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1622 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1625 ++ExactSIVapplications;
1626 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1628 Result.Consistent =
false;
1629 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1631 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
1636 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1641 APInt AM = ConstSrcCoeff->
getAPInt();
1642 APInt BM = ConstDstCoeff->
getAPInt();
1647 ++ExactSIVindependence;
1648 ++ExactSIVsuccesses;
1655 std::optional<APInt> UM;
1657 if (
const SCEVConstant *CUB =
1658 collectConstantUpperBound(CurLoop, Delta->
getType())) {
1659 UM = CUB->getAPInt();
1665 APInt TC = CM.
sdiv(
G);
1687 auto CreateVec = [](
const std::optional<APInt> &V0,
1688 const std::optional<APInt> &V1) {
1711 ++ExactSIVindependence;
1712 ++ExactSIVsuccesses;
1718 APInt LowerDistance, UpperDistance;
1720 LowerDistance = (TY - TX) + (TA - TB) * TL;
1721 UpperDistance = (TY - TX) + (TA - TB) * TU;
1723 LowerDistance = (TY - TX) + (TA - TB) * TU;
1724 UpperDistance = (TY - TX) + (TA - TB) * TL;
1727 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1728 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1730 APInt
Zero(Bits, 0,
true);
1731 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1733 ++ExactSIVsuccesses;
1735 if (LowerDistance.
slt(0)) {
1737 ++ExactSIVsuccesses;
1739 if (UpperDistance.
sgt(0)) {
1741 ++ExactSIVsuccesses;
1747 ++ExactSIVindependence;
1758 return ConstDividend.
srem(ConstDivisor) == 0;
1792bool DependenceInfo::weakZeroSrcSIVtest(
const SCEV *DstCoeff,
1793 const SCEV *SrcConst,
1794 const SCEV *DstConst,
1795 const Loop *CurLoop,
unsigned Level,
1796 FullDependence &Result,
1797 Constraint &NewConstraint)
const {
1805 ++WeakZeroSIVapplications;
1806 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1808 Result.Consistent =
false;
1809 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1810 NewConstraint.setLine(SE->getZero(Delta->
getType()), DstCoeff, Delta,
1814 if (Level < CommonLevels) {
1817 ++WeakZeroSIVsuccesses;
1824 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1825 ? SE->getNegativeSCEV(ConstCoeff)
1827 const SCEV *NewDelta =
1828 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1832 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1834 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1836 ++WeakZeroSIVindependence;
1837 ++WeakZeroSIVsuccesses;
1842 if (Level < CommonLevels) {
1845 ++WeakZeroSIVsuccesses;
1853 if (SE->isKnownNegative(NewDelta)) {
1855 ++WeakZeroSIVindependence;
1856 ++WeakZeroSIVsuccesses;
1863 ++WeakZeroSIVindependence;
1864 ++WeakZeroSIVsuccesses;
1901bool DependenceInfo::weakZeroDstSIVtest(
const SCEV *SrcCoeff,
1902 const SCEV *SrcConst,
1903 const SCEV *DstConst,
1904 const Loop *CurLoop,
unsigned Level,
1905 FullDependence &Result,
1906 Constraint &NewConstraint)
const {
1913 ++WeakZeroSIVapplications;
1914 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
1916 Result.Consistent =
false;
1917 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1918 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->
getType()), Delta,
1922 if (Level < CommonLevels) {
1925 ++WeakZeroSIVsuccesses;
1932 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1933 ? SE->getNegativeSCEV(ConstCoeff)
1935 const SCEV *NewDelta =
1936 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1940 if (
const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->
getType())) {
1942 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1944 ++WeakZeroSIVindependence;
1945 ++WeakZeroSIVsuccesses;
1950 if (Level < CommonLevels) {
1953 ++WeakZeroSIVsuccesses;
1961 if (SE->isKnownNegative(NewDelta)) {
1963 ++WeakZeroSIVindependence;
1964 ++WeakZeroSIVsuccesses;
1971 ++WeakZeroSIVindependence;
1972 ++WeakZeroSIVsuccesses;
1985bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1986 const SCEV *SrcConst,
const SCEV *DstConst,
1987 const Loop *SrcLoop,
const Loop *DstLoop,
1988 FullDependence &Result)
const {
1992 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1993 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1996 ++ExactRDIVapplications;
1997 Result.Consistent =
false;
1998 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2003 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2008 APInt AM = ConstSrcCoeff->
getAPInt();
2009 APInt BM = ConstDstCoeff->
getAPInt();
2014 ++ExactRDIVindependence;
2021 std::optional<APInt> SrcUM;
2023 if (
const SCEVConstant *UpperBound =
2024 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2025 SrcUM = UpperBound->getAPInt();
2029 std::optional<APInt> DstUM;
2031 if (
const SCEVConstant *UpperBound =
2032 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2033 DstUM = UpperBound->getAPInt();
2039 APInt TC = CM.
sdiv(
G);
2064 auto CreateVec = [](
const std::optional<APInt> &V0,
2065 const std::optional<APInt> &V1) {
2085 ++ExactRDIVindependence;
2131bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2132 const SCEV *C1,
const SCEV *C2,
2134 const Loop *Loop2)
const {
2137 ++SymbolicRDIVapplications;
2144 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2145 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2148 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2149 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2152 if (SE->isKnownNonNegative(A1)) {
2153 if (SE->isKnownNonNegative(A2)) {
2157 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2160 ++SymbolicRDIVindependence;
2166 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2169 ++SymbolicRDIVindependence;
2173 }
else if (SE->isKnownNonPositive(A2)) {
2177 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2178 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2179 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2180 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2182 ++SymbolicRDIVindependence;
2187 if (SE->isKnownNegative(C2_C1)) {
2188 ++SymbolicRDIVindependence;
2192 }
else if (SE->isKnownNonPositive(A1)) {
2193 if (SE->isKnownNonNegative(A2)) {
2197 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2198 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2199 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2200 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2202 ++SymbolicRDIVindependence;
2207 if (SE->isKnownPositive(C2_C1)) {
2208 ++SymbolicRDIVindependence;
2211 }
else if (SE->isKnownNonPositive(A2)) {
2215 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2218 ++SymbolicRDIVindependence;
2224 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2227 ++SymbolicRDIVindependence;
2244bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2245 FullDependence &Result, Constraint &NewConstraint,
2246 const SCEV *&SplitIter)
const {
2251 if (SrcAddRec && DstAddRec) {
2252 const SCEV *SrcConst = SrcAddRec->
getStart();
2253 const SCEV *DstConst = DstAddRec->
getStart();
2256 const Loop *CurLoop = SrcAddRec->
getLoop();
2258 "both loops in SIV should be same");
2259 Level = mapSrcLoop(CurLoop);
2261 if (SrcCoeff == DstCoeff)
2262 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop, Level,
2263 Result, NewConstraint);
2264 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2265 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2266 Level, Result, NewConstraint, SplitIter);
2268 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2269 Level, Result, NewConstraint);
2270 return disproven || gcdMIVtest(Src, Dst, Result) ||
2271 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2275 const SCEV *SrcConst = SrcAddRec->
getStart();
2277 const SCEV *DstConst = Dst;
2278 const Loop *CurLoop = SrcAddRec->
getLoop();
2279 Level = mapSrcLoop(CurLoop);
2280 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop, Level,
2281 Result, NewConstraint) ||
2282 gcdMIVtest(Src, Dst, Result);
2285 const SCEV *DstConst = DstAddRec->
getStart();
2287 const SCEV *SrcConst = Src;
2288 const Loop *CurLoop = DstAddRec->
getLoop();
2289 Level = mapDstLoop(CurLoop);
2290 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurLoop, Level,
2291 Result, NewConstraint) ||
2292 gcdMIVtest(Src, Dst, Result);
2311bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2312 FullDependence &Result)
const {
2319 const SCEV *SrcConst, *DstConst;
2320 const SCEV *SrcCoeff, *DstCoeff;
2321 const Loop *SrcLoop, *DstLoop;
2327 if (SrcAddRec && DstAddRec) {
2330 SrcLoop = SrcAddRec->
getLoop();
2333 DstLoop = DstAddRec->
getLoop();
2334 }
else if (SrcAddRec) {
2335 if (
const SCEVAddRecExpr *tmpAddRec =
2337 SrcConst = tmpAddRec->getStart();
2338 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2339 SrcLoop = tmpAddRec->getLoop();
2342 DstLoop = SrcAddRec->
getLoop();
2345 }
else if (DstAddRec) {
2346 if (
const SCEVAddRecExpr *tmpAddRec =
2348 DstConst = tmpAddRec->getStart();
2349 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2350 DstLoop = tmpAddRec->getLoop();
2353 SrcLoop = DstAddRec->
getLoop();
2358 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2360 gcdMIVtest(Src, Dst, Result) ||
2361 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2368bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2369 const SmallBitVector &
Loops,
2370 FullDependence &Result)
const {
2373 Result.Consistent =
false;
2374 return gcdMIVtest(Src, Dst, Result) ||
2375 banerjeeMIVtest(Src, Dst,
Loops, Result);
2386 return std::nullopt;
2389bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2390 const Loop *CurLoop,
2391 const SCEV *&CurLoopCoeff,
2392 APInt &RunningGCD)
const {
2395 if (RunningGCD == 1)
2400 assert(isLoopInvariant(Expr, CurLoop) &&
2401 "Expected loop invariant expression");
2408 if (AddRec->
getLoop() == CurLoop) {
2409 CurLoopCoeff = Step;
2423 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2444bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2445 FullDependence &Result)
const {
2450 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2457 const SCEV *Coefficients = Src;
2458 while (
const SCEVAddRecExpr *AddRec =
2469 const SCEV *SrcConst = Coefficients;
2476 while (
const SCEVAddRecExpr *AddRec =
2487 const SCEV *DstConst = Coefficients;
2490 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2495 for (
const SCEV *Operand : Sum->
operands()) {
2497 assert(!Constant &&
"Surprised to find multiple constants");
2514 if (ConstDelta == 0)
2518 APInt Remainder = ConstDelta.
srem(RunningGCD);
2519 if (Remainder != 0) {
2538 bool Improved =
false;
2540 while (
const SCEVAddRecExpr *AddRec =
2543 const Loop *CurLoop = AddRec->
getLoop();
2544 RunningGCD = ExtraGCD;
2546 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2548 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2549 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2552 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2562 if (RunningGCD != 0) {
2563 Remainder = ConstDelta.
srem(RunningGCD);
2565 if (Remainder != 0) {
2566 unsigned Level = mapSrcLoop(CurLoop);
2567 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2611bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2612 const SmallBitVector &
Loops,
2613 FullDependence &Result)
const {
2617 ++BanerjeeApplications;
2620 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2623 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2624 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2625 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2630 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2631 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2634 findBoundsALL(
A,
B, Bound, K);
2649 bool Disproved =
false;
2652 unsigned DepthExpanded = 0;
2654 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2656 bool Improved =
false;
2657 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2659 unsigned Old =
Result.DV[
K - 1].Direction;
2660 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2661 Improved |= Old !=
Result.DV[
K - 1].Direction;
2662 if (!
Result.DV[K - 1].Direction) {
2670 ++BanerjeeSuccesses;
2672 ++BanerjeeIndependence;
2676 ++BanerjeeIndependence;
2690unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2691 CoefficientInfo *
B, BoundInfo *Bound,
2692 const SmallBitVector &
Loops,
2693 unsigned &DepthExpanded,
2694 const SCEV *Delta)
const {
2700 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2701 "direction exploration is terminated.\n");
2702 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2708 if (Level > CommonLevels) {
2711 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2713 Bound[
K].DirSet |= Bound[
K].Direction;
2738 if (Level > DepthExpanded) {
2739 DepthExpanded =
Level;
2741 findBoundsLT(
A,
B, Bound, Level);
2742 findBoundsGT(
A,
B, Bound, Level);
2743 findBoundsEQ(
A,
B, Bound, Level);
2782 unsigned NewDeps = 0;
2786 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2791 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2796 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2802 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2807bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2808 BoundInfo *Bound,
const SCEV *Delta)
const {
2809 Bound[
Level].Direction = DirKind;
2810 if (
const SCEV *LowerBound = getLowerBound(Bound))
2813 if (
const SCEV *UpperBound = getUpperBound(Bound))
2834void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2835 BoundInfo *Bound,
unsigned K)
const {
2840 if (Bound[K].Iterations) {
2842 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2844 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2849 SE->getZero(
A[K].Coeff->
getType());
2852 SE->getZero(
A[K].Coeff->
getType());
2871void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2872 BoundInfo *Bound,
unsigned K)
const {
2877 if (Bound[K].Iterations) {
2878 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2879 const SCEV *NegativePart = getNegativePart(Delta);
2881 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2882 const SCEV *PositivePart = getPositivePart(Delta);
2884 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2888 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2889 const SCEV *NegativePart = getNegativePart(Delta);
2890 if (NegativePart->
isZero())
2892 const SCEV *PositivePart = getPositivePart(Delta);
2893 if (PositivePart->
isZero())
2911void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
2912 BoundInfo *Bound,
unsigned K)
const {
2917 if (Bound[K].Iterations) {
2918 const SCEV *Iter_1 = SE->getMinusSCEV(
2919 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2920 const SCEV *NegPart =
2921 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2923 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
2924 const SCEV *PosPart =
2925 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2927 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
2931 const SCEV *NegPart =
2932 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
2935 const SCEV *PosPart =
2936 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
2955void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
2956 BoundInfo *Bound,
unsigned K)
const {
2961 if (Bound[K].Iterations) {
2962 const SCEV *Iter_1 = SE->getMinusSCEV(
2963 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2964 const SCEV *NegPart =
2965 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2967 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
2968 const SCEV *PosPart =
2969 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2971 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
2975 const SCEV *NegPart =
2976 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
2979 const SCEV *PosPart =
2980 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
2987const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
2988 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
2992const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
2993 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
2999DependenceInfo::CoefficientInfo *
3000DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3001 const SCEV *&Constant)
const {
3002 const SCEV *
Zero = SE->getZero(Subscript->getType());
3003 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3004 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3006 CI[
K].PosPart =
Zero;
3007 CI[
K].NegPart =
Zero;
3008 CI[
K].Iterations =
nullptr;
3012 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3014 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3015 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3016 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3022 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3029 if (CI[K].Iterations)
3044const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3045 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3046 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3059const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3060 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3061 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3079const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3080 const Loop *TargetLoop)
const {
3083 return SE->getZero(Expr->
getType());
3084 if (AddRec->
getLoop() == TargetLoop)
3086 return findCoefficient(AddRec->
getStart(), TargetLoop);
3094const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3095 const Loop *TargetLoop)
const {
3099 if (AddRec->
getLoop() == TargetLoop)
3101 return SE->getAddRecExpr(zeroCoefficient(AddRec->
getStart(), TargetLoop),
3111const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3112 const Loop *TargetLoop,
3113 const SCEV *
Value)
const {
3116 return SE->getAddRecExpr(Expr,
Value, TargetLoop,
3118 if (AddRec->
getLoop() == TargetLoop) {
3125 if (SE->isLoopInvariant(AddRec, TargetLoop))
3127 return SE->getAddRecExpr(
3143bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3144 SmallBitVector &
Loops,
3145 SmallVectorImpl<Constraint> &Constraints,
3148 for (
unsigned LI :
Loops.set_bits()) {
3151 if (Constraints[LI].isDistance())
3152 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3153 else if (Constraints[LI].isLine())
3154 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3155 else if (Constraints[LI].isPoint())
3156 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3166bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3167 Constraint &CurConstraint,
3169 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3171 const SCEV *A_K = findCoefficient(Src, CurLoop);
3174 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3175 Src = SE->getMinusSCEV(Src, DA_K);
3176 Src = zeroCoefficient(Src, CurLoop);
3179 Dst = addToCoefficient(Dst, CurLoop, SE->getNegativeSCEV(A_K));
3181 if (!findCoefficient(Dst, CurLoop)->
isZero())
3191bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3192 Constraint &CurConstraint,
3194 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3195 const SCEV *
A = CurConstraint.getA();
3196 const SCEV *
B = CurConstraint.getB();
3197 const SCEV *
C = CurConstraint.getC();
3205 if (!Bconst || !Cconst)
3208 APInt Charlie = Cconst->
getAPInt();
3209 APInt CdivB = Charlie.
sdiv(Beta);
3210 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3211 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3212 Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
3213 Dst = zeroCoefficient(Dst, CurLoop);
3214 if (!findCoefficient(Src, CurLoop)->
isZero())
3216 }
else if (
B->isZero()) {
3219 if (!Aconst || !Cconst)
3222 APInt Charlie = Cconst->
getAPInt();
3223 APInt CdivA = Charlie.
sdiv(Alpha);
3224 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3225 const SCEV *A_K = findCoefficient(Src, CurLoop);
3226 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3227 Src = zeroCoefficient(Src, CurLoop);
3228 if (!findCoefficient(Dst, CurLoop)->
isZero())
3233 if (!Aconst || !Cconst)
3236 APInt Charlie = Cconst->
getAPInt();
3237 APInt CdivA = Charlie.
sdiv(Alpha);
3238 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3239 const SCEV *A_K = findCoefficient(Src, CurLoop);
3240 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3241 Src = zeroCoefficient(Src, CurLoop);
3242 Dst = addToCoefficient(Dst, CurLoop, A_K);
3243 if (!findCoefficient(Dst, CurLoop)->
isZero())
3247 const SCEV *A_K = findCoefficient(Src, CurLoop);
3248 Src = SE->getMulExpr(Src,
A);
3249 Dst = SE->getMulExpr(Dst,
A);
3250 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K,
C));
3251 Src = zeroCoefficient(Src, CurLoop);
3252 Dst = addToCoefficient(Dst, CurLoop, SE->getMulExpr(A_K,
B));
3253 if (!findCoefficient(Dst, CurLoop)->
isZero())
3264bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3265 Constraint &CurConstraint) {
3266 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3267 const SCEV *A_K = findCoefficient(Src, CurLoop);
3268 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3269 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3270 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3272 Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
3273 Src = zeroCoefficient(Src, CurLoop);
3276 Dst = zeroCoefficient(Dst, CurLoop);
3282void DependenceInfo::updateDirection(Dependence::DVEntry &Level,
3283 const Constraint &CurConstraint)
const {
3286 if (CurConstraint.isAny())
3288 else if (CurConstraint.isDistance()) {
3290 Level.Scalar =
false;
3291 Level.Distance = CurConstraint.getD();
3293 if (!SE->isKnownNonZero(
Level.Distance))
3295 if (!SE->isKnownNonPositive(
Level.Distance))
3297 if (!SE->isKnownNonNegative(
Level.Distance))
3299 Level.Direction &= NewDirection;
3300 }
else if (CurConstraint.isLine()) {
3301 Level.Scalar =
false;
3302 Level.Distance =
nullptr;
3304 }
else if (CurConstraint.isPoint()) {
3305 Level.Scalar =
false;
3306 Level.Distance =
nullptr;
3309 CurConstraint.getX()))
3313 CurConstraint.getX()))
3317 CurConstraint.getX()))
3320 Level.Direction &= NewDirection;
3329bool DependenceInfo::tryDelinearize(Instruction *Src, Instruction *Dst,
3330 SmallVectorImpl<Subscript> &Pair) {
3335 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3336 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3337 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3338 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3339 const SCEVUnknown *SrcBase =
3341 const SCEVUnknown *DstBase =
3344 if (!SrcBase || !DstBase || SrcBase != DstBase)
3349 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3350 SrcSubscripts, DstSubscripts) &&
3351 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3352 SrcSubscripts, DstSubscripts))
3355 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3356 isLoopInvariant(DstBase, DstLoop) &&
3357 "Expected SrcBase and DstBase to be loop invariant");
3361 dbgs() <<
"\nSrcSubscripts: ";
3362 for (
int I = 0;
I <
Size;
I++)
3363 dbgs() << *SrcSubscripts[
I];
3364 dbgs() <<
"\nDstSubscripts: ";
3365 for (
int I = 0;
I <
Size;
I++)
3366 dbgs() << *DstSubscripts[
I];
3374 for (
int I = 0;
I <
Size; ++
I) {
3375 Pair[
I].Src = SrcSubscripts[
I];
3376 Pair[
I].Dst = DstSubscripts[
I];
3377 unifySubscriptType(&Pair[
I]);
3386bool DependenceInfo::tryDelinearizeFixedSize(
3387 Instruction *Src, Instruction *Dst,
const SCEV *SrcAccessFn,
3388 const SCEV *DstAccessFn, SmallVectorImpl<const SCEV *> &SrcSubscripts,
3389 SmallVectorImpl<const SCEV *> &DstSubscripts) {
3391 const SCEVUnknown *SrcBase =
3393 const SCEVUnknown *DstBase =
3395 assert(SrcBase && DstBase && SrcBase == DstBase &&
3396 "expected src and dst scev unknowns to be equal");
3399 SmallVector<int, 4> SrcSizes;
3400 SmallVector<int, 4> DstSizes;
3409 if (SrcSizes.size() != DstSizes.
size() ||
3410 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3411 SrcSubscripts.
clear();
3412 DstSubscripts.
clear();
3417 "Expected equal number of entries in the list of SrcSubscripts and "
3430 auto AllIndicesInRange = [&](SmallVector<int, 4> &DimensionSizes,
3431 SmallVectorImpl<const SCEV *> &Subscripts,
3433 size_t SSize = Subscripts.
size();
3434 for (
size_t I = 1;
I < SSize; ++
I) {
3435 const SCEV *S = Subscripts[
I];
3436 if (!isKnownNonNegative(S,
Ptr)) {
3438 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3439 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *
Ptr <<
"\n";
3444 const SCEV *
Range = SE->getConstant(
3445 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3446 if (!isKnownLessThan(S,
Range)) {
3448 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3449 dbgs() <<
" S: " << *S <<
"\n"
3450 <<
" Range: " << *
Range <<
"\n";
3459 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3460 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3462 SrcSubscripts.
clear();
3463 DstSubscripts.
clear();
3468 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3469 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3470 <<
"DstGEP:" << *DstPtr <<
"\n";
3475bool DependenceInfo::tryDelinearizeParametricSize(
3476 Instruction *Src, Instruction *Dst,
const SCEV *SrcAccessFn,
3477 const SCEV *DstAccessFn, SmallVectorImpl<const SCEV *> &SrcSubscripts,
3478 SmallVectorImpl<const SCEV *> &DstSubscripts) {
3482 const SCEVUnknown *SrcBase =
3484 const SCEVUnknown *DstBase =
3486 assert(SrcBase && DstBase && SrcBase == DstBase &&
3487 "expected src and dst scev unknowns to be equal");
3489 const SCEV *ElementSize = SE->getElementSize(Src);
3490 if (ElementSize != SE->getElementSize(Dst))
3493 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3494 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3515 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3516 SrcSubscripts.
size() != DstSubscripts.
size())
3519 size_t Size = SrcSubscripts.
size();
3528 for (
size_t I = 1;
I <
Size; ++
I) {
3529 bool SNN = isKnownNonNegative(SrcSubscripts[
I], SrcPtr);
3530 bool DNN = isKnownNonNegative(DstSubscripts[
I], DstPtr);
3531 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
3532 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
3533 if (SNN && DNN && SLT && DLT)
3537 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
3539 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
3541 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
3543 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
3544 << *
Sizes[
I - 1] <<
")\n";
3546 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
3547 << *
Sizes[
I - 1] <<
")\n";
3561 for (
unsigned VI : BV.
set_bits()) {
3571 FunctionAnalysisManager::Invalidator &Inv) {
3578 return Inv.invalidate<
AAManager>(F, PA) ||
3598std::unique_ptr<Dependence>
3600 bool UnderRuntimeAssumptions) {
3602 bool PossiblyLoopIndependent =
true;
3604 PossiblyLoopIndependent =
false;
3606 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3612 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3613 return std::make_unique<Dependence>(Src, Dst,
3625 return std::make_unique<Dependence>(Src, Dst,
3639 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3640 return std::make_unique<Dependence>(Src, Dst,
3646 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3647 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3650 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3651 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3652 if (SrcBase != DstBase) {
3659 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3660 return std::make_unique<Dependence>(Src, Dst,
3668 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3669 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3670 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3671 !isLoopInvariant(DstBase, DstLoop)) {
3672 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3673 return std::make_unique<Dependence>(Src, Dst,
3678 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3679 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3682 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3683 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3684 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3685 return std::make_unique<Dependence>(Src, Dst,
3689 if (!Assume.empty()) {
3690 if (!UnderRuntimeAssumptions)
3691 return std::make_unique<Dependence>(Src, Dst,
3694 unsigned N = Assumptions.size();
3696 bool Implied =
false;
3697 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
3698 if (Assumptions[
I]->implies(
P, *SE))
3701 Assumptions.push_back(
P);
3705 establishNestingLevels(Src, Dst);
3706 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3707 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3710 PossiblyLoopIndependent, CommonLevels);
3715 Pair[0].Src = SrcEv;
3716 Pair[0].Dst = DstEv;
3719 if (tryDelinearize(Src, Dst, Pair)) {
3721 Pairs = Pair.
size();
3725 for (
unsigned P = 0;
P < Pairs; ++
P) {
3726 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3727 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3728 Pair[
P].Loops.
resize(MaxLevels + 1);
3729 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3731 removeMatchingExtensions(&Pair[
P]);
3732 Pair[
P].Classification =
3733 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3734 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3735 Pair[
P].GroupLoops = Pair[
P].Loops;
3736 Pair[
P].Group.set(
P);
3805 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3806 if (Pair[
SI].Classification == Subscript::NonLinear) {
3808 ++NonlinearSubscriptPairs;
3809 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3811 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3813 Result.Consistent =
false;
3814 }
else if (Pair[
SI].Classification == Subscript::ZIV) {
3820 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
3822 Intersection &= Pair[SJ].GroupLoops;
3823 if (Intersection.
any()) {
3825 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
3827 Pair[SJ].Group |= Pair[
SI].Group;
3832 if (Pair[
SI].Group.count() == 1) {
3834 ++SeparableSubscriptPairs;
3837 ++CoupledSubscriptPairs;
3848 Constraint NewConstraint;
3849 NewConstraint.setAny(SE);
3854 switch (Pair[
SI].Classification) {
3855 case Subscript::ZIV:
3857 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3860 case Subscript::SIV: {
3863 const SCEV *SplitIter =
nullptr;
3864 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
3869 case Subscript::RDIV:
3871 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
3874 case Subscript::MIV:
3876 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
3884 if (Coupled.
count()) {
3887 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
3889 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
3890 Constraints[
II].setAny(SE);
3898 for (
unsigned SJ : Group.set_bits()) {
3900 if (Pair[SJ].Classification == Subscript::SIV)
3906 unifySubscriptType(PairsInGroup);
3908 while (Sivs.
any()) {
3910 for (
unsigned SJ : Sivs.
set_bits()) {
3914 const SCEV *SplitIter =
nullptr;
3916 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
3919 ConstrainedLevels.
set(Level);
3920 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
3921 if (Constraints[Level].isEmpty()) {
3922 ++DeltaIndependence;
3934 for (
unsigned SJ : Mivs.
set_bits()) {
3937 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
3938 Constraints, Result.Consistent)) {
3940 ++DeltaPropagations;
3941 Pair[SJ].Classification = classifyPair(
3942 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
3943 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
3944 switch (Pair[SJ].Classification) {
3945 case Subscript::ZIV:
3947 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3951 case Subscript::SIV:
3955 case Subscript::RDIV:
3956 case Subscript::MIV:
3967 for (
unsigned SJ : Mivs.
set_bits()) {
3968 if (Pair[SJ].Classification == Subscript::RDIV) {
3970 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3980 for (
unsigned SJ : Mivs.
set_bits()) {
3981 if (Pair[SJ].Classification == Subscript::MIV) {
3983 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
3991 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
3992 if (SJ > CommonLevels)
3994 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
4003 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
4004 CompleteLoops |= Pair[
SI].
Loops;
4005 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
4006 if (CompleteLoops[
II])
4007 Result.DV[
II - 1].Scalar =
false;
4012 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
4014 if (Result.DV[
II - 1].Distance ==
nullptr)
4015 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
4017 assert(Result.DV[
II - 1].Distance->isZero() &&
4018 "Inconsistency between distance and direction");
4024 const SCEV *Distance = Result.getDistance(
II);
4025 if (Distance && Distance->
isZero())
4027 "Distance is zero, but direction is not EQ");
4031 if (PossiblyLoopIndependent) {
4035 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4037 Result.LoopIndependent =
false;
4044 bool AllEqual =
true;
4045 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4055 return std::make_unique<FullDependence>(std::move(Result));
4106 unsigned SplitLevel) {
4108 "Dep should be splitable at SplitLevel");
4111 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4112 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4122 establishNestingLevels(Src, Dst);
4124 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4128 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4129 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4130 Pair[0].Src = SE->removePointerBase(SrcSCEV);
4131 Pair[0].Dst = SE->removePointerBase(DstSCEV);
4134 if (tryDelinearize(Src, Dst, Pair)) {
4136 Pairs = Pair.
size();
4140 for (
unsigned P = 0;
P < Pairs; ++
P) {
4141 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4142 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4143 Pair[
P].Loops.
resize(MaxLevels + 1);
4144 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4146 removeMatchingExtensions(&Pair[
P]);
4147 Pair[
P].Classification =
4148 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4149 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4150 Pair[
P].GroupLoops = Pair[
P].Loops;
4151 Pair[
P].Group.set(
P);
4158 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4159 if (Pair[
SI].Classification == Subscript::NonLinear) {
4161 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4163 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4165 Result.Consistent =
false;
4166 }
else if (Pair[
SI].Classification == Subscript::ZIV)
4171 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4173 Intersection &= Pair[SJ].GroupLoops;
4174 if (Intersection.
any()) {
4176 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4178 Pair[SJ].Group |= Pair[
SI].Group;
4183 if (Pair[
SI].Group.count() == 1)
4191 Constraint NewConstraint;
4192 NewConstraint.setAny(SE);
4196 switch (Pair[
SI].Classification) {
4197 case Subscript::SIV: {
4199 const SCEV *SplitIter =
nullptr;
4200 (void)testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4202 if (Level == SplitLevel) {
4203 assert(SplitIter !=
nullptr);
4208 case Subscript::ZIV:
4209 case Subscript::RDIV:
4210 case Subscript::MIV:
4217 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4221 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4222 Constraints[
II].setAny(SE);
4228 for (
unsigned SJ : Group.set_bits()) {
4229 if (Pair[SJ].Classification == Subscript::SIV)
4234 while (Sivs.
any()) {
4236 for (
unsigned SJ : Sivs.
set_bits()) {
4239 const SCEV *SplitIter =
nullptr;
4240 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4242 if (Level == SplitLevel && SplitIter)
4244 ConstrainedLevels.
set(Level);
4245 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4252 for (
unsigned SJ : Mivs.
set_bits()) {
4254 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4257 Pair[SJ].Classification = classifyPair(
4258 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4259 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4260 switch (Pair[SJ].Classification) {
4261 case Subscript::ZIV:
4264 case Subscript::SIV:
4268 case Subscript::RDIV:
4269 case Subscript::MIV:
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define 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 cl::opt< bool > RunSIVRoutinesOnly("da-run-siv-routines-only", cl::init(false), cl::ReallyHidden, cl::desc("Run only SIV routines and disable others (ZIV, RDIV, and MIV). " "The purpose is mainly to exclude the influence of those routines " "in regression tests for SIV routines."))
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."))
Module.h This file contains the declarations for the Module class.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Loop::LoopBounds::Direction Direction
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static bool isInput(const ArrayRef< StringRef > &Prefixes, StringRef Arg)
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)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
static LLVM_ABI void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
APInt abs() const
Get the absolute value.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
bool sle(const APInt &RHS) const
Signed less or equal comparison.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
void enableCrossIterationMode()
Assume that values may come from different cycle iterations.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
DependenceAnalysisWrapperPass()
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
LLVM_ABI const SCEV * getSplitIteration(const Dependence &Dep, unsigned Level)
getSplitIteration - Give a dependence that's splittable at some particular level, return the iteratio...
LLVM_ABI SCEVUnionPredicate getRuntimeAssumptions() const
getRuntimeAssumptions - Returns all the runtime assumptions under which the dependence test is valid.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
Dependence - This class represents a dependence between two memory memory references in a function.
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.
Dependence(Dependence &&)=default
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.
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.
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.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
const SCEV * getStart() const
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
const SCEV * getOperand() const
This class represents a constant integer value.
const APInt & getAPInt() const
bool hasNoSignedWrap() const
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
const SCEV * getOperand(unsigned i) const
This class represents an assumption made using SCEV expressions which can be checked at run-time.
This class represents a composition of other SCEV predicates, and is the class that most clients will...
void print(raw_ostream &OS, unsigned Depth) const override
Prints a textual representation of this predicate with an indentation of Depth.
bool isAlwaysTrue() const override
Implementation of the SCEVPredicate interface.
This class represents an analyzed expression in the program.
LLVM_ABI ArrayRef< const SCEV * > operands() const
Return operands of this SCEV expression.
LLVM_ABI bool isOne() const
Return true if the expression is a constant one.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
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.
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.
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.
Abstract Attribute helper functions.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
LLVM_ABI APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
inst_iterator inst_begin(Function *F)
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Implementation of fixed size array delinearization.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool 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...