70#define DEBUG_TYPE "da"
76STATISTIC(SeparableSubscriptPairs,
"Separable subscript pairs");
77STATISTIC(CoupledSubscriptPairs,
"Coupled subscript pairs");
78STATISTIC(NonlinearSubscriptPairs,
"Nonlinear subscript pairs");
81STATISTIC(StrongSIVapplications,
"Strong SIV applications");
82STATISTIC(StrongSIVsuccesses,
"Strong SIV successes");
83STATISTIC(StrongSIVindependence,
"Strong SIV independence");
84STATISTIC(WeakCrossingSIVapplications,
"Weak-Crossing SIV applications");
85STATISTIC(WeakCrossingSIVsuccesses,
"Weak-Crossing SIV successes");
86STATISTIC(WeakCrossingSIVindependence,
"Weak-Crossing SIV independence");
87STATISTIC(ExactSIVapplications,
"Exact SIV applications");
89STATISTIC(ExactSIVindependence,
"Exact SIV independence");
90STATISTIC(WeakZeroSIVapplications,
"Weak-Zero SIV applications");
91STATISTIC(WeakZeroSIVsuccesses,
"Weak-Zero SIV successes");
92STATISTIC(WeakZeroSIVindependence,
"Weak-Zero SIV independence");
93STATISTIC(ExactRDIVapplications,
"Exact RDIV applications");
94STATISTIC(ExactRDIVindependence,
"Exact RDIV independence");
95STATISTIC(SymbolicRDIVapplications,
"Symbolic RDIV applications");
96STATISTIC(SymbolicRDIVindependence,
"Symbolic RDIV independence");
104STATISTIC(BanerjeeApplications,
"Banerjee applications");
105STATISTIC(BanerjeeIndependence,
"Banerjee independence");
107STATISTIC(SameSDLoopsCount,
"Loops with Same iteration Space and Depth");
111 cl::desc(
"Try to delinearize array references."));
113 "da-disable-delinearization-checks",
cl::Hidden,
115 "Disable checks that try to statically verify validity of "
116 "delinearized subscripts. Enabling this option may result in incorrect "
117 "dependence vectors for languages that allow the subscript of one "
118 "dimension to underflow or overflow into another dimension."));
122 cl::desc(
"Maximum depth allowed for the recursive algorithm used to "
123 "explore MIV direction vectors."));
127 cl::desc(
"Run only SIV routines and disable others (ZIV, RDIV, and MIV). "
128 "The purpose is mainly to exclude the influence of those routines "
129 "in regression tests for SIV routines."));
145 "Dependence Analysis",
true,
true)
186 auto *
F = DA->getFunction();
189 if (SrcI->mayReadOrWriteMemory()) {
192 if (DstI->mayReadOrWriteMemory()) {
193 OS <<
"Src:" << *SrcI <<
" --> Dst:" << *DstI <<
"\n";
194 OS <<
" da analyze - ";
195 if (
auto D = DA->depends(&*SrcI, &*DstI,
201 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
202 const SCEV *Distance =
D->getDistance(Level);
203 bool IsDistanceZero = Distance && Distance->
isZero();
206 assert(IsDistanceZero == IsDirectionEQ &&
207 "Inconsistent distance and direction.");
212 if (NormalizeResults &&
D->normalize(&SE))
213 OS <<
"normalized - ";
215 for (
unsigned Level = 1; Level <=
D->getLevels(); Level++) {
216 if (
D->isSplitable(Level)) {
217 OS <<
" da analyze - split level = " << Level;
218 OS <<
", iteration = " << *DA->getSplitIteration(*
D, Level);
230 OS <<
"Runtime Assumptions:\n";
231 Assumptions.
print(OS, 0);
243 OS <<
"Printing analysis 'Dependence Analysis' for function '" <<
F.getName()
256 return Src->mayReadFromMemory() &&
Dst->mayReadFromMemory();
261 return Src->mayWriteToMemory() &&
Dst->mayWriteToMemory();
266 return Src->mayWriteToMemory() &&
Dst->mayReadFromMemory();
271 return Src->mayReadFromMemory() &&
Dst->mayWriteToMemory();
285 bool PossiblyLoopIndependent,
286 unsigned CommonLevels)
287 :
Dependence(Source, Destination, Assumes), Levels(CommonLevels),
288 LoopIndependent(PossiblyLoopIndependent) {
292 DV = std::make_unique<
DVEntry[]>(CommonLevels);
311 for (
unsigned Level = 1; Level <= Levels; ++Level) {
312 unsigned char Direction = DV[Level - 1].Direction;
327 LLVM_DEBUG(
dbgs() <<
"Before normalizing negative direction vectors:\n";
330 for (
unsigned Level = 1; Level <= Levels; ++Level) {
331 unsigned char Direction = DV[Level - 1].Direction;
339 DV[Level - 1].Direction = RevDirection;
341 if (DV[Level - 1].Distance !=
nullptr)
345 LLVM_DEBUG(
dbgs() <<
"After normalizing negative direction vectors:\n";
392 assert(0 < Level && Level <=
static_cast<unsigned>(Levels) + SameSDLevels &&
393 "Level out of range");
394 return Level > Levels;
402const SCEV *DependenceInfo::Constraint::getX()
const {
403 assert(Kind == Point &&
"Kind should be Point");
409const SCEV *DependenceInfo::Constraint::getY()
const {
410 assert(Kind == Point &&
"Kind should be Point");
416const SCEV *DependenceInfo::Constraint::getA()
const {
417 assert((Kind == Line || Kind == Distance) &&
418 "Kind should be Line (or Distance)");
424const SCEV *DependenceInfo::Constraint::getB()
const {
425 assert((Kind == Line || Kind == Distance) &&
426 "Kind should be Line (or Distance)");
432const SCEV *DependenceInfo::Constraint::getC()
const {
433 assert((Kind == Line || Kind == Distance) &&
434 "Kind should be Line (or Distance)");
440const SCEV *DependenceInfo::Constraint::getD()
const {
441 assert(Kind == Distance &&
"Kind should be Distance");
442 return SE->getNegativeSCEV(
C);
446const Loop *DependenceInfo::Constraint::getAssociatedSrcLoop()
const {
447 assert((Kind == Distance || Kind == Line || Kind == Point) &&
448 "Kind should be Distance, Line, or Point");
449 return AssociatedSrcLoop;
453const Loop *DependenceInfo::Constraint::getAssociatedDstLoop()
const {
454 assert((Kind == Distance || Kind == Line || Kind == Point) &&
455 "Kind should be Distance, Line, or Point");
456 return AssociatedDstLoop;
459void DependenceInfo::Constraint::setPoint(
const SCEV *
X,
const SCEV *
Y,
460 const Loop *CurSrcLoop,
461 const Loop *CurDstLoop) {
465 AssociatedSrcLoop = CurSrcLoop;
466 AssociatedDstLoop = CurDstLoop;
469void DependenceInfo::Constraint::setLine(
const SCEV *AA,
const SCEV *BB,
470 const SCEV *CC,
const Loop *CurSrcLoop,
471 const Loop *CurDstLoop) {
476 AssociatedSrcLoop = CurSrcLoop;
477 AssociatedDstLoop = CurDstLoop;
480void DependenceInfo::Constraint::setDistance(
const SCEV *
D,
481 const Loop *CurSrcLoop,
482 const Loop *CurDstLoop) {
484 A = SE->getOne(
D->getType());
485 B = SE->getNegativeSCEV(
A);
486 C = SE->getNegativeSCEV(
D);
487 AssociatedSrcLoop = CurSrcLoop;
488 AssociatedDstLoop = CurDstLoop;
491void DependenceInfo::Constraint::setEmpty() {
Kind =
Empty; }
493void DependenceInfo::Constraint::setAny(ScalarEvolution *NewSE) {
498#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
500LLVM_DUMP_METHOD void DependenceInfo::Constraint::dump(raw_ostream &OS)
const {
506 OS <<
" Point is <" << *getX() <<
", " << *getY() <<
">\n";
507 else if (isDistance())
508 OS <<
" Distance is " << *getD() <<
" (" << *getA() <<
"*X + " << *getB()
509 <<
"*Y = " << *getC() <<
")\n";
511 OS <<
" Line is " << *getA() <<
"*X + " << *getB() <<
"*Y = " << *getC()
525bool DependenceInfo::intersectConstraints(Constraint *
X,
const Constraint *
Y) {
530 assert(!
Y->isPoint() &&
"Y must not be a Point");
544 if (
X->isDistance() &&
Y->isDistance()) {
568 assert(!(
X->isPoint() &&
Y->isPoint()) &&
569 "We shouldn't ever see X->isPoint() && Y->isPoint()");
571 if (
X->isLine() &&
Y->isLine()) {
573 const SCEV *Prod1 = SE->getMulExpr(
X->getA(),
Y->getB());
574 const SCEV *Prod2 = SE->getMulExpr(
X->getB(),
Y->getA());
578 Prod1 = SE->getMulExpr(
X->getC(),
Y->getB());
579 Prod2 = SE->getMulExpr(
X->getB(),
Y->getC());
592 const SCEV *C1B2 = SE->getMulExpr(
X->getC(),
Y->getB());
593 const SCEV *C1A2 = SE->getMulExpr(
X->getC(),
Y->getA());
594 const SCEV *C2B1 = SE->getMulExpr(
Y->getC(),
X->getB());
595 const SCEV *C2A1 = SE->getMulExpr(
Y->getC(),
X->getA());
596 const SCEV *A1B2 = SE->getMulExpr(
X->getA(),
Y->getB());
597 const SCEV *A2B1 = SE->getMulExpr(
Y->getA(),
X->getB());
598 const SCEVConstant *C1A2_C2A1 =
600 const SCEVConstant *C1B2_C2B1 =
602 const SCEVConstant *A1B2_A2B1 =
604 const SCEVConstant *A2B1_A1B2 =
606 if (!C1B2_C2B1 || !C1A2_C2A1 || !A1B2_A2B1 || !A2B1_A1B2)
622 if (Xr != 0 || Yr != 0) {
628 if (Xq.
slt(0) || Yq.
slt(0)) {
633 if (
const SCEVConstant *CUB = collectConstantUpperBound(
634 X->getAssociatedSrcLoop(), Prod1->
getType())) {
635 const APInt &UpperBound = CUB->getAPInt();
637 if (Xq.
sgt(UpperBound) || Yq.
sgt(UpperBound)) {
643 X->setPoint(SE->getConstant(Xq), SE->getConstant(Yq),
644 X->getAssociatedSrcLoop(),
X->getAssociatedDstLoop());
652 assert(!(
X->isLine() &&
Y->isPoint()) &&
"This case should never occur");
654 if (
X->isPoint() &&
Y->isLine()) {
656 const SCEV *A1X1 = SE->getMulExpr(
Y->getA(),
X->getX());
657 const SCEV *B1Y1 = SE->getMulExpr(
Y->getB(),
X->getY());
658 const SCEV *Sum = SE->getAddExpr(A1X1, B1Y1);
693 if (SameSDLevels > 0) {
694 OS <<
" / assuming " << SameSDLevels <<
" loop level(s) fused: ";
701 if (!Assumptions.isAlwaysTrue()) {
702 OS <<
" Runtime Assumptions:\n";
703 Assumptions.print(OS, 2);
710 bool Splitable =
false;
713 bool OnSameSD =
false;
714 unsigned LevelNum = Levels;
716 LevelNum += SameSDLevels;
718 for (
unsigned II = 1;
II <= LevelNum; ++
II) {
797 return LI->isUnordered();
799 return SI->isUnordered();
807bool DependenceInfo::haveSameSD(
const Loop *SrcLoop,
808 const Loop *DstLoop)
const {
809 if (SrcLoop == DstLoop)
819 const SCEV *SrcUB =
nullptr, *DstUP =
nullptr;
820 if (SE->hasLoopInvariantBackedgeTakenCount(SrcLoop))
821 SrcUB = SE->getBackedgeTakenCount(SrcLoop);
822 if (SE->hasLoopInvariantBackedgeTakenCount(DstLoop))
823 DstUP = SE->getBackedgeTakenCount(DstLoop);
825 if (SrcUB !=
nullptr && DstUP !=
nullptr &&
894void DependenceInfo::establishNestingLevels(
const Instruction *Src,
895 const Instruction *Dst) {
896 const BasicBlock *SrcBlock = Src->getParent();
897 const BasicBlock *DstBlock = Dst->getParent();
898 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
899 unsigned DstLevel = LI->getLoopDepth(DstBlock);
900 const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
901 const Loop *DstLoop = LI->getLoopFor(DstBlock);
902 SrcLevels = SrcLevel;
903 MaxLevels = SrcLevel + DstLevel;
905 while (SrcLevel > DstLevel) {
909 while (DstLevel > SrcLevel) {
915 while (SrcLoop != DstLoop) {
917 if (!haveSameSD(SrcLoop, DstLoop))
923 CommonLevels = SrcLevel;
924 MaxLevels -= CommonLevels;
929unsigned DependenceInfo::mapSrcLoop(
const Loop *SrcLoop)
const {
935unsigned DependenceInfo::mapDstLoop(
const Loop *DstLoop)
const {
937 if (
D > CommonLevels)
940 return D - CommonLevels + SrcLevels;
946bool DependenceInfo::isLoopInvariant(
const SCEV *Expression,
947 const Loop *LoopNest)
const {
962void DependenceInfo::collectCommonLoops(
const SCEV *Expression,
963 const Loop *LoopNest,
964 SmallBitVector &
Loops)
const {
967 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
975 unsigned widestWidthSeen = 0;
980 for (Subscript *Pair : Pairs) {
981 const SCEV *Src = Pair->Src;
982 const SCEV *Dst = Pair->Dst;
985 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
987 "This function only unify integer types and "
988 "expect Src and Dst share the same type otherwise.");
1001 assert(widestWidthSeen > 0);
1004 for (Subscript *Pair : Pairs) {
1005 const SCEV *Src = Pair->Src;
1006 const SCEV *Dst = Pair->Dst;
1009 if (SrcTy ==
nullptr || DstTy ==
nullptr) {
1011 "This function only unify integer types and "
1012 "expect Src and Dst share the same type otherwise.");
1017 Pair->Src = SE->getSignExtendExpr(Src, widestType);
1020 Pair->Dst = SE->getSignExtendExpr(Dst, widestType);
1029void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
1030 const SCEV *Src = Pair->Src;
1031 const SCEV *Dst = Pair->Dst;
1036 const SCEV *SrcCastOp = SrcCast->
getOperand();
1037 const SCEV *DstCastOp = DstCast->
getOperand();
1039 Pair->Src = SrcCastOp;
1040 Pair->Dst = DstCastOp;
1047bool DependenceInfo::checkSubscript(
const SCEV *Expr,
const Loop *LoopNest,
1048 SmallBitVector &
Loops,
bool IsSrc) {
1051 return isLoopInvariant(Expr, LoopNest);
1058 const Loop *
L = LoopNest;
1059 while (L && AddRec->
getLoop() != L)
1060 L =
L->getParentLoop();
1066 if (!isLoopInvariant(Step, LoopNest))
1072 return checkSubscript(Start, LoopNest,
Loops, IsSrc);
1077bool DependenceInfo::checkSrcSubscript(
const SCEV *Src,
const Loop *LoopNest,
1078 SmallBitVector &
Loops) {
1079 return checkSubscript(Src, LoopNest,
Loops,
true);
1084bool DependenceInfo::checkDstSubscript(
const SCEV *Dst,
const Loop *LoopNest,
1085 SmallBitVector &
Loops) {
1086 return checkSubscript(Dst, LoopNest,
Loops,
false);
1092DependenceInfo::Subscript::ClassificationKind
1093DependenceInfo::classifyPair(
const SCEV *Src,
const Loop *SrcLoopNest,
1094 const SCEV *Dst,
const Loop *DstLoopNest,
1095 SmallBitVector &
Loops) {
1096 SmallBitVector SrcLoops(MaxLevels + 1);
1097 SmallBitVector DstLoops(MaxLevels + 1);
1098 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1099 return Subscript::NonLinear;
1100 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1101 return Subscript::NonLinear;
1104 unsigned N =
Loops.count();
1106 return Subscript::ZIV;
1108 return Subscript::SIV;
1109 if (
N == 2 && (SrcLoops.count() == 0 || DstLoops.count() == 0 ||
1110 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1111 return Subscript::RDIV;
1112 return Subscript::MIV;
1126 const SCEV *
Y)
const {
1140 if (SE->isKnownPredicate(Pred,
X,
Y))
1147 const SCEV *Delta = SE->getMinusSCEV(
X,
Y);
1152 return SE->isKnownNonZero(Delta);
1154 return SE->isKnownNonNegative(Delta);
1156 return SE->isKnownNonPositive(Delta);
1158 return SE->isKnownPositive(Delta);
1160 return SE->isKnownNegative(Delta);
1172bool DependenceInfo::isKnownLessThan(
const SCEV *S,
const SCEV *
Size)
const {
1176 if (!SType || !SizeType)
1179 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1180 S = SE->getTruncateOrZeroExtend(S, MaxType);
1181 Size = SE->getTruncateOrZeroExtend(
Size, MaxType);
1183 auto CheckAddRecBECount = [&]() {
1187 const SCEV *BECount = collectUpperBound(AddRec->
getLoop(), MaxType);
1194 const SCEV *Diff0 = SE->getMinusSCEV(Start,
Size);
1195 const SCEV *Diff1 = SE->getMinusSCEV(End,
Size);
1200 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
1205 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
1210 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
1216 if (CheckAddRecBECount())
1220 const SCEV *LimitedBound = SE->getMinusSCEV(S,
Size);
1221 return SE->isKnownNegative(LimitedBound);
1224bool DependenceInfo::isKnownNonNegative(
const SCEV *S,
const Value *
Ptr)
const {
1225 bool Inbounds =
false;
1227 Inbounds = SrcGEP->isInBounds();
1233 if (SE->isKnownNonNegative(AddRec->
getStart()) &&
1234 SE->isKnownNonNegative(AddRec->
getOperand(1)))
1240 return SE->isKnownNonNegative(S);
1250const SCEV *DependenceInfo::collectUpperBound(
const Loop *L,
Type *
T)
const {
1251 if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1252 const SCEV *UB = SE->getBackedgeTakenCount(L);
1253 return SE->getTruncateOrZeroExtend(UB,
T);
1260const SCEVConstant *DependenceInfo::collectConstantUpperBound(
const Loop *L,
1262 if (
const SCEV *UB = collectUpperBound(L,
T))
1286bool DependenceInfo::testZIV(
const SCEV *Src,
const SCEV *Dst,
1287 FullDependence &Result)
const {
1301 Result.Consistent =
false;
1332bool DependenceInfo::strongSIVtest(
const SCEV *Coeff,
const SCEV *SrcConst,
1333 const SCEV *DstConst,
const Loop *CurSrcLoop,
1334 const Loop *CurDstLoop,
unsigned Level,
1335 FullDependence &Result,
1336 Constraint &NewConstraint)
const {
1344 ++StrongSIVapplications;
1345 assert(0 < Level && Level <= CommonLevels &&
"level out of range");
1348 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1353 if (
const SCEV *UpperBound =
1354 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1357 const SCEV *AbsDelta =
1358 SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
1359 const SCEV *AbsCoeff =
1360 SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
1361 const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
1364 ++StrongSIVindependence;
1365 ++StrongSIVsuccesses;
1374 APInt Distance = ConstDelta;
1375 APInt Remainder = ConstDelta;
1380 if (Remainder != 0) {
1382 ++StrongSIVindependence;
1383 ++StrongSIVsuccesses;
1386 Result.DV[
Level].Distance = SE->getConstant(Distance);
1387 NewConstraint.setDistance(SE->getConstant(Distance), CurSrcLoop,
1389 if (Distance.
sgt(0))
1391 else if (Distance.
slt(0))
1395 ++StrongSIVsuccesses;
1396 }
else if (Delta->
isZero()) {
1399 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1401 ++StrongSIVsuccesses;
1403 if (Coeff->
isOne()) {
1406 NewConstraint.setDistance(Delta, CurSrcLoop, CurDstLoop);
1408 Result.Consistent =
false;
1409 NewConstraint.setLine(Coeff, SE->getNegativeSCEV(Coeff),
1410 SE->getNegativeSCEV(Delta), CurSrcLoop, CurDstLoop);
1414 bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
1415 bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
1416 bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
1417 bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
1418 bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
1423 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1424 (DeltaMaybeNegative && CoeffMaybeNegative))
1428 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1429 (DeltaMaybePositive && CoeffMaybeNegative))
1431 if (NewDirection <
Result.DV[Level].Direction)
1432 ++StrongSIVsuccesses;
1466bool DependenceInfo::weakCrossingSIVtest(
1467 const SCEV *Coeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1468 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
1469 FullDependence &Result, Constraint &NewConstraint,
1470 const SCEV *&SplitIter)
const {
1475 ++WeakCrossingSIVapplications;
1476 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1478 Result.Consistent =
false;
1479 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
1481 NewConstraint.setLine(Coeff, Coeff, Delta, CurSrcLoop, CurDstLoop);
1483 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1484 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1485 ++WeakCrossingSIVsuccesses;
1486 if (!
Result.DV[Level].Direction) {
1487 ++WeakCrossingSIVindependence;
1498 if (SE->isKnownNegative(ConstCoeff)) {
1501 "dynamic cast of negative of ConstCoeff should yield constant");
1502 Delta = SE->getNegativeSCEV(Delta);
1504 assert(SE->isKnownPositive(ConstCoeff) &&
"ConstCoeff should be positive");
1507 SplitIter = SE->getUDivExpr(
1508 SE->getSMaxExpr(SE->getZero(Delta->
getType()), Delta),
1509 SE->getMulExpr(SE->getConstant(Delta->
getType(), 2), ConstCoeff));
1520 if (SE->isKnownNegative(Delta)) {
1522 ++WeakCrossingSIVindependence;
1523 ++WeakCrossingSIVsuccesses;
1529 if (
const SCEV *UpperBound =
1530 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1532 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1534 SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
1538 ++WeakCrossingSIVindependence;
1539 ++WeakCrossingSIVsuccesses;
1544 Result.DV[
Level].Direction &= ~Dependence::DVEntry::LT;
1545 Result.DV[
Level].Direction &= ~Dependence::DVEntry::GT;
1546 ++WeakCrossingSIVsuccesses;
1547 if (!
Result.DV[Level].Direction) {
1548 ++WeakCrossingSIVindependence;
1558 APInt APDelta = ConstDelta->
getAPInt();
1559 APInt APCoeff = ConstCoeff->
getAPInt();
1560 APInt Distance = APDelta;
1561 APInt Remainder = APDelta;
1564 if (Remainder != 0) {
1566 ++WeakCrossingSIVindependence;
1567 ++WeakCrossingSIVsuccesses;
1573 APInt Two = APInt(Distance.
getBitWidth(), 2,
true);
1574 Remainder = Distance.
srem(Two);
1576 if (Remainder != 0) {
1578 Result.DV[
Level].Direction &= ~Dependence::DVEntry::EQ;
1579 ++WeakCrossingSIVsuccesses;
1596 APInt A0(Bits, 1,
true), A1(Bits, 0,
true);
1597 APInt B0(Bits, 0,
true), B1(Bits, 1,
true);
1605 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1606 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1613 X = AM.
slt(0) ? -A1 : A1;
1614 Y = BM.
slt(0) ? B1 : -B1;
1630 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1642 if ((
A.sgt(0) &&
B.sgt(0)) || (
A.slt(0) &&
B.slt(0)))
1677static std::pair<std::optional<APInt>, std::optional<APInt>>
1679 const std::optional<APInt> &UB) {
1680 assert(
A != 0 &&
"A must be non-zero");
1681 std::optional<APInt> TL, TU;
1701 return std::make_pair(TL, TU);
1723bool DependenceInfo::exactSIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
1724 const SCEV *SrcConst,
const SCEV *DstConst,
1725 const Loop *CurSrcLoop,
1726 const Loop *CurDstLoop,
unsigned Level,
1727 FullDependence &Result,
1728 Constraint &NewConstraint)
const {
1730 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
1731 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
1734 ++ExactSIVapplications;
1735 assert(0 < Level && Level <= CommonLevels &&
"Level out of range");
1737 Result.Consistent =
false;
1742 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
1743 CurSrcLoop, CurDstLoop);
1747 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1752 APInt AM = ConstSrcCoeff->
getAPInt();
1753 APInt BM = ConstDstCoeff->
getAPInt();
1758 ++ExactSIVindependence;
1759 ++ExactSIVsuccesses;
1766 std::optional<APInt> UM;
1768 if (
const SCEVConstant *CUB =
1769 collectConstantUpperBound(CurSrcLoop, Delta->
getType())) {
1770 UM = CUB->getAPInt();
1776 APInt TC = CM.
sdiv(
G);
1798 auto CreateVec = [](
const std::optional<APInt> &V0,
1799 const std::optional<APInt> &V1) {
1822 ++ExactSIVindependence;
1823 ++ExactSIVsuccesses;
1829 APInt LowerDistance, UpperDistance;
1832 LowerDistance = (TY - TX) + (TA - TB) * TL;
1833 UpperDistance = (TY - TX) + (TA - TB) * TU;
1835 LowerDistance = (TY - TX) + (TA - TB) * TU;
1836 UpperDistance = (TY - TX) + (TA - TB) * TL;
1839 LLVM_DEBUG(
dbgs() <<
"\t LowerDistance = " << LowerDistance <<
"\n");
1840 LLVM_DEBUG(
dbgs() <<
"\t UpperDistance = " << UpperDistance <<
"\n");
1842 APInt
Zero(Bits, 0,
true);
1843 if (LowerDistance.
sle(Zero) && UpperDistance.
sge(Zero)) {
1845 ++ExactSIVsuccesses;
1847 if (LowerDistance.
slt(0)) {
1849 ++ExactSIVsuccesses;
1851 if (UpperDistance.
sgt(0)) {
1853 ++ExactSIVsuccesses;
1859 ++ExactSIVindependence;
1870 return ConstDividend.
srem(ConstDivisor) == 0;
1904bool DependenceInfo::weakZeroSrcSIVtest(
1905 const SCEV *DstCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
1906 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
1907 FullDependence &Result, Constraint &NewConstraint)
const {
1915 ++WeakZeroSIVapplications;
1916 assert(0 < Level && Level <= MaxLevels &&
"Level out of range");
1918 Result.Consistent =
false;
1919 const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
1920 NewConstraint.setLine(SE->getZero(Delta->
getType()), DstCoeff, Delta,
1921 CurSrcLoop, CurDstLoop);
1924 if (Level < CommonLevels) {
1927 ++WeakZeroSIVsuccesses;
1934 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
1935 ? SE->getNegativeSCEV(ConstCoeff)
1937 const SCEV *NewDelta =
1938 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
1942 if (
const SCEV *UpperBound =
1943 collectUpperBound(CurSrcLoop, Delta->
getType())) {
1945 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1947 ++WeakZeroSIVindependence;
1948 ++WeakZeroSIVsuccesses;
1953 if (Level < CommonLevels) {
1956 ++WeakZeroSIVsuccesses;
1964 if (SE->isKnownNegative(NewDelta)) {
1966 ++WeakZeroSIVindependence;
1967 ++WeakZeroSIVsuccesses;
1974 ++WeakZeroSIVindependence;
1975 ++WeakZeroSIVsuccesses;
2012bool DependenceInfo::weakZeroDstSIVtest(
2013 const SCEV *SrcCoeff,
const SCEV *SrcConst,
const SCEV *DstConst,
2014 const Loop *CurSrcLoop,
const Loop *CurDstLoop,
unsigned Level,
2015 FullDependence &Result, Constraint &NewConstraint)
const {
2022 ++WeakZeroSIVapplications;
2023 assert(0 < Level && Level <= SrcLevels &&
"Level out of range");
2025 Result.Consistent =
false;
2026 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2027 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->
getType()), Delta,
2028 CurSrcLoop, CurDstLoop);
2031 if (Level < CommonLevels) {
2034 ++WeakZeroSIVsuccesses;
2041 const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
2042 ? SE->getNegativeSCEV(ConstCoeff)
2044 const SCEV *NewDelta =
2045 SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
2049 if (
const SCEV *UpperBound =
2050 collectUpperBound(CurSrcLoop, Delta->
getType())) {
2052 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
2054 ++WeakZeroSIVindependence;
2055 ++WeakZeroSIVsuccesses;
2060 if (Level < CommonLevels) {
2063 ++WeakZeroSIVsuccesses;
2071 if (SE->isKnownNegative(NewDelta)) {
2073 ++WeakZeroSIVindependence;
2074 ++WeakZeroSIVsuccesses;
2081 ++WeakZeroSIVindependence;
2082 ++WeakZeroSIVsuccesses;
2095bool DependenceInfo::exactRDIVtest(
const SCEV *SrcCoeff,
const SCEV *DstCoeff,
2096 const SCEV *SrcConst,
const SCEV *DstConst,
2097 const Loop *SrcLoop,
const Loop *DstLoop,
2098 FullDependence &Result)
const {
2102 LLVM_DEBUG(
dbgs() <<
"\t SrcCoeff = " << *SrcCoeff <<
" = AM\n");
2103 LLVM_DEBUG(
dbgs() <<
"\t DstCoeff = " << *DstCoeff <<
" = BM\n");
2106 ++ExactRDIVapplications;
2107 Result.Consistent =
false;
2108 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2113 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
2118 APInt AM = ConstSrcCoeff->
getAPInt();
2119 APInt BM = ConstDstCoeff->
getAPInt();
2124 ++ExactRDIVindependence;
2131 std::optional<APInt> SrcUM;
2133 if (
const SCEVConstant *UpperBound =
2134 collectConstantUpperBound(SrcLoop, Delta->
getType())) {
2135 SrcUM = UpperBound->getAPInt();
2139 std::optional<APInt> DstUM;
2141 if (
const SCEVConstant *UpperBound =
2142 collectConstantUpperBound(DstLoop, Delta->
getType())) {
2143 DstUM = UpperBound->getAPInt();
2149 APInt TC = CM.
sdiv(
G);
2174 auto CreateVec = [](
const std::optional<APInt> &V0,
2175 const std::optional<APInt> &V1) {
2195 ++ExactRDIVindependence;
2241bool DependenceInfo::symbolicRDIVtest(
const SCEV *A1,
const SCEV *A2,
2242 const SCEV *C1,
const SCEV *C2,
2244 const Loop *Loop2)
const {
2247 ++SymbolicRDIVapplications;
2254 const SCEV *N1 = collectUpperBound(Loop1, A1->
getType());
2255 const SCEV *N2 = collectUpperBound(Loop2, A1->
getType());
2258 const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
2259 const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
2262 if (SE->isKnownNonNegative(A1)) {
2263 if (SE->isKnownNonNegative(A2)) {
2267 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2270 ++SymbolicRDIVindependence;
2276 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2279 ++SymbolicRDIVindependence;
2283 }
else if (SE->isKnownNonPositive(A2)) {
2287 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2288 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2289 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2290 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2292 ++SymbolicRDIVindependence;
2297 if (SE->isKnownNegative(C2_C1)) {
2298 ++SymbolicRDIVindependence;
2302 }
else if (SE->isKnownNonPositive(A1)) {
2303 if (SE->isKnownNonNegative(A2)) {
2307 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2308 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2309 const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
2310 LLVM_DEBUG(
dbgs() <<
"\t A1*N1 - A2*N2 = " << *A1N1_A2N2 <<
"\n");
2312 ++SymbolicRDIVindependence;
2317 if (SE->isKnownPositive(C2_C1)) {
2318 ++SymbolicRDIVindependence;
2321 }
else if (SE->isKnownNonPositive(A2)) {
2325 const SCEV *A1N1 = SE->getMulExpr(A1, N1);
2328 ++SymbolicRDIVindependence;
2334 const SCEV *A2N2 = SE->getMulExpr(A2, N2);
2337 ++SymbolicRDIVindependence;
2354bool DependenceInfo::testSIV(
const SCEV *Src,
const SCEV *Dst,
unsigned &Level,
2355 FullDependence &Result, Constraint &NewConstraint,
2356 const SCEV *&SplitIter)
const {
2361 if (SrcAddRec && DstAddRec) {
2362 const SCEV *SrcConst = SrcAddRec->
getStart();
2363 const SCEV *DstConst = DstAddRec->
getStart();
2366 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2367 const Loop *CurDstLoop = DstAddRec->
getLoop();
2368 assert(haveSameSD(CurSrcLoop, CurDstLoop) &&
2369 "Loops in the SIV test should have the same iteration space and "
2371 Level = mapSrcLoop(CurSrcLoop);
2373 if (SrcCoeff == DstCoeff)
2374 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2375 CurDstLoop, Level, Result, NewConstraint);
2376 else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
2377 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2378 CurDstLoop, Level, Result, NewConstraint,
2382 exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2383 CurDstLoop, Level, Result, NewConstraint);
2384 return disproven || gcdMIVtest(Src, Dst, Result) ||
2385 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurSrcLoop,
2389 const SCEV *SrcConst = SrcAddRec->
getStart();
2391 const SCEV *DstConst = Dst;
2392 const Loop *CurSrcLoop = SrcAddRec->
getLoop();
2393 Level = mapSrcLoop(CurSrcLoop);
2394 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
2395 CurSrcLoop, Level, Result, NewConstraint) ||
2396 gcdMIVtest(Src, Dst, Result);
2399 const SCEV *DstConst = DstAddRec->
getStart();
2401 const SCEV *SrcConst = Src;
2402 const Loop *CurDstLoop = DstAddRec->
getLoop();
2403 Level = mapDstLoop(CurDstLoop);
2404 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
2405 CurDstLoop, Level, Result, NewConstraint) ||
2406 gcdMIVtest(Src, Dst, Result);
2425bool DependenceInfo::testRDIV(
const SCEV *Src,
const SCEV *Dst,
2426 FullDependence &Result)
const {
2433 const SCEV *SrcConst, *DstConst;
2434 const SCEV *SrcCoeff, *DstCoeff;
2435 const Loop *SrcLoop, *DstLoop;
2441 if (SrcAddRec && DstAddRec) {
2444 SrcLoop = SrcAddRec->
getLoop();
2447 DstLoop = DstAddRec->
getLoop();
2448 }
else if (SrcAddRec) {
2449 if (
const SCEVAddRecExpr *tmpAddRec =
2451 SrcConst = tmpAddRec->getStart();
2452 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2453 SrcLoop = tmpAddRec->getLoop();
2456 DstLoop = SrcAddRec->
getLoop();
2459 }
else if (DstAddRec) {
2460 if (
const SCEVAddRecExpr *tmpAddRec =
2462 DstConst = tmpAddRec->getStart();
2463 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2464 DstLoop = tmpAddRec->getLoop();
2467 SrcLoop = DstAddRec->
getLoop();
2472 return exactRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop, DstLoop,
2474 gcdMIVtest(Src, Dst, Result) ||
2475 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, SrcLoop,
2482bool DependenceInfo::testMIV(
const SCEV *Src,
const SCEV *Dst,
2483 const SmallBitVector &
Loops,
2484 FullDependence &Result)
const {
2487 Result.Consistent =
false;
2488 return gcdMIVtest(Src, Dst, Result) ||
2489 banerjeeMIVtest(Src, Dst,
Loops, Result);
2500 return std::nullopt;
2503bool DependenceInfo::accumulateCoefficientsGCD(
const SCEV *Expr,
2504 const Loop *CurLoop,
2505 const SCEV *&CurLoopCoeff,
2506 APInt &RunningGCD)
const {
2509 if (RunningGCD == 1)
2514 assert(isLoopInvariant(Expr, CurLoop) &&
2515 "Expected loop invariant expression");
2522 if (AddRec->
getLoop() == CurLoop) {
2523 CurLoopCoeff = Step;
2537 return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
2558bool DependenceInfo::gcdMIVtest(
const SCEV *Src,
const SCEV *Dst,
2559 FullDependence &Result)
const {
2564 unsigned BitWidth = SE->getTypeSizeInBits(Src->getType());
2571 const SCEV *Coefficients = Src;
2572 while (
const SCEVAddRecExpr *AddRec =
2583 const SCEV *SrcConst = Coefficients;
2590 while (
const SCEVAddRecExpr *AddRec =
2601 const SCEV *DstConst = Coefficients;
2604 const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
2609 for (
const SCEV *Operand : Sum->
operands()) {
2611 assert(!Constant &&
"Surprised to find multiple constants");
2628 if (ConstDelta == 0)
2632 APInt Remainder = ConstDelta.
srem(RunningGCD);
2633 if (Remainder != 0) {
2652 bool Improved =
false;
2654 while (
const SCEVAddRecExpr *AddRec =
2657 const Loop *CurLoop = AddRec->
getLoop();
2658 RunningGCD = ExtraGCD;
2660 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2662 if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
2663 !accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
2666 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2676 if (RunningGCD != 0) {
2677 Remainder = ConstDelta.
srem(RunningGCD);
2679 if (Remainder != 0) {
2680 unsigned Level = mapSrcLoop(CurLoop);
2681 Result.DV[
Level - 1].Direction &= ~Dependence::DVEntry::EQ;
2725bool DependenceInfo::banerjeeMIVtest(
const SCEV *Src,
const SCEV *Dst,
2726 const SmallBitVector &
Loops,
2727 FullDependence &Result)
const {
2731 ++BanerjeeApplications;
2734 CoefficientInfo *
A = collectCoeffInfo(Src,
true, A0);
2737 CoefficientInfo *
B = collectCoeffInfo(Dst,
false, B0);
2738 BoundInfo *Bound =
new BoundInfo[MaxLevels + 1];
2739 const SCEV *Delta = SE->getMinusSCEV(B0, A0);
2744 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
2745 Bound[
K].Iterations =
A[
K].Iterations ?
A[
K].Iterations :
B[
K].Iterations;
2748 findBoundsALL(
A,
B, Bound, K);
2763 bool Disproved =
false;
2766 unsigned DepthExpanded = 0;
2768 exploreDirections(1,
A,
B, Bound,
Loops, DepthExpanded, Delta);
2770 bool Improved =
false;
2771 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2773 unsigned Old =
Result.DV[
K - 1].Direction;
2774 Result.DV[
K - 1].Direction = Old & Bound[
K].DirSet;
2775 Improved |= Old !=
Result.DV[
K - 1].Direction;
2776 if (!
Result.DV[K - 1].Direction) {
2784 ++BanerjeeSuccesses;
2786 ++BanerjeeIndependence;
2790 ++BanerjeeIndependence;
2804unsigned DependenceInfo::exploreDirections(
unsigned Level, CoefficientInfo *
A,
2805 CoefficientInfo *
B, BoundInfo *Bound,
2806 const SmallBitVector &
Loops,
2807 unsigned &DepthExpanded,
2808 const SCEV *Delta)
const {
2814 LLVM_DEBUG(
dbgs() <<
"Number of common levels exceeded the threshold. MIV "
2815 "direction exploration is terminated.\n");
2816 for (
unsigned K = 1;
K <= CommonLevels; ++
K)
2822 if (Level > CommonLevels) {
2825 for (
unsigned K = 1;
K <= CommonLevels; ++
K) {
2827 Bound[
K].DirSet |= Bound[
K].Direction;
2852 if (Level > DepthExpanded) {
2853 DepthExpanded =
Level;
2855 findBoundsLT(
A,
B, Bound, Level);
2856 findBoundsGT(
A,
B, Bound, Level);
2857 findBoundsEQ(
A,
B, Bound, Level);
2896 unsigned NewDeps = 0;
2900 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2905 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2910 NewDeps += exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2916 return exploreDirections(Level + 1,
A,
B, Bound,
Loops, DepthExpanded,
2921bool DependenceInfo::testBounds(
unsigned char DirKind,
unsigned Level,
2922 BoundInfo *Bound,
const SCEV *Delta)
const {
2923 Bound[
Level].Direction = DirKind;
2924 if (
const SCEV *LowerBound = getLowerBound(Bound))
2927 if (
const SCEV *UpperBound = getUpperBound(Bound))
2948void DependenceInfo::findBoundsALL(CoefficientInfo *
A, CoefficientInfo *
B,
2949 BoundInfo *Bound,
unsigned K)
const {
2954 if (Bound[K].Iterations) {
2956 SE->getMinusSCEV(
A[K].NegPart,
B[K].PosPart), Bound[K].Iterations);
2958 SE->getMinusSCEV(
A[K].PosPart,
B[K].NegPart), Bound[K].Iterations);
2963 SE->getZero(
A[K].Coeff->
getType());
2966 SE->getZero(
A[K].Coeff->
getType());
2985void DependenceInfo::findBoundsEQ(CoefficientInfo *
A, CoefficientInfo *
B,
2986 BoundInfo *Bound,
unsigned K)
const {
2991 if (Bound[K].Iterations) {
2992 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
2993 const SCEV *NegativePart = getNegativePart(Delta);
2995 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2996 const SCEV *PositivePart = getPositivePart(Delta);
2998 SE->getMulExpr(PositivePart, Bound[K].Iterations);
3002 const SCEV *Delta = SE->getMinusSCEV(
A[K].Coeff,
B[K].Coeff);
3003 const SCEV *NegativePart = getNegativePart(Delta);
3004 if (NegativePart->
isZero())
3006 const SCEV *PositivePart = getPositivePart(Delta);
3007 if (PositivePart->
isZero())
3025void DependenceInfo::findBoundsLT(CoefficientInfo *
A, CoefficientInfo *
B,
3026 BoundInfo *Bound,
unsigned K)
const {
3031 if (Bound[K].Iterations) {
3032 const SCEV *Iter_1 = SE->getMinusSCEV(
3033 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3034 const SCEV *NegPart =
3035 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3037 SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1),
B[K].Coeff);
3038 const SCEV *PosPart =
3039 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3041 SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1),
B[K].Coeff);
3045 const SCEV *NegPart =
3046 getNegativePart(SE->getMinusSCEV(
A[K].NegPart,
B[K].Coeff));
3049 const SCEV *PosPart =
3050 getPositivePart(SE->getMinusSCEV(
A[K].PosPart,
B[K].Coeff));
3069void DependenceInfo::findBoundsGT(CoefficientInfo *
A, CoefficientInfo *
B,
3070 BoundInfo *Bound,
unsigned K)
const {
3075 if (Bound[K].Iterations) {
3076 const SCEV *Iter_1 = SE->getMinusSCEV(
3077 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
3078 const SCEV *NegPart =
3079 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3081 SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1),
A[K].Coeff);
3082 const SCEV *PosPart =
3083 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3085 SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1),
A[K].Coeff);
3089 const SCEV *NegPart =
3090 getNegativePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].PosPart));
3093 const SCEV *PosPart =
3094 getPositivePart(SE->getMinusSCEV(
A[K].Coeff,
B[K].NegPart));
3101const SCEV *DependenceInfo::getPositivePart(
const SCEV *
X)
const {
3102 return SE->getSMaxExpr(
X, SE->getZero(
X->getType()));
3106const SCEV *DependenceInfo::getNegativePart(
const SCEV *
X)
const {
3107 return SE->getSMinExpr(
X, SE->getZero(
X->getType()));
3113DependenceInfo::CoefficientInfo *
3114DependenceInfo::collectCoeffInfo(
const SCEV *Subscript,
bool SrcFlag,
3115 const SCEV *&Constant)
const {
3116 const SCEV *
Zero = SE->getZero(Subscript->getType());
3117 CoefficientInfo *CI =
new CoefficientInfo[MaxLevels + 1];
3118 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3120 CI[
K].PosPart =
Zero;
3121 CI[
K].NegPart =
Zero;
3122 CI[
K].Iterations =
nullptr;
3126 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(
L);
3128 CI[
K].PosPart = getPositivePart(CI[K].Coeff);
3129 CI[
K].NegPart = getNegativePart(CI[K].Coeff);
3130 CI[
K].Iterations = collectUpperBound(L, Subscript->getType());
3136 for (
unsigned K = 1;
K <= MaxLevels; ++
K) {
3143 if (CI[K].Iterations)
3158const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound)
const {
3159 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3160 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3173const SCEV *DependenceInfo::getUpperBound(BoundInfo *Bound)
const {
3174 const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
3175 for (
unsigned K = 2; Sum &&
K <= MaxLevels; ++
K) {
3193const SCEV *DependenceInfo::findCoefficient(
const SCEV *Expr,
3194 const Loop *TargetLoop)
const {
3197 return SE->getZero(Expr->
getType());
3198 if (AddRec->
getLoop() == TargetLoop)
3200 return findCoefficient(AddRec->
getStart(), TargetLoop);
3208const SCEV *DependenceInfo::zeroCoefficient(
const SCEV *Expr,
3209 const Loop *TargetLoop)
const {
3213 if (AddRec->
getLoop() == TargetLoop)
3215 return SE->getAddRecExpr(zeroCoefficient(AddRec->
getStart(), TargetLoop),
3225const SCEV *DependenceInfo::addToCoefficient(
const SCEV *Expr,
3226 const Loop *TargetLoop,
3227 const SCEV *
Value)
const {
3230 return SE->getAddRecExpr(Expr,
Value, TargetLoop,
3232 if (AddRec->
getLoop() == TargetLoop) {
3239 if (SE->isLoopInvariant(AddRec, TargetLoop))
3241 return SE->getAddRecExpr(
3257bool DependenceInfo::propagate(
const SCEV *&Src,
const SCEV *&Dst,
3258 SmallBitVector &
Loops,
3259 SmallVectorImpl<Constraint> &Constraints,
3262 for (
unsigned LI :
Loops.set_bits()) {
3265 if (Constraints[LI].isDistance())
3266 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3267 else if (Constraints[LI].isLine())
3268 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3269 else if (Constraints[LI].isPoint())
3270 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3280bool DependenceInfo::propagateDistance(
const SCEV *&Src,
const SCEV *&Dst,
3281 Constraint &CurConstraint,
3283 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3284 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3286 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3289 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3290 Src = SE->getMinusSCEV(Src, DA_K);
3291 Src = zeroCoefficient(Src, CurSrcLoop);
3294 Dst = addToCoefficient(Dst, CurDstLoop, SE->getNegativeSCEV(A_K));
3296 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3306bool DependenceInfo::propagateLine(
const SCEV *&Src,
const SCEV *&Dst,
3307 Constraint &CurConstraint,
3309 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3310 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3311 const SCEV *
A = CurConstraint.getA();
3312 const SCEV *
B = CurConstraint.getB();
3313 const SCEV *
C = CurConstraint.getC();
3321 if (!Bconst || !Cconst)
3324 APInt Charlie = Cconst->
getAPInt();
3325 APInt CdivB = Charlie.
sdiv(Beta);
3326 assert(Charlie.
srem(Beta) == 0 &&
"C should be evenly divisible by B");
3327 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3328 Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
3329 Dst = zeroCoefficient(Dst, CurDstLoop);
3330 if (!findCoefficient(Src, CurSrcLoop)->
isZero())
3332 }
else if (
B->isZero()) {
3335 if (!Aconst || !Cconst)
3338 APInt Charlie = Cconst->
getAPInt();
3339 APInt CdivA = Charlie.
sdiv(Alpha);
3340 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3341 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3342 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3343 Src = zeroCoefficient(Src, CurSrcLoop);
3344 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3349 if (!Aconst || !Cconst)
3352 APInt Charlie = Cconst->
getAPInt();
3353 APInt CdivA = Charlie.
sdiv(Alpha);
3354 assert(Charlie.
srem(Alpha) == 0 &&
"C should be evenly divisible by A");
3355 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3356 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
3357 Src = zeroCoefficient(Src, CurSrcLoop);
3358 Dst = addToCoefficient(Dst, CurDstLoop, A_K);
3359 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3363 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3364 Src = SE->getMulExpr(Src,
A);
3365 Dst = SE->getMulExpr(Dst,
A);
3366 Src = SE->getAddExpr(Src, SE->getMulExpr(A_K,
C));
3367 Src = zeroCoefficient(Src, CurSrcLoop);
3368 Dst = addToCoefficient(Dst, CurDstLoop, SE->getMulExpr(A_K,
B));
3369 if (!findCoefficient(Dst, CurDstLoop)->
isZero())
3380bool DependenceInfo::propagatePoint(
const SCEV *&Src,
const SCEV *&Dst,
3381 Constraint &CurConstraint) {
3382 const Loop *CurSrcLoop = CurConstraint.getAssociatedSrcLoop();
3383 const Loop *CurDstLoop = CurConstraint.getAssociatedDstLoop();
3384 const SCEV *A_K = findCoefficient(Src, CurSrcLoop);
3385 const SCEV *AP_K = findCoefficient(Dst, CurDstLoop);
3386 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3387 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3389 Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
3390 Src = zeroCoefficient(Src, CurSrcLoop);
3393 Dst = zeroCoefficient(Dst, CurDstLoop);
3399void DependenceInfo::updateDirection(Dependence::DVEntry &Level,
3400 const Constraint &CurConstraint)
const {
3403 if (CurConstraint.isAny())
3405 else if (CurConstraint.isDistance()) {
3407 Level.Scalar =
false;
3408 Level.Distance = CurConstraint.getD();
3410 if (!SE->isKnownNonZero(
Level.Distance))
3412 if (!SE->isKnownNonPositive(
Level.Distance))
3414 if (!SE->isKnownNonNegative(
Level.Distance))
3416 Level.Direction &= NewDirection;
3417 }
else if (CurConstraint.isLine()) {
3418 Level.Scalar =
false;
3419 Level.Distance =
nullptr;
3421 }
else if (CurConstraint.isPoint()) {
3422 Level.Scalar =
false;
3423 Level.Distance =
nullptr;
3426 CurConstraint.getX()))
3430 CurConstraint.getX()))
3434 CurConstraint.getX()))
3437 Level.Direction &= NewDirection;
3446bool DependenceInfo::tryDelinearize(Instruction *Src, Instruction *Dst,
3447 SmallVectorImpl<Subscript> &Pair) {
3452 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3453 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3454 const SCEV *SrcAccessFn = SE->getSCEVAtScope(SrcPtr, SrcLoop);
3455 const SCEV *DstAccessFn = SE->getSCEVAtScope(DstPtr, DstLoop);
3456 const SCEVUnknown *SrcBase =
3458 const SCEVUnknown *DstBase =
3461 if (!SrcBase || !DstBase || SrcBase != DstBase)
3466 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3467 SrcSubscripts, DstSubscripts) &&
3468 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3469 SrcSubscripts, DstSubscripts))
3472 assert(isLoopInvariant(SrcBase, SrcLoop) &&
3473 isLoopInvariant(DstBase, DstLoop) &&
3474 "Expected SrcBase and DstBase to be loop invariant");
3478 dbgs() <<
"\nSrcSubscripts: ";
3479 for (
int I = 0;
I <
Size;
I++)
3480 dbgs() << *SrcSubscripts[
I];
3481 dbgs() <<
"\nDstSubscripts: ";
3482 for (
int I = 0;
I <
Size;
I++)
3483 dbgs() << *DstSubscripts[
I];
3491 for (
int I = 0;
I <
Size; ++
I) {
3492 Pair[
I].Src = SrcSubscripts[
I];
3493 Pair[
I].Dst = DstSubscripts[
I];
3494 unifySubscriptType(&Pair[
I]);
3503bool DependenceInfo::tryDelinearizeFixedSize(
3504 Instruction *Src, Instruction *Dst,
const SCEV *SrcAccessFn,
3505 const SCEV *DstAccessFn, SmallVectorImpl<const SCEV *> &SrcSubscripts,
3506 SmallVectorImpl<const SCEV *> &DstSubscripts) {
3508 const SCEVUnknown *SrcBase =
3510 const SCEVUnknown *DstBase =
3512 assert(SrcBase && DstBase && SrcBase == DstBase &&
3513 "expected src and dst scev unknowns to be equal");
3516 SmallVector<int, 4> SrcSizes;
3517 SmallVector<int, 4> DstSizes;
3526 if (SrcSizes.size() != DstSizes.
size() ||
3527 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.
begin())) {
3528 SrcSubscripts.
clear();
3529 DstSubscripts.
clear();
3534 "Expected equal number of entries in the list of SrcSubscripts and "
3547 auto AllIndicesInRange = [&](SmallVector<int, 4> &DimensionSizes,
3548 SmallVectorImpl<const SCEV *> &Subscripts,
3550 size_t SSize = Subscripts.
size();
3551 for (
size_t I = 1;
I < SSize; ++
I) {
3552 const SCEV *S = Subscripts[
I];
3553 if (!isKnownNonNegative(S,
Ptr)) {
3555 dbgs() <<
"Check failed: !isKnownNonNegative(S, Ptr)\n";
3556 dbgs() <<
" S: " << *S <<
"\n" <<
" Ptr: " << *
Ptr <<
"\n";
3561 const SCEV *
Range = SE->getConstant(
3562 ConstantInt::get(SType, DimensionSizes[
I - 1],
false));
3563 if (!isKnownLessThan(S,
Range)) {
3565 dbgs() <<
"Check failed: !isKnownLessThan(S, Range)\n";
3566 dbgs() <<
" S: " << *S <<
"\n"
3567 <<
" Range: " << *
Range <<
"\n";
3576 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3577 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3579 SrcSubscripts.
clear();
3580 DstSubscripts.
clear();
3585 dbgs() <<
"Delinearized subscripts of fixed-size array\n"
3586 <<
"SrcGEP:" << *SrcPtr <<
"\n"
3587 <<
"DstGEP:" << *DstPtr <<
"\n";
3592bool DependenceInfo::tryDelinearizeParametricSize(
3593 Instruction *Src, Instruction *Dst,
const SCEV *SrcAccessFn,
3594 const SCEV *DstAccessFn, SmallVectorImpl<const SCEV *> &SrcSubscripts,
3595 SmallVectorImpl<const SCEV *> &DstSubscripts) {
3599 const SCEVUnknown *SrcBase =
3601 const SCEVUnknown *DstBase =
3603 assert(SrcBase && DstBase && SrcBase == DstBase &&
3604 "expected src and dst scev unknowns to be equal");
3606 const SCEV *ElementSize = SE->getElementSize(Src);
3607 if (ElementSize != SE->getElementSize(Dst))
3610 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3611 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3632 if (SrcSubscripts.
size() < 2 || DstSubscripts.
size() < 2 ||
3633 SrcSubscripts.
size() != DstSubscripts.
size())
3636 size_t Size = SrcSubscripts.
size();
3645 for (
size_t I = 1;
I <
Size; ++
I) {
3646 bool SNN = isKnownNonNegative(SrcSubscripts[
I], SrcPtr);
3647 bool DNN = isKnownNonNegative(DstSubscripts[
I], DstPtr);
3648 bool SLT = isKnownLessThan(SrcSubscripts[
I], Sizes[
I - 1]);
3649 bool DLT = isKnownLessThan(DstSubscripts[
I], Sizes[
I - 1]);
3650 if (SNN && DNN && SLT && DLT)
3654 dbgs() <<
"Delinearization checks failed: can't prove the following\n";
3656 dbgs() <<
" isKnownNonNegative(" << *SrcSubscripts[
I] <<
")\n";
3658 dbgs() <<
" isKnownNonNegative(" << *DstSubscripts[
I] <<
")\n";
3660 dbgs() <<
" isKnownLessThan(" << *SrcSubscripts[
I] <<
", "
3661 << *
Sizes[
I - 1] <<
")\n";
3663 dbgs() <<
" isKnownLessThan(" << *DstSubscripts[
I] <<
", "
3664 << *
Sizes[
I - 1] <<
")\n";
3678 for (
unsigned VI : BV.
set_bits()) {
3688 FunctionAnalysisManager::Invalidator &Inv) {
3695 return Inv.invalidate<
AAManager>(F, PA) ||
3715std::unique_ptr<Dependence>
3717 bool UnderRuntimeAssumptions) {
3719 bool PossiblyLoopIndependent =
true;
3721 PossiblyLoopIndependent =
false;
3723 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3729 LLVM_DEBUG(
dbgs() <<
"can only handle simple loads and stores\n");
3730 return std::make_unique<Dependence>(Src, Dst,
3742 return std::make_unique<Dependence>(Src, Dst,
3756 LLVM_DEBUG(
dbgs() <<
"can't analyze must alias with different sizes\n");
3757 return std::make_unique<Dependence>(Src, Dst,
3763 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3764 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3767 const SCEV *SrcBase = SE->getPointerBase(SrcSCEV);
3768 const SCEV *DstBase = SE->getPointerBase(DstSCEV);
3769 if (SrcBase != DstBase) {
3776 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different pointer base\n");
3777 return std::make_unique<Dependence>(Src, Dst,
3785 Loop *SrcLoop = LI->getLoopFor(Src->getParent());
3786 Loop *DstLoop = LI->getLoopFor(Dst->getParent());
3787 if (!isLoopInvariant(SrcBase, SrcLoop) ||
3788 !isLoopInvariant(DstBase, DstLoop)) {
3789 LLVM_DEBUG(
dbgs() <<
"The base pointer is not loop invariant.\n");
3790 return std::make_unique<Dependence>(Src, Dst,
3795 const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
3796 const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
3799 if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3800 !SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
3801 LLVM_DEBUG(
dbgs() <<
"can't analyze SCEV with different offsets\n");
3802 return std::make_unique<Dependence>(Src, Dst,
3806 if (!Assume.empty()) {
3807 if (!UnderRuntimeAssumptions)
3808 return std::make_unique<Dependence>(Src, Dst,
3811 unsigned N = Assumptions.size();
3813 bool Implied =
false;
3814 for (
unsigned I = 0;
I !=
N && !Implied;
I++)
3815 if (Assumptions[
I]->implies(
P, *SE))
3818 Assumptions.push_back(
P);
3824 Pair[0].Src = SrcEv;
3825 Pair[0].Dst = DstEv;
3828 if (tryDelinearize(Src, Dst, Pair)) {
3830 Pairs = Pair.
size();
3835 establishNestingLevels(Src, Dst);
3837 LLVM_DEBUG(
dbgs() <<
" common nesting levels = " << CommonLevels <<
"\n");
3838 LLVM_DEBUG(
dbgs() <<
" maximum nesting levels = " << MaxLevels <<
"\n");
3839 LLVM_DEBUG(
dbgs() <<
" SameSD nesting levels = " << SameSDLevels <<
"\n");
3842 CommonLevels += SameSDLevels;
3843 MaxLevels -= SameSDLevels;
3844 if (SameSDLevels > 0) {
3847 for (
unsigned P = 0;
P < Pairs; ++
P) {
3849 Subscript::ClassificationKind TestClass =
3850 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()),
3851 Pair[
P].Dst, LI->getLoopFor(Dst->getParent()),
Loops);
3853 if (TestClass != Subscript::ZIV && TestClass != Subscript::SIV &&
3854 TestClass != Subscript::RDIV) {
3856 CommonLevels -= SameSDLevels;
3857 MaxLevels += SameSDLevels;
3864 if (SameSDLevels > 0)
3868 PossiblyLoopIndependent, CommonLevels);
3871 for (
unsigned P = 0;
P < Pairs; ++
P) {
3872 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
3873 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
3874 Pair[
P].Loops.
resize(MaxLevels + 1);
3875 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
3877 removeMatchingExtensions(&Pair[
P]);
3878 Pair[
P].Classification =
3879 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
3880 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
3881 Pair[
P].GroupLoops = Pair[
P].Loops;
3882 Pair[
P].Group.set(
P);
3951 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
3952 if (Pair[
SI].Classification == Subscript::NonLinear) {
3954 ++NonlinearSubscriptPairs;
3955 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
3957 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
3959 Result.Consistent =
false;
3960 }
else if (Pair[
SI].Classification == Subscript::ZIV) {
3966 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
3968 Intersection &= Pair[SJ].GroupLoops;
3969 if (Intersection.
any()) {
3971 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
3973 Pair[SJ].Group |= Pair[
SI].Group;
3978 if (Pair[
SI].Group.count() == 1) {
3980 ++SeparableSubscriptPairs;
3983 ++CoupledSubscriptPairs;
3994 Constraint NewConstraint;
3995 NewConstraint.setAny(SE);
4000 switch (Pair[
SI].Classification) {
4001 case Subscript::ZIV:
4003 if (testZIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4006 case Subscript::SIV: {
4009 const SCEV *SplitIter =
nullptr;
4010 if (testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4015 case Subscript::RDIV:
4017 if (testRDIV(Pair[
SI].Src, Pair[
SI].Dst, Result))
4020 case Subscript::MIV:
4022 if (testMIV(Pair[
SI].Src, Pair[
SI].Dst, Pair[
SI].
Loops, Result))
4030 if (Coupled.
count()) {
4033 LLVM_DEBUG(
dbgs() <<
"MaxLevels + 1 = " << MaxLevels + 1 <<
"\n");
4035 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4036 Constraints[
II].setAny(SE);
4044 for (
unsigned SJ : Group.set_bits()) {
4046 if (Pair[SJ].Classification == Subscript::SIV)
4052 unifySubscriptType(PairsInGroup);
4054 while (Sivs.
any()) {
4056 for (
unsigned SJ : Sivs.
set_bits()) {
4060 const SCEV *SplitIter =
nullptr;
4062 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4065 ConstrainedLevels.
set(Level);
4066 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
4067 if (Constraints[Level].isEmpty()) {
4068 ++DeltaIndependence;
4080 for (
unsigned SJ : Mivs.
set_bits()) {
4083 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops,
4084 Constraints, Result.Consistent)) {
4086 ++DeltaPropagations;
4087 Pair[SJ].Classification = classifyPair(
4088 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4089 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4090 switch (Pair[SJ].Classification) {
4091 case Subscript::ZIV:
4093 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4097 case Subscript::SIV:
4101 case Subscript::RDIV:
4102 case Subscript::MIV:
4113 for (
unsigned SJ : Mivs.
set_bits()) {
4114 if (Pair[SJ].Classification == Subscript::RDIV) {
4116 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
4126 for (
unsigned SJ : Mivs.
set_bits()) {
4127 if (Pair[SJ].Classification == Subscript::MIV) {
4129 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Result))
4137 for (
unsigned SJ : ConstrainedLevels.
set_bits()) {
4138 if (SJ > CommonLevels)
4140 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
4149 for (
unsigned SI = 0;
SI < Pairs; ++
SI)
4150 CompleteLoops |= Pair[
SI].
Loops;
4151 for (
unsigned II = 1;
II <= CommonLevels; ++
II)
4152 if (CompleteLoops[
II])
4153 Result.DV[
II - 1].Scalar =
false;
4158 for (
unsigned II = 1;
II <= Result.getLevels(); ++
II) {
4160 if (Result.DV[
II - 1].Distance ==
nullptr)
4161 Result.DV[
II - 1].Distance = SE->getZero(SrcSCEV->
getType());
4163 assert(Result.DV[
II - 1].Distance->isZero() &&
4164 "Inconsistency between distance and direction");
4170 const SCEV *Distance = Result.getDistance(
II);
4171 if (Distance && Distance->
isZero())
4173 "Distance is zero, but direction is not EQ");
4177 if (SameSDLevels > 0) {
4180 assert(CommonLevels >= SameSDLevels);
4181 CommonLevels -= SameSDLevels;
4182 MaxLevels += SameSDLevels;
4183 std::unique_ptr<FullDependence::DVEntry[]> DV, DVSameSD;
4184 DV = std::make_unique<FullDependence::DVEntry[]>(CommonLevels);
4185 DVSameSD = std::make_unique<FullDependence::DVEntry[]>(SameSDLevels);
4186 for (
unsigned Level = 0; Level < CommonLevels; ++Level)
4187 DV[Level] = Result.DV[Level];
4188 for (
unsigned Level = 0; Level < SameSDLevels; ++Level)
4189 DVSameSD[Level] = Result.DV[CommonLevels + Level];
4190 Result.DV = std::move(DV);
4191 Result.DVSameSD = std::move(DVSameSD);
4192 Result.Levels = CommonLevels;
4193 Result.SameSDLevels = SameSDLevels;
4195 Result.Consistent =
false;
4198 if (PossiblyLoopIndependent) {
4202 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4204 Result.LoopIndependent =
false;
4211 bool AllEqual =
true;
4212 for (
unsigned II = 1;
II <= CommonLevels; ++
II) {
4222 return std::make_unique<FullDependence>(std::move(Result));
4273 unsigned SplitLevel) {
4275 "Dep should be splitable at SplitLevel");
4278 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4279 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4289 establishNestingLevels(Src, Dst);
4291 FullDependence Result(Src, Dst, Dep.Assumptions,
false, CommonLevels);
4295 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4296 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4297 Pair[0].Src = SE->removePointerBase(SrcSCEV);
4298 Pair[0].Dst = SE->removePointerBase(DstSCEV);
4301 if (tryDelinearize(Src, Dst, Pair)) {
4303 Pairs = Pair.
size();
4307 for (
unsigned P = 0;
P < Pairs; ++
P) {
4308 assert(Pair[
P].Src->getType()->isIntegerTy() &&
"Src must be an integer");
4309 assert(Pair[
P].Dst->getType()->isIntegerTy() &&
"Dst must be an integer");
4310 Pair[
P].Loops.
resize(MaxLevels + 1);
4311 Pair[
P].GroupLoops.
resize(MaxLevels + 1);
4313 removeMatchingExtensions(&Pair[
P]);
4314 Pair[
P].Classification =
4315 classifyPair(Pair[
P].Src, LI->getLoopFor(Src->getParent()), Pair[
P].Dst,
4316 LI->getLoopFor(Dst->getParent()), Pair[
P].Loops);
4317 Pair[
P].GroupLoops = Pair[
P].Loops;
4318 Pair[
P].Group.set(
P);
4325 for (
unsigned SI = 0;
SI < Pairs; ++
SI) {
4326 if (Pair[
SI].Classification == Subscript::NonLinear) {
4328 collectCommonLoops(Pair[
SI].Src, LI->getLoopFor(Src->getParent()),
4330 collectCommonLoops(Pair[
SI].Dst, LI->getLoopFor(Dst->getParent()),
4332 Result.Consistent =
false;
4333 }
else if (Pair[
SI].Classification == Subscript::ZIV)
4338 for (
unsigned SJ =
SI + 1; SJ < Pairs; ++SJ) {
4340 Intersection &= Pair[SJ].GroupLoops;
4341 if (Intersection.
any()) {
4343 Pair[SJ].GroupLoops |= Pair[
SI].GroupLoops;
4345 Pair[SJ].Group |= Pair[
SI].Group;
4350 if (Pair[
SI].Group.count() == 1)
4358 Constraint NewConstraint;
4359 NewConstraint.setAny(SE);
4363 switch (Pair[
SI].Classification) {
4364 case Subscript::SIV: {
4366 const SCEV *SplitIter =
nullptr;
4367 (void)testSIV(Pair[
SI].Src, Pair[
SI].Dst, Level, Result, NewConstraint,
4369 if (Level == SplitLevel) {
4370 assert(SplitIter !=
nullptr);
4375 case Subscript::ZIV:
4376 case Subscript::RDIV:
4377 case Subscript::MIV:
4384 assert(!Coupled.
empty() &&
"coupled expected non-empty");
4388 for (
unsigned II = 0;
II <= MaxLevels; ++
II)
4389 Constraints[
II].setAny(SE);
4395 for (
unsigned SJ : Group.set_bits()) {
4396 if (Pair[SJ].Classification == Subscript::SIV)
4401 while (Sivs.
any()) {
4403 for (
unsigned SJ : Sivs.
set_bits()) {
4406 const SCEV *SplitIter =
nullptr;
4407 (void)testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
4409 if (Level == SplitLevel && SplitIter)
4411 ConstrainedLevels.
set(Level);
4412 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4419 for (
unsigned SJ : Mivs.
set_bits()) {
4421 if (!propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].
Loops, Constraints,
4424 Pair[SJ].Classification = classifyPair(
4425 Pair[SJ].Src, LI->getLoopFor(Src->getParent()), Pair[SJ].Dst,
4426 LI->getLoopFor(Dst->getParent()), Pair[SJ].Loops);
4427 switch (Pair[SJ].Classification) {
4428 case Subscript::ZIV:
4431 case Subscript::SIV:
4435 case Subscript::RDIV:
4436 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 const SCEV * minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, ScalarEvolution &SE)
Returns A - B if it guaranteed not to signed wrap.
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static 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.
Instruction * getDst() const
getDst - Returns the destination instruction for this dependence.
void dumpImp(raw_ostream &OS, bool IsSameSD=false) const
dumpImp - For debugging purposes.
Dependence(Dependence &&)=default
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual unsigned getSameSDLevels() const
getSameSDLevels - Returns the number of separate SameSD loops surrounding the source and destination ...
virtual const SCEV * getDistance(unsigned Level, bool SameSD=false) const
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
virtual bool isPeelLast(unsigned Level, bool SameSD=false) const
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
virtual unsigned getDirection(unsigned Level, bool SameSD=false) const
getDirection - Returns the direction associated with a particular common or SameSD level.
virtual bool isScalar(unsigned Level, bool SameSD=false) const
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
virtual bool isPeelFirst(unsigned Level, bool SameSD=false) const
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
virtual bool isSplitable(unsigned Level, bool SameSD=false) const
isSplitable - Returns true if splitting the loop will break the dependence.
Instruction * getSrc() const
getSrc - Returns the source instruction for this dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
virtual bool inSameSDLoops(unsigned Level) const
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
FullDependence - This class represents a dependence between two memory references in a function.
FullDependence(Instruction *Source, Instruction *Destination, const SCEVUnionPredicate &Assumes, bool PossiblyLoopIndependent, unsigned Levels)
unsigned getDirection(unsigned Level, bool SameSD=false) const override
getDirection - Returns the direction associated with a particular common or SameSD level.
bool isScalar(unsigned Level, bool SameSD=false) const override
isScalar - Returns true if a particular regular or SameSD level is scalar; that is,...
bool isDirectionNegative() const override
Check if the direction vector is negative.
const SCEV * getDistance(unsigned Level, bool SameSD=false) const override
getDistance - Returns the distance (or NULL) associated with a particular common or SameSD level.
DVEntry getDVEntry(unsigned Level, bool IsSameSD) const
getDVEntry - Returns the DV entry associated with a regular or a SameSD level.
bool isSplitable(unsigned Level, bool SameSD=false) const override
isSplitable - Returns true if splitting the loop will break the dependence.
bool isPeelLast(unsigned Level, bool SameSD=false) const override
isPeelLast - Returns true if peeling the last iteration from this regular or SameSD loop level will b...
bool isPeelFirst(unsigned Level, bool SameSD=false) const override
isPeelFirst - Returns true if peeling the first iteration from this regular or SameSD loop level will...
bool inSameSDLoops(unsigned Level) const override
inSameSDLoops - Returns true if this level is an SameSD level, i.e., performed across two separate lo...
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
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.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
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.
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
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...