30#include "llvm/Config/llvm-config.h"
61#define DEBUG_TYPE "memoryssa"
76 "memssa-check-limit",
cl::Hidden,
cl::init(100),
77 cl::desc(
"The maximum number of stores/phis MemorySSA"
78 "will consider trying to walk past (default = 100)"));
81#ifdef EXPENSIVE_CHECKS
101 MemorySSAAnnotatedWriter(
const MemorySSA *M) : MSSA(M) {}
103 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
106 OS <<
"; " << *MA <<
"\n";
112 OS <<
"; " << *MA <<
"\n";
124 MemorySSAWalkerAnnotatedWriter(
MemorySSA *M)
125 : MSSA(M), Walker(M->getWalker()), BAA(M->getAA()) {}
127 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
130 OS <<
"; " << *MA <<
"\n";
139 OS <<
" - clobbered by ";
159class MemoryLocOrCall {
163 MemoryLocOrCall(MemoryUseOrDef *MUD)
164 : MemoryLocOrCall(MUD->getMemoryInst()) {}
165 MemoryLocOrCall(
const MemoryUseOrDef *MUD)
166 : MemoryLocOrCall(MUD->getMemoryInst()) {}
168 MemoryLocOrCall(Instruction *Inst) {
181 explicit MemoryLocOrCall(
const MemoryLocation &Loc) : Loc(Loc) {}
183 const CallBase *getCall()
const {
188 MemoryLocation getLoc()
const {
194 if (IsCall !=
Other.IsCall)
198 return Loc ==
Other.Loc;
205 Other.Call->arg_begin());
210 const CallBase *
Call;
232 MLOC.getCall()->getCalledOperand()));
234 for (
const Value *Arg : MLOC.getCall()->args())
239 static bool isEqual(
const MemoryLocOrCall &LHS,
const MemoryLocOrCall &RHS) {
254 bool VolatileUse =
Use->isVolatile();
255 bool VolatileClobber = MayClobber->
isVolatile();
257 if (VolatileUse && VolatileClobber)
273 return !(SeqCstUse || MayClobberIsAcquire);
276template <
typename AliasAnalysisType>
281 assert(DefInst &&
"Defining instruction not actually an instruction");
291 switch (
II->getIntrinsicID()) {
292 case Intrinsic::allow_runtime_check:
293 case Intrinsic::allow_ubsan_check:
294 case Intrinsic::invariant_start:
295 case Intrinsic::invariant_end:
296 case Intrinsic::assume:
297 case Intrinsic::experimental_noalias_scope_decl:
298 case Intrinsic::pseudoprobe:
300 case Intrinsic::dbg_declare:
301 case Intrinsic::dbg_label:
302 case Intrinsic::dbg_value:
322template <
typename AliasAnalysisType>
324 const MemoryLocOrCall &UseMLOC,
325 AliasAnalysisType &
AA) {
343struct UpwardsMemoryQuery {
353 bool SkipSelfAccess =
false;
355 UpwardsMemoryQuery() =
default;
366template <
typename AliasAnalysisType>
372 return I->hasMetadata(LLVMContext::MD_invariant_load) ||
392[[maybe_unused]]
static void
396 bool AllowImpreciseClobber =
false) {
397 assert(MSSA.
dominates(ClobberAt, Start) &&
"Clobber doesn't dominate start?");
401 "liveOnEntry must clobber itself");
405 bool FoundClobber =
false;
408 Worklist.
push_back({Start, StartLoc,
false});
411 while (!Worklist.
empty()) {
419 if (MA == ClobberAt) {
446 "Found clobber before reaching ClobberAt!");
453 "Can only find use in def chain if Start is a use");
474 if (AllowImpreciseClobber)
480 "ClobberAt never acted as a clobber");
489 using ListIndex = unsigned;
499 std::optional<ListIndex> Previous;
500 bool MayBeCrossIteration;
502 DefPath(
const MemoryLocation &Loc, MemoryAccess *
First, MemoryAccess *
Last,
503 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
505 MayBeCrossIteration(MayBeCrossIteration) {}
507 DefPath(
const MemoryLocation &Loc, MemoryAccess *Init,
508 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
509 : DefPath(Loc, Init, Init, MayBeCrossIteration, Previous) {}
515 UpwardsMemoryQuery *Query;
516 unsigned *UpwardWalkLimit;
523 DenseSet<UpwardDefsElem> VisitedPhis;
526 const MemoryAccess *getWalkTarget(
const MemoryPhi *From)
const {
532 while ((Node =
Node->getIDom())) {
541 struct UpwardsWalkResult {
554 walkToPhiOrClobber(DefPath &
Desc,
const MemoryAccess *
StopAt =
nullptr,
555 const MemoryAccess *SkipStopAt =
nullptr)
const {
557 assert(UpwardWalkLimit &&
"Need a valid walk limit");
558 bool LimitAlreadyReached =
false;
563 if (!*UpwardWalkLimit) {
564 *UpwardWalkLimit = 1;
565 LimitAlreadyReached =
true;
570 if (Current ==
StopAt || Current == SkipStopAt)
571 return {Current,
false};
577 if (!--*UpwardWalkLimit)
578 return {Current,
true};
580 BatchAACrossIterationScope
_(*AA,
Desc.MayBeCrossIteration);
586 if (LimitAlreadyReached)
587 *UpwardWalkLimit = 0;
590 "Ended at a non-clobber that's not a phi?");
591 return {
Desc.Last,
false};
594 void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
595 ListIndex PriorNode,
bool MayBeCrossIteration) {
596 auto UpwardDefsBegin =
599 for (
const UpwardDefsElem &
E : UpwardDefs) {
608 struct TerminatedPath {
609 MemoryAccess *Clobber;
622 std::optional<TerminatedPath>
623 getBlockingAccess(
const MemoryAccess *StopWhere,
624 SmallVectorImpl<ListIndex> &PausedSearches,
625 SmallVectorImpl<ListIndex> &NewPaused,
626 SmallVectorImpl<TerminatedPath> &Terminated) {
627 assert(!PausedSearches.
empty() &&
"No searches to continue?");
631 while (!PausedSearches.
empty()) {
633 DefPath &
Node = Paths[PathIndex];
653 if (!VisitedPhis.
insert({Node.Last, Node.Loc, Node.MayBeCrossIteration})
657 const MemoryAccess *SkipStopWhere =
nullptr;
658 if (Query->SkipSelfAccess &&
Node.Loc == Query->StartingLoc) {
660 SkipStopWhere = Query->OriginalAccess;
663 UpwardsWalkResult Res = walkToPhiOrClobber(Node,
666 if (Res.IsKnownClobber) {
667 assert(Res.Result != StopWhere && Res.Result != SkipStopWhere);
671 TerminatedPath
Term{Res.Result, PathIndex};
672 if (!MSSA.
dominates(Res.Result, StopWhere))
680 if (Res.Result == StopWhere || Res.Result == SkipStopWhere) {
685 if (Res.Result != SkipStopWhere)
692 Node.MayBeCrossIteration);
698 template <
typename T,
typename Walker>
699 struct generic_def_path_iterator
700 :
public iterator_facade_base<generic_def_path_iterator<T, Walker>,
701 std::forward_iterator_tag, T *> {
702 generic_def_path_iterator() =
default;
703 generic_def_path_iterator(Walker *W, ListIndex
N) :
W(
W),
N(
N) {}
707 generic_def_path_iterator &operator++() {
708 N = curNode().Previous;
712 bool operator==(
const generic_def_path_iterator &O)
const {
713 if (
N.has_value() !=
O.N.has_value())
715 return !
N || *
N == *
O.N;
719 T &curNode()
const {
return W->Paths[*
N]; }
722 std::optional<ListIndex>
N;
725 using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
726 using const_def_path_iterator =
727 generic_def_path_iterator<const DefPath, const ClobberWalker>;
730 return make_range(def_path_iterator(
this, From), def_path_iterator());
734 return make_range(const_def_path_iterator(
this, From),
735 const_def_path_iterator());
740 TerminatedPath PrimaryClobber;
746 ListIndex defPathIndex(
const DefPath &
N)
const {
748 const DefPath *NP = &
N;
750 "Out of bounds DefPath!");
751 return NP - &Paths.
front();
767 OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
768 const MemoryLocation &Loc) {
770 "Reset the optimization state.");
776 auto PriorPathsSize = Paths.
size();
782 addSearches(Phi, PausedSearches, 0,
false);
786 auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
788 auto Dom = Paths.
begin();
789 for (
auto I = std::next(Dom),
E = Paths.
end();
I !=
E; ++
I)
790 if (!MSSA.
dominates(
I->Clobber, Dom->Clobber))
794 std::iter_swap(
Last, Dom);
797 MemoryPhi *Current =
Phi;
800 "liveOnEntry wasn't treated as a clobber?");
802 const auto *
Target = getWalkTarget(Current);
805 assert(
all_of(TerminatedPaths, [&](
const TerminatedPath &
P) {
812 if (std::optional<TerminatedPath> Blocker = getBlockingAccess(
813 Target, PausedSearches, NewPaused, TerminatedPaths)) {
817 auto Iter =
find_if(def_path(Blocker->LastNode), [&](
const DefPath &
N) {
818 return defPathIndex(N) < PriorPathsSize;
820 assert(Iter != def_path_iterator());
822 DefPath &CurNode = *Iter;
823 assert(CurNode.Last == Current);
850 TerminatedPath
Result{CurNode.Last, defPathIndex(CurNode)};
857 if (NewPaused.
empty()) {
858 MoveDominatedPathToEnd(TerminatedPaths);
860 return {
Result, std::move(TerminatedPaths)};
863 MemoryAccess *DefChainEnd =
nullptr;
865 for (ListIndex Paused : NewPaused) {
866 UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
867 if (WR.IsKnownClobber)
871 DefChainEnd = WR.Result;
874 if (!TerminatedPaths.
empty()) {
878 for (
auto *MA :
def_chain(
const_cast<MemoryAccess *
>(Target)))
880 assert(DefChainEnd &&
"Failed to find dominating phi/liveOnEntry");
885 for (
const TerminatedPath &TP : TerminatedPaths) {
888 if (DT.
dominates(ChainBB, TP.Clobber->getBlock()))
895 if (!Clobbers.
empty()) {
896 MoveDominatedPathToEnd(Clobbers);
898 return {
Result, std::move(Clobbers)};
902 [&](ListIndex
I) {
return Paths[
I].Last == DefChainEnd; }));
907 PriorPathsSize = Paths.
size();
908 PausedSearches.
clear();
909 for (ListIndex
I : NewPaused)
910 addSearches(DefChainPhi, PausedSearches,
I,
911 Paths[
I].MayBeCrossIteration);
914 Current = DefChainPhi;
918 void verifyOptResult(
const OptznResult &R)
const {
920 return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
924 void resetPhiOptznState() {
930 ClobberWalker(
const MemorySSA &MSSA, DominatorTree &DT)
931 : MSSA(MSSA), DT(DT) {}
935 MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
936 UpwardsMemoryQuery &Q,
unsigned &UpWalkLimit) {
939 UpwardWalkLimit = &UpWalkLimit;
944 MemoryAccess *Current =
Start;
948 Current = MU->getDefiningAccess();
950 DefPath FirstDesc(Q.StartingLoc, Current, Current,
951 false, std::nullopt);
954 UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
956 if (WalkResult.IsKnownClobber) {
957 Result = WalkResult.Result;
960 Current, Q.StartingLoc);
961 verifyOptResult(OptRes);
962 resetPhiOptznState();
963 Result = OptRes.PrimaryClobber.Clobber;
966#ifdef EXPENSIVE_CHECKS
967 if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
974struct RenamePassData {
976 DomTreeNode::const_iterator ChildIt;
977 MemoryAccess *IncomingVal;
979 RenamePassData(
DomTreeNode *
D, DomTreeNode::const_iterator It,
981 : DTN(
D), ChildIt(It), IncomingVal(
M) {}
983 void swap(RenamePassData &
RHS) {
995 ClobberWalker Walker;
1012 bool UseInvariantGroup =
true);
1030 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false);
1035 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1040 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false,
false);
1057 MUD->resetOptimized();
1073 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
true);
1078 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1095 MUD->resetOptimized();
1102 bool RenameAllUses) {
1105 auto It = PerBlockAccesses.find(S);
1107 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1111 if (RenameAllUses) {
1112 bool ReplacementDone =
false;
1113 for (
unsigned I = 0,
E = Phi->getNumIncomingValues();
I !=
E; ++
I)
1114 if (Phi->getIncomingBlock(
I) == BB) {
1115 Phi->setIncomingValue(
I, IncomingVal);
1116 ReplacementDone =
true;
1118 (void) ReplacementDone;
1119 assert(ReplacementDone &&
"Incomplete phi during partial rename");
1121 Phi->addIncoming(IncomingVal, BB);
1129 bool RenameAllUses) {
1130 auto It = PerBlockAccesses.find(BB);
1132 if (It != PerBlockAccesses.end()) {
1134 for (MemoryAccess &L : *
Accesses) {
1136 if (MUD->getDefiningAccess() ==
nullptr || RenameAllUses)
1137 MUD->setDefiningAccess(IncomingVal);
1154 bool SkipVisited,
bool RenameAllUses) {
1155 assert(Root &&
"Trying to rename accesses in an unreachable block");
1162 if (SkipVisited && AlreadyVisited)
1165 IncomingVal = renameBlock(Root->
getBlock(), IncomingVal, RenameAllUses);
1166 renameSuccessorPhis(Root->
getBlock(), IncomingVal, RenameAllUses);
1169 while (!WorkStack.
empty()) {
1171 DomTreeNode::const_iterator ChildIt = WorkStack.
back().ChildIt;
1172 IncomingVal = WorkStack.
back().IncomingVal;
1174 if (ChildIt ==
Node->end()) {
1178 ++WorkStack.
back().ChildIt;
1182 AlreadyVisited = !Visited.
insert(BB).second;
1183 if (SkipVisited && AlreadyVisited) {
1190 IncomingVal = &*BlockDefs->rbegin();
1192 IncomingVal = renameBlock(BB, IncomingVal, RenameAllUses);
1193 renameSuccessorPhis(BB, IncomingVal, RenameAllUses);
1202void MemorySSA::markUnreachableAsLiveOnEntry(
BasicBlock *BB) {
1203 assert(!DT->isReachableFromEntry(BB) &&
1204 "Reachable block found while handling unreachable blocks");
1211 if (!DT->isReachableFromEntry(S))
1213 auto It = PerBlockAccesses.find(S);
1215 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1219 Phi->addIncoming(LiveOnEntryDef.get(), BB);
1222 auto It = PerBlockAccesses.find(BB);
1223 if (It == PerBlockAccesses.end())
1228 auto Next = std::next(AI);
1232 UseOrDef->setDefiningAccess(LiveOnEntryDef.get());
1240 : DT(DT), F(&Func), LiveOnEntryDef(nullptr), Walker(nullptr),
1241 SkipWalker(nullptr) {
1247 assert(AA &&
"No alias analysis?");
1258 : DT(DT), L(&L), LiveOnEntryDef(nullptr), Walker(nullptr),
1259 SkipWalker(nullptr) {
1265 assert(AA &&
"No alias analysis?");
1269 return *const_cast<BasicBlock *>(BB);
1280 for (
const auto &Pair : PerBlockAccesses)
1286 auto Res = PerBlockAccesses.try_emplace(BB);
1289 Res.first->second = std::make_unique<AccessList>();
1290 return Res.first->second.get();
1294 auto Res = PerBlockDefs.try_emplace(BB);
1297 Res.first->second = std::make_unique<DefsList>();
1298 return Res.first->second.get();
1314 : MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
1320 struct MemlocStackInfo {
1323 unsigned long StackEpoch;
1324 unsigned long PopEpoch;
1329 unsigned long LowerBound;
1332 unsigned long LastKill;
1336 void optimizeUsesInBlock(
const BasicBlock *,
unsigned long &,
unsigned long &,
1341 CachingWalker *Walker;
1360void MemorySSA::OptimizeUses::optimizeUsesInBlock(
1361 const BasicBlock *BB,
unsigned long &StackEpoch,
unsigned long &PopEpoch,
1374 !VersionStack.
empty() &&
1375 "Version stack should have liveOnEntry sentinel dominating everything");
1377 if (DT->dominates(BackBlock, BB))
1379 while (VersionStack.
back()->getBlock() == BackBlock)
1384 for (MemoryAccess &MA : *
Accesses) {
1392 if (MU->isOptimized())
1395 MemoryLocOrCall UseMLOC(MU);
1396 auto &LocInfo = LocStackInfo[UseMLOC];
1400 if (LocInfo.PopEpoch != PopEpoch) {
1401 LocInfo.PopEpoch = PopEpoch;
1402 LocInfo.StackEpoch = StackEpoch;
1414 if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
1415 !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
1419 LocInfo.LowerBound = 0;
1420 LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
1421 LocInfo.LastKillValid =
false;
1423 }
else if (LocInfo.StackEpoch != StackEpoch) {
1427 LocInfo.PopEpoch = PopEpoch;
1428 LocInfo.StackEpoch = StackEpoch;
1430 if (!LocInfo.LastKillValid) {
1431 LocInfo.LastKill = VersionStack.
size() - 1;
1432 LocInfo.LastKillValid =
true;
1437 assert(LocInfo.LowerBound < VersionStack.
size() &&
1438 "Lower bound out of range");
1439 assert(LocInfo.LastKill < VersionStack.
size() &&
1440 "Last kill info out of range");
1442 unsigned long UpperBound = VersionStack.
size() - 1;
1445 LLVM_DEBUG(
dbgs() <<
"MemorySSA skipping optimization of " << *MU <<
" ("
1446 << *(MU->getMemoryInst()) <<
")"
1447 <<
" because there are "
1448 << UpperBound - LocInfo.LowerBound
1449 <<
" stores to disambiguate\n");
1452 LocInfo.LastKillValid =
false;
1455 bool FoundClobberResult =
false;
1457 while (UpperBound > LocInfo.LowerBound) {
1463 Walker->getClobberingMemoryAccessWithoutInvariantGroup(
1464 MU, *AA, UpwardWalkLimit);
1466 while (VersionStack[UpperBound] != Result) {
1470 FoundClobberResult =
true;
1476 FoundClobberResult =
true;
1484 if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
1485 MU->setDefiningAccess(VersionStack[UpperBound],
true);
1486 LocInfo.LastKill = UpperBound;
1490 MU->setDefiningAccess(VersionStack[LocInfo.LastKill],
true);
1492 LocInfo.LowerBound = VersionStack.
size() - 1;
1493 LocInfo.LowerBoundBlock = BB;
1501 VersionStack.
push_back(MSSA->getLiveOnEntryDef());
1503 unsigned long StackEpoch = 1;
1504 unsigned long PopEpoch = 1;
1506 for (
const auto *DomNode :
depth_first(DT->getRootNode()))
1507 optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
1511void MemorySSA::placePHINodes(
1515 IDFs.setDefiningBlocks(DefiningBlocks);
1517 IDFs.calculate(IDFBlocks);
1520 for (
auto &BB : IDFBlocks)
1521 createMemoryPhi(BB);
1524template <
typename IterT>
1525void MemorySSA::buildMemorySSA(
BatchAAResults &BAA, IterT Blocks) {
1534 nullptr, &StartingPoint, NextID++));
1543 bool InsertIntoDef =
false;
1555 InsertIntoDef =
true;
1557 Defs = getOrCreateDefsList(&
B);
1558 Defs->push_back(*MUD);
1564 placePHINodes(DefiningBlocks);
1568 SmallPtrSet<BasicBlock *, 16> Visited;
1575 U.set(LiveOnEntryDef.get());
1581 L->getExitBlocks(ExitBlocks);
1583 renamePass(DT->getNode(L->getLoopPreheader()), LiveOnEntryDef.get(),
1586 renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
1591 for (
auto &BB : Blocks)
1592 if (!Visited.
count(&BB))
1593 markUnreachableAsLiveOnEntry(&BB);
1600 return Walker.get();
1603 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1605 Walker = std::make_unique<CachingWalker>(
this, WalkerBase.get());
1606 return Walker.get();
1611 return SkipWalker.get();
1614 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1616 SkipWalker = std::make_unique<SkipSelfWalker>(
this, WalkerBase.get());
1617 return SkipWalker.get();
1627 auto *
Accesses = getOrCreateAccessList(BB);
1633 auto *Defs = getOrCreateDefsList(BB);
1634 Defs->push_front(*NewAccess);
1640 auto *Defs = getOrCreateDefsList(BB);
1643 Defs->insert(DI, *NewAccess);
1649 auto *Defs = getOrCreateDefsList(BB);
1650 Defs->push_back(*NewAccess);
1653 BlockNumberingValid.erase(BB);
1659 bool WasEnd = InsertPt ==
Accesses->end();
1662 auto *Defs = getOrCreateDefsList(BB);
1668 Defs->push_back(*What);
1670 Defs->insert(InsertPt->getDefsIterator(), *What);
1676 Defs->push_back(*What);
1678 Defs->insert(InsertPt->getDefsIterator(), *What);
1681 BlockNumberingValid.erase(BB);
1702 prepareForMoveTo(What, BB);
1710 "Can only move a Phi at the beginning of the block");
1712 ValueToMemoryAccess.erase(What->
getBlock());
1713 bool Inserted = ValueToMemoryAccess.insert({BB, What}).second;
1715 assert(Inserted &&
"Cannot move a Phi to a block that already has one");
1718 prepareForMoveTo(What, BB);
1727 ValueToMemoryAccess[BB] = Phi;
1734 bool CreationMustSucceed) {
1737 if (CreationMustSucceed)
1738 assert(NewAccess !=
nullptr &&
"Tried to create a memory access for a "
1739 "non-memory touching instruction");
1742 "A use cannot be a defining access");
1753 if (!
SI->isUnordered())
1756 if (!LI->isUnordered())
1763template <
typename AliasAnalysisType>
1764MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *
I,
1765 AliasAnalysisType *AAP,
1774 switch (
II->getIntrinsicID()) {
1777 case Intrinsic::allow_runtime_check:
1778 case Intrinsic::allow_ubsan_check:
1779 case Intrinsic::assume:
1780 case Intrinsic::experimental_noalias_scope_decl:
1781 case Intrinsic::pseudoprobe:
1789 if (!
I->mayReadFromMemory() && !
I->mayWriteToMemory())
1798 bool DefCheck, UseCheck;
1803 assert((Def == DefCheck || !DefCheck) &&
1804 "Memory accesses should only be reduced");
1805 if (!Def && Use != UseCheck) {
1807 assert(!UseCheck &&
"Invalid template");
1830 MemoryUseOrDef *MUD;
1832 MUD =
new MemoryDef(
I->getContext(),
nullptr,
I,
I->getParent(), NextID++);
1834 MUD =
new MemoryUse(
I->getContext(),
nullptr,
I,
I->getParent());
1840 ValueToMemoryAccess[
I] = MUD;
1847 "Trying to remove memory access that still has uses");
1848 BlockNumbering.erase(MA);
1861 auto VMA = ValueToMemoryAccess.find(MemoryInst);
1862 if (VMA->second == MA)
1863 ValueToMemoryAccess.
erase(VMA);
1877 auto DefsIt = PerBlockDefs.find(BB);
1878 std::unique_ptr<DefsList> &Defs = DefsIt->second;
1881 PerBlockDefs.erase(DefsIt);
1886 auto AccessIt = PerBlockAccesses.find(BB);
1887 std::unique_ptr<AccessList> &
Accesses = AccessIt->second;
1894 PerBlockAccesses.erase(AccessIt);
1895 BlockNumberingValid.erase(BB);
1900 MemorySSAAnnotatedWriter Writer(
this);
1904 F->
print(OS, &Writer);
1907#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1912#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS)
1924 assert(L &&
"must either have loop or function");
1927 return *const_cast<BasicBlock *>(BB);
1947template <
typename IterT>
1951 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
1952 auto *Pred = Phi->getIncomingBlock(
I);
1953 auto *IncAcc = Phi->getIncomingValue(
I);
1957 if (
auto *DTNode = DT->getNode(Pred)) {
1959 if (
auto *DefList =
getBlockDefs(DTNode->getBlock())) {
1960 auto *LastAcc = &*(--DefList->end());
1961 assert(LastAcc == IncAcc &&
1962 "Incorrect incoming access into phi.");
1967 DTNode = DTNode->getIDom();
1984template <
typename IterT>
1986 if (BlockNumberingValid.empty())
1991 if (!ValidBlocks.
count(&BB))
1994 ValidBlocks.
erase(&BB);
2002 unsigned long LastNumber = 0;
2004 auto ThisNumberIter = BlockNumbering.find(&MA);
2005 assert(ThisNumberIter != BlockNumbering.end() &&
2006 "MemoryAccess has no domination number in a valid block!");
2008 unsigned long ThisNumber = ThisNumberIter->second;
2009 assert(ThisNumber > LastNumber &&
2010 "Domination numbers should be strictly increasing!");
2012 LastNumber = ThisNumber;
2017 "All valid BasicBlocks should exist in F -- dangling pointers?");
2026template <
typename IterT>
2043 for (
const Use &U : Phi->uses()) {
2044 assert(
dominates(Phi, U) &&
"Memory PHI does not dominate it's uses");
2050 "Incomplete MemoryPhi Node");
2051 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
2052 verifyUseInDefs(Phi->getIncomingValue(
I), Phi);
2054 "Incoming phi block not a block predecessor");
2062 "We have memory affecting instructions "
2063 "in this block but they are not in the "
2064 "access list or defs list");
2072 for (
const Use &U : MD->
uses()) {
2074 "Memory Def does not dominate it's uses");
2088 assert(AL->size() == ActualAccesses.
size() &&
2089 "We don't have the same number of accesses in the block as on the "
2092 "Either we should have a defs list, or we should have no defs");
2094 "We don't have the same number of defs in the block as on the "
2096 auto ALI = AL->begin();
2097 auto AAI = ActualAccesses.
begin();
2098 while (ALI != AL->end() && AAI != ActualAccesses.
end()) {
2099 assert(&*ALI == *AAI &&
"Not the same accesses in the same order");
2103 ActualAccesses.
clear();
2105 auto DLI =
DL->begin();
2106 auto ADI = ActualDefs.
begin();
2107 while (DLI !=
DL->end() && ADI != ActualDefs.
end()) {
2108 assert(&*DLI == *ADI &&
"Not the same defs in the same order");
2123 "Null def but use not point to live on entry def");
2126 "Did not find use in def's use list");
2135void MemorySSA::renumberBlock(
const BasicBlock *
B)
const {
2137 unsigned long CurrentNumber = 0;
2139 assert(AL !=
nullptr &&
"Asking to renumber an empty block");
2140 for (
const auto &
I : *AL)
2141 BlockNumbering[&
I] = ++CurrentNumber;
2142 BlockNumberingValid.insert(
B);
2153 "Asking for local domination when accesses are in different blocks!");
2155 if (Dominatee == Dominator)
2168 if (!BlockNumberingValid.count(DominatorBlock))
2169 renumberBlock(DominatorBlock);
2171 unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
2173 assert(DominatorNum != 0 &&
"Block was not numbered properly");
2174 unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
2175 assert(DominateeNum != 0 &&
"Block was not numbered properly");
2176 return DominatorNum < DominateeNum;
2181 if (Dominator == Dominatee)
2193 const Use &Dominatee)
const {
2195 BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
2197 if (UseBB != Dominator->
getBlock())
2198 return DT->dominates(Dominator->
getBlock(), UseBB);
2219 case MemoryPhiVal:
return static_cast<const MemoryPhi *
>(
this)->
print(OS);
2220 case MemoryDefVal:
return static_cast<const MemoryDef *
>(
this)->
print(OS);
2221 case MemoryUseVal:
return static_cast<const MemoryUse *
>(
this)->
print(OS);
2230 if (
A &&
A->getID())
2236 OS <<
getID() <<
" = MemoryDef(";
2248 OS <<
getID() <<
" = MemoryPhi(";
2259 if (
unsigned ID = MA->
getID())
2271 if (UO && UO->
getID())
2280#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2289 MemorySSAAnnotatedWriter MSSAWriter;
2293 : F(F), MSSAWriter(&MSSA) {}
2296 MemorySSAAnnotatedWriter &
getWriter() {
return MSSAWriter; }
2304 return &(CFGInfo->
getFunction()->getEntryBlock());
2339 [](std::string &S,
unsigned &
I,
unsigned Idx) ->
void {
2340 std::string Str = S.substr(
I, Idx -
I);
2342 if (SR.
count(
" = MemoryDef(") || SR.
count(
" = MemoryPhi(") ||
2343 SR.
count(
"MemoryUse("))
2363 ?
"style=filled, fillcolor=lightpink"
2370AnalysisKey MemorySSAAnalysis::Key;
2381 FunctionAnalysisManager::Invalidator &Inv) {
2391 if (EnsureOptimizedUses)
2397 OS <<
"MemorySSA for function: " <<
F.getName() <<
"\n";
2407 OS <<
"MemorySSA (walker) for function: " <<
F.getName() <<
"\n";
2408 MemorySSAWalkerAnnotatedWriter Writer(&MSSA);
2409 F.print(OS, &Writer);
2442 MSSA->verifyMemorySSA();
2461 if (
Loc.Ptr ==
nullptr)
2462 return StartingAccess;
2467 return StartingUseOrDef;
2469 I = StartingUseOrDef->getMemoryInst();
2474 return StartingUseOrDef;
2477 UpwardsMemoryQuery Q;
2478 Q.OriginalAccess = StartingAccess;
2479 Q.StartingLoc =
Loc;
2487 Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
2489 dbgs() <<
"Clobber starting at access " << *StartingAccess <<
"\n";
2491 dbgs() <<
" for instruction " << *
I <<
"\n";
2492 dbgs() <<
" is " << *Clobber <<
"\n";
2499 if (!
I.hasMetadata(LLVMContext::MD_invariant_group) ||
I.isVolatile())
2516 for (
const User *Us : PointerOperand->
users()) {
2518 if (!U || U == &
I || !DT.
dominates(U, MostDominatingInstruction))
2524 if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
2526 MostDominatingInstruction = U;
2530 return MostDominatingInstruction == &
I ? nullptr : MostDominatingInstruction;
2534 MemoryAccess *MA, BatchAAResults &BAA,
unsigned &UpwardWalkLimit,
2535 bool SkipSelf,
bool UseInvariantGroup) {
2538 if (!StartingAccess)
2541 if (UseInvariantGroup) {
2543 *StartingAccess->getMemoryInst(), MSSA->
getDomTree())) {
2549 return ClobberMA->getDefiningAccess();
2554 bool IsOptimized =
false;
2559 if (StartingAccess->isOptimized()) {
2561 return StartingAccess->getOptimized();
2565 const Instruction *
I = StartingAccess->getMemoryInst();
2570 return StartingAccess;
2572 UpwardsMemoryQuery Q(
I, StartingAccess);
2576 StartingAccess->setOptimized(LiveOnEntry);
2580 MemoryAccess *OptimizedAccess;
2583 MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
2588 StartingAccess->setOptimized(DefiningAccess);
2589 return DefiningAccess;
2593 Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
2594 StartingAccess->setOptimized(OptimizedAccess);
2596 OptimizedAccess = StartingAccess->getOptimized();
2598 LLVM_DEBUG(
dbgs() <<
"Starting Memory SSA clobber for " << *
I <<
" is ");
2600 LLVM_DEBUG(
dbgs() <<
"Optimized Memory SSA clobber for " << *
I <<
" is ");
2607 Q.SkipSelfAccess =
true;
2608 Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
2610 Result = OptimizedAccess;
2612 LLVM_DEBUG(
dbgs() <<
"Result Memory SSA clobber [SkipSelf = " << SkipSelf);
2622 return Use->getDefiningAccess();
2629 return Use->getDefiningAccess();
2630 return StartingAccess;
2641void MemoryUse::deleteMe(DerivedUser *Self) {
2642 delete static_cast<MemoryUse *
>(Self);
2645bool upward_defs_iterator::IsGuaranteedLoopInvariant(
const Value *Ptr)
const {
2646 auto IsGuaranteedLoopInvariantBase = [](
const Value *Ptr) {
2655 if (
I->getParent()->isEntryBlock())
2659 return IsGuaranteedLoopInvariantBase(
GEP->getPointerOperand()) &&
2660 GEP->hasAllConstantIndices();
2662 return IsGuaranteedLoopInvariantBase(Ptr);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
DXIL Forward Handle Accesses
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
early cse Early CSE w MemorySSA
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file provides utility analysis objects describing memory locations.
static bool instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc, const Instruction *UseInst, AliasAnalysisType &AA)
Memory static true cl::opt< unsigned > MaxCheckLimit("memssa-check-limit", cl::Hidden, cl::init(100), cl::desc("The maximum number of stores/phis MemorySSA" "will consider trying to walk past (default = 100)"))
static void checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt, const MemoryLocation &StartLoc, const MemorySSA &MSSA, const UpwardsMemoryQuery &Query, BatchAAResults &AA, bool AllowImpreciseClobber=false)
Verifies that Start is clobbered by ClobberAt, and that nothing inbetween Start and ClobberAt can clo...
static cl::opt< bool, true > VerifyMemorySSAX("verify-memoryssa", cl::location(VerifyMemorySSA), cl::Hidden, cl::desc("Enable verification of MemorySSA."))
static const char LiveOnEntryStr[]
static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA, const Instruction *I)
static bool areLoadsReorderable(const LoadInst *Use, const LoadInst *MayClobber)
This does one-way checks to see if Use could theoretically be hoisted above MayClobber.
static const Instruction * getInvariantGroupClobberingInstruction(Instruction &I, DominatorTree &DT)
static cl::opt< std::string > DotCFGMSSA("dot-cfg-mssa", cl::value_desc("file name for generated dot file"), cl::desc("file name for generated dot file"), cl::init(""))
static bool isOrdered(const Instruction *I)
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
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.
DOTFuncMSSAInfo(const Function &F, MemorySSA &MSSA)
const Function * getFunction()
MemorySSAAnnotatedWriter & getWriter()
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
This templated class represents "all analyses that operate over <aparticular IR unit>" (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.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
LLVM Basic Block Representation.
LLVM_ABI BasicBlock::iterator erase(BasicBlock::iterator FromIt, BasicBlock::iterator ToIt)
Erases a range of instructions from FromIt to (not including) ToIt.
iterator begin()
Instruction iterator methods.
LLVM_ABI void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW=nullptr, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the basic block to an output stream with an optional AssemblyAnnotationWriter.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
Temporarily set the cross iteration mode on a BatchAA instance.
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getCalledOperand() const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
Implements a dense probed hash-table based set.
Extension point for the Value hierarchy.
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *, BatchAAResults &) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Module * getParent()
Get the module that this global value is contained inside of...
A wrapper class for inspecting calls to intrinsic functions.
A helper class to return the specified delimiter string after the first invocation of operator String...
An instruction for reading from memory.
bool isVolatile() const
Return true if this is a load from a volatile memory location.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Represents a single loop in the control flow graph.
LLVM_ABI void dump() const
MemoryAccess(const MemoryAccess &)=delete
BasicBlock * getBlock() const
LLVM_ABI void print(raw_ostream &OS) const
unsigned getID() const
Used for debugging and tracking things about MemoryAccesses.
void setBlock(BasicBlock *BB)
Used by MemorySSA to change the block of a MemoryAccess when it is moved.
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
LLVM_ABI void print(raw_ostream &OS) const
MemoryAccess * getOptimized() const
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Represents phi nodes for memory accesses.
BasicBlock * getIncomingBlock(unsigned I) const
Return incoming basic block number i.
LLVM_ABI void print(raw_ostream &OS) const
An analysis that produces MemorySSA for a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static LLVM_ABI bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU, AliasAnalysis &AA)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This is the generic walker interface for walkers of MemorySSA.
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
LLVM_ABI MemorySSAWalker(MemorySSA *)
virtual void invalidateInfo(MemoryAccess *)
Given a memory access, invalidate anything this walker knows about that access.
Legacy analysis pass which computes MemorySSA.
void verifyAnalysis() const override
verifyAnalysis() - This member can be implemented by a analysis pass to check state of analysis infor...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
bool runOnFunction(Function &) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void print(raw_ostream &OS, const Module *M=nullptr) const override
print - Print out the internal state of the pass.
A MemorySSAWalker that does AA walks to disambiguate accesses.
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
MemoryAccess * getClobberingMemoryAccessWithoutInvariantGroup(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA, unsigned &UWL)
void invalidateInfo(MemoryAccess *MA) override
Given a memory access, invalidate anything this walker knows about that access.
~CachingWalker() override=default
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
CachingWalker(MemorySSA *M, ClobberWalkerBase *W)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA) override
Given a potentially clobbering memory access and a new location, calling this will give you the neare...
ClobberWalkerBase(MemorySSA *M, DominatorTree *D)
MemoryAccess * getClobberingMemoryAccessBase(MemoryAccess *, BatchAAResults &, unsigned &, bool, bool UseInvariantGroup=true)
MemoryAccess * getClobberingMemoryAccessBase(MemoryAccess *, const MemoryLocation &, BatchAAResults &, unsigned &)
This class is a batch walker of all MemoryUse's in the program, and points their defining access at t...
void optimizeUses()
Optimize uses to point to their actual clobbering definitions.
OptimizeUses(MemorySSA *MSSA, CachingWalker *Walker, BatchAAResults *BAA, DominatorTree *DT)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA) override
Given a potentially clobbering memory access and a new location, calling this will give you the neare...
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA, unsigned &UWL)
~SkipSelfWalker() override=default
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
SkipSelfWalker(MemorySSA *M, ClobberWalkerBase *W)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
void invalidateInfo(MemoryAccess *MA) override
Given a memory access, invalidate anything this walker knows about that access.
Encapsulates MemorySSA, including all data associated with memory accesses.
LLVM_ABI void dump() const
simple_ilist< MemoryAccess, ilist_tag< MSSAHelpers::DefsOnlyTag > > DefsList
LLVM_ABI void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where)
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal, SmallPtrSetImpl< BasicBlock * > &Visited)
DefsList * getBlockDefs(const BasicBlock *BB) const
Return the list of MemoryDef's and MemoryPhi's for a given basic block.
LLVM_ABI MemorySSAWalker * getSkipSelfWalker()
LLVM_ABI MemorySSA(Function &, AliasAnalysis *, DominatorTree *)
iplist< MemoryAccess, ilist_tag< MSSAHelpers::AllAccessTag > > AccessList
AccessList * getBlockAccesses(const BasicBlock *BB) const
Return the list of MemoryAccess's for a given basic block.
LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
void verifyOrderingDominationAndDefUses(IterT Blocks, VerificationLevel=VerificationLevel::Fast) const
Verify ordering: the order and existence of MemoryAccesses matches the order and existence of memory ...
LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
LLVM_ABI void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *, InsertionPlace)
LLVM_ABI MemorySSAWalker * getWalker()
InsertionPlace
Used in various insertion functions to specify whether we are talking about the beginning or end of a...
LLVM_ABI void insertIntoListsBefore(MemoryAccess *, const BasicBlock *, AccessList::iterator)
LLVM_ABI MemoryUseOrDef * createDefinedAccess(Instruction *, MemoryAccess *, const MemoryUseOrDef *Template=nullptr, bool CreationMustSucceed=true)
DominatorTree & getDomTree() const
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
MemoryAccess * getLiveOnEntryDef() const
LLVM_ABI void removeFromLookups(MemoryAccess *)
Properly remove MA from all of MemorySSA's lookup tables.
LLVM_ABI void ensureOptimizedUses()
By default, uses are not optimized during MemorySSA construction.
void verifyDominationNumbers(IterT Blocks) const
Verify that all of the blocks we believe to have valid domination numbers actually have valid dominat...
void verifyPrevDefInPhis(IterT Blocks) const
LLVM_ABI bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...
LLVM_ABI void removeFromLists(MemoryAccess *, bool ShouldDelete=true)
Properly remove MA from all of MemorySSA's lists.
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
LLVM_ABI void print(raw_ostream &) const
Class that has the common methods + fields of memory uses/defs.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
void setDefiningAccess(MemoryAccess *DMA, bool Optimized=false)
void setOptimized(MemoryAccess *)
Sets the optimized use for a MemoryDef.
Instruction * getMemoryInst() const
Get the instruction that this MemoryUse represents.
LLVM_ABI void print(raw_ostream &OS) const
A Module instance is used to store all the information related to an LLVM module.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the module to an output stream with an optional AssemblyAnnotationWriter.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
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...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
size_t count(char C) const
Return the number of occurrences of C in the string.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
void dropAllReferences()
Drop all references to operands.
unsigned getNumOperands() const
LLVM Value Representation.
iterator_range< user_iterator > users()
unsigned getValueID() const
Return an ID for the concrete type of this object.
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
An opaque object representing a hash code.
typename base_list_type::iterator iterator
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
reverse_iterator rbegin()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
This namespace contains all of the command line option processing machinery.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static cl::opt< unsigned long > StopAt("sbvec-stop-at", cl::init(StopAtDisabled), cl::Hidden, cl::desc("Vectorize if the invocation count is < than this. 0 " "disables vectorization."))
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
auto successors(const MachineBasicBlock *BB)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto pred_size(const MachineBasicBlock *BB)
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
DomTreeNodeBase< BasicBlock > DomTreeNode
auto dyn_cast_or_null(const Y &Val)
iterator_range< def_chain_iterator< T > > def_chain(T MA, MemoryAccess *UpTo=nullptr)
bool isModSet(const ModRefInfo MRI)
auto find_if_not(R &&Range, UnaryPredicate P)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IDFCalculator< false > ForwardIDFCalculator
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
upward_defs_iterator upward_defs_end()
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Instruction::const_succ_iterator const_succ_iterator
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
upward_defs_iterator upward_defs_begin(const UpwardDefsElem &Pair, DominatorTree &DT)
bool isRefSet(const ModRefInfo MRI)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
std::string getEdgeAttributes(const BasicBlock *Node, const_succ_iterator I, DOTFuncMSSAInfo *CFGInfo)
Display the raw branch weights from PGO.
std::string getNodeAttributes(const BasicBlock *Node, DOTFuncMSSAInfo *CFGInfo)
static std::string getEdgeSourceLabel(const BasicBlock *Node, const_succ_iterator I)
std::string getNodeLabel(const BasicBlock *Node, DOTFuncMSSAInfo *CFGInfo)
static std::string getGraphName(DOTFuncMSSAInfo *CFGInfo)
DOTGraphTraits(bool IsSimple=false)
DefaultDOTGraphTraits(bool simple=false)
static std::string getEdgeSourceLabel(const void *, EdgeIter)
getEdgeSourceLabel - If you want to label the edge source itself, implement this method.
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS)
static unsigned getHashValue(const MemoryLocOrCall &MLOC)
static MemoryLocOrCall getEmptyKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
pointer_iterator< Function::const_iterator > nodes_iterator
static size_t size(DOTFuncMSSAInfo *CFGInfo)
static NodeRef getEntryNode(DOTFuncMSSAInfo *CFGInfo)
static nodes_iterator nodes_begin(DOTFuncMSSAInfo *CFGInfo)
static nodes_iterator nodes_end(DOTFuncMSSAInfo *CFGInfo)
typename DOTFuncMSSAInfo *::UnknownGraphTypeError NodeRef
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)