LLVM: lib/Analysis/MemoryDependenceAnalysis.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
50#include
51#include
52#include
53#include
54
55using namespace llvm;
56
57#define DEBUG_TYPE "memdep"
58
59STATISTIC(NumCacheNonLocal, "Number of fully cached non-local responses");
60STATISTIC(NumCacheDirtyNonLocal, "Number of dirty cached non-local responses");
61STATISTIC(NumUncacheNonLocal, "Number of uncached non-local responses");
62
64 "Number of fully cached non-local ptr responses");
66 "Number of cached, but dirty, non-local ptr responses");
67STATISTIC(NumUncacheNonLocalPtr, "Number of uncached non-local ptr responses");
69 "Number of block queries that were completely cached");
70
71
72
75 cl::desc("The number of instructions to scan in a block in memory "
76 "dependency analysis (default = 100)"));
77
80 cl::desc("The number of blocks to scan during memory "
81 "dependency analysis (default = 200)"));
82
85 cl::desc("The max number of entries allowed in a cache (default = 10000)"));
86
87
89
90
91
92
93template
94static void
98 ReverseMap.find(Inst);
99 assert(InstIt != ReverseMap.end() && "Reverse map out of sync?");
100 bool Found = InstIt->second.erase(Val);
101 assert(Found && "Invalid reverse map!");
102 (void)Found;
103 if (InstIt->second.empty())
104 ReverseMap.erase(InstIt);
105}
106
107
108
109
110
111
115 if (LI->isUnordered()) {
118 }
122 }
125 }
126
128 if (SI->isUnordered()) {
131 }
135 }
138 }
139
143 }
144
147
150 }
151 }
152
154 switch (II->getIntrinsicID()) {
155 case Intrinsic::lifetime_start:
156 case Intrinsic::lifetime_end:
158
159
161 case Intrinsic::invariant_start:
163
164
166 case Intrinsic::invariant_end:
168
169
171 case Intrinsic::masked_load:
174 case Intrinsic::masked_store:
177 default:
178 break;
179 }
180 }
181
182
188}
189
190
191MemDepResult MemoryDependenceResults::getCallDependencyFrom(
195
196
197 while (ScanIt != BB->begin()) {
199
200
201
202 --Limit;
203 if (!Limit)
205
206
207 MemoryLocation Loc;
209 if (Loc.Ptr) {
210
213 continue;
214 }
215
217
219
220
221 if (isReadOnlyCall && (MR) &&
224
225
226
227 continue;
228 } else
230 }
231
232
233
236 }
237
238
239
243}
244
250 if (QueryInst != nullptr) {
253
254 if (InvariantGroupDependency.isDef())
255 return InvariantGroupDependency;
256 }
257 }
259 MemLoc, isLoad, ScanIt, BB, QueryInst, Limit, BatchAA);
260 if (SimpleDep.isDef())
261 return SimpleDep;
262
263
264
265 if (InvariantGroupDependency.isNonLocal())
266 return InvariantGroupDependency;
267
269 "InvariantGroupDependency should be only unknown at this point");
270 return SimpleDep;
271}
272
280
284
285 if (!LI->hasMetadata(LLVMContext::MD_invariant_group))
287
288
289
291
292
293
294
295
298
299 Instruction *ClosestDependency = nullptr;
300
301
303 assert(Other && "Must call it with not null instruction");
304 if (Best == nullptr || DT.dominates(Best, Other))
306 return Best;
307 };
308
309 for (const Use &Us : LoadOperand->uses()) {
311 if (!U || U == LI || !DT.dominates(U, LI))
312 continue;
313
314
315
316
320 U->hasMetadata(LLVMContext::MD_invariant_group))
321 ClosestDependency = GetClosestDependency(ClosestDependency, U);
322 }
323
324 if (!ClosestDependency)
326 if (ClosestDependency->getParent() == BB)
328
329
330
331
332 NonLocalDefsCache.try_emplace(
335 ReverseNonLocalDefsCache[ClosestDependency].insert(LI);
337}
338
339
340
341
342
343
347 unsigned ScanLimit) {
349 return false;
351 return false;
353 return false;
354 if (std::min(MemLocAlign, SI->getAlign()).value() <
356 return false;
357
359 if (!LI || LI->getParent() != SI->getParent())
360 return false;
362 return false;
363 unsigned NumVisitedInsts = 0;
365 if (++NumVisitedInsts > ScanLimit ||
367 return false;
368
369 return true;
370}
371
377 Align MemLocAlign =
379
381 if (!Limit)
382 Limit = &DefaultLimit;
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 if (isLoad && QueryInst)
418 if (LI->hasMetadata(LLVMContext::MD_invariant_load))
420 MemLocAlign = LI->getAlign();
421 }
422
423
424
425
427 if (I->isVolatile())
428 return true;
433 return I->mayReadOrWriteMemory();
434 };
435
436
437 while (ScanIt != BB->begin()) {
439
440
441
442 --*Limit;
443 if (!*Limit)
445
447
448
450 switch (ID) {
451 case Intrinsic::lifetime_start: {
455 continue;
456 }
457 case Intrinsic::masked_load:
458 case Intrinsic::masked_store: {
463 continue;
466 if (ID == Intrinsic::masked_load)
467 continue;
469 }
470 }
471 }
472
473
474
475
476
477
479
480
481
482 if (LI->isVolatile()) {
483 if (!QueryInst)
484
487
489
490 }
491
492
493
494
495
497 if (!QueryInst ||
502 }
503
505
506
508
510 continue;
511
513
516
517
518
520 ClobberOffsets[LI] = R.getOffset();
522 }
523
524
525
526 continue;
527 }
528
529
531 continue;
532
533
535 }
536
538
539
540
541 if (->isUnordered() && SI->isAtomic()) {
542 if (!QueryInst ||
545
546
547
548
549
550
551
552
553
554 }
555
556
557
558
559 if (SI->isVolatile())
560 if (!QueryInst || QueryInst->isVolatile())
562
563
564
565
567 continue;
568
569
570
571
573
574
576
578 continue;
582 continue;
584 continue;
586 }
587
588
589
590
591
592
593
596 if (AccessPtr == Inst || BatchAA.isMustAlias(Inst, AccessPtr))
598 }
599
600
601
604
606 continue;
607
608
609
610
611
612
615 continue;
616
617
620
621 continue;
625
626
628 continue;
629 [[fallthrough]];
630 default:
631
633 }
634 }
635
636
637
641}
642
644 ClobberOffsets.clear();
646
647
648 MemDepResult &LocalCache = LocalDeps[QueryInst];
649
650
651
652 if (!LocalCache.isDirty())
653 return LocalCache;
654
655
656
658 ScanPos = Inst;
659
661 }
662
664
665
667
668
671 else
673 } else {
676 if (MemLoc.Ptr) {
677
680 isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_start;
681
682 LocalCache =
684 QueryParent, QueryInst, nullptr);
686 bool isReadOnly = AA.onlyReadsMemory(QueryCall);
687 LocalCache = getCallDependencyFrom(QueryCall, isReadOnly,
689 } else
690
692 }
693
694
696 ReverseLocalDeps[I].insert(QueryInst);
697
698 return LocalCache;
699}
700
701#ifndef NDEBUG
702
703
705 int Count = -1) {
707 Count = Cache.size();
708 assert(std::is_sorted(Cache.begin(), Cache.begin() + Count) &&
709 "Cache isn't sorted!");
710}
711#endif
712
716 "getNonLocalCallDependency should only be used on calls with "
717 "non-local deps!");
718 PerInstNLInfo &CacheP = NonLocalDepsMap[QueryCall];
720
721
722
723
725
726 if (!Cache.empty()) {
727
728
729 if (!CacheP.second) {
730 ++NumCacheNonLocal;
731 return Cache;
732 }
733
734
735
736 for (auto &Entry : Cache)
737 if (Entry.getResult().isDirty())
738 DirtyBlocks.push_back(Entry.getBB());
739
740
742
743 ++NumCacheDirtyNonLocal;
744 } else {
745
747 append_range(DirtyBlocks, PredCache.get(QueryBB));
748 ++NumUncacheNonLocal;
749 }
750
751
752 bool isReadonlyCall = AA.onlyReadsMemory(QueryCall);
753
755
756 unsigned NumSortedEntries = Cache.size();
758
759
760 while (!DirtyBlocks.empty()) {
762
763
764 if (!Visited.insert(DirtyBB).second)
765 continue;
766
767
768
770 NonLocalDepInfo::iterator Entry =
771 std::upper_bound(Cache.begin(), Cache.begin() + NumSortedEntries,
773 if (Entry != Cache.begin() && std::prev(Entry)->getBB() == DirtyBB)
774 --Entry;
775
777 if (Entry != Cache.begin() + NumSortedEntries &&
778 Entry->getBB() == DirtyBB) {
779
780
781 if (!Entry->getResult().isDirty())
782 continue;
783
784
785 ExistingResult = &*Entry;
786 }
787
788
789
791 if (ExistingResult) {
794
796 QueryCall);
797 }
798 }
799
800
802
803 if (ScanPos != DirtyBB->begin()) {
804 Dep = getCallDependencyFrom(QueryCall, isReadonlyCall, ScanPos, DirtyBB);
806
807
809 } else {
811 }
812
813
814
815 if (ExistingResult)
817 else
819
820
821
823
824
826 ReverseNonLocalDeps[Inst].insert(QueryCall);
827 } else {
828
829
830
831 append_range(DirtyBlocks, PredCache.get(DirtyBB));
832 }
833 }
834
835 return Cache;
836}
837
844
845 assert(Loc.Ptr->getType()->isPointerTy() &&
846 "Can't get pointer deps of a non-pointer!");
847 Result.clear();
848 {
849
850 auto NonLocalDefIt = NonLocalDefsCache.find(QueryInst);
851 if (NonLocalDefIt != NonLocalDefsCache.end()) {
852 Result.push_back(NonLocalDefIt->second);
853 ReverseNonLocalDefsCache[NonLocalDefIt->second.getResult().getInst()]
854 .erase(QueryInst);
855 NonLocalDefsCache.erase(NonLocalDefIt);
856 return;
857 }
858 }
859
860
861
862
863
864
865
866
869 return !LI->isUnordered();
871 return ->isUnordered();
872 }
873 return false;
874 };
877 const_cast<Value *>(Loc.Ptr)));
878 return;
879 }
882
883
884
885
886
888 if (getNonLocalPointerDepFromBB(QueryInst, Address, Loc, isLoad, FromBB,
889 Result, Visited, true))
890 return;
891 Result.clear();
893 const_cast<Value *>(Loc.Ptr)));
894}
895
896
897
898
899
900
901MemDepResult MemoryDependenceResults::getNonLocalInfoForBlock(
903 BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries,
905
907
909 isInvariantLoad = LI->getMetadata(LLVMContext::MD_invariant_load);
910
911
912
913 NonLocalDepInfo::iterator Entry = std::upper_bound(
914 Cache->begin(), Cache->begin() + NumSortedEntries, NonLocalDepEntry(BB));
915 if (Entry != Cache->begin() && (Entry - 1)->getBB() == BB)
916 --Entry;
917
919 if (Entry != Cache->begin() + NumSortedEntries && Entry->getBB() == BB)
920 ExistingResult = &*Entry;
921
922
923
924
927 ExistingResult = nullptr;
928
929
930
931 if (ExistingResult && !ExistingResult->getResult().isDirty()) {
932 ++NumCacheNonLocalPtr;
933 return ExistingResult->getResult();
934 }
935
936
937
938
940 if (ExistingResult && ExistingResult->getResult().getInst()) {
942 "Instruction invalidated?");
943 ++NumCacheDirtyNonLocalPtr;
945
946
947 ValueIsLoadPair CacheKey(Loc.Ptr, isLoad);
949 } else {
950 ++NumUncacheNonLocalPtr;
951 }
952
953
955 QueryInst, nullptr, BatchAA);
956
957
959 return Dep;
960
961
962
963 if (ExistingResult)
965 else
966 Cache->push_back(NonLocalDepEntry(BB, Dep));
967
968
969
970
972 return Dep;
973
974
975
977 assert(Inst && "Didn't depend on anything?");
978 ValueIsLoadPair CacheKey(Loc.Ptr, isLoad);
979 ReverseNonLocalPtrDeps[Inst].insert(CacheKey);
980 return Dep;
981}
982
983
984
985
986
987static void
989 unsigned NumSortedEntries) {
990
991
992 if (Cache.size() < 2)
993 return;
994
995 unsigned s = Cache.size() - NumSortedEntries;
996
997
998 if (s == 0)
999 return;
1000
1001
1002 if (NumSortedEntries == 0) {
1004 return;
1005 }
1006
1007
1008
1009
1010 if (s < Log2_32(Cache.size())) {
1011 while (s > 0) {
1013 Cache.pop_back();
1014 MemoryDependenceResults::NonLocalDepInfo::iterator Entry =
1015 std::upper_bound(Cache.begin(), Cache.end() - s + 1, Val);
1016 Cache.insert(Entry, Val);
1017 s--;
1018 }
1019 } else {
1021 }
1022}
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
1042 bool IsIncomplete) {
1043
1044 ValueIsLoadPair CacheKey(Pointer.getAddr(), isLoad);
1045
1046
1047
1048
1049
1050 NonLocalPointerInfo InitialNLPI;
1051 InitialNLPI.Size = Loc.Size;
1052 InitialNLPI.AATags = Loc.AATags;
1053
1056 isInvariantLoad = LI->getMetadata(LLVMContext::MD_invariant_load);
1057
1058
1059
1060 std::pair<CachedNonLocalPointerInfo::iterator, bool> Pair =
1061 NonLocalPointerDeps.insert(std::make_pair(CacheKey, InitialNLPI));
1062 NonLocalPointerInfo *CacheInfo = &Pair.first->second;
1063
1064
1065
1066
1068 if (CacheInfo->Size != Loc.Size) {
1069
1070
1071 CacheInfo->Pair = BBSkipFirstBlockPair();
1072 CacheInfo->Size = Loc.Size;
1073 for (auto &Entry : CacheInfo->NonLocalDeps)
1074 if (Instruction *Inst = Entry.getResult().getInst())
1076 CacheInfo->NonLocalDeps.clear();
1077
1078
1079
1080 IsIncomplete = true;
1081 }
1082
1083
1084
1085
1086 if (CacheInfo->AATags != Loc.AATags) {
1087 if (CacheInfo->AATags) {
1088 CacheInfo->Pair = BBSkipFirstBlockPair();
1089 CacheInfo->AATags = AAMDNodes();
1090 for (auto &Entry : CacheInfo->NonLocalDeps)
1091 if (Instruction *Inst = Entry.getResult().getInst())
1093 CacheInfo->NonLocalDeps.clear();
1094
1095
1096
1097 IsIncomplete = true;
1098 }
1100 return getNonLocalPointerDepFromBB(
1102 Visited, SkipFirstBlock, IsIncomplete);
1103 }
1104 }
1105
1107
1108
1109
1110
1111
1113 CacheInfo->Pair == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) {
1114
1115
1116
1117
1118
1119 if (!Visited.empty()) {
1120 for (auto &Entry : *Cache) {
1123 if (VI == Visited.end() || VI->second == Pointer.getAddr())
1124 continue;
1125
1126
1127
1128
1129 return false;
1130 }
1131 }
1132
1134 for (auto &Entry : *Cache) {
1135 Visited.insert(std::make_pair(Entry.getBB(), Addr));
1136 if (Entry.getResult().isNonLocal()) {
1137 continue;
1138 }
1139
1140 if (DT.isReachableFromEntry(Entry.getBB())) {
1142 NonLocalDepResult(Entry.getBB(), Entry.getResult(), Addr));
1143 }
1144 }
1145 ++NumCacheCompleteNonLocalPtr;
1146 return true;
1147 }
1148
1149
1151 return false;
1152
1153
1154
1155
1156
1157
1158
1159
1161 if (!IsIncomplete && Cache->empty())
1162 CacheInfo->Pair = BBSkipFirstBlockPair(StartBB, SkipFirstBlock);
1163 else
1164 CacheInfo->Pair = BBSkipFirstBlockPair();
1165 }
1166
1169
1170
1172
1173
1174
1175
1176
1177
1178 unsigned NumSortedEntries = Cache->size();
1180 bool GotWorklistLimit = false;
1182
1183 BatchAAResults BatchAA(AA, &EEA);
1184 while (!Worklist.empty()) {
1186
1187
1188
1190
1191
1192
1193 if (Cache && NumSortedEntries != Cache->size()) {
1195 }
1196
1197
1198
1199
1200 CacheInfo->Pair = BBSkipFirstBlockPair();
1201 return false;
1202 }
1203
1204
1205 if (!SkipFirstBlock) {
1206
1207
1208 assert(Visited.count(BB) && "Should check 'visited' before adding to WL");
1209
1210
1211
1213 MemDepResult Dep = getNonLocalInfoForBlock(
1214 QueryInst, Loc, isLoad, BB, Cache, NumSortedEntries, BatchAA);
1215
1216
1218 if (DT.isReachableFromEntry(BB)) {
1219 Result.push_back(NonLocalDepResult(BB, Dep, Pointer.getAddr()));
1220 continue;
1221 }
1222 }
1223 }
1224
1225
1226
1227
1228
1229 if (.needsPHITranslationFromBlock(BB)) {
1230 SkipFirstBlock = false;
1231 SmallVector<BasicBlock *, 16> NewBlocks;
1232 for (BasicBlock *Pred : PredCache.get(BB)) {
1233
1234 std::pair<DenseMap<BasicBlock *, Value *>::iterator, bool> InsertRes =
1235 Visited.insert(std::make_pair(Pred, Pointer.getAddr()));
1236 if (InsertRes.second) {
1237
1239 continue;
1240 }
1241
1242
1243
1244
1245 if (InsertRes.first->second != Pointer.getAddr()) {
1246
1247
1248 for (auto *NewBlock : NewBlocks)
1249 Visited.erase(NewBlock);
1250 goto PredTranslationFailure;
1251 }
1252 }
1253 if (NewBlocks.size() > WorklistEntries) {
1254
1255
1256 for (auto *NewBlock : NewBlocks)
1257 Visited.erase(NewBlock);
1258 GotWorklistLimit = true;
1259 goto PredTranslationFailure;
1260 }
1261 WorklistEntries -= NewBlocks.size();
1262 Worklist.append(NewBlocks.begin(), NewBlocks.end());
1263 continue;
1264 }
1265
1266
1267
1268 if (.isPotentiallyPHITranslatable())
1269 goto PredTranslationFailure;
1270
1271
1272
1273
1274
1275
1276 if (Cache && NumSortedEntries != Cache->size()) {
1278 NumSortedEntries = Cache->size();
1279 }
1280 Cache = nullptr;
1281
1282 PredList.clear();
1283 for (BasicBlock *Pred : PredCache.get(BB)) {
1284 PredList.push_back(std::make_pair(Pred, Pointer));
1285
1286
1287
1288 PHITransAddr &PredPointer = PredList.back().second;
1289 Value *PredPtrVal =
1290 PredPointer.translateValue(BB, Pred, &DT, false);
1291
1292
1293
1294
1295
1296
1297 std::pair<DenseMap<BasicBlock *, Value *>::iterator, bool> InsertRes =
1298 Visited.insert(std::make_pair(Pred, PredPtrVal));
1299
1300 if (!InsertRes.second) {
1301
1303
1304
1305
1306 if (InsertRes.first->second == PredPtrVal)
1307 continue;
1308
1309
1310
1311
1312
1313
1314
1315 for (const auto &Pred : PredList)
1316 Visited.erase(Pred.first);
1317
1318 goto PredTranslationFailure;
1319 }
1320 }
1321
1322
1323
1324
1325
1326
1327 for (auto &I : PredList) {
1329 PHITransAddr &PredPointer = I.second;
1331
1332 bool CanTranslate = true;
1333
1334
1335
1336
1337 if (!PredPtrVal)
1338 CanTranslate = false;
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348 if (!CanTranslate ||
1349 !getNonLocalPointerDepFromBB(QueryInst, PredPointer,
1351 Pred, Result, Visited)) {
1352
1354 Result.push_back(Entry);
1355
1356
1357
1358
1359
1360
1361 NonLocalPointerInfo &NLPI = NonLocalPointerDeps[CacheKey];
1362 NLPI.Pair = BBSkipFirstBlockPair();
1363 continue;
1364 }
1365 }
1366
1367
1368 CacheInfo = &NonLocalPointerDeps[CacheKey];
1369 Cache = &CacheInfo->NonLocalDeps;
1370 NumSortedEntries = Cache->size();
1371
1372
1373
1374
1375
1376 CacheInfo->Pair = BBSkipFirstBlockPair();
1377 SkipFirstBlock = false;
1378 continue;
1379
1380 PredTranslationFailure:
1381
1382
1383
1384
1385 if (!Cache) {
1386
1387 CacheInfo = &NonLocalPointerDeps[CacheKey];
1388 Cache = &CacheInfo->NonLocalDeps;
1389 NumSortedEntries = Cache->size();
1390 }
1391
1392
1393
1394
1395
1396 CacheInfo->Pair = BBSkipFirstBlockPair();
1397
1398
1399
1400
1401
1402
1403 if (SkipFirstBlock)
1404 return false;
1405
1406
1407
1410 if (I.getBB() != BB)
1411 continue;
1412
1413 assert((GotWorklistLimit || I.getResult().isNonLocal() ||
1414 !DT.isReachableFromEntry(BB)) &&
1415 "Should only be here with transparent block");
1416
1418
1419
1420 break;
1421 }
1422 }
1423 (void)GotWorklistLimit;
1424
1427 }
1428
1429
1432 return true;
1433}
1434
1435
1436void MemoryDependenceResults::removeCachedNonLocalPointerDependencies(
1437 ValueIsLoadPair P) {
1438
1439
1440 if (!NonLocalDefsCache.empty()) {
1441 auto it = NonLocalDefsCache.find(P.getPointer());
1442 if (it != NonLocalDefsCache.end()) {
1444 it->second.getResult().getInst(), P.getPointer());
1445 NonLocalDefsCache.erase(it);
1446 }
1447
1449 auto toRemoveIt = ReverseNonLocalDefsCache.find(I);
1450 if (toRemoveIt != ReverseNonLocalDefsCache.end()) {
1451 for (const auto *entry : toRemoveIt->second)
1452 NonLocalDefsCache.erase(entry);
1453 ReverseNonLocalDefsCache.erase(toRemoveIt);
1454 }
1455 }
1456 }
1457
1459 if (It == NonLocalPointerDeps.end())
1460 return;
1461
1462
1463
1465
1466 for (const NonLocalDepEntry &DE : PInfo) {
1468 if (!Target)
1469 continue;
1471
1472
1474 }
1475
1476
1477 NonLocalPointerDeps.erase(It);
1478}
1479
1481
1483 return;
1484
1485 removeCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, false));
1486
1487 removeCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true));
1488}
1489
1491 PredCache.clear();
1492}
1493
1495 EEA.removeInstruction(RemInst);
1496
1497
1498
1500 if (NLDI != NonLocalDepsMap.end()) {
1502 for (auto &Entry : BlockMap)
1503 if (Instruction *Inst = Entry.getResult().getInst())
1505 NonLocalDepsMap.erase(NLDI);
1506 }
1507
1508
1510 if (LocalDepEntry != LocalDeps.end()) {
1511
1512 if (Instruction *Inst = LocalDepEntry->second.getInst())
1514
1515
1516 LocalDeps.erase(LocalDepEntry);
1517 }
1518
1519
1520
1521
1522
1523
1525 removeCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, false));
1526 removeCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, true));
1527 } else {
1528
1529
1530 auto toRemoveIt = NonLocalDefsCache.find(RemInst);
1531 if (toRemoveIt != NonLocalDefsCache.end()) {
1533 "only load instructions should be added directly");
1534 const Instruction *DepV = toRemoveIt->second.getResult().getInst();
1535 ReverseNonLocalDefsCache.find(DepV)->second.erase(RemInst);
1536 NonLocalDefsCache.erase(toRemoveIt);
1537 }
1538 }
1539
1540
1542
1543
1544
1545
1546
1547
1548
1551 NewDirtyVal = MemDepResult::getDirty(&*++RemInst->getIterator());
1552
1553 ReverseDepMapType::iterator ReverseDepIt = ReverseLocalDeps.find(RemInst);
1554 if (ReverseDepIt != ReverseLocalDeps.end()) {
1555
1557 "Nothing can locally depend on a terminator");
1558
1559 for (Instruction *InstDependingOnRemInst : ReverseDepIt->second) {
1560 assert(InstDependingOnRemInst != RemInst &&
1561 "Already removed our local dep info");
1562
1563 LocalDeps[InstDependingOnRemInst] = NewDirtyVal;
1564
1565
1567 "There is no way something else can have "
1568 "a local dep on this if it is a terminator!");
1570 std::make_pair(NewDirtyVal.getInst(), InstDependingOnRemInst));
1571 }
1572
1573 ReverseLocalDeps.erase(ReverseDepIt);
1574
1575
1576
1577 while (!ReverseDepsToAdd.empty()) {
1578 ReverseLocalDeps[ReverseDepsToAdd.back().first].insert(
1579 ReverseDepsToAdd.back().second);
1580 ReverseDepsToAdd.pop_back();
1581 }
1582 }
1583
1584 ReverseDepIt = ReverseNonLocalDeps.find(RemInst);
1585 if (ReverseDepIt != ReverseNonLocalDeps.end()) {
1586 for (Instruction *I : ReverseDepIt->second) {
1587 assert(I != RemInst && "Already removed NonLocalDep info for RemInst");
1588
1589 PerInstNLInfo &INLD = NonLocalDepsMap[I];
1590
1591 INLD.second = true;
1592
1593 for (auto &Entry : INLD.first) {
1594 if (Entry.getResult().getInst() != RemInst)
1595 continue;
1596
1597
1598 Entry.setResult(NewDirtyVal);
1599
1601 ReverseDepsToAdd.push_back(std::make_pair(NextI, I));
1602 }
1603 }
1604
1605 ReverseNonLocalDeps.erase(ReverseDepIt);
1606
1607
1608 while (!ReverseDepsToAdd.empty()) {
1609 ReverseNonLocalDeps[ReverseDepsToAdd.back().first].insert(
1610 ReverseDepsToAdd.back().second);
1611 ReverseDepsToAdd.pop_back();
1612 }
1613 }
1614
1615
1616
1617 ReverseNonLocalPtrDepTy::iterator ReversePtrDepIt =
1618 ReverseNonLocalPtrDeps.find(RemInst);
1619 if (ReversePtrDepIt != ReverseNonLocalPtrDeps.end()) {
1621 ReversePtrDepsToAdd;
1622
1623 for (ValueIsLoadPair P : ReversePtrDepIt->second) {
1624 assert(P.getPointer() != RemInst &&
1625 "Already removed NonLocalPointerDeps info for RemInst");
1626
1627 auto &NLPD = NonLocalPointerDeps[P];
1628
1630
1631
1632 NLPD.Pair = BBSkipFirstBlockPair();
1633
1634
1635 for (auto &Entry : NLPDI) {
1636 if (Entry.getResult().getInst() != RemInst)
1637 continue;
1638
1639
1640 Entry.setResult(NewDirtyVal);
1641
1643 ReversePtrDepsToAdd.push_back(std::make_pair(NewDirtyInst, P));
1644 }
1645
1646
1647
1649 }
1650
1651 ReverseNonLocalPtrDeps.erase(ReversePtrDepIt);
1652
1653 while (!ReversePtrDepsToAdd.empty()) {
1654 ReverseNonLocalPtrDeps[ReversePtrDepsToAdd.back().first].insert(
1655 ReversePtrDepsToAdd.back().second);
1656 ReversePtrDepsToAdd.pop_back();
1657 }
1658 }
1659
1660 assert(!NonLocalDepsMap.count(RemInst) && "RemInst got reinserted?");
1662}
1663
1664
1665
1666
1667
1668void MemoryDependenceResults::verifyRemoved(Instruction *D) const {
1669#ifndef NDEBUG
1670 for (const auto &DepKV : LocalDeps) {
1671 assert(DepKV.first != D && "Inst occurs in data structures");
1672 assert(DepKV.second.getInst() != D && "Inst occurs in data structures");
1673 }
1674
1675 for (const auto &DepKV : NonLocalPointerDeps) {
1676 assert(DepKV.first.getPointer() != D && "Inst occurs in NLPD map key");
1677 for (const auto &Entry : DepKV.second.NonLocalDeps)
1678 assert(Entry.getResult().getInst() != D && "Inst occurs as NLPD value");
1679 }
1680
1681 for (const auto &DepKV : NonLocalDepsMap) {
1682 assert(DepKV.first != D && "Inst occurs in data structures");
1683 const PerInstNLInfo &INLD = DepKV.second;
1684 for (const auto &Entry : INLD.first)
1686 "Inst occurs in data structures");
1687 }
1688
1689 for (const auto &DepKV : ReverseLocalDeps) {
1690 assert(DepKV.first != D && "Inst occurs in data structures");
1691 for (Instruction *Inst : DepKV.second)
1692 assert(Inst != D && "Inst occurs in data structures");
1693 }
1694
1695 for (const auto &DepKV : ReverseNonLocalDeps) {
1696 assert(DepKV.first != D && "Inst occurs in data structures");
1697 for (Instruction *Inst : DepKV.second)
1698 assert(Inst != D && "Inst occurs in data structures");
1699 }
1700
1701 for (const auto &DepKV : ReverseNonLocalPtrDeps) {
1702 assert(DepKV.first != D && "Inst occurs in rev NLPD map");
1703
1704 for (ValueIsLoadPair P : DepKV.second)
1705 assert(P != ValueIsLoadPair(D, false) && P != ValueIsLoadPair(D, true) &&
1706 "Inst occurs in ReverseNonLocalPtrDeps map");
1707 }
1708#endif
1709}
1710
1711AnalysisKey MemoryDependenceAnalysis::Key;
1712
1715
1724
1726
1728 "Memory Dependence Analysis", false, true)
1735
1737
1739
1741 MemDep.reset();
1742}
1743
1751
1753 FunctionAnalysisManager::Invalidator &Inv) {
1754
1757
1758 return true;
1759
1760
1761 if (Inv.invalidate<AAManager>(F, PA) ||
1764 return true;
1765
1766
1767 return false;
1768}
1769
1771 return DefaultBlockScanLimit;
1772}
1773
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isLoad(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
This defines the Use class.
static const unsigned int NumResultsLimit
Definition MemoryDependenceAnalysis.cpp:88
static cl::opt< unsigned > CacheGlobalLimit("memdep-cache-global-limit", cl::Hidden, cl::init(10000), cl::desc("The max number of entries allowed in a cache (default = 10000)"))
static ModRefInfo GetLocation(const Instruction *Inst, MemoryLocation &Loc, const TargetLibraryInfo &TLI)
If the given instruction references a specific memory location, fill in Loc with the details,...
Definition MemoryDependenceAnalysis.cpp:112
static cl::opt< unsigned > BlockNumberLimit("memdep-block-number-limit", cl::Hidden, cl::init(200), cl::desc("The number of blocks to scan during memory " "dependency analysis (default = 200)"))
static void RemoveFromReverseMap(DenseMap< Instruction *, SmallPtrSet< KeyTy, 4 > > &ReverseMap, Instruction *Inst, KeyTy Val)
This is a helper function that removes Val from 'Inst's set in ReverseMap.
Definition MemoryDependenceAnalysis.cpp:95
static void SortNonLocalDepInfoCache(MemoryDependenceResults::NonLocalDepInfo &Cache, unsigned NumSortedEntries)
Sort the NonLocalDepInfo cache, given a certain number of elements in the array that are already prop...
Definition MemoryDependenceAnalysis.cpp:988
static void AssertSorted(MemoryDependenceResults::NonLocalDepInfo &Cache, int Count=-1)
This method is used when -debug is specified to verify that cache arrays are properly kept sorted.
Definition MemoryDependenceAnalysis.cpp:704
static bool canSkipClobberingStore(const StoreInst *SI, const MemoryLocation &MemLoc, Align MemLocAlign, BatchAAResults &BatchAA, unsigned ScanLimit)
Definition MemoryDependenceAnalysis.cpp:344
static cl::opt< unsigned > BlockScanLimit("memdep-block-scan-limit", cl::Hidden, cl::init(100), cl::desc("The number of instructions to scan in a block in memory " "dependency analysis (default = 100)"))
This file provides utility analysis objects describing memory locations.
static bool isOrdered(const Instruction *I)
static bool isInvariantLoad(const Instruction *I, const Value *Ptr, const bool IsKernelFn)
uint64_t IntrinsicInst * II
#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 SmallPtrSet class.
This file defines the SmallVector class.
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.
The possible results of an alias query.
@ 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....
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.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
InstListType::iterator iterator
Instruction iterators...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
An instruction for ordering other memory operations.
const BasicBlock & getEntryBlock() const
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isIdenticalToWhenDefined(const Instruction *I, bool IntersectAttrs=false) const LLVM_READONLY
This is like isIdenticalTo, except that it ignores the SubclassOptionalData flags,...
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI bool isVolatile() const LLVM_READONLY
Return true if this instruction has a volatile memory access.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Value * getPointerOperand()
TypeSize getValue() const
A memory dependence query can return one of three different answers.
bool isNonLocal() const
Tests if this MemDepResult represents a query that is transparent to the start of the block,...
static MemDepResult getNonLocal()
bool isNonFuncLocal() const
Tests if this MemDepResult represents a query that is transparent to the start of the function.
static MemDepResult getClobber(Instruction *Inst)
bool isDef() const
Tests if this MemDepResult represents a query that is an instruction definition dependency.
static MemDepResult getUnknown()
bool isLocal() const
Tests if this MemDepResult represents a valid local query (Clobber/Def).
bool isUnknown() const
Tests if this MemDepResult represents a query which cannot and/or will not be computed.
static MemDepResult getNonFuncLocal()
static MemDepResult getDef(Instruction *Inst)
get methods: These are static ctor methods for creating various MemDepResult kinds.
Instruction * getInst() const
If this is a normal dependency, returns the instruction that is depended on.
An analysis that produces MemoryDependenceResults for a function.
MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM)
Definition MemoryDependenceAnalysis.cpp:1717
MemoryDependenceAnalysis()
Definition MemoryDependenceAnalysis.cpp:1713
Provides a lazy, caching interface for making common memory aliasing information queries,...
MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB, Instruction *QueryInst, unsigned *Limit, BatchAAResults &BatchAA)
Definition MemoryDependenceAnalysis.cpp:372
std::vector< NonLocalDepEntry > NonLocalDepInfo
void invalidateCachedPredecessors()
Clears the PredIteratorCache info.
Definition MemoryDependenceAnalysis.cpp:1490
void invalidateCachedPointerInfo(Value *Ptr)
Invalidates cached information about the specified pointer, because it may be too conservative in mem...
Definition MemoryDependenceAnalysis.cpp:1480
MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB, Instruction *QueryInst=nullptr, unsigned *Limit=nullptr)
Returns the instruction on which a memory location depends.
Definition MemoryDependenceAnalysis.cpp:273
void removeInstruction(Instruction *InstToRemove)
Removes an instruction from the dependence analysis, updating the dependence of instructions that pre...
Definition MemoryDependenceAnalysis.cpp:1494
MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB)
This analysis looks for other loads and stores with invariant.group metadata and the same pointer ope...
Definition MemoryDependenceAnalysis.cpp:282
unsigned getDefaultBlockScanLimit() const
Some methods limit the number of instructions they will examine.
Definition MemoryDependenceAnalysis.cpp:1770
MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
Definition MemoryDependenceAnalysis.cpp:643
const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
Definition MemoryDependenceAnalysis.cpp:714
void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl< NonLocalDepResult > &Result)
Perform a full dependency query for an access to the QueryInst's specified memory location,...
Definition MemoryDependenceAnalysis.cpp:838
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle invalidation in the new PM.
Definition MemoryDependenceAnalysis.cpp:1752
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
bool runOnFunction(Function &) override
Pass Implementation stuff. This doesn't do any analysis eagerly.
Definition MemoryDependenceAnalysis.cpp:1774
~MemoryDependenceWrapperPass() override
void getAnalysisUsage(AnalysisUsage &AU) const override
Does not modify anything. It uses Value Numbering and Alias Analysis.
Definition MemoryDependenceAnalysis.cpp:1744
void releaseMemory() override
Clean up memory in between runs.
Definition MemoryDependenceAnalysis.cpp:1740
MemoryDependenceWrapperPass()
Definition MemoryDependenceAnalysis.cpp:1736
Representation for a specific memory location.
MemoryLocation getWithoutAATags() const
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 getAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location after Ptr, while remaining within the underlying objec...
MemoryLocation getWithNewPtr(const Value *NewPtr) const
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.
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
This is an entry in the NonLocalDepInfo cache.
void setResult(const MemDepResult &R)
const MemDepResult & getResult() const
This is a result from a NonLocal dependence query.
PHITransAddr - An address value which tracks and handles phi translation.
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
AnalysisType & getAnalysis() const
getAnalysis() - 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.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool isPointerTy() const
True if this is an instance of PointerType.
A Use represents the edge between a Value definition and its users.
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
const ParentTy * getParent() const
self_iterator getIterator()
Abstract Attribute helper functions.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool isStrongerThanUnordered(AtomicOrdering AO)
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
FunctionAddr VTableAddr Count
bool isModOrRefSet(const ModRefInfo MRI)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
decltype(auto) cast(const From &Val)
cast - 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....
bool isNoModRef(const ModRefInfo MRI)
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
This struct is a compact representation of a valid (non-zero power of two) alignment.
A special type used by analysis passes to provide an address that identifies that particular analysis...