57#define DEBUG_TYPE "memdep"
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");
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");
75 cl::desc(
"The number of instructions to scan in a block in memory "
76 "dependency analysis (default = 100)"));
80 cl::desc(
"The number of blocks to scan during memory "
81 "dependency analysis (default = 200)"));
89template <
typename KeyTy>
94 ReverseMap.
find(Inst);
95 assert(InstIt != ReverseMap.
end() &&
"Reverse map out of sync?");
96 bool Found = InstIt->second.
erase(Val);
97 assert(Found &&
"Invalid reverse map!");
99 if (InstIt->second.
empty())
100 ReverseMap.erase(InstIt);
110 if (
const LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
111 if (LI->isUnordered()) {
113 return ModRefInfo::Ref;
115 if (LI->getOrdering() == AtomicOrdering::Monotonic) {
117 return ModRefInfo::ModRef;
120 return ModRefInfo::ModRef;
123 if (
const StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
124 if (SI->isUnordered()) {
126 return ModRefInfo::Mod;
128 if (SI->getOrdering() == AtomicOrdering::Monotonic) {
130 return ModRefInfo::ModRef;
133 return ModRefInfo::ModRef;
136 if (
const VAArgInst *V = dyn_cast<VAArgInst>(Inst)) {
138 return ModRefInfo::ModRef;
141 if (
const CallBase *CB = dyn_cast<CallBase>(Inst)) {
145 return ModRefInfo::Mod;
150 switch (
II->getIntrinsicID()) {
151 case Intrinsic::lifetime_start:
152 case Intrinsic::lifetime_end:
153 case Intrinsic::invariant_start:
157 return ModRefInfo::Mod;
158 case Intrinsic::invariant_end:
162 return ModRefInfo::Mod;
163 case Intrinsic::masked_load:
165 return ModRefInfo::Ref;
166 case Intrinsic::masked_store:
168 return ModRefInfo::Mod;
176 return ModRefInfo::ModRef;
178 return ModRefInfo::Ref;
179 return ModRefInfo::NoModRef;
183MemDepResult MemoryDependenceResults::getCallDependencyFrom(
189 while (ScanIt != BB->
begin()) {
192 if (isa<DbgInfoIntrinsic>(Inst))
211 if (
auto *CallB = dyn_cast<CallBase>(Inst)) {
216 if (isReadOnlyCall && !
isModSet(MR) &&
217 Call->isIdenticalToWhenDefined(CallB))
245 if (QueryInst !=
nullptr) {
246 if (
auto *LI = dyn_cast<LoadInst>(QueryInst)) {
249 if (InvariantGroupDependency.
isDef())
250 return InvariantGroupDependency;
254 MemLoc,
isLoad, ScanIt, BB, QueryInst, Limit, BatchAA);
255 if (SimpleDep.
isDef())
261 return InvariantGroupDependency;
264 "InvariantGroupDependency should be only unknown at this point");
280 if (!LI->
hasMetadata(LLVMContext::MD_invariant_group))
291 if (isa<GlobalValue>(LoadOperand))
298 assert(
Other &&
"Must call it with not null instruction");
304 for (
const Use &Us : LoadOperand->
uses()) {
305 auto *U = dyn_cast<Instruction>(Us.getUser());
306 if (!U || U == LI || !DT.
dominates(U, LI))
312 if ((isa<LoadInst>(U) ||
313 (isa<StoreInst>(U) &&
315 U->hasMetadata(LLVMContext::MD_invariant_group))
316 ClosestDependency = GetClosestDependency(ClosestDependency, U);
319 if (!ClosestDependency)
321 if (ClosestDependency->
getParent() == BB)
327 NonLocalDefsCache.try_emplace(
330 ReverseNonLocalDefsCache[ClosestDependency].
insert(LI);
342 unsigned ScanLimit) {
349 if (std::min(MemLocAlign, SI->getAlign()).value() <
353 auto *LI = dyn_cast<LoadInst>(SI->getValueOperand());
354 if (!LI || LI->getParent() != SI->getParent())
358 unsigned NumVisitedInsts = 0;
359 for (
const Instruction *
I = LI;
I != SI;
I =
I->getNextNonDebugInstruction())
360 if (++NumVisitedInsts > ScanLimit ||
371 bool isInvariantLoad =
false;
377 Limit = &DefaultLimit;
412 if (
LoadInst *LI = dyn_cast<LoadInst>(QueryInst)) {
413 if (LI->hasMetadata(LLVMContext::MD_invariant_load))
414 isInvariantLoad =
true;
415 MemLocAlign = LI->getAlign();
424 if (
auto *LI = dyn_cast<LoadInst>(
I))
426 if (
auto *SI = dyn_cast<StoreInst>(
I))
428 return I->mayReadOrWriteMemory();
432 while (ScanIt != BB->
begin()) {
437 if (isa<DbgInfoIntrinsic>(
II))
451 case Intrinsic::lifetime_start: {
461 case Intrinsic::masked_load:
462 case Intrinsic::masked_store: {
470 if (
ID == Intrinsic::masked_load)
482 if (
LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
486 if (LI->isVolatile()) {
524 ClobberOffsets[LI] = R.getOffset();
541 if (
StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
545 if (!SI->isUnordered() && SI->isAtomic()) {
563 if (SI->isVolatile())
600 if (AccessPtr == Inst || BatchAA.
isMustAlias(Inst, AccessPtr))
606 if (isa<SelectInst>(Inst) && MemLoc.
Ptr == Inst)
617 if (
FenceInst *FI = dyn_cast<FenceInst>(Inst))
648 ClobberOffsets.
clear();
656 if (!LocalCache.isDirty())
683 if (
auto *
II = dyn_cast<IntrinsicInst>(QueryInst))
684 isLoad |=
II->getIntrinsicID() == Intrinsic::lifetime_start;
688 QueryParent, QueryInst,
nullptr);
689 }
else if (
auto *QueryCall = dyn_cast<CallBase>(QueryInst)) {
691 LocalCache = getCallDependencyFrom(QueryCall, isReadOnly,
700 ReverseLocalDeps[
I].
insert(QueryInst);
711 Count = Cache.size();
712 assert(std::is_sorted(Cache.begin(), Cache.begin() + Count) &&
713 "Cache isn't sorted!");
720 "getNonLocalCallDependency should only be used on calls with "
722 PerInstNLInfo &CacheP = NonLocalDepsMap[QueryCall];
730 if (!Cache.empty()) {
733 if (!CacheP.second) {
740 for (
auto &Entry : Cache)
741 if (Entry.getResult().isDirty())
747 ++NumCacheDirtyNonLocal;
752 ++NumUncacheNonLocal;
760 unsigned NumSortedEntries = Cache.
size();
764 while (!DirtyBlocks.
empty()) {
768 if (!Visited.
insert(DirtyBB).second)
774 NonLocalDepInfo::iterator Entry =
775 std::upper_bound(Cache.begin(), Cache.begin() + NumSortedEntries,
777 if (Entry != Cache.begin() && std::prev(Entry)->getBB() == DirtyBB)
781 if (Entry != Cache.begin() + NumSortedEntries &&
782 Entry->getBB() == DirtyBB) {
785 if (!Entry->getResult().isDirty())
789 ExistingResult = &*Entry;
795 if (ExistingResult) {
799 RemoveFromReverseMap<Instruction *>(ReverseNonLocalDeps, Inst,
807 if (ScanPos != DirtyBB->
begin()) {
808 Dep = getCallDependencyFrom(QueryCall, isReadonlyCall, ScanPos, DirtyBB);
830 ReverseNonLocalDeps[Inst].
insert(QueryCall);
845 bool isLoad = isa<LoadInst>(QueryInst);
850 "Can't get pointer deps of a non-pointer!");
854 auto NonLocalDefIt = NonLocalDefsCache.find(QueryInst);
855 if (NonLocalDefIt != NonLocalDefsCache.end()) {
856 Result.push_back(NonLocalDefIt->second);
857 ReverseNonLocalDefsCache[NonLocalDefIt->second.getResult().getInst()]
859 NonLocalDefsCache.erase(NonLocalDefIt);
872 if (
LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
873 return !LI->isUnordered();
874 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
875 return !SI->isUnordered();
892 if (getNonLocalPointerDepFromBB(QueryInst,
Address, Loc,
isLoad, FromBB,
893 Result, Visited,
true))
905MemDepResult MemoryDependenceResults::getNonLocalInfoForBlock(
907 BasicBlock *BB, NonLocalDepInfo *Cache,
unsigned NumSortedEntries,
910 bool isInvariantLoad =
false;
912 if (
LoadInst *LI = dyn_cast_or_null<LoadInst>(QueryInst))
913 isInvariantLoad = LI->getMetadata(LLVMContext::MD_invariant_load);
917 NonLocalDepInfo::iterator Entry = std::upper_bound(
919 if (Entry != Cache->begin() && (Entry - 1)->getBB() == BB)
923 if (Entry != Cache->begin() + NumSortedEntries && Entry->getBB() == BB)
924 ExistingResult = &*Entry;
929 if (ExistingResult && isInvariantLoad &&
931 ExistingResult =
nullptr;
935 if (ExistingResult && !ExistingResult->
getResult().isDirty()) {
936 ++NumCacheNonLocalPtr;
946 "Instruction invalidated?");
947 ++NumCacheDirtyNonLocalPtr;
951 ValueIsLoadPair CacheKey(Loc.
Ptr,
isLoad);
954 ++NumUncacheNonLocalPtr;
959 QueryInst,
nullptr, BatchAA);
981 assert(Inst &&
"Didn't depend on anything?");
982 ValueIsLoadPair CacheKey(Loc.
Ptr,
isLoad);
983 ReverseNonLocalPtrDeps[Inst].
insert(CacheKey);
993 unsigned NumSortedEntries) {
994 switch (Cache.size() - NumSortedEntries) {
1002 MemoryDependenceResults::NonLocalDepInfo::iterator Entry =
1003 std::upper_bound(Cache.begin(), Cache.end() - 1, Val);
1004 Cache.insert(Entry, Val);
1009 if (Cache.size() != 1) {
1012 MemoryDependenceResults::NonLocalDepInfo::iterator Entry =
1014 Cache.insert(Entry, Val);
1037bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
1042 bool IsIncomplete) {
1050 NonLocalPointerInfo InitialNLPI;
1051 InitialNLPI.Size = Loc.
Size;
1052 InitialNLPI.AATags = Loc.
AATags;
1054 bool isInvariantLoad =
false;
1055 if (
LoadInst *LI = dyn_cast_or_null<LoadInst>(QueryInst))
1056 isInvariantLoad = LI->getMetadata(LLVMContext::MD_invariant_load);
1060 std::pair<CachedNonLocalPointerInfo::iterator, bool> Pair =
1061 NonLocalPointerDeps.
insert(std::make_pair(CacheKey, InitialNLPI));
1062 NonLocalPointerInfo *CacheInfo = &Pair.first->second;
1067 if (!isInvariantLoad && !Pair.second) {
1068 if (CacheInfo->Size != Loc.
Size) {
1069 bool ThrowOutEverything;
1070 if (CacheInfo->Size.hasValue() && Loc.
Size.
hasValue()) {
1074 ThrowOutEverything =
1083 if (ThrowOutEverything) {
1086 CacheInfo->Pair = BBSkipFirstBlockPair();
1087 CacheInfo->Size = Loc.
Size;
1088 for (
auto &Entry : CacheInfo->NonLocalDeps)
1091 CacheInfo->NonLocalDeps.clear();
1095 IsIncomplete =
true;
1099 return getNonLocalPointerDepFromBB(
1101 StartBB, Result, Visited, SkipFirstBlock, IsIncomplete);
1108 if (CacheInfo->AATags != Loc.
AATags) {
1109 if (CacheInfo->AATags) {
1110 CacheInfo->Pair = BBSkipFirstBlockPair();
1112 for (
auto &Entry : CacheInfo->NonLocalDeps)
1115 CacheInfo->NonLocalDeps.clear();
1119 IsIncomplete =
true;
1122 return getNonLocalPointerDepFromBB(
1124 Visited, SkipFirstBlock, IsIncomplete);
1134 if (!IsIncomplete && !isInvariantLoad &&
1135 CacheInfo->Pair == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) {
1141 if (!Visited.
empty()) {
1142 for (
auto &Entry : *Cache) {
1145 if (VI == Visited.
end() ||
VI->second ==
Pointer.getAddr())
1156 for (
auto &Entry : *Cache) {
1158 if (
Entry.getResult().isNonLocal()) {
1167 ++NumCacheCompleteNonLocalPtr;
1178 if (!isInvariantLoad) {
1179 if (!IsIncomplete && Cache->empty())
1180 CacheInfo->Pair = BBSkipFirstBlockPair(StartBB, SkipFirstBlock);
1182 CacheInfo->Pair = BBSkipFirstBlockPair();
1196 unsigned NumSortedEntries = Cache->size();
1198 bool GotWorklistLimit =
false;
1202 while (!Worklist.
empty()) {
1211 if (Cache && NumSortedEntries != Cache->size()) {
1218 CacheInfo->Pair = BBSkipFirstBlockPair();
1223 if (!SkipFirstBlock) {
1226 assert(Visited.
count(BB) &&
"Should check 'visited' before adding to WL");
1232 QueryInst, Loc,
isLoad, BB, Cache, NumSortedEntries, BatchAA);
1247 if (!
Pointer.needsPHITranslationFromBlock(BB)) {
1248 SkipFirstBlock =
false;
1252 std::pair<DenseMap<BasicBlock *, Value *>::iterator,
bool> InsertRes =
1254 if (InsertRes.second) {
1263 if (InsertRes.first->second !=
Pointer.getAddr()) {
1266 for (
auto *NewBlock : NewBlocks)
1267 Visited.
erase(NewBlock);
1268 goto PredTranslationFailure;
1271 if (NewBlocks.
size() > WorklistEntries) {
1274 for (
auto *NewBlock : NewBlocks)
1275 Visited.
erase(NewBlock);
1276 GotWorklistLimit =
true;
1277 goto PredTranslationFailure;
1279 WorklistEntries -= NewBlocks.size();
1280 Worklist.
append(NewBlocks.begin(), NewBlocks.end());
1286 if (!
Pointer.isPotentiallyPHITranslatable())
1287 goto PredTranslationFailure;
1294 if (Cache && NumSortedEntries != Cache->size()) {
1296 NumSortedEntries = Cache->size();
1302 PredList.
push_back(std::make_pair(Pred, Pointer));
1315 std::pair<DenseMap<BasicBlock *, Value *>::iterator,
bool> InsertRes =
1316 Visited.
insert(std::make_pair(Pred, PredPtrVal));
1318 if (!InsertRes.second) {
1324 if (InsertRes.first->second == PredPtrVal)
1333 for (
const auto &Pred : PredList)
1334 Visited.
erase(Pred.first);
1336 goto PredTranslationFailure;
1345 for (
auto &
I : PredList) {
1350 bool CanTranslate =
true;
1356 CanTranslate =
false;
1366 if (!CanTranslate ||
1367 !getNonLocalPointerDepFromBB(QueryInst, PredPointer,
1369 Pred, Result, Visited)) {
1379 NonLocalPointerInfo &NLPI = NonLocalPointerDeps[CacheKey];
1380 NLPI.Pair = BBSkipFirstBlockPair();
1386 CacheInfo = &NonLocalPointerDeps[CacheKey];
1387 Cache = &CacheInfo->NonLocalDeps;
1388 NumSortedEntries = Cache->size();
1394 CacheInfo->Pair = BBSkipFirstBlockPair();
1395 SkipFirstBlock =
false;
1398 PredTranslationFailure:
1405 CacheInfo = &NonLocalPointerDeps[CacheKey];
1406 Cache = &CacheInfo->NonLocalDeps;
1407 NumSortedEntries = Cache->size();
1414 CacheInfo->Pair = BBSkipFirstBlockPair();
1426 if (!isInvariantLoad) {
1428 if (
I.getBB() != BB)
1431 assert((GotWorklistLimit ||
I.getResult().isNonLocal() ||
1433 "Should only be here with transparent block");
1441 (void)GotWorklistLimit;
1454void MemoryDependenceResults::removeCachedNonLocalPointerDependencies(
1455 ValueIsLoadPair
P) {
1458 if (!NonLocalDefsCache.empty()) {
1459 auto it = NonLocalDefsCache.find(
P.getPointer());
1460 if (it != NonLocalDefsCache.end()) {
1462 it->second.getResult().getInst(),
P.getPointer());
1463 NonLocalDefsCache.erase(it);
1466 if (
auto *
I = dyn_cast<Instruction>(
P.getPointer())) {
1467 auto toRemoveIt = ReverseNonLocalDefsCache.
find(
I);
1468 if (toRemoveIt != ReverseNonLocalDefsCache.
end()) {
1469 for (
const auto *entry : toRemoveIt->second)
1470 NonLocalDefsCache.erase(entry);
1471 ReverseNonLocalDefsCache.
erase(toRemoveIt);
1477 if (It == NonLocalPointerDeps.
end())
1495 NonLocalPointerDeps.
erase(It);
1500 if (!
Ptr->getType()->isPointerTy())
1518 if (NLDI != NonLocalDepsMap.
end()) {
1520 for (
auto &Entry : BlockMap)
1521 if (
Instruction *Inst = Entry.getResult().getInst())
1523 NonLocalDepsMap.
erase(NLDI);
1528 if (LocalDepEntry != LocalDeps.
end()) {
1530 if (
Instruction *Inst = LocalDepEntry->second.getInst())
1534 LocalDeps.
erase(LocalDepEntry);
1543 removeCachedNonLocalPointerDependencies(
ValueIsLoadPair(RemInst,
false));
1544 removeCachedNonLocalPointerDependencies(
ValueIsLoadPair(RemInst,
true));
1548 auto toRemoveIt = NonLocalDefsCache.find(RemInst);
1549 if (toRemoveIt != NonLocalDefsCache.end()) {
1550 assert(isa<LoadInst>(RemInst) &&
1551 "only load instructions should be added directly");
1552 const Instruction *DepV = toRemoveIt->second.getResult().getInst();
1553 ReverseNonLocalDefsCache.
find(DepV)->second.erase(RemInst);
1554 NonLocalDefsCache.erase(toRemoveIt);
1569 NewDirtyVal = MemDepResult::getDirty(&*++RemInst->
getIterator());
1572 if (ReverseDepIt != ReverseLocalDeps.
end()) {
1575 "Nothing can locally depend on a terminator");
1577 for (
Instruction *InstDependingOnRemInst : ReverseDepIt->second) {
1578 assert(InstDependingOnRemInst != RemInst &&
1579 "Already removed our local dep info");
1581 LocalDeps[InstDependingOnRemInst] = NewDirtyVal;
1585 "There is no way something else can have "
1586 "a local dep on this if it is a terminator!");
1588 std::make_pair(NewDirtyVal.
getInst(), InstDependingOnRemInst));
1591 ReverseLocalDeps.
erase(ReverseDepIt);
1595 while (!ReverseDepsToAdd.
empty()) {
1596 ReverseLocalDeps[ReverseDepsToAdd.
back().first].
insert(
1597 ReverseDepsToAdd.
back().second);
1602 ReverseDepIt = ReverseNonLocalDeps.
find(RemInst);
1603 if (ReverseDepIt != ReverseNonLocalDeps.
end()) {
1605 assert(
I != RemInst &&
"Already removed NonLocalDep info for RemInst");
1607 PerInstNLInfo &INLD = NonLocalDepsMap[
I];
1611 for (
auto &Entry : INLD.first) {
1612 if (Entry.getResult().getInst() != RemInst)
1616 Entry.setResult(NewDirtyVal);
1619 ReverseDepsToAdd.
push_back(std::make_pair(NextI,
I));
1623 ReverseNonLocalDeps.
erase(ReverseDepIt);
1626 while (!ReverseDepsToAdd.
empty()) {
1627 ReverseNonLocalDeps[ReverseDepsToAdd.
back().first].
insert(
1628 ReverseDepsToAdd.
back().second);
1636 ReverseNonLocalPtrDeps.
find(RemInst);
1637 if (ReversePtrDepIt != ReverseNonLocalPtrDeps.
end()) {
1639 ReversePtrDepsToAdd;
1642 assert(
P.getPointer() != RemInst &&
1643 "Already removed NonLocalPointerDeps info for RemInst");
1651 for (
auto &Entry : NLPDI) {
1652 if (Entry.getResult().getInst() != RemInst)
1656 Entry.setResult(NewDirtyVal);
1659 ReversePtrDepsToAdd.
push_back(std::make_pair(NewDirtyInst,
P));
1667 ReverseNonLocalPtrDeps.
erase(ReversePtrDepIt);
1669 while (!ReversePtrDepsToAdd.
empty()) {
1670 ReverseNonLocalPtrDeps[ReversePtrDepsToAdd.
back().first].
insert(
1671 ReversePtrDepsToAdd.
back().second);
1676 assert(!NonLocalDepsMap.
count(RemInst) &&
"RemInst got reinserted?");
1684void MemoryDependenceResults::verifyRemoved(
Instruction *
D)
const {
1686 for (
const auto &DepKV : LocalDeps) {
1687 assert(DepKV.first !=
D &&
"Inst occurs in data structures");
1688 assert(DepKV.second.getInst() !=
D &&
"Inst occurs in data structures");
1691 for (
const auto &DepKV : NonLocalPointerDeps) {
1692 assert(DepKV.first.getPointer() !=
D &&
"Inst occurs in NLPD map key");
1693 for (
const auto &Entry : DepKV.second.NonLocalDeps)
1694 assert(Entry.getResult().getInst() !=
D &&
"Inst occurs as NLPD value");
1697 for (
const auto &DepKV : NonLocalDepsMap) {
1698 assert(DepKV.first !=
D &&
"Inst occurs in data structures");
1699 const PerInstNLInfo &INLD = DepKV.second;
1700 for (
const auto &Entry : INLD.first)
1702 "Inst occurs in data structures");
1705 for (
const auto &DepKV : ReverseLocalDeps) {
1706 assert(DepKV.first !=
D &&
"Inst occurs in data structures");
1708 assert(Inst !=
D &&
"Inst occurs in data structures");
1711 for (
const auto &DepKV : ReverseNonLocalDeps) {
1712 assert(DepKV.first !=
D &&
"Inst occurs in data structures");
1714 assert(Inst !=
D &&
"Inst occurs in data structures");
1717 for (
const auto &DepKV : ReverseNonLocalPtrDeps) {
1718 assert(DepKV.first !=
D &&
"Inst occurs in rev NLPD map");
1720 for (ValueIsLoadPair
P : DepKV.second)
1721 assert(
P != ValueIsLoadPair(
D,
false) &&
P != ValueIsLoadPair(
D,
true) &&
1722 "Inst occurs in ReverseNonLocalPtrDeps map");
1744 "Memory Dependence Analysis",
false,
true)
1789 return DefaultBlockScanLimit;
1793 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
1794 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1795 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
1796 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
static bool isLoad(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
block Block Frequency Analysis
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
This defines the Use class.
static const unsigned int NumResultsLimit
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,...
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.
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...
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.
static bool canSkipClobberingStore(const StoreInst *SI, const MemoryLocation &MemLoc, Align MemLocAlign, BatchAAResults &BatchAA, unsigned ScanLimit)
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)
Module.h This file contains the declarations for the Module class.
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Check whether or not an instruction may read or write the optionally specified memory location.
bool onlyReadsMemory(const CallBase *Call)
Checks if the specified call is known to only read from non-volatile memory (or not access memory at ...
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 <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
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.
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)
Dependence - This class represents a dependence between two memory memory references in a function.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
void removeInstruction(Instruction *I)
An instruction for ordering other memory operations.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
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.
bool isTerminator() const
bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
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)
MemoryDependenceAnalysis()
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)
std::vector< NonLocalDepEntry > NonLocalDepInfo
void invalidateCachedPredecessors()
Clears the PredIteratorCache info.
void invalidateCachedPointerInfo(Value *Ptr)
Invalidates cached information about the specified pointer, because it may be too conservative in mem...
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.
void removeInstruction(Instruction *InstToRemove)
Removes an instruction from the dependence analysis, updating the dependence of instructions that pre...
MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB)
This analysis looks for other loads and stores with invariant.group metadata and the same pointer ope...
unsigned getDefaultBlockScanLimit() const
Some methods limit the number of instructions they will examine.
MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl< NonLocalDepResult > &Result)
Perform a full dependency query for an access to the QueryInst's specified memory location,...
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
Handle invalidation in the new PM.
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.
~MemoryDependenceWrapperPass() override
void getAnalysisUsage(AnalysisUsage &AU) const override
Does not modify anything. It uses Value Numbering and Alias Analysis.
void releaseMemory() override
Clean up memory in between runs.
Representation for a specific memory location.
MemoryLocation getWithNewSize(LocationSize NewSize) const
MemoryLocation getWithoutAATags() const
static 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 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.
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 ...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void clear()
clear - Remove all information.
ArrayRef< BasicBlock * > get(BasicBlock *BB)
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...
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.
Target - Wrapper for Target specific information.
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.
Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
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.
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
const ParentTy * getParent() const
self_iterator getIterator()
This class provides various memory handling functions that manipulate MemoryBlock instances.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void initializeMemoryDependenceWrapperPassPass(PassRegistry &)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool isStrongerThanUnordered(AtomicOrdering AO)
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
auto reverse(ContainerTy &&C)
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
bool isModOrRefSet(const ModRefInfo MRI)
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.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
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,...
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
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...