LLVM: lib/Analysis/DependenceAnalysis.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
67
68using namespace llvm;
69
70#define DEBUG_TYPE "da"
71
72
73
74
75STATISTIC(TotalArrayPairs, "Array pairs tested");
76STATISTIC(SeparableSubscriptPairs, "Separable subscript pairs");
77STATISTIC(CoupledSubscriptPairs, "Coupled subscript pairs");
78STATISTIC(NonlinearSubscriptPairs, "Nonlinear subscript pairs");
79STATISTIC(ZIVapplications, "ZIV applications");
80STATISTIC(ZIVindependence, "ZIV independence");
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");
88STATISTIC(ExactSIVsuccesses, "Exact SIV successes");
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");
97STATISTIC(DeltaApplications, "Delta applications");
98STATISTIC(DeltaSuccesses, "Delta successes");
99STATISTIC(DeltaIndependence, "Delta independence");
100STATISTIC(DeltaPropagations, "Delta propagations");
101STATISTIC(GCDapplications, "GCD applications");
103STATISTIC(GCDindependence, "GCD independence");
104STATISTIC(BanerjeeApplications, "Banerjee applications");
105STATISTIC(BanerjeeIndependence, "Banerjee independence");
106STATISTIC(BanerjeeSuccesses, "Banerjee successes");
107
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."));
118
121 cl::desc("Maximum depth allowed for the recursive algorithm used to "
122 "explore MIV direction vectors."));
123
124
125
126
133}
134
136
138 "Dependence Analysis", true, true)
144
146
150}
151
154}
155
157 auto &AA = getAnalysis().getAAResults();
158 auto &SE = getAnalysis().getSE();
159 auto &LI = getAnalysis().getLoopInfo();
161 return false;
162}
163
165
167
173}
174
175
176
177
178
181 auto *F = DA->getFunction();
183 ++SrcI) {
184 if (SrcI->mayReadOrWriteMemory()) {
186 DstI != DstE; ++DstI) {
187 if (DstI->mayReadOrWriteMemory()) {
188 OS << "Src:" << *SrcI << " --> Dst:" << *DstI << "\n";
189 OS << " da analyze - ";
190 if (auto D = DA->depends(&*SrcI, &*DstI, true)) {
191
192 if (NormalizeResults && D->normalize(&SE))
193 OS << "normalized - ";
195 for (unsigned Level = 1; Level <= D->getLevels(); Level++) {
196 if (D->isSplitable(Level)) {
197 OS << " da analyze - split level = " << Level;
198 OS << ", iteration = " << *DA->getSplitIteration(*D, Level);
199 OS << "!\n";
200 }
201 }
202 }
203 else
204 OS << "none!\n";
205 }
206 }
207 }
208 }
209}
210
212 const Module *) const {
214 getAnalysis().getSE(), false);
215}
216
219 OS << "'Dependence Analysis' for function '" << F.getName() << "':\n";
222 NormalizeResults);
224}
225
226
227
228
229
232}
233
234
235
238}
239
240
241
244}
245
246
247
250}
251
252
253
254
255
256
258 return false;
259}
260
261
262
263
264
266 bool PossiblyLoopIndependent,
267 unsigned CommonLevels)
268 : Dependence(Source, Destination), Levels(CommonLevels),
269 LoopIndependent(PossiblyLoopIndependent) {
270 Consistent = true;
271 if (CommonLevels)
272 DV = std::make_unique<DVEntry[]>(CommonLevels);
273}
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
291 for (unsigned Level = 1; Level <= Levels; ++Level) {
292 unsigned char Direction = DV[Level - 1].Direction;
294 continue;
297 return true;
298 return false;
299 }
300 return false;
301}
302
305 return false;
306
307 LLVM_DEBUG(dbgs() << "Before normalizing negative direction vectors:\n";
310 for (unsigned Level = 1; Level <= Levels; ++Level) {
311 unsigned char Direction = DV[Level - 1].Direction;
312
313
319 DV[Level - 1].Direction = RevDirection;
320
321 if (DV[Level - 1].Distance != nullptr)
322 DV[Level - 1].Distance =
324 }
325
326 LLVM_DEBUG(dbgs() << "After normalizing negative direction vectors:\n";
328 return true;
329}
330
331
332
333
335 assert(0 < Level && Level <= Levels && "Level out of range");
336 return DV[Level - 1].Direction;
337}
338
339
340
342 assert(0 < Level && Level <= Levels && "Level out of range");
343 return DV[Level - 1].Distance;
344}
345
346
347
348
349
351 assert(0 < Level && Level <= Levels && "Level out of range");
352 return DV[Level - 1].Scalar;
353}
354
355
356
357
359 assert(0 < Level && Level <= Levels && "Level out of range");
360 return DV[Level - 1].PeelFirst;
361}
362
363
364
365
367 assert(0 < Level && Level <= Levels && "Level out of range");
368 return DV[Level - 1].PeelLast;
369}
370
371
372
374 assert(0 < Level && Level <= Levels && "Level out of range");
375 return DV[Level - 1].Splitable;
376}
377
378
379
380
381
382
383
384const SCEV *DependenceInfo::Constraint::getX() const {
385 assert(Kind == Point && "Kind should be Point");
386 return A;
387}
388
389
390
391
392const SCEV *DependenceInfo::Constraint::getY() const {
393 assert(Kind == Point && "Kind should be Point");
394 return B;
395}
396
397
398
399
400const SCEV *DependenceInfo::Constraint::getA() const {
401 assert((Kind == Line || Kind == Distance) &&
402 "Kind should be Line (or Distance)");
403 return A;
404}
405
406
407
408
409const SCEV *DependenceInfo::Constraint::getB() const {
410 assert((Kind == Line || Kind == Distance) &&
411 "Kind should be Line (or Distance)");
412 return B;
413}
414
415
416
417
418const SCEV *DependenceInfo::Constraint::getC() const {
419 assert((Kind == Line || Kind == Distance) &&
420 "Kind should be Line (or Distance)");
421 return C;
422}
423
424
425
426
427const SCEV *DependenceInfo::Constraint::getD() const {
428 assert(Kind == Distance && "Kind should be Distance");
429 return SE->getNegativeSCEV(C);
430}
431
432
433
434const Loop *DependenceInfo::Constraint::getAssociatedLoop() const {
435 assert((Kind == Distance || Kind == Line || Kind == Point) &&
436 "Kind should be Distance, Line, or Point");
437 return AssociatedLoop;
438}
439
440void DependenceInfo::Constraint::setPoint(const SCEV *X, const SCEV *Y,
441 const Loop *CurLoop) {
442 Kind = Point;
445 AssociatedLoop = CurLoop;
446}
447
448void DependenceInfo::Constraint::setLine(const SCEV *AA, const SCEV *BB,
449 const SCEV *CC, const Loop *CurLoop) {
451 A = AA;
452 B = BB;
454 AssociatedLoop = CurLoop;
455}
456
457void DependenceInfo::Constraint::setDistance(const SCEV *D,
458 const Loop *CurLoop) {
459 Kind = Distance;
460 A = SE->getOne(D->getType());
461 B = SE->getNegativeSCEV(A);
462 C = SE->getNegativeSCEV(D);
463 AssociatedLoop = CurLoop;
464}
465
466void DependenceInfo::Constraint::setEmpty() { Kind = Empty; }
467
468void DependenceInfo::Constraint::setAny(ScalarEvolution *NewSE) {
469 SE = NewSE;
471}
472
473#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
474
476 if (isEmpty())
477 OS << " Empty\n";
478 else if (isAny())
479 OS << " Any\n";
480 else if (isPoint())
481 OS << " Point is <" << *getX() << ", " << *getY() << ">\n";
482 else if (isDistance())
483 OS << " Distance is " << *getD() <<
484 " (" << *getA() << "*X + " << *getB() << "*Y = " << *getC() << ")\n";
485 else if (isLine())
486 OS << " Line is " << *getA() << "*X + " <<
487 *getB() << "*Y = " << *getC() << "\n";
488 else
489 llvm_unreachable("unknown constraint type in Constraint::dump");
490}
491#endif
492
493
494
495
496
497
498
499
500
501bool DependenceInfo::intersectConstraints(Constraint *X, const Constraint *Y) {
502 ++DeltaApplications;
506 assert(->isPoint() && "Y must not be a Point");
507 if (X->isAny()) {
508 if (Y->isAny())
509 return false;
511 return true;
512 }
513 if (X->isEmpty())
514 return false;
515 if (Y->isEmpty()) {
516 X->setEmpty();
517 return true;
518 }
519
520 if (X->isDistance() && Y->isDistance()) {
523 return false;
525 X->setEmpty();
526 ++DeltaSuccesses;
527 return true;
528 }
529
530
531 if (isa(Y->getD())) {
533 return true;
534 }
535 return false;
536 }
537
538
539
540
541
542
543
544 assert(!(X->isPoint() && Y->isPoint()) &&
545 "We shouldn't ever see X->isPoint() && Y->isPoint()");
546
547 if (X->isLine() && Y->isLine()) {
552
554 Prod1 = SE->getMulExpr(X->getC(), Y->getB());
555 Prod2 = SE->getMulExpr(X->getB(), Y->getC());
557 return false;
559 X->setEmpty();
560 ++DeltaSuccesses;
561 return true;
562 }
563 return false;
564 }
566
575 dyn_cast(SE->getMinusSCEV(C1A2, C2A1));
577 dyn_cast(SE->getMinusSCEV(C1B2, C2B1));
579 dyn_cast(SE->getMinusSCEV(A1B2, A2B1));
581 dyn_cast(SE->getMinusSCEV(A2B1, A1B2));
582 if (!C1B2_C2B1 || !C1A2_C2A1 ||
583 !A1B2_A2B1 || !A2B1_A1B2)
584 return false;
593 APInt Xq = Xtop;
594 APInt Xr = Xtop;
599 if (Xr != 0 || Yr != 0) {
600 X->setEmpty();
601 ++DeltaSuccesses;
602 return true;
603 }
604 LLVM_DEBUG(dbgs() << "\t\tX = " << Xq << ", Y = " << Yq << "\n");
605 if (Xq.slt(0) || Yq.slt(0)) {
606 X->setEmpty();
607 ++DeltaSuccesses;
608 return true;
609 }
611 collectConstantUpperBound(X->getAssociatedLoop(), Prod1->getType())) {
612 const APInt &UpperBound = CUB->getAPInt();
613 LLVM_DEBUG(dbgs() << "\t\tupper bound = " << UpperBound << "\n");
614 if (Xq.sgt(UpperBound) || Yq.sgt(UpperBound)) {
615 X->setEmpty();
616 ++DeltaSuccesses;
617 return true;
618 }
619 }
622 X->getAssociatedLoop());
623 ++DeltaSuccesses;
624 return true;
625 }
626 return false;
627 }
628
629
630 assert(!(X->isLine() && Y->isPoint()) && "This case should never occur");
631
632 if (X->isPoint() && Y->isLine()) {
633 LLVM_DEBUG(dbgs() << "\t intersect Point and Line\n");
638 return false;
640 X->setEmpty();
641 ++DeltaSuccesses;
642 return true;
643 }
644 return false;
645 }
646
647 llvm_unreachable("shouldn't reach the end of Constraint intersection");
648 return false;
649}
650
651
652
653
654
655
657 bool Splitable = false;
659 OS << "confused";
660 else {
662 OS << "consistent ";
664 OS << "flow";
666 OS << "output";
668 OS << "anti";
670 OS << "input";
672 OS << " [";
673 for (unsigned II = 1; II <= Levels; ++II) {
675 Splitable = true;
677 OS << 'p';
679 if (Distance)
680 OS << *Distance;
682 OS << "S";
683 else {
686 OS << "*";
687 else {
689 OS << "<";
691 OS << "=";
693 OS << ">";
694 }
695 }
697 OS << 'p';
698 if (II < Levels)
699 OS << " ";
700 }
702 OS << "|<";
703 OS << "]";
704 if (Splitable)
705 OS << " splitable";
706 }
707 OS << "!\n";
708}
709
710
711
712
713
714
719
720
727
728
731
732
733 if (AObj == BObj)
735
736
737
740
741
742
744}
745
746
747
748
749static
751 if (const LoadInst *LI = dyn_cast(I))
752 return LI->isUnordered();
753 else if (const StoreInst *SI = dyn_cast(I))
754 return SI->isUnordered();
755 return false;
756}
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809void DependenceInfo::establishNestingLevels(const Instruction *Src,
811 const BasicBlock *SrcBlock = Src->getParent();
812 const BasicBlock *DstBlock = Dst->getParent();
813 unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
814 unsigned DstLevel = LI->getLoopDepth(DstBlock);
817 SrcLevels = SrcLevel;
818 MaxLevels = SrcLevel + DstLevel;
819 while (SrcLevel > DstLevel) {
821 SrcLevel--;
822 }
823 while (DstLevel > SrcLevel) {
825 DstLevel--;
826 }
827 while (SrcLoop != DstLoop) {
830 SrcLevel--;
831 }
832 CommonLevels = SrcLevel;
833 MaxLevels -= CommonLevels;
834}
835
836
837
838
839unsigned DependenceInfo::mapSrcLoop(const Loop *SrcLoop) const {
841}
842
843
844
845
846unsigned DependenceInfo::mapDstLoop(const Loop *DstLoop) const {
848 if (D > CommonLevels)
849
850
851 return D - CommonLevels + SrcLevels;
852 else
853 return D;
854}
855
856
857
858bool DependenceInfo::isLoopInvariant(const SCEV *Expression,
860
861
862
863
865 return true;
866
867
868
870}
871
872
873
874
875
876void DependenceInfo::collectCommonLoops(const SCEV *Expression,
880 unsigned Level = LoopNest->getLoopDepth();
881 if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
882 Loops.set(Level);
884 }
885}
886
888
889 unsigned widestWidthSeen = 0;
890 Type *widestType;
891
892
893
894 for (Subscript *Pair : Pairs) {
895 const SCEV *Src = Pair->Src;
896 const SCEV *Dst = Pair->Dst;
897 IntegerType *SrcTy = dyn_cast(Src->getType());
898 IntegerType *DstTy = dyn_cast(Dst->getType());
899 if (SrcTy == nullptr || DstTy == nullptr) {
900 assert(SrcTy == DstTy && "This function only unify integer types and "
901 "expect Src and Dst share the same type "
902 "otherwise.");
903 continue;
904 }
905 if (SrcTy->getBitWidth() > widestWidthSeen) {
907 widestType = SrcTy;
908 }
909 if (DstTy->getBitWidth() > widestWidthSeen) {
911 widestType = DstTy;
912 }
913 }
914
915
916 assert(widestWidthSeen > 0);
917
918
919 for (Subscript *Pair : Pairs) {
920 const SCEV *Src = Pair->Src;
921 const SCEV *Dst = Pair->Dst;
922 IntegerType *SrcTy = dyn_cast(Src->getType());
923 IntegerType *DstTy = dyn_cast(Dst->getType());
924 if (SrcTy == nullptr || DstTy == nullptr) {
925 assert(SrcTy == DstTy && "This function only unify integer types and "
926 "expect Src and Dst share the same type "
927 "otherwise.");
928 continue;
929 }
930 if (SrcTy->getBitWidth() < widestWidthSeen)
931
933 if (DstTy->getBitWidth() < widestWidthSeen) {
934
936 }
937 }
938}
939
940
941
942
943
944void DependenceInfo::removeMatchingExtensions(Subscript *Pair) {
945 const SCEV *Src = Pair->Src;
946 const SCEV *Dst = Pair->Dst;
947 if ((isa(Src) && isa(Dst)) ||
948 (isa(Src) && isa(Dst))) {
954 Pair->Src = SrcCastOp;
955 Pair->Dst = DstCastOp;
956 }
957 }
958}
959
960
961
962bool DependenceInfo::checkSubscript(const SCEV *Expr, const Loop *LoopNest,
964 const SCEVAddRecExpr *AddRec = dyn_cast(Expr);
965 if (!AddRec)
966 return isLoopInvariant(Expr, LoopNest);
967
968
969
970
971
972
974 while (L && AddRec->getLoop() != L)
976 if (!L)
977 return false;
978
982 if (!isa(UB)) {
986 return false;
987 }
988 }
989 if (!isLoopInvariant(Step, LoopNest))
990 return false;
991 if (IsSrc)
993 else
995 return checkSubscript(Start, LoopNest, Loops, IsSrc);
996}
997
998
999
1000bool DependenceInfo::checkSrcSubscript(const SCEV *Src, const Loop *LoopNest,
1002 return checkSubscript(Src, LoopNest, Loops, true);
1003}
1004
1005
1006
1007bool DependenceInfo::checkDstSubscript(const SCEV *Dst, const Loop *LoopNest,
1009 return checkSubscript(Dst, LoopNest, Loops, false);
1010}
1011
1012
1013
1014
1015
1016DependenceInfo::Subscript::ClassificationKind
1017DependenceInfo::classifyPair(const SCEV *Src, const Loop *SrcLoopNest,
1018 const SCEV *Dst, const Loop *DstLoopNest,
1022 if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
1023 return Subscript::NonLinear;
1024 if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
1025 return Subscript::NonLinear;
1026 Loops = SrcLoops;
1027 Loops |= DstLoops;
1028 unsigned N = Loops.count();
1029 if (N == 0)
1030 return Subscript::ZIV;
1031 if (N == 1)
1032 return Subscript::SIV;
1033 if (N == 2 && (SrcLoops.count() == 0 ||
1034 DstLoops.count() == 0 ||
1035 (SrcLoops.count() == 1 && DstLoops.count() == 1)))
1036 return Subscript::RDIV;
1037 return Subscript::MIV;
1038}
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1055 if ((isa(X) &&
1056 isa(Y)) ||
1057 (isa(X) &&
1058 isa(Y))) {
1064 X = Xop;
1065 Y = Yop;
1066 }
1067 }
1068 }
1070 return true;
1071
1072
1073
1074
1075
1077 switch (Pred) {
1079 return Delta->isZero();
1090 default:
1091 llvm_unreachable("unexpected predicate in isKnownPredicate");
1092 }
1093}
1094
1095
1096
1097
1098bool DependenceInfo::isKnownLessThan(const SCEV *S, const SCEV *Size) const {
1099
1100 auto *SType = dyn_cast(S->getType());
1101 auto *SizeType = dyn_cast(Size->getType());
1102 if (!SType || !SizeType)
1103 return false;
1104 Type *MaxType =
1105 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
1108
1109
1111 if (const SCEVAddRecExpr *AddRec = dyn_cast(Bound)) {
1114 if (!isa(BECount)) {
1117 return true;
1118 }
1119 }
1120 }
1121
1122
1123 const SCEV *LimitedBound =
1126}
1127
1128bool DependenceInfo::isKnownNonNegative(const SCEV *S, const Value *Ptr) const {
1129 bool Inbounds = false;
1130 if (auto *SrcGEP = dyn_cast(Ptr))
1131 Inbounds = SrcGEP->isInBounds();
1132 if (Inbounds) {
1133 if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) {
1135
1136
1139 return true;
1140 }
1141 }
1142 }
1143
1145}
1146
1147
1148
1149
1150
1151
1152
1153
1154const SCEV *DependenceInfo::collectUpperBound(const Loop *L, Type *T) const {
1158 }
1159 return nullptr;
1160}
1161
1162
1163
1164
1165const SCEVConstant *DependenceInfo::collectConstantUpperBound(const Loop *L,
1167 if (const SCEV *UB = collectUpperBound(L, T))
1168 return dyn_cast(UB);
1169 return nullptr;
1170}
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183bool DependenceInfo::testZIV(const SCEV *Src, const SCEV *Dst,
1187 ++ZIVapplications;
1190 return false;
1191 }
1194 ++ZIVindependence;
1195 return true;
1196 }
1198 Result.Consistent = false;
1199 return false;
1200}
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
1231 const SCEV *DstConst, const Loop *CurLoop,
1233 Constraint &NewConstraint) const {
1237 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst);
1239 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst);
1241 ++StrongSIVapplications;
1242 assert(0 < Level && Level <= CommonLevels && "level out of range");
1243 Level--;
1244
1248
1249
1250 if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
1251 LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound);
1252 LLVM_DEBUG(dbgs() << ", " << *UpperBound->getType() << "\n");
1253 const SCEV *AbsDelta =
1255 const SCEV *AbsCoeff =
1257 const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
1259
1260 ++StrongSIVindependence;
1261 ++StrongSIVsuccesses;
1262 return true;
1263 }
1264 }
1265
1266
1267 if (isa(Delta) && isa(Coeff)) {
1268 APInt ConstDelta = cast(Delta)->getAPInt();
1269 APInt ConstCoeff = cast(Coeff)->getAPInt();
1270 APInt Distance = ConstDelta;
1271 APInt Remainder = ConstDelta;
1272 APInt::sdivrem(ConstDelta, ConstCoeff, Distance, Remainder);
1273 LLVM_DEBUG(dbgs() << "\t Distance = " << Distance << "\n");
1274 LLVM_DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
1275
1276 if (Remainder != 0) {
1277
1278 ++StrongSIVindependence;
1279 ++StrongSIVsuccesses;
1280 return true;
1281 }
1283 NewConstraint.setDistance(SE->getConstant(Distance), CurLoop);
1284 if (Distance.sgt(0))
1286 else if (Distance.slt(0))
1288 else
1290 ++StrongSIVsuccesses;
1291 }
1292 else if (Delta->isZero()) {
1293
1294 Result.DV[Level].Distance = Delta;
1295 NewConstraint.setDistance(Delta, CurLoop);
1297 ++StrongSIVsuccesses;
1298 }
1299 else {
1300 if (Coeff->isOne()) {
1301 LLVM_DEBUG(dbgs() << "\t Distance = " << *Delta << "\n");
1302 Result.DV[Level].Distance = Delta;
1303 NewConstraint.setDistance(Delta, CurLoop);
1304 }
1305 else {
1306 Result.Consistent = false;
1307 NewConstraint.setLine(Coeff,
1310 }
1311
1312
1318
1319
1320
1322 if ((DeltaMaybePositive && CoeffMaybePositive) ||
1323 (DeltaMaybeNegative && CoeffMaybeNegative))
1325 if (DeltaMaybeZero)
1327 if ((DeltaMaybeNegative && CoeffMaybePositive) ||
1328 (DeltaMaybePositive && CoeffMaybeNegative))
1330 if (NewDirection < Result.DV[Level].Direction)
1331 ++StrongSIVsuccesses;
1332 Result.DV[Level].Direction &= NewDirection;
1333 }
1334 return false;
1335}
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366bool DependenceInfo::weakCrossingSIVtest(
1367 const SCEV *Coeff, const SCEV *SrcConst, const SCEV *DstConst,
1369 Constraint &NewConstraint, const SCEV *&SplitIter) const {
1371 LLVM_DEBUG(dbgs() << "\t Coeff = " << *Coeff << "\n");
1372 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
1373 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
1374 ++WeakCrossingSIVapplications;
1375 assert(0 < Level && Level <= CommonLevels && "Level out of range");
1376 Level--;
1377 Result.Consistent = false;
1379 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1380 NewConstraint.setLine(Coeff, Coeff, Delta, CurLoop);
1381 if (Delta->isZero()) {
1384 ++WeakCrossingSIVsuccesses;
1385 if (.DV[Level].Direction) {
1386 ++WeakCrossingSIVindependence;
1387 return true;
1388 }
1389 Result.DV[Level].Distance = Delta;
1390 return false;
1391 }
1392 const SCEVConstant *ConstCoeff = dyn_cast(Coeff);
1393 if (!ConstCoeff)
1394 return false;
1395
1396 Result.DV[Level].Splitable = true;
1398 ConstCoeff = dyn_cast(SE->getNegativeSCEV(ConstCoeff));
1399 assert(ConstCoeff &&
1400 "dynamic cast of negative of ConstCoeff should yield constant");
1402 }
1404
1405
1409 LLVM_DEBUG(dbgs() << "\t Split iter = " << *SplitIter << "\n");
1410
1411 const SCEVConstant *ConstDelta = dyn_cast(Delta);
1412 if (!ConstDelta)
1413 return false;
1414
1415
1416
1417 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1418 LLVM_DEBUG(dbgs() << "\t ConstCoeff = " << *ConstCoeff << "\n");
1420
1421 ++WeakCrossingSIVindependence;
1422 ++WeakCrossingSIVsuccesses;
1423 return true;
1424 }
1425
1426
1427
1428 if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
1429 LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
1430 const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
1432 ConstantTwo);
1435
1436 ++WeakCrossingSIVindependence;
1437 ++WeakCrossingSIVsuccesses;
1438 return true;
1439 }
1441
1444 ++WeakCrossingSIVsuccesses;
1445 if (.DV[Level].Direction) {
1446 ++WeakCrossingSIVindependence;
1447 return true;
1448 }
1449 Result.DV[Level].Splitable = false;
1451 return false;
1452 }
1453 }
1454
1455
1458 APInt Distance = APDelta;
1459 APInt Remainder = APDelta;
1460 APInt::sdivrem(APDelta, APCoeff, Distance, Remainder);
1461 LLVM_DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
1462 if (Remainder != 0) {
1463
1464 ++WeakCrossingSIVindependence;
1465 ++WeakCrossingSIVsuccesses;
1466 return true;
1467 }
1468 LLVM_DEBUG(dbgs() << "\t Distance = " << Distance << "\n");
1469
1470
1472 Remainder = Distance.srem(Two);
1473 LLVM_DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
1474 if (Remainder != 0) {
1475
1477 ++WeakCrossingSIVsuccesses;
1478 }
1479 return false;
1480}
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1495 APInt A0(Bits, 1, true), A1(Bits, 0, true);
1496 APInt B0(Bits, 0, true), B1(Bits, 1, true);
1499 APInt Q = G0;
1502 while (R != 0) {
1503 APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
1504 APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
1505 G0 = G1; G1 = R;
1507 }
1508 G = G1;
1510 X = AM.slt(0) ? -A1 : A1;
1511 Y = BM.slt(0) ? B1 : -B1;
1512
1513
1515 if (R != 0)
1516 return true;
1518 return false;
1519}
1520
1525 if (R == 0)
1526 return Q;
1527 if ((A.sgt(0) && B.sgt(0)) ||
1529 return Q;
1530 else
1531 return Q - 1;
1532}
1533
1538 if (R == 0)
1539 return Q;
1540 if ((A.sgt(0) && B.sgt(0)) ||
1542 return Q + 1;
1543 else
1544 return Q;
1545}
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566bool DependenceInfo::exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
1567 const SCEV *SrcConst, const SCEV *DstConst,
1568 const Loop *CurLoop, unsigned Level,
1570 Constraint &NewConstraint) const {
1572 LLVM_DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << " = AM\n");
1573 LLVM_DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << " = BM\n");
1574 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
1575 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
1576 ++ExactSIVapplications;
1577 assert(0 < Level && Level <= CommonLevels && "Level out of range");
1578 Level--;
1579 Result.Consistent = false;
1581 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1582 NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
1583 CurLoop);
1584 const SCEVConstant *ConstDelta = dyn_cast(Delta);
1585 const SCEVConstant *ConstSrcCoeff = dyn_cast(SrcCoeff);
1586 const SCEVConstant *ConstDstCoeff = dyn_cast(DstCoeff);
1587 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1588 return false;
1589
1590
1596 if (findGCD(Bits, AM, BM, CM, G, X, Y)) {
1597
1598 ++ExactSIVindependence;
1599 ++ExactSIVsuccesses;
1600 return true;
1601 }
1602
1603 LLVM_DEBUG(dbgs() << "\t X = " << X << ", Y = " << Y << "\n");
1604
1605
1606 APInt UM(Bits, 1, true);
1607 bool UMValid = false;
1608
1610 collectConstantUpperBound(CurLoop, Delta->getType())) {
1611 UM = CUB->getAPInt();
1613 UMValid = true;
1614 }
1615
1624
1627 if (TB.sgt(0)) {
1630
1631 if (UMValid) {
1634 }
1635 } else {
1638
1639 if (UMValid) {
1642 }
1643 }
1644
1646 if (TA.sgt(0)) {
1647 if (UMValid) {
1650 }
1651
1654 } else {
1655 if (UMValid) {
1658 }
1659
1662 }
1663
1666
1668 return false;
1673
1674 if (TL.sgt(TU)) {
1675 ++ExactSIVindependence;
1676 ++ExactSIVsuccesses;
1677 return true;
1678 }
1679
1680
1682 APInt LowerDistance, UpperDistance;
1683 if (TA.sgt(TB)) {
1684 LowerDistance = (TY - TX) + (TA - TB) * TL;
1685 UpperDistance = (TY - TX) + (TA - TB) * TU;
1686 } else {
1687 LowerDistance = (TY - TX) + (TA - TB) * TU;
1688 UpperDistance = (TY - TX) + (TA - TB) * TL;
1689 }
1690
1691 LLVM_DEBUG(dbgs() << "\t LowerDistance = " << LowerDistance << "\n");
1692 LLVM_DEBUG(dbgs() << "\t UpperDistance = " << UpperDistance << "\n");
1693
1695 if (LowerDistance.sle(Zero) && UpperDistance.sge(Zero)) {
1697 ++ExactSIVsuccesses;
1698 }
1699 if (LowerDistance.slt(0)) {
1701 ++ExactSIVsuccesses;
1702 }
1703 if (UpperDistance.sgt(0)) {
1705 ++ExactSIVsuccesses;
1706 }
1707
1708
1709 Result.DV[Level].Direction &= NewDirection;
1711 ++ExactSIVindependence;
1715}
1716
1717
1718
1719static
1722 const APInt &ConstDividend = Dividend->getAPInt();
1723 const APInt &ConstDivisor = Divisor->getAPInt();
1724 return ConstDividend.srem(ConstDivisor) == 0;
1725}
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
1760 const SCEV *SrcConst,
1761 const SCEV *DstConst,
1762 const Loop *CurLoop, unsigned Level,
1764 Constraint &NewConstraint) const {
1765
1766
1767
1768 LLVM_DEBUG(dbgs() << "\tWeak-Zero (src) SIV test\n");
1769 LLVM_DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << "\n");
1770 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
1771 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
1772 ++WeakZeroSIVapplications;
1773 assert(0 < Level && Level <= MaxLevels && "Level out of range");
1774 Level--;
1775 Result.Consistent = false;
1777 NewConstraint.setLine(SE->getZero(Delta->getType()), DstCoeff, Delta,
1778 CurLoop);
1779 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1780 if (isKnownPredicate(CmpInst::ICMP_EQ, SrcConst, DstConst)) {
1781 if (Level < CommonLevels) {
1783 Result.DV[Level].PeelFirst = true;
1784 ++WeakZeroSIVsuccesses;
1785 }
1786 return false;
1787 }
1788 const SCEVConstant *ConstCoeff = dyn_cast(DstCoeff);
1789 if (!ConstCoeff)
1790 return false;
1791 const SCEV *AbsCoeff =
1794 const SCEV *NewDelta =
1796
1797
1798
1799 if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
1800 LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
1801 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1803 ++WeakZeroSIVindependence;
1804 ++WeakZeroSIVsuccesses;
1805 return true;
1806 }
1807 if (isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
1808
1809 if (Level < CommonLevels) {
1811 Result.DV[Level].PeelLast = true;
1812 ++WeakZeroSIVsuccesses;
1813 }
1814 return false;
1815 }
1816 }
1817
1818
1819
1821
1822 ++WeakZeroSIVindependence;
1823 ++WeakZeroSIVsuccesses;
1824 return true;
1825 }
1826
1827
1828 if (isa(Delta) &&
1829 (cast(Delta), ConstCoeff)) {
1830 ++WeakZeroSIVindependence;
1831 ++WeakZeroSIVsuccesses;
1832 return true;
1833 }
1834 return false;
1835}
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869bool DependenceInfo::weakZeroDstSIVtest(const SCEV *SrcCoeff,
1870 const SCEV *SrcConst,
1871 const SCEV *DstConst,
1872 const Loop *CurLoop, unsigned Level,
1874 Constraint &NewConstraint) const {
1875
1876
1877 LLVM_DEBUG(dbgs() << "\tWeak-Zero (dst) SIV test\n");
1878 LLVM_DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << "\n");
1879 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
1880 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
1881 ++WeakZeroSIVapplications;
1882 assert(0 < Level && Level <= SrcLevels && "Level out of range");
1883 Level--;
1884 Result.Consistent = false;
1886 NewConstraint.setLine(SrcCoeff, SE->getZero(Delta->getType()), Delta,
1887 CurLoop);
1888 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1889 if (isKnownPredicate(CmpInst::ICMP_EQ, DstConst, SrcConst)) {
1890 if (Level < CommonLevels) {
1892 Result.DV[Level].PeelFirst = true;
1893 ++WeakZeroSIVsuccesses;
1894 }
1895 return false;
1896 }
1897 const SCEVConstant *ConstCoeff = dyn_cast(SrcCoeff);
1898 if (!ConstCoeff)
1899 return false;
1900 const SCEV *AbsCoeff =
1903 const SCEV *NewDelta =
1905
1906
1907
1908 if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
1909 LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
1910 const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
1912 ++WeakZeroSIVindependence;
1913 ++WeakZeroSIVsuccesses;
1914 return true;
1915 }
1916 if (isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
1917
1918 if (Level < CommonLevels) {
1920 Result.DV[Level].PeelLast = true;
1921 ++WeakZeroSIVsuccesses;
1922 }
1923 return false;
1924 }
1925 }
1926
1927
1928
1930
1931 ++WeakZeroSIVindependence;
1932 ++WeakZeroSIVsuccesses;
1933 return true;
1934 }
1935
1936
1937 if (isa(Delta) &&
1938 (cast(Delta), ConstCoeff)) {
1939 ++WeakZeroSIVindependence;
1940 ++WeakZeroSIVsuccesses;
1941 return true;
1942 }
1943 return false;
1944}
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954bool DependenceInfo::exactRDIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
1955 const SCEV *SrcConst, const SCEV *DstConst,
1956 const Loop *SrcLoop, const Loop *DstLoop,
1959 LLVM_DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << " = AM\n");
1960 LLVM_DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << " = BM\n");
1961 LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
1962 LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
1963 ++ExactRDIVapplications;
1964 Result.Consistent = false;
1966 LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
1967 const SCEVConstant *ConstDelta = dyn_cast(Delta);
1968 const SCEVConstant *ConstSrcCoeff = dyn_cast(SrcCoeff);
1969 const SCEVConstant *ConstDstCoeff = dyn_cast(DstCoeff);
1970 if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
1971 return false;
1972
1973
1979 if (findGCD(Bits, AM, BM, CM, G, X, Y)) {
1980
1981 ++ExactRDIVindependence;
1982 return true;
1983 }
1984
1985 LLVM_DEBUG(dbgs() << "\t X = " << X << ", Y = " << Y << "\n");
1986
1987
1988 APInt SrcUM(Bits, 1, true);
1989 bool SrcUMvalid = false;
1990
1992 collectConstantUpperBound(SrcLoop, Delta->getType())) {
1993 SrcUM = UpperBound->getAPInt();
1994 LLVM_DEBUG(dbgs() << "\t SrcUM = " << SrcUM << "\n");
1995 SrcUMvalid = true;
1996 }
1997
1998 APInt DstUM(Bits, 1, true);
1999 bool DstUMvalid = false;
2000
2002 collectConstantUpperBound(DstLoop, Delta->getType())) {
2003 DstUM = UpperBound->getAPInt();
2004 LLVM_DEBUG(dbgs() << "\t DstUM = " << DstUM << "\n");
2005 DstUMvalid = true;
2006 }
2007
2016
2019 if (TB.sgt(0)) {
2022 if (SrcUMvalid) {
2025 }
2026 } else {
2029 if (SrcUMvalid) {
2032 }
2033 }
2034
2036 if (TA.sgt(0)) {
2039 if (DstUMvalid) {
2042 }
2043 } else {
2046 if (DstUMvalid) {
2049 }
2050 }
2051
2053 return false;
2054
2057
2062
2063 if (TL.sgt(TU))
2064 ++ExactRDIVindependence;
2065 return TL.sgt(TU);
2066}
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111bool DependenceInfo::symbolicRDIVtest(const SCEV *A1, const SCEV *A2,
2112 const SCEV *C1, const SCEV *C2,
2113 const Loop *Loop1,
2114 const Loop *Loop2) const {
2115 ++SymbolicRDIVapplications;
2122 const SCEV *N1 = collectUpperBound(Loop1, A1->getType());
2123 const SCEV *N2 = collectUpperBound(Loop2, A1->getType());
2124 LLVM_DEBUG(if (N1) dbgs() << "\t N1 = " << *N1 << "\n");
2125 LLVM_DEBUG(if (N2) dbgs() << "\t N2 = " << *N2 << "\n");
2128 LLVM_DEBUG(dbgs() << "\t C2 - C1 = " << *C2_C1 << "\n");
2129 LLVM_DEBUG(dbgs() << "\t C1 - C2 = " << *C1_C2 << "\n");
2132
2133 if (N1) {
2134
2136 LLVM_DEBUG(dbgs() << "\t A1*N1 = " << *A1N1 << "\n");
2138 ++SymbolicRDIVindependence;
2139 return true;
2140 }
2141 }
2142 if (N2) {
2143
2145 LLVM_DEBUG(dbgs() << "\t A2*N2 = " << *A2N2 << "\n");
2147 ++SymbolicRDIVindependence;
2148 return true;
2149 }
2150 }
2151 }
2153
2154 if (N1 && N2) {
2155
2159 LLVM_DEBUG(dbgs() << "\t A1*N1 - A2*N2 = " << *A1N1_A2N2 << "\n");
2161 ++SymbolicRDIVindependence;
2162 return true;
2163 }
2164 }
2165
2167 ++SymbolicRDIVindependence;
2168 return true;
2169 }
2170 }
2171 }
2174
2175 if (N1 && N2) {
2176
2180 LLVM_DEBUG(dbgs() << "\t A1*N1 - A2*N2 = " << *A1N1_A2N2 << "\n");
2182 ++SymbolicRDIVindependence;
2183 return true;
2184 }
2185 }
2186
2188 ++SymbolicRDIVindependence;
2189 return true;
2190 }
2191 }
2193
2194 if (N1) {
2195
2197 LLVM_DEBUG(dbgs() << "\t A1*N1 = " << *A1N1 << "\n");
2199 ++SymbolicRDIVindependence;
2200 return true;
2201 }
2202 }
2203 if (N2) {
2204
2206 LLVM_DEBUG(dbgs() << "\t A2*N2 = " << *A2N2 << "\n");
2208 ++SymbolicRDIVindependence;
2209 return true;
2210 }
2211 }
2212 }
2213 }
2214 return false;
2215}
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226bool DependenceInfo::testSIV(const SCEV *Src, const SCEV *Dst, unsigned &Level,
2228 const SCEV *&SplitIter) const {
2231 const SCEVAddRecExpr *SrcAddRec = dyn_cast(Src);
2232 const SCEVAddRecExpr *DstAddRec = dyn_cast(Dst);
2233 if (SrcAddRec && DstAddRec) {
2234 const SCEV *SrcConst = SrcAddRec->getStart();
2235 const SCEV *DstConst = DstAddRec->getStart();
2238 const Loop *CurLoop = SrcAddRec->getLoop();
2240 "both loops in SIV should be same");
2241 Level = mapSrcLoop(CurLoop);
2242 bool disproven;
2243 if (SrcCoeff == DstCoeff)
2244 disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2245 Level, Result, NewConstraint);
2247 disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2248 Level, Result, NewConstraint, SplitIter);
2249 else
2250 disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
2251 Level, Result, NewConstraint);
2252 return disproven ||
2253 gcdMIVtest(Src, Dst, Result) ||
2254 symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop, CurLoop);
2255 }
2256 if (SrcAddRec) {
2257 const SCEV *SrcConst = SrcAddRec->getStart();
2259 const SCEV *DstConst = Dst;
2260 const Loop *CurLoop = SrcAddRec->getLoop();
2261 Level = mapSrcLoop(CurLoop);
2262 return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
2263 Level, Result, NewConstraint) ||
2264 gcdMIVtest(Src, Dst, Result);
2265 }
2266 if (DstAddRec) {
2267 const SCEV *DstConst = DstAddRec->getStart();
2269 const SCEV *SrcConst = Src;
2270 const Loop *CurLoop = DstAddRec->getLoop();
2271 Level = mapDstLoop(CurLoop);
2272 return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst,
2273 CurLoop, Level, Result, NewConstraint) ||
2274 gcdMIVtest(Src, Dst, Result);
2275 }
2277 return false;
2278}
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294bool DependenceInfo::testRDIV(const SCEV *Src, const SCEV *Dst,
2296
2297
2298
2299
2300
2301
2302 const SCEV *SrcConst, *DstConst;
2303 const SCEV *SrcCoeff, *DstCoeff;
2304 const Loop *SrcLoop, *DstLoop;
2305
2308 const SCEVAddRecExpr *SrcAddRec = dyn_cast(Src);
2309 const SCEVAddRecExpr *DstAddRec = dyn_cast(Dst);
2310 if (SrcAddRec && DstAddRec) {
2311 SrcConst = SrcAddRec->getStart();
2313 SrcLoop = SrcAddRec->getLoop();
2314 DstConst = DstAddRec->getStart();
2316 DstLoop = DstAddRec->getLoop();
2317 }
2318 else if (SrcAddRec) {
2320 dyn_cast(SrcAddRec->getStart())) {
2321 SrcConst = tmpAddRec->getStart();
2322 SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
2323 SrcLoop = tmpAddRec->getLoop();
2324 DstConst = Dst;
2326 DstLoop = SrcAddRec->getLoop();
2327 }
2328 else
2330 }
2331 else if (DstAddRec) {
2333 dyn_cast(DstAddRec->getStart())) {
2334 DstConst = tmpAddRec->getStart();
2335 DstCoeff = tmpAddRec->getStepRecurrence(*SE);
2336 DstLoop = tmpAddRec->getLoop();
2337 SrcConst = Src;
2339 SrcLoop = DstAddRec->getLoop();
2340 }
2341 else
2343 }
2344 else
2346 return exactRDIVtest(SrcCoeff, DstCoeff,
2347 SrcConst, DstConst,
2348 SrcLoop, DstLoop,
2349 Result) ||
2350 gcdMIVtest(Src, Dst, Result) ||
2351 symbolicRDIVtest(SrcCoeff, DstCoeff,
2352 SrcConst, DstConst,
2353 SrcLoop, DstLoop);
2354}
2355
2356
2357
2358
2359
2360bool DependenceInfo::testMIV(const SCEV *Src, const SCEV *Dst,
2365 Result.Consistent = false;
2366 return gcdMIVtest(Src, Dst, Result) ||
2367 banerjeeMIVtest(Src, Dst, Loops, Result);
2368}
2369
2370
2371
2372
2373static
2375 if (const auto *Constant = dyn_cast(Expr))
2377 else if (const auto *Product = dyn_cast(Expr))
2378 if (const auto *Constant = dyn_cast(Product->getOperand(0)))
2380 return nullptr;
2381}
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,
2405 ++GCDapplications;
2408
2409
2410
2411
2412
2413 const SCEV *Coefficients = Src;
2415 dyn_cast(Coefficients)) {
2417
2418
2421 return false;
2424 Coefficients = AddRec->getStart();
2425 }
2426 const SCEV *SrcConst = Coefficients;
2427
2428
2429
2430
2431
2432 Coefficients = Dst;
2434 dyn_cast(Coefficients)) {
2436
2437
2440 return false;
2443 Coefficients = AddRec->getStart();
2444 }
2445 const SCEV *DstConst = Coefficients;
2446
2449 LLVM_DEBUG(dbgs() << " Delta = " << *Delta << "\n");
2451 if (const SCEVAddExpr *Sum = dyn_cast(Delta)) {
2452
2453 for (const SCEV *Operand : Sum->operands()) {
2454 if (isa(Operand)) {
2455 assert( && "Surprised to find multiple constants");
2456 Constant = cast(Operand);
2457 }
2458 else if (const SCEVMulExpr *Product = dyn_cast(Operand)) {
2459
2460
2462 if (!ConstOp)
2463 return false;
2466 ConstOpValue.abs());
2467 }
2468 else
2469 return false;
2470 }
2471 }
2473 return false;
2475 LLVM_DEBUG(dbgs() << " ConstDelta = " << ConstDelta << "\n");
2476 if (ConstDelta == 0)
2477 return false;
2479 LLVM_DEBUG(dbgs() << " RunningGCD = " << RunningGCD << "\n");
2480 APInt Remainder = ConstDelta.srem(RunningGCD);
2481 if (Remainder != 0) {
2482 ++GCDindependence;
2483 return true;
2484 }
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498 LLVM_DEBUG(dbgs() << " ExtraGCD = " << ExtraGCD << '\n');
2499
2500 bool Improved = false;
2501 Coefficients = Src;
2503 dyn_cast(Coefficients)) {
2504 Coefficients = AddRec->getStart();
2505 const Loop *CurLoop = AddRec->getLoop();
2506 RunningGCD = ExtraGCD;
2508 const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
2509 const SCEV *Inner = Src;
2510 while (RunningGCD != 1 && isa(Inner)) {
2511 AddRec = cast(Inner);
2513 if (CurLoop == AddRec->getLoop())
2514 ;
2515 else {
2516
2517
2520 return false;
2523 }
2525 }
2526 Inner = Dst;
2527 while (RunningGCD != 1 && isa(Inner)) {
2528 AddRec = cast(Inner);
2530 if (CurLoop == AddRec->getLoop())
2531 DstCoeff = Coeff;
2532 else {
2533
2534
2537 return false;
2540 }
2542 }
2543 Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
2544
2545
2548
2549
2550 continue;
2553 LLVM_DEBUG(dbgs() << "\tRunningGCD = " << RunningGCD << "\n");
2554 if (RunningGCD != 0) {
2555 Remainder = ConstDelta.srem(RunningGCD);
2556 LLVM_DEBUG(dbgs() << "\tRemainder = " << Remainder << "\n");
2557 if (Remainder != 0) {
2558 unsigned Level = mapSrcLoop(CurLoop);
2560 Improved = true;
2561 }
2562 }
2563 }
2564 if (Improved)
2565 ++GCDsuccesses;
2567 return false;
2568}
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604bool DependenceInfo::banerjeeMIVtest(const SCEV *Src, const SCEV *Dst,
2608 ++BanerjeeApplications;
2610 const SCEV *A0;
2611 CoefficientInfo *A = collectCoeffInfo(Src, true, A0);
2613 const SCEV *B0;
2614 CoefficientInfo *B = collectCoeffInfo(Dst, false, B0);
2615 BoundInfo *Bound = new BoundInfo[MaxLevels + 1];
2617 LLVM_DEBUG(dbgs() << "\tDelta = " << *Delta << '\n');
2618
2619
2621 for (unsigned K = 1; K <= MaxLevels; ++K) {
2622 Bound[K].Iterations = A[K].Iterations ? A[K].Iterations : B[K].Iterations;
2625 findBoundsALL(A, B, Bound, K);
2626#ifndef NDEBUG
2630 else
2634 else
2636#endif
2637 }
2638
2639
2640 bool Disproved = false;
2642
2643 unsigned DepthExpanded = 0;
2644 unsigned NewDeps = exploreDirections(1, A, B, Bound,
2645 Loops, DepthExpanded, Delta);
2646 if (NewDeps > 0) {
2647 bool Improved = false;
2648 for (unsigned K = 1; K <= CommonLevels; ++K) {
2650 unsigned Old = Result.DV[K - 1].Direction;
2651 Result.DV[K - 1].Direction = Old & Bound[K].DirSet;
2652 Improved |= Old != Result.DV[K - 1].Direction;
2653 if (.DV[K - 1].Direction) {
2654 Improved = false;
2655 Disproved = true;
2656 break;
2657 }
2658 }
2659 }
2660 if (Improved)
2661 ++BanerjeeSuccesses;
2662 }
2663 else {
2664 ++BanerjeeIndependence;
2665 Disproved = true;
2666 }
2667 }
2668 else {
2669 ++BanerjeeIndependence;
2670 Disproved = true;
2671 }
2672 delete [] Bound;
2673 delete [] A;
2674 delete [] B;
2675 return Disproved;
2676}
2677
2678
2679
2680
2681
2682
2683
2684unsigned DependenceInfo::exploreDirections(unsigned Level, CoefficientInfo *A,
2685 CoefficientInfo *B, BoundInfo *Bound,
2687 unsigned &DepthExpanded,
2688 const SCEV *Delta) const {
2689
2690
2691
2692
2694 LLVM_DEBUG(dbgs() << "Number of common levels exceeded the threshold. MIV "
2695 "direction exploration is terminated.\n");
2696 for (unsigned K = 1; K <= CommonLevels; ++K)
2699 return 1;
2700 }
2701
2702 if (Level > CommonLevels) {
2703
2705 for (unsigned K = 1; K <= CommonLevels; ++K) {
2707 Bound[K].DirSet |= Bound[K].Direction;
2708#ifndef NDEBUG
2712 break;
2715 break;
2718 break;
2721 break;
2722 default:
2724 }
2725#endif
2726 }
2727 }
2729 return 1;
2730 }
2731 if (Loops[Level]) {
2732 if (Level > DepthExpanded) {
2733 DepthExpanded = Level;
2734
2735 findBoundsLT(A, B, Bound, Level);
2736 findBoundsGT(A, B, Bound, Level);
2737 findBoundsEQ(A, B, Bound, Level);
2738#ifndef NDEBUG
2739 LLVM_DEBUG(dbgs() << "\tBound for level = " << Level << '\n');
2743 << '\t');
2744 else
2748 << '\n');
2749 else
2754 << '\t');
2755 else
2759 << '\n');
2760 else
2765 << '\t');
2766 else
2770 << '\n');
2771 else
2773#endif
2774 }
2775
2776 unsigned NewDeps = 0;
2777
2778
2780 NewDeps += exploreDirections(Level + 1, A, B, Bound,
2781 Loops, DepthExpanded, Delta);
2782
2783
2785 NewDeps += exploreDirections(Level + 1, A, B, Bound,
2786 Loops, DepthExpanded, Delta);
2787
2788
2790 NewDeps += exploreDirections(Level + 1, A, B, Bound,
2791 Loops, DepthExpanded, Delta);
2792
2794 return NewDeps;
2795 }
2796 else
2797 return exploreDirections(Level + 1, A, B, Bound, Loops, DepthExpanded, Delta);
2798}
2799
2800
2801
2802bool DependenceInfo::testBounds(unsigned char DirKind, unsigned Level,
2803 BoundInfo *Bound, const SCEV *Delta) const {
2804 Bound[Level].Direction = DirKind;
2805 if (const SCEV *LowerBound = getLowerBound(Bound))
2807 return false;
2808 if (const SCEV *UpperBound = getUpperBound(Bound))
2810 return false;
2811 return true;
2812}
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830void DependenceInfo::findBoundsALL(CoefficientInfo *A, CoefficientInfo *B,
2831 BoundInfo *Bound, unsigned K) const {
2834 if (Bound[K].Iterations) {
2837 Bound[K].Iterations);
2840 Bound[K].Iterations);
2841 }
2842 else {
2843
2850 }
2851}
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869void DependenceInfo::findBoundsEQ(CoefficientInfo *A, CoefficientInfo *B,
2870 BoundInfo *Bound, unsigned K) const {
2873 if (Bound[K].Iterations) {
2875 const SCEV *NegativePart = getNegativePart(Delta);
2877 SE->getMulExpr(NegativePart, Bound[K].Iterations);
2878 const SCEV *PositivePart = getPositivePart(Delta);
2880 SE->getMulExpr(PositivePart, Bound[K].Iterations);
2881 }
2882 else {
2883
2884
2886 const SCEV *NegativePart = getNegativePart(Delta);
2887 if (NegativePart->isZero())
2889 const SCEV *PositivePart = getPositivePart(Delta);
2890 if (PositivePart->isZero())
2892 }
2893}
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909void DependenceInfo::findBoundsLT(CoefficientInfo *A, CoefficientInfo *B,
2910 BoundInfo *Bound, unsigned K) const {
2913 if (Bound[K].Iterations) {
2915 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2916 const SCEV *NegPart =
2917 getNegativePart(SE->getMinusSCEV(A[K].NegPart, B[K].Coeff));
2920 const SCEV *PosPart =
2921 getPositivePart(SE->getMinusSCEV(A[K].PosPart, B[K].Coeff));
2924 }
2925 else {
2926
2927
2928 const SCEV *NegPart =
2929 getNegativePart(SE->getMinusSCEV(A[K].NegPart, B[K].Coeff));
2930 if (NegPart->isZero())
2932 const SCEV *PosPart =
2933 getPositivePart(SE->getMinusSCEV(A[K].PosPart, B[K].Coeff));
2934 if (PosPart->isZero())
2936 }
2937}
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953void DependenceInfo::findBoundsGT(CoefficientInfo *A, CoefficientInfo *B,
2954 BoundInfo *Bound, unsigned K) const {
2957 if (Bound[K].Iterations) {
2959 Bound[K].Iterations, SE->getOne(Bound[K].Iterations->getType()));
2960 const SCEV *NegPart =
2961 getNegativePart(SE->getMinusSCEV(A[K].Coeff, B[K].PosPart));
2964 const SCEV *PosPart =
2965 getPositivePart(SE->getMinusSCEV(A[K].Coeff, B[K].NegPart));
2968 }
2969 else {
2970
2971
2972 const SCEV *NegPart = getNegativePart(SE->getMinusSCEV(A[K].Coeff, B[K].PosPart));
2973 if (NegPart->isZero())
2975 const SCEV *PosPart = getPositivePart(SE->getMinusSCEV(A[K].Coeff, B[K].NegPart));
2976 if (PosPart->isZero())
2978 }
2979}
2980
2981
2982
2983const SCEV *DependenceInfo::getPositivePart(const SCEV *X) const {
2985}
2986
2987
2988
2989const SCEV *DependenceInfo::getNegativePart(const SCEV *X) const {
2991}
2992
2993
2994
2995
2996
2997DependenceInfo::CoefficientInfo *
2998DependenceInfo::collectCoeffInfo(const SCEV *Subscript, bool SrcFlag,
3001 CoefficientInfo *CI = new CoefficientInfo[MaxLevels + 1];
3002 for (unsigned K = 1; K <= MaxLevels; ++K) {
3006 CI[K].Iterations = nullptr;
3007 }
3008 while (const SCEVAddRecExpr *AddRec = dyn_cast(Subscript)) {
3010 unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(L);
3012 CI[K].PosPart = getPositivePart(CI[K].Coeff);
3013 CI[K].NegPart = getNegativePart(CI[K].Coeff);
3014 CI[K].Iterations = collectUpperBound(L, Subscript->getType());
3015 Subscript = AddRec->getStart();
3016 }
3018#ifndef NDEBUG
3020 for (unsigned K = 1; K <= MaxLevels; ++K) {
3021 LLVM_DEBUG(dbgs() << "\t " << K << "\t" << *CI[K].Coeff);
3027 if (CI[K].Iterations)
3029 else
3032 }
3033 LLVM_DEBUG(dbgs() << "\t Constant = " << *Subscript << '\n');
3034#endif
3035 return CI;
3036}
3037
3038
3039
3040
3041
3042
3043const SCEV *DependenceInfo::getLowerBound(BoundInfo *Bound) const {
3044 const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
3045 for (unsigned K = 2; Sum && K <= MaxLevels; ++K) {
3048 else
3049 Sum = nullptr;
3050 }
3051 return Sum;
3052}
3053
3054
3055
3056
3057
3058
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) {
3064 else
3065 Sum = nullptr;
3066 }
3067 return Sum;
3068}
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080const SCEV *DependenceInfo::findCoefficient(const SCEV *Expr,
3081 const Loop *TargetLoop) const {
3082 const SCEVAddRecExpr *AddRec = dyn_cast(Expr);
3083 if (!AddRec)
3085 if (AddRec->getLoop() == TargetLoop)
3087 return findCoefficient(AddRec->getStart(), TargetLoop);
3088}
3089
3090
3091
3092
3093
3094
3095
3096const SCEV *DependenceInfo::zeroCoefficient(const SCEV *Expr,
3097 const Loop *TargetLoop) const {
3098 const SCEVAddRecExpr *AddRec = dyn_cast(Expr);
3099 if (!AddRec)
3100 return Expr;
3101 if (AddRec->getLoop() == TargetLoop)
3107}
3108
3109
3110
3111
3112
3113
3114
3115const SCEV *DependenceInfo::addToCoefficient(const SCEV *Expr,
3116 const Loop *TargetLoop,
3118 const SCEVAddRecExpr *AddRec = dyn_cast(Expr);
3119 if (!AddRec)
3122 TargetLoop,
3124 if (AddRec->getLoop() == TargetLoop) {
3129 Sum,
3132 }
3136 addToCoefficient(AddRec->getStart(), TargetLoop, Value),
3139}
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152bool DependenceInfo::propagate(const SCEV *&Src, const SCEV *&Dst,
3155 bool &Consistent) {
3156 bool Result = false;
3157 for (unsigned LI : Loops.set_bits()) {
3158 LLVM_DEBUG(dbgs() << "\t Constraint[" << LI << "] is");
3160 if (Constraints[LI].isDistance())
3161 Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
3162 else if (Constraints[LI].isLine())
3163 Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
3164 else if (Constraints[LI].isPoint())
3165 Result |= propagatePoint(Src, Dst, Constraints[LI]);
3166 }
3168}
3169
3170
3171
3172
3173
3174
3175
3176bool DependenceInfo::propagateDistance(const SCEV *&Src, const SCEV *&Dst,
3177 Constraint &CurConstraint,
3178 bool &Consistent) {
3179 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3180 LLVM_DEBUG(dbgs() << "\t\tSrc is " << *Src << "\n");
3181 const SCEV *A_K = findCoefficient(Src, CurLoop);
3183 return false;
3184 const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
3186 Src = zeroCoefficient(Src, CurLoop);
3187 LLVM_DEBUG(dbgs() << "\t\tnew Src is " << *Src << "\n");
3188 LLVM_DEBUG(dbgs() << "\t\tDst is " << *Dst << "\n");
3189 Dst = addToCoefficient(Dst, CurLoop, SE->getNegativeSCEV(A_K));
3190 LLVM_DEBUG(dbgs() << "\t\tnew Dst is " << *Dst << "\n");
3191 if (!findCoefficient(Dst, CurLoop)->isZero())
3192 Consistent = false;
3193 return true;
3194}
3195
3196
3197
3198
3199
3200
3201
3202bool DependenceInfo::propagateLine(const SCEV *&Src, const SCEV *&Dst,
3203 Constraint &CurConstraint,
3204 bool &Consistent) {
3205 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3206 const SCEV *A = CurConstraint.getA();
3207 const SCEV *B = CurConstraint.getB();
3208 const SCEV *C = CurConstraint.getC();
3209 LLVM_DEBUG(dbgs() << "\t\tA = " << *A << ", B = " << *B << ", C = " << *C
3210 << "\n");
3213 if (A->isZero()) {
3214 const SCEVConstant *Bconst = dyn_cast(B);
3215 const SCEVConstant *Cconst = dyn_cast(C);
3216 if (!Bconst || !Cconst) return false;
3219 APInt CdivB = Charlie.sdiv(Beta);
3220 assert(Charlie.srem(Beta) == 0 && "C should be evenly divisible by B");
3221 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3222
3224 Dst = zeroCoefficient(Dst, CurLoop);
3225 if (!findCoefficient(Src, CurLoop)->isZero())
3226 Consistent = false;
3227 }
3228 else if (B->isZero()) {
3229 const SCEVConstant *Aconst = dyn_cast(A);
3230 const SCEVConstant *Cconst = dyn_cast(C);
3231 if (!Aconst || !Cconst) return false;
3234 APInt CdivA = Charlie.sdiv(Alpha);
3235 assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
3236 const SCEV *A_K = findCoefficient(Src, CurLoop);
3238 Src = zeroCoefficient(Src, CurLoop);
3239 if (!findCoefficient(Dst, CurLoop)->isZero())
3240 Consistent = false;
3241 }
3243 const SCEVConstant *Aconst = dyn_cast(A);
3244 const SCEVConstant *Cconst = dyn_cast(C);
3245 if (!Aconst || !Cconst) return false;
3248 APInt CdivA = Charlie.sdiv(Alpha);
3249 assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
3250 const SCEV *A_K = findCoefficient(Src, CurLoop);
3252 Src = zeroCoefficient(Src, CurLoop);
3253 Dst = addToCoefficient(Dst, CurLoop, A_K);
3254 if (!findCoefficient(Dst, CurLoop)->isZero())
3255 Consistent = false;
3256 }
3257 else {
3258
3259 const SCEV *A_K = findCoefficient(Src, CurLoop);
3263 Src = zeroCoefficient(Src, CurLoop);
3264 Dst = addToCoefficient(Dst, CurLoop, SE->getMulExpr(A_K, B));
3265 if (!findCoefficient(Dst, CurLoop)->isZero())
3266 Consistent = false;
3267 }
3268 LLVM_DEBUG(dbgs() << "\t\tnew Src = " << *Src << "\n");
3269 LLVM_DEBUG(dbgs() << "\t\tnew Dst = " << *Dst << "\n");
3270 return true;
3271}
3272
3273
3274
3275
3276
3277bool DependenceInfo::propagatePoint(const SCEV *&Src, const SCEV *&Dst,
3278 Constraint &CurConstraint) {
3279 const Loop *CurLoop = CurConstraint.getAssociatedLoop();
3280 const SCEV *A_K = findCoefficient(Src, CurLoop);
3281 const SCEV *AP_K = findCoefficient(Dst, CurLoop);
3282 const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
3283 const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
3284 LLVM_DEBUG(dbgs() << "\t\tSrc is " << *Src << "\n");
3286 Src = zeroCoefficient(Src, CurLoop);
3287 LLVM_DEBUG(dbgs() << "\t\tnew Src is " << *Src << "\n");
3288 LLVM_DEBUG(dbgs() << "\t\tDst is " << *Dst << "\n");
3289 Dst = zeroCoefficient(Dst, CurLoop);
3290 LLVM_DEBUG(dbgs() << "\t\tnew Dst is " << *Dst << "\n");
3291 return true;
3292}
3293
3294
3295
3297 const Constraint &CurConstraint) const {
3298 LLVM_DEBUG(dbgs() << "\tUpdate direction, constraint =");
3300 if (CurConstraint.isAny())
3301 ;
3302 else if (CurConstraint.isDistance()) {
3303
3304 Level.Scalar = false;
3305 Level.Distance = CurConstraint.getD();
3307 if (!SE->isKnownNonZero(Level.Distance))
3313 Level.Direction &= NewDirection;
3314 }
3315 else if (CurConstraint.isLine()) {
3316 Level.Scalar = false;
3317 Level.Distance = nullptr;
3318
3319 }
3320 else if (CurConstraint.isPoint()) {
3321 Level.Scalar = false;
3322 Level.Distance = nullptr;
3325 CurConstraint.getY(),
3326 CurConstraint.getX()))
3327
3330 CurConstraint.getY(),
3331 CurConstraint.getX()))
3332
3335 CurConstraint.getY(),
3336 CurConstraint.getX()))
3337
3339 Level.Direction &= NewDirection;
3340 }
3341 else
3343}
3344
3345
3346
3347
3348
3360 dyn_cast(SE->getPointerBase(SrcAccessFn));
3362 dyn_cast(SE->getPointerBase(DstAccessFn));
3363
3364 if (!SrcBase || !DstBase || SrcBase != DstBase)
3365 return false;
3366
3368
3369 if (!tryDelinearizeFixedSize(Src, Dst, SrcAccessFn, DstAccessFn,
3370 SrcSubscripts, DstSubscripts) &&
3371 !tryDelinearizeParametricSize(Src, Dst, SrcAccessFn, DstAccessFn,
3372 SrcSubscripts, DstSubscripts))
3373 return false;
3374
3375 int Size = SrcSubscripts.size();
3377 dbgs() << "\nSrcSubscripts: ";
3378 for (int I = 0; I < Size; I++)
3379 dbgs() << *SrcSubscripts[I];
3380 dbgs() << "\nDstSubscripts: ";
3381 for (int I = 0; I < Size; I++)
3382 dbgs() << *DstSubscripts[I];
3383 });
3384
3385
3386
3387
3388
3390 for (int I = 0; I < Size; ++I) {
3391 Pair[I].Src = SrcSubscripts[I];
3392 Pair[I].Dst = DstSubscripts[I];
3393 unifySubscriptType(&Pair[I]);
3394 }
3395
3396 return true;
3397}
3398
3399
3400
3401
3402bool DependenceInfo::tryDelinearizeFixedSize(
3408 dyn_cast(SE->getPointerBase(SrcAccessFn));
3410 dyn_cast(SE->getPointerBase(DstAccessFn));
3411 assert(SrcBase && DstBase && SrcBase == DstBase &&
3412 "expected src and dst scev unknowns to be equal");
3413 });
3414
3418 SrcSizes) ||
3420 DstSizes))
3421 return false;
3422
3423
3424
3425 if (SrcSizes.size() != DstSizes.size() ||
3426 !std::equal(SrcSizes.begin(), SrcSizes.end(), DstSizes.begin())) {
3427 SrcSubscripts.clear();
3428 DstSubscripts.clear();
3429 return false;
3430 }
3431
3432 assert(SrcSubscripts.size() == DstSubscripts.size() &&
3433 "Expected equal number of entries in the list of SrcSubscripts and "
3434 "DstSubscripts.");
3435
3438
3439
3440
3441
3442
3443
3444
3449 size_t SSize = Subscripts.size();
3450 for (size_t I = 1; I < SSize; ++I) {
3451 const SCEV *S = Subscripts[I];
3452 if (!isKnownNonNegative(S, Ptr))
3453 return false;
3454 if (auto *SType = dyn_cast(S->getType())) {
3456 ConstantInt::get(SType, DimensionSizes[I - 1], false));
3457 if (!isKnownLessThan(S, Range))
3458 return false;
3459 }
3460 }
3461 return true;
3462 };
3463
3464 if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) ||
3465 !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) {
3466 SrcSubscripts.clear();
3467 DstSubscripts.clear();
3468 return false;
3469 }
3470 }
3472 dbgs() << "Delinearized subscripts of fixed-size array\n"
3473 << "SrcGEP:" << *SrcPtr << "\n"
3474 << "DstGEP:" << *DstPtr << "\n";
3475 });
3476 return true;
3477}
3478
3479bool DependenceInfo::tryDelinearizeParametricSize(
3483
3487 dyn_cast(SE->getPointerBase(SrcAccessFn));
3489 dyn_cast(SE->getPointerBase(DstAccessFn));
3490 assert(SrcBase && DstBase && SrcBase == DstBase &&
3491 "expected src and dst scev unknowns to be equal");
3492
3495 return false;
3496
3497 const SCEV *SrcSCEV = SE->getMinusSCEV(SrcAccessFn, SrcBase);
3498 const SCEV *DstSCEV = SE->getMinusSCEV(DstAccessFn, DstBase);
3499
3500 const SCEVAddRecExpr *SrcAR = dyn_cast(SrcSCEV);
3501 const SCEVAddRecExpr *DstAR = dyn_cast(DstSCEV);
3502 if (!SrcAR || !DstAR || !SrcAR->isAffine() || !DstAR->isAffine())
3503 return false;
3504
3505
3509
3510
3513
3514
3517
3518
3519 if (SrcSubscripts.size() < 2 || DstSubscripts.size() < 2 ||
3520 SrcSubscripts.size() != DstSubscripts.size())
3521 return false;
3522
3523 size_t Size = SrcSubscripts.size();
3524
3525
3526
3527
3528
3529
3530
3532 for (size_t I = 1; I < Size; ++I) {
3533 if (!isKnownNonNegative(SrcSubscripts[I], SrcPtr))
3534 return false;
3535
3536 if (!isKnownLessThan(SrcSubscripts[I], Sizes[I - 1]))
3537 return false;
3538
3539 if (!isKnownNonNegative(DstSubscripts[I], DstPtr))
3540 return false;
3541
3542 if (!isKnownLessThan(DstSubscripts[I], Sizes[I - 1]))
3543 return false;
3544 }
3545
3546 return true;
3547}
3548
3549
3550
3551#ifndef NDEBUG
3552
3554 dbgs() << "{";
3555 for (unsigned VI : BV.set_bits()) {
3556 dbgs() << VI;
3558 dbgs() << ' ';
3559 }
3560 dbgs() << "}\n";
3561}
3562#endif
3563
3566
3569 return true;
3570
3571
3575}
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588std::unique_ptr
3590 bool PossiblyLoopIndependent) {
3591 if (Src == Dst)
3592 PossiblyLoopIndependent = false;
3593
3594 if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
3595
3596 return nullptr;
3597
3599
3600 LLVM_DEBUG(dbgs() << "can only handle simple loads and stores\n");
3601 return std::make_unique(Src, Dst);
3602 }
3603
3608
3614
3615 LLVM_DEBUG(dbgs() << "can't analyze may or partial alias\n");
3616 return std::make_unique(Src, Dst);
3618
3620 return nullptr;
3622 break;
3623 }
3624
3625
3626 establishNestingLevels(Src, Dst);
3627 LLVM_DEBUG(dbgs() << " common nesting levels = " << CommonLevels << "\n");
3628 LLVM_DEBUG(dbgs() << " maximum nesting levels = " << MaxLevels << "\n");
3629
3630 FullDependence Result(Src, Dst, PossiblyLoopIndependent, CommonLevels);
3631 ++TotalArrayPairs;
3632
3633 unsigned Pairs = 1;
3635 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
3636 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
3637 LLVM_DEBUG(dbgs() << " SrcSCEV = " << *SrcSCEV << "\n");
3638 LLVM_DEBUG(dbgs() << " DstSCEV = " << *DstSCEV << "\n");
3640
3641
3642
3643
3644
3645
3646 LLVM_DEBUG(dbgs() << "can't analyze SCEV with different pointer base\n");
3647 return std::make_unique(Src, Dst);
3648 }
3649 Pair[0].Src = SrcSCEV;
3650 Pair[0].Dst = DstSCEV;
3651
3653 if (tryDelinearize(Src, Dst, Pair)) {
3655 Pairs = Pair.size();
3656 }
3657 }
3658
3659 for (unsigned P = 0; P < Pairs; ++P) {
3660 Pair[P].Loops.resize(MaxLevels + 1);
3661 Pair[P].GroupLoops.resize(MaxLevels + 1);
3662 Pair[P].Group.resize(Pairs);
3663 removeMatchingExtensions(&Pair[P]);
3664 Pair[P].Classification =
3665 classifyPair(Pair[P].Src, LI->getLoopFor(Src->getParent()),
3666 Pair[P].Dst, LI->getLoopFor(Dst->getParent()),
3667 Pair[P].Loops);
3668 Pair[P].GroupLoops = Pair[P].Loops;
3671 LLVM_DEBUG(dbgs() << "\tsrc = " << *Pair[P].Src << "\n");
3672 LLVM_DEBUG(dbgs() << "\tdst = " << *Pair[P].Dst << "\n");
3673 LLVM_DEBUG(dbgs() << "\tclass = " << Pair[P].Classification << "\n");
3676 }
3677
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738 for (unsigned SI = 0; SI < Pairs; ++SI) {
3739 if (Pair[SI].Classification == Subscript::NonLinear) {
3740
3741 ++NonlinearSubscriptPairs;
3742 collectCommonLoops(Pair[SI].Src,
3744 Pair[SI].Loops);
3745 collectCommonLoops(Pair[SI].Dst,
3747 Pair[SI].Loops);
3748 Result.Consistent = false;
3749 } else if (Pair[SI].Classification == Subscript::ZIV) {
3750
3751 Separable.set(SI);
3752 }
3753 else {
3754
3755 bool Done = true;
3756 for (unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
3758 Intersection &= Pair[SJ].GroupLoops;
3759 if (Intersection.any()) {
3760
3761 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
3762
3763 Pair[SJ].Group |= Pair[SI].Group;
3764 Done = false;
3765 }
3766 }
3768 if (Pair[SI].Group.count() == 1) {
3769 Separable.set(SI);
3770 ++SeparableSubscriptPairs;
3771 }
3772 else {
3773 Coupled.set(SI);
3774 ++CoupledSubscriptPairs;
3775 }
3776 }
3777 }
3778 }
3779
3784
3785 Constraint NewConstraint;
3786 NewConstraint.setAny(SE);
3787
3788
3789 for (unsigned SI : Separable.set_bits()) {
3791 switch (Pair[SI].Classification) {
3792 case Subscript::ZIV:
3794 if (testZIV(Pair[SI].Src, Pair[SI].Dst, Result))
3795 return nullptr;
3796 break;
3797 case Subscript::SIV: {
3799 unsigned Level;
3800 const SCEV *SplitIter = nullptr;
3801 if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level, Result, NewConstraint,
3802 SplitIter))
3803 return nullptr;
3804 break;
3805 }
3806 case Subscript::RDIV:
3808 if (testRDIV(Pair[SI].Src, Pair[SI].Dst, Result))
3809 return nullptr;
3810 break;
3811 case Subscript::MIV:
3813 if (testMIV(Pair[SI].Src, Pair[SI].Dst, Pair[SI].Loops, Result))
3814 return nullptr;
3815 break;
3816 default:
3817 llvm_unreachable("subscript has unexpected classification");
3818 }
3819 }
3820
3821 if (Coupled.count()) {
3822
3823 LLVM_DEBUG(dbgs() << "starting on coupled subscripts\n");
3824 LLVM_DEBUG(dbgs() << "MaxLevels + 1 = " << MaxLevels + 1 << "\n");
3826 for (unsigned II = 0; II <= MaxLevels; ++II)
3827 Constraints[II].setAny(SE);
3828 for (unsigned SI : Coupled.set_bits()) {
3829 LLVM_DEBUG(dbgs() << "testing subscript group " << SI << " { ");
3835 for (unsigned SJ : Group.set_bits()) {
3837 if (Pair[SJ].Classification == Subscript::SIV)
3838 Sivs.set(SJ);
3839 else
3840 Mivs.set(SJ);
3841 PairsInGroup.push_back(&Pair[SJ]);
3842 }
3843 unifySubscriptType(PairsInGroup);
3845 while (Sivs.any()) {
3846 bool Changed = false;
3847 for (unsigned SJ : Sivs.set_bits()) {
3848 LLVM_DEBUG(dbgs() << "testing subscript " << SJ << ", SIV\n");
3849
3850 unsigned Level;
3851 const SCEV *SplitIter = nullptr;
3853 if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level, Result, NewConstraint,
3854 SplitIter))
3855 return nullptr;
3856 ConstrainedLevels.set(Level);
3857 if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
3858 if (Constraints[Level].isEmpty()) {
3859 ++DeltaIndependence;
3860 return nullptr;
3861 }
3862 Changed = true;
3863 }
3865 }
3866 if (Changed) {
3867
3871 for (unsigned SJ : Mivs.set_bits()) {
3872
3874 if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops,
3875 Constraints, Result.Consistent)) {
3877 ++DeltaPropagations;
3878 Pair[SJ].Classification =
3879 classifyPair(Pair[SJ].Src, LI->getLoopFor(Src->getParent()),
3880 Pair[SJ].Dst, LI->getLoopFor(Dst->getParent()),
3881 Pair[SJ].Loops);
3882 switch (Pair[SJ].Classification) {
3883 case Subscript::ZIV:
3885 if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3886 return nullptr;
3888 break;
3889 case Subscript::SIV:
3890 Sivs.set(SJ);
3892 break;
3893 case Subscript::RDIV:
3894 case Subscript::MIV:
3895 break;
3896 default:
3898 }
3899 }
3900 }
3901 }
3902 }
3903
3904
3905 for (unsigned SJ : Mivs.set_bits()) {
3906 if (Pair[SJ].Classification == Subscript::RDIV) {
3908 if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
3909 return nullptr;
3910
3912 }
3913 }
3914
3915
3916
3917
3918 for (unsigned SJ : Mivs.set_bits()) {
3919 if (Pair[SJ].Classification == Subscript::MIV) {
3921 if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops, Result))
3922 return nullptr;
3923 }
3924 else
3925 llvm_unreachable("expected only MIV subscripts at this point");
3926 }
3927
3928
3930 for (unsigned SJ : ConstrainedLevels.set_bits()) {
3931 if (SJ > CommonLevels)
3932 break;
3933 updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
3935 return nullptr;
3936 }
3937 }
3938 }
3939
3940
3942 for (unsigned SI = 0; SI < Pairs; ++SI)
3943 CompleteLoops |= Pair[SI].Loops;
3944 for (unsigned II = 1; II <= CommonLevels; ++II)
3945 if (CompleteLoops[II])
3946 Result.DV[II - 1].Scalar = false;
3947
3948 if (PossiblyLoopIndependent) {
3949
3950
3951
3952 for (unsigned II = 1; II <= CommonLevels; ++II) {
3954 Result.LoopIndependent = false;
3955 break;
3956 }
3957 }
3958 }
3959 else {
3960
3961
3962 bool AllEqual = true;
3963 for (unsigned II = 1; II <= CommonLevels; ++II) {
3965 AllEqual = false;
3966 break;
3967 }
3968 }
3969 if (AllEqual)
3970 return nullptr;
3971 }
3972
3973 return std::make_unique(std::move(Result));
3974}
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4024 unsigned SplitLevel) {
4026 "Dep should be splitable at SplitLevel");
4029 assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
4030 assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
4038
4039
4040 establishNestingLevels(Src, Dst);
4041
4042 FullDependence Result(Src, Dst, false, CommonLevels);
4043
4044 unsigned Pairs = 1;
4046 const SCEV *SrcSCEV = SE->getSCEV(SrcPtr);
4047 const SCEV *DstSCEV = SE->getSCEV(DstPtr);
4048 Pair[0].Src = SrcSCEV;
4049 Pair[0].Dst = DstSCEV;
4050
4052 if (tryDelinearize(Src, Dst, Pair)) {
4054 Pairs = Pair.size();
4055 }
4056 }
4057
4058 for (unsigned P = 0; P < Pairs; ++P) {
4059 Pair[P].Loops.resize(MaxLevels + 1);
4060 Pair[P].GroupLoops.resize(MaxLevels + 1);
4061 Pair[P].Group.resize(Pairs);
4062 removeMatchingExtensions(&Pair[P]);
4063 Pair[P].Classification =
4064 classifyPair(Pair[P].Src, LI->getLoopFor(Src->getParent()),
4065 Pair[P].Dst, LI->getLoopFor(Dst->getParent()),
4066 Pair[P].Loops);
4067 Pair[P].GroupLoops = Pair[P].Loops;
4069 }
4070
4073
4074
4075 for (unsigned SI = 0; SI < Pairs; ++SI) {
4076 if (Pair[SI].Classification == Subscript::NonLinear) {
4077
4078 collectCommonLoops(Pair[SI].Src,
4080 Pair[SI].Loops);
4081 collectCommonLoops(Pair[SI].Dst,
4083 Pair[SI].Loops);
4084 Result.Consistent = false;
4085 }
4086 else if (Pair[SI].Classification == Subscript::ZIV)
4087 Separable.set(SI);
4088 else {
4089
4090 bool Done = true;
4091 for (unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
4093 Intersection &= Pair[SJ].GroupLoops;
4094 if (Intersection.any()) {
4095
4096 Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
4097
4098 Pair[SJ].Group |= Pair[SI].Group;
4099 Done = false;
4100 }
4101 }
4103 if (Pair[SI].Group.count() == 1)
4104 Separable.set(SI);
4105 else
4106 Coupled.set(SI);
4107 }
4108 }
4109 }
4110
4111 Constraint NewConstraint;
4112 NewConstraint.setAny(SE);
4113
4114
4115 for (unsigned SI : Separable.set_bits()) {
4116 switch (Pair[SI].Classification) {
4117 case Subscript::SIV: {
4118 unsigned Level;
4119 const SCEV *SplitIter = nullptr;
4120 (void) testSIV(Pair[SI].Src, Pair[SI].Dst, Level,
4121 Result, NewConstraint, SplitIter);
4122 if (Level == SplitLevel) {
4123 assert(SplitIter != nullptr);
4124 return SplitIter;
4125 }
4126 break;
4127 }
4128 case Subscript::ZIV:
4129 case Subscript::RDIV:
4130 case Subscript::MIV:
4131 break;
4132 default:
4133 llvm_unreachable("subscript has unexpected classification");
4134 }
4135 }
4136
4137 if (Coupled.count()) {
4138
4140 for (unsigned II = 0; II <= MaxLevels; ++II)
4141 Constraints[II].setAny(SE);
4142 for (unsigned SI : Coupled.set_bits()) {
4147 for (unsigned SJ : Group.set_bits()) {
4148 if (Pair[SJ].Classification == Subscript::SIV)
4149 Sivs.set(SJ);
4150 else
4151 Mivs.set(SJ);
4152 }
4153 while (Sivs.any()) {
4154 bool Changed = false;
4155 for (unsigned SJ : Sivs.set_bits()) {
4156
4157 unsigned Level;
4158 const SCEV *SplitIter = nullptr;
4159 (void) testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level,
4160 Result, NewConstraint, SplitIter);
4161 if (Level == SplitLevel && SplitIter)
4162 return SplitIter;
4163 ConstrainedLevels.set(Level);
4164 if (intersectConstraints(&Constraints[Level], &NewConstraint))
4165 Changed = true;
4167 }
4168 if (Changed) {
4169
4170 for (unsigned SJ : Mivs.set_bits()) {
4171
4172 if (propagate(Pair[SJ].Src, Pair[SJ].Dst,
4173 Pair[SJ].Loops, Constraints, Result.Consistent)) {
4174 Pair[SJ].Classification =
4175 classifyPair(Pair[SJ].Src, LI->getLoopFor(Src->getParent()),
4176 Pair[SJ].Dst, LI->getLoopFor(Dst->getParent()),
4177 Pair[SJ].Loops);
4178 switch (Pair[SJ].Classification) {
4179 case Subscript::ZIV:
4181 break;
4182 case Subscript::SIV:
4183 Sivs.set(SJ);
4185 break;
4186 case Subscript::RDIV:
4187 case Subscript::MIV:
4188 break;
4189 default:
4191 }
4192 }
4193 }
4194 }
4195 }
4196 }
4197 }
4199 return nullptr;
4200}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
block Block Frequency Analysis
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static bool isLoadOrStore(const Instruction *I)
static bool findGCD(unsigned Bits, const APInt &AM, const APInt &BM, const APInt &Delta, APInt &G, APInt &X, APInt &Y)
static void dumpSmallBitVector(SmallBitVector &BV)
static const SCEVConstant * getConstantPart(const SCEV *Expr)
static APInt ceilingOfQuotient(const APInt &A, const APInt &B)
static APInt floorOfQuotient(const APInt &A, const APInt &B)
static AliasResult underlyingObjectsAlias(AAResults *AA, const DataLayout &DL, const MemoryLocation &LocA, const MemoryLocation &LocB)
static bool isRemainderZero(const SCEVConstant *Dividend, const SCEVConstant *Divisor)
static cl::opt< bool > Delinearize("da-delinearize", cl::init(true), cl::Hidden, cl::desc("Try to delinearize array references."))
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, ScalarEvolution &SE, bool NormalizeResults)
static cl::opt< unsigned > MIVMaxLevelThreshold("da-miv-max-level-threshold", cl::init(7), cl::Hidden, cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors."))
static cl::opt< bool > DisableDelinearizationChecks("da-disable-delinearization-checks", cl::Hidden, cl::desc("Disable checks that try to statically verify validity of " "delinearized subscripts. Enabling this option may result in incorrect " "dependence vectors for languages that allow the subscript of one " "dimension to underflow or overflow into another dimension."))
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
APInt abs() const
Get the absolute value.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
bool sle(const APInt &RHS) const
Signed less or equal comparison.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
The possible results of an alias query.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
This templated class represents "all analyses that operate over " (e....
API to communicate dependencies between analyses during invalidation.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Legacy pass manager pass to access dependence information.
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void print(raw_ostream &, const Module *=nullptr) const override
print - Print out the internal state of the pass.
DependenceInfo & getDI() const
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
AnalysisPass to compute dependence information in a function.
Result run(Function &F, FunctionAnalysisManager &FAM)
DependenceInfo - This class is the main dependence-analysis driver.
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle transitive invalidation when the cached analysis results go away.
const SCEV * getSplitIteration(const Dependence &Dep, unsigned Level)
getSplitIteration - Give a dependence that's splittable at some particular level, return the iteratio...
std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool PossiblyLoopIndependent)
depends - Tests for a dependence between the Src and Dst instructions.
Dependence - This class represents a dependence between two memory memory references in a function.
virtual unsigned getDirection(unsigned Level) const
getDirection - Returns the direction associated with a particular level.
virtual bool isPeelFirst(unsigned Level) const
isPeelFirst - Returns true if peeling the first iteration from this loop will break this dependence.
Instruction * getDst() const
getDst - Returns the destination instruction for this dependence.
virtual bool isConfused() const
isConfused - Returns true if this dependence is confused (the compiler understands nothing and makes ...
virtual bool isSplitable(unsigned Level) const
isSplitable - Returns true if splitting this loop will break the dependence.
virtual const SCEV * getDistance(unsigned Level) const
getDistance - Returns the distance (or NULL) associated with a particular level.
virtual bool isScalar(unsigned Level) const
isScalar - Returns true if a particular level is scalar; that is, if no subscript in the source or de...
virtual bool isConsistent() const
isConsistent - Returns true if this dependence is consistent (occurs every time the source and destin...
virtual bool isPeelLast(unsigned Level) const
isPeelLast - Returns true if peeling the last iteration from this loop will break this dependence.
virtual unsigned getLevels() const
getLevels - Returns the number of common loops surrounding the source and destination of the dependen...
bool isFlow() const
isFlow - Returns true if this is a flow (aka true) dependence.
bool isInput() const
isInput - Returns true if this is an input dependence.
bool isAnti() const
isAnti - Returns true if this is an anti dependence.
Instruction * getSrc() const
getSrc - Returns the source instruction for this dependence.
virtual bool isLoopIndependent() const
isLoopIndependent - Returns true if this is a loop-independent dependence.
bool isOutput() const
isOutput - Returns true if this is an output dependence.
void dump(raw_ostream &OS) const
dump - For debugging purposes, dumps a dependence to OS.
Class representing an expression and its matching format.
FullDependence - This class represents a dependence between two memory references in a function.
unsigned getDirection(unsigned Level) const override
getDirection - Returns the direction associated with a particular level.
const SCEV * getDistance(unsigned Level) const override
getDistance - Returns the distance (or NULL) associated with a particular level.
bool isDirectionNegative() const override
Check if the direction vector is negative.
bool isSplitable(unsigned Level) const override
isSplitable - Returns true if splitting the loop will break the dependence.
FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, unsigned Levels)
bool isScalar(unsigned Level) const override
isScalar - Returns true if a particular level is scalar; that is, if no subscript in the source or de...
bool isPeelLast(unsigned Level) const override
isPeelLast - Returns true if peeling the last iteration from this loop will break this dependence.
bool isPeelFirst(unsigned Level) const override
isPeelFirst - Returns true if peeling the first iteration from this loop will break this dependence.
bool normalize(ScalarEvolution *SE) override
If the direction vector is negative, normalize the direction vector to make it non-negative.
FunctionPass class - This class is used to implement most global optimizations.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
unsigned getLoopDepth(const BlockT *BB) const
Return the loop nesting level of the specified block.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
This class represents a loop nest and can be used to query its properties.
Loop & getOutermostLoop() const
Return the outermost loop in the loop nest.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
AAMDNodes AATags
The metadata nodes which describes the aliasing of the location (each member is null if that kind of ...
const Value * Ptr
The address of the start of the location.
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
This node represents an addition of some number of SCEVs.
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStart() const
const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
const Loop * getLoop() const
const SCEV * getOperand() const
This class represents a constant integer value.
const APInt & getAPInt() const
This is the base class for unary integral cast operator classes.
This node represents multiplication of some number of SCEVs.
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask=NoWrapMask) const
const SCEV * getOperand(unsigned i) const
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
ArrayRef< const SCEV * > operands() const
Return operands of this SCEV expression.
bool isOne() const
Return true if the expression is a constant one.
bool isZero() const
Return true if the expression is a constant zero.
Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
const SCEV * getSMaxExpr(const SCEV *LHS, const SCEV *RHS)
bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
bool isKnownNonZero(const SCEV *S)
Test if the given expression is known to be non-zero.
const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
const SCEV * getSMinExpr(const SCEV *LHS, const SCEV *RHS)
const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
uint64_t getTypeSizeInBits(Type *Ty) const
Return the size in bits of the specified type, for which isSCEVable must return true.
const SCEV * getConstant(ConstantInt *V)
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
const SCEV * getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, SCEV::NoWrapFlags Flags)
Get an add recurrence expression for the specified loop.
const SCEV * getUDivExpr(const SCEV *LHS, const SCEV *RHS)
Get a canonical unsigned division expression, or something simpler if possible.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
bool hasLoopInvariantBackedgeTakenCount(const Loop *L)
Return true if the specified loop has an analyzable loop-invariant backedge-taken count.
const SCEV * getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
const SCEV * getTruncateOrZeroExtend(const SCEV *V, Type *Ty, unsigned Depth=0)
Return a SCEV corresponding to a conversion of the input value to the specified type.
const SCEV * getAddExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
iterator_range< const_set_bits_iterator > set_bits() const
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
bool any() const
Returns true if any bit is set.
size_type count() const
Returns the number of bits which are set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
@ C
The default llvm calling convention, compatible with C.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
void initializeDependenceAnalysisWrapperPassPass(PassRegistry &)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
inst_iterator inst_begin(Function *F)
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
inst_iterator inst_end(Function *F)
bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Implementation of fixed size array delinearization.
constexpr unsigned BitWidth
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
FunctionPass * createDependenceAnalysisWrapperPass()
createDependenceAnalysisPass - This creates an instance of the DependenceAnalysis wrapper pass.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A special type used by analysis passes to provide an address that identifies that particular analysis...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Dependence::DVEntry - Each level in the distance/direction vector has a direction (or perhaps a union...
Direction
An enum for the direction of the loop.