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;
228 MLOC.getCall()->getCalledOperand()));
230 for (
const Value *Arg : MLOC.getCall()->args())
235 static bool isEqual(
const MemoryLocOrCall &LHS,
const MemoryLocOrCall &RHS) {
250 bool VolatileUse =
Use->isVolatile();
251 bool VolatileClobber = MayClobber->
isVolatile();
253 if (VolatileUse && VolatileClobber)
269 return !(SeqCstUse || MayClobberIsAcquire);
272template <
typename AliasAnalysisType>
277 assert(DefInst &&
"Defining instruction not actually an instruction");
287 switch (
II->getIntrinsicID()) {
288 case Intrinsic::allow_runtime_check:
289 case Intrinsic::allow_ubsan_check:
290 case Intrinsic::invariant_start:
291 case Intrinsic::invariant_end:
292 case Intrinsic::assume:
293 case Intrinsic::experimental_noalias_scope_decl:
294 case Intrinsic::pseudoprobe:
296 case Intrinsic::dbg_declare:
297 case Intrinsic::dbg_label:
298 case Intrinsic::dbg_value:
318template <
typename AliasAnalysisType>
320 const MemoryLocOrCall &UseMLOC,
321 AliasAnalysisType &
AA) {
339struct UpwardsMemoryQuery {
349 bool SkipSelfAccess =
false;
351 UpwardsMemoryQuery() =
default;
362template <
typename AliasAnalysisType>
368 return I->hasMetadata(LLVMContext::MD_invariant_load) ||
388[[maybe_unused]]
static void
392 bool AllowImpreciseClobber =
false) {
393 assert(MSSA.
dominates(ClobberAt, Start) &&
"Clobber doesn't dominate start?");
397 "liveOnEntry must clobber itself");
401 bool FoundClobber =
false;
404 Worklist.
push_back({Start, StartLoc,
false});
407 while (!Worklist.
empty()) {
415 if (MA == ClobberAt) {
442 "Found clobber before reaching ClobberAt!");
449 "Can only find use in def chain if Start is a use");
470 if (AllowImpreciseClobber)
476 "ClobberAt never acted as a clobber");
485 using ListIndex = unsigned;
495 std::optional<ListIndex> Previous;
496 bool MayBeCrossIteration;
498 DefPath(
const MemoryLocation &Loc, MemoryAccess *
First, MemoryAccess *
Last,
499 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
501 MayBeCrossIteration(MayBeCrossIteration) {}
503 DefPath(
const MemoryLocation &Loc, MemoryAccess *Init,
504 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
505 : DefPath(Loc, Init, Init, MayBeCrossIteration, Previous) {}
511 UpwardsMemoryQuery *Query;
512 unsigned *UpwardWalkLimit;
519 DenseSet<UpwardDefsElem> VisitedPhis;
522 const MemoryAccess *getWalkTarget(
const MemoryPhi *From)
const {
528 while ((Node =
Node->getIDom())) {
537 struct UpwardsWalkResult {
550 walkToPhiOrClobber(DefPath &
Desc,
const MemoryAccess *
StopAt =
nullptr,
551 const MemoryAccess *SkipStopAt =
nullptr)
const {
553 assert(UpwardWalkLimit &&
"Need a valid walk limit");
554 bool LimitAlreadyReached =
false;
559 if (!*UpwardWalkLimit) {
560 *UpwardWalkLimit = 1;
561 LimitAlreadyReached =
true;
566 if (Current ==
StopAt || Current == SkipStopAt)
567 return {Current,
false};
573 if (!--*UpwardWalkLimit)
574 return {Current,
true};
576 BatchAACrossIterationScope
_(*AA,
Desc.MayBeCrossIteration);
582 if (LimitAlreadyReached)
583 *UpwardWalkLimit = 0;
586 "Ended at a non-clobber that's not a phi?");
587 return {
Desc.Last,
false};
590 void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
591 ListIndex PriorNode,
bool MayBeCrossIteration) {
592 auto UpwardDefsBegin =
595 for (
const UpwardDefsElem &
E : UpwardDefs) {
604 struct TerminatedPath {
605 MemoryAccess *Clobber;
618 std::optional<TerminatedPath>
619 getBlockingAccess(
const MemoryAccess *StopWhere,
620 SmallVectorImpl<ListIndex> &PausedSearches,
621 SmallVectorImpl<ListIndex> &NewPaused,
622 SmallVectorImpl<TerminatedPath> &Terminated) {
623 assert(!PausedSearches.
empty() &&
"No searches to continue?");
627 while (!PausedSearches.
empty()) {
629 DefPath &
Node = Paths[PathIndex];
649 if (!VisitedPhis.
insert({Node.Last, Node.Loc, Node.MayBeCrossIteration})
653 const MemoryAccess *SkipStopWhere =
nullptr;
654 if (Query->SkipSelfAccess &&
Node.Loc == Query->StartingLoc) {
656 SkipStopWhere = Query->OriginalAccess;
659 UpwardsWalkResult Res = walkToPhiOrClobber(Node,
662 if (Res.IsKnownClobber) {
663 assert(Res.Result != StopWhere && Res.Result != SkipStopWhere);
667 TerminatedPath
Term{Res.Result, PathIndex};
668 if (!MSSA.
dominates(Res.Result, StopWhere))
676 if (Res.Result == StopWhere || Res.Result == SkipStopWhere) {
681 if (Res.Result != SkipStopWhere)
688 Node.MayBeCrossIteration);
694 template <
typename T,
typename Walker>
695 struct generic_def_path_iterator
696 :
public iterator_facade_base<generic_def_path_iterator<T, Walker>,
697 std::forward_iterator_tag, T *> {
698 generic_def_path_iterator() =
default;
699 generic_def_path_iterator(Walker *W, ListIndex
N) :
W(
W),
N(
N) {}
703 generic_def_path_iterator &operator++() {
704 N = curNode().Previous;
708 bool operator==(
const generic_def_path_iterator &O)
const {
709 if (
N.has_value() !=
O.N.has_value())
711 return !
N || *
N == *
O.N;
715 T &curNode()
const {
return W->Paths[*
N]; }
718 std::optional<ListIndex>
N;
721 using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
722 using const_def_path_iterator =
723 generic_def_path_iterator<const DefPath, const ClobberWalker>;
726 return make_range(def_path_iterator(
this, From), def_path_iterator());
730 return make_range(const_def_path_iterator(
this, From),
731 const_def_path_iterator());
736 TerminatedPath PrimaryClobber;
742 ListIndex defPathIndex(
const DefPath &
N)
const {
744 const DefPath *NP = &
N;
746 "Out of bounds DefPath!");
747 return NP - &Paths.
front();
763 OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
764 const MemoryLocation &Loc) {
766 "Reset the optimization state.");
772 auto PriorPathsSize = Paths.
size();
778 addSearches(Phi, PausedSearches, 0,
false);
782 auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
784 auto Dom = Paths.
begin();
785 for (
auto I = std::next(Dom),
E = Paths.
end();
I !=
E; ++
I)
786 if (!MSSA.
dominates(
I->Clobber, Dom->Clobber))
790 std::iter_swap(
Last, Dom);
793 MemoryPhi *Current =
Phi;
796 "liveOnEntry wasn't treated as a clobber?");
798 const auto *
Target = getWalkTarget(Current);
801 assert(
all_of(TerminatedPaths, [&](
const TerminatedPath &
P) {
808 if (std::optional<TerminatedPath> Blocker = getBlockingAccess(
809 Target, PausedSearches, NewPaused, TerminatedPaths)) {
813 auto Iter =
find_if(def_path(Blocker->LastNode), [&](
const DefPath &
N) {
814 return defPathIndex(N) < PriorPathsSize;
816 assert(Iter != def_path_iterator());
818 DefPath &CurNode = *Iter;
819 assert(CurNode.Last == Current);
846 TerminatedPath
Result{CurNode.Last, defPathIndex(CurNode)};
853 if (NewPaused.
empty()) {
854 MoveDominatedPathToEnd(TerminatedPaths);
856 return {
Result, std::move(TerminatedPaths)};
859 MemoryAccess *DefChainEnd =
nullptr;
861 for (ListIndex Paused : NewPaused) {
862 UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
863 if (WR.IsKnownClobber)
867 DefChainEnd = WR.Result;
870 if (!TerminatedPaths.
empty()) {
874 for (
auto *MA :
def_chain(
const_cast<MemoryAccess *
>(Target)))
876 assert(DefChainEnd &&
"Failed to find dominating phi/liveOnEntry");
881 for (
const TerminatedPath &TP : TerminatedPaths) {
884 if (DT.
dominates(ChainBB, TP.Clobber->getBlock()))
891 if (!Clobbers.
empty()) {
892 MoveDominatedPathToEnd(Clobbers);
894 return {
Result, std::move(Clobbers)};
898 [&](ListIndex
I) {
return Paths[
I].Last == DefChainEnd; }));
903 PriorPathsSize = Paths.
size();
904 PausedSearches.
clear();
905 for (ListIndex
I : NewPaused)
906 addSearches(DefChainPhi, PausedSearches,
I,
907 Paths[
I].MayBeCrossIteration);
910 Current = DefChainPhi;
914 void verifyOptResult(
const OptznResult &R)
const {
916 return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
920 void resetPhiOptznState() {
926 ClobberWalker(
const MemorySSA &MSSA, DominatorTree &DT)
927 : MSSA(MSSA), DT(DT) {}
931 MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
932 UpwardsMemoryQuery &Q,
unsigned &UpWalkLimit) {
935 UpwardWalkLimit = &UpWalkLimit;
940 MemoryAccess *Current =
Start;
944 Current = MU->getDefiningAccess();
946 DefPath FirstDesc(Q.StartingLoc, Current, Current,
947 false, std::nullopt);
950 UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
952 if (WalkResult.IsKnownClobber) {
953 Result = WalkResult.Result;
956 Current, Q.StartingLoc);
957 verifyOptResult(OptRes);
958 resetPhiOptznState();
959 Result = OptRes.PrimaryClobber.Clobber;
962#ifdef EXPENSIVE_CHECKS
963 if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
970struct RenamePassData {
972 DomTreeNode::const_iterator ChildIt;
973 MemoryAccess *IncomingVal;
975 RenamePassData(
DomTreeNode *
D, DomTreeNode::const_iterator It,
977 : DTN(
D), ChildIt(It), IncomingVal(
M) {}
979 void swap(RenamePassData &
RHS) {
991 ClobberWalker Walker;
1008 bool UseInvariantGroup =
true);
1026 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false);
1031 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1036 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false,
false);
1053 MUD->resetOptimized();
1069 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
true);
1074 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1091 MUD->resetOptimized();
1098 bool RenameAllUses) {
1101 auto It = PerBlockAccesses.find(S);
1103 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1107 if (RenameAllUses) {
1108 bool ReplacementDone =
false;
1109 for (
unsigned I = 0,
E = Phi->getNumIncomingValues();
I !=
E; ++
I)
1110 if (Phi->getIncomingBlock(
I) == BB) {
1111 Phi->setIncomingValue(
I, IncomingVal);
1112 ReplacementDone =
true;
1114 (void) ReplacementDone;
1115 assert(ReplacementDone &&
"Incomplete phi during partial rename");
1117 Phi->addIncoming(IncomingVal, BB);
1125 bool RenameAllUses) {
1126 auto It = PerBlockAccesses.find(BB);
1128 if (It != PerBlockAccesses.end()) {
1130 for (MemoryAccess &L : *
Accesses) {
1132 if (MUD->getDefiningAccess() ==
nullptr || RenameAllUses)
1133 MUD->setDefiningAccess(IncomingVal);
1150 bool SkipVisited,
bool RenameAllUses) {
1151 assert(Root &&
"Trying to rename accesses in an unreachable block");
1158 if (SkipVisited && AlreadyVisited)
1161 IncomingVal = renameBlock(Root->
getBlock(), IncomingVal, RenameAllUses);
1162 renameSuccessorPhis(Root->
getBlock(), IncomingVal, RenameAllUses);
1165 while (!WorkStack.
empty()) {
1167 DomTreeNode::const_iterator ChildIt = WorkStack.
back().ChildIt;
1168 IncomingVal = WorkStack.
back().IncomingVal;
1170 if (ChildIt ==
Node->end()) {
1174 ++WorkStack.
back().ChildIt;
1178 AlreadyVisited = !Visited.
insert(BB).second;
1179 if (SkipVisited && AlreadyVisited) {
1186 IncomingVal = &*BlockDefs->rbegin();
1188 IncomingVal = renameBlock(BB, IncomingVal, RenameAllUses);
1189 renameSuccessorPhis(BB, IncomingVal, RenameAllUses);
1198void MemorySSA::markUnreachableAsLiveOnEntry(
BasicBlock *BB) {
1199 assert(!DT->isReachableFromEntry(BB) &&
1200 "Reachable block found while handling unreachable blocks");
1207 if (!DT->isReachableFromEntry(S))
1209 auto It = PerBlockAccesses.find(S);
1211 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1215 Phi->addIncoming(LiveOnEntryDef.get(), BB);
1218 auto It = PerBlockAccesses.find(BB);
1219 if (It == PerBlockAccesses.end())
1224 auto Next = std::next(AI);
1228 UseOrDef->setDefiningAccess(LiveOnEntryDef.get());
1236 : DT(DT), F(&Func), LiveOnEntryDef(nullptr), Walker(nullptr),
1237 SkipWalker(nullptr) {
1243 assert(AA &&
"No alias analysis?");
1254 : DT(DT), L(&L), LiveOnEntryDef(nullptr), Walker(nullptr),
1255 SkipWalker(nullptr) {
1261 assert(AA &&
"No alias analysis?");
1265 return *const_cast<BasicBlock *>(BB);
1276 for (
const auto &Pair : PerBlockAccesses)
1282 auto Res = PerBlockAccesses.try_emplace(BB);
1285 Res.first->second = std::make_unique<AccessList>();
1286 return Res.first->second.get();
1290 auto Res = PerBlockDefs.try_emplace(BB);
1293 Res.first->second = std::make_unique<DefsList>();
1294 return Res.first->second.get();
1310 : MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
1316 struct MemlocStackInfo {
1319 unsigned long StackEpoch;
1320 unsigned long PopEpoch;
1325 unsigned long LowerBound;
1328 unsigned long LastKill;
1332 void optimizeUsesInBlock(
const BasicBlock *,
unsigned long &,
unsigned long &,
1337 CachingWalker *Walker;
1356void MemorySSA::OptimizeUses::optimizeUsesInBlock(
1357 const BasicBlock *BB,
unsigned long &StackEpoch,
unsigned long &PopEpoch,
1370 !VersionStack.
empty() &&
1371 "Version stack should have liveOnEntry sentinel dominating everything");
1373 if (DT->dominates(BackBlock, BB))
1375 while (VersionStack.
back()->getBlock() == BackBlock)
1380 for (MemoryAccess &MA : *
Accesses) {
1388 if (MU->isOptimized())
1391 MemoryLocOrCall UseMLOC(MU);
1392 auto &LocInfo = LocStackInfo[UseMLOC];
1396 if (LocInfo.PopEpoch != PopEpoch) {
1397 LocInfo.PopEpoch = PopEpoch;
1398 LocInfo.StackEpoch = StackEpoch;
1410 if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
1411 !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
1415 LocInfo.LowerBound = 0;
1416 LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
1417 LocInfo.LastKillValid =
false;
1419 }
else if (LocInfo.StackEpoch != StackEpoch) {
1423 LocInfo.PopEpoch = PopEpoch;
1424 LocInfo.StackEpoch = StackEpoch;
1426 if (!LocInfo.LastKillValid) {
1427 LocInfo.LastKill = VersionStack.
size() - 1;
1428 LocInfo.LastKillValid =
true;
1433 assert(LocInfo.LowerBound < VersionStack.
size() &&
1434 "Lower bound out of range");
1435 assert(LocInfo.LastKill < VersionStack.
size() &&
1436 "Last kill info out of range");
1438 unsigned long UpperBound = VersionStack.
size() - 1;
1441 LLVM_DEBUG(
dbgs() <<
"MemorySSA skipping optimization of " << *MU <<
" ("
1442 << *(MU->getMemoryInst()) <<
")"
1443 <<
" because there are "
1444 << UpperBound - LocInfo.LowerBound
1445 <<
" stores to disambiguate\n");
1448 LocInfo.LastKillValid =
false;
1451 bool FoundClobberResult =
false;
1453 while (UpperBound > LocInfo.LowerBound) {
1459 Walker->getClobberingMemoryAccessWithoutInvariantGroup(
1460 MU, *AA, UpwardWalkLimit);
1462 while (VersionStack[UpperBound] != Result) {
1466 FoundClobberResult =
true;
1472 FoundClobberResult =
true;
1480 if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
1481 MU->setDefiningAccess(VersionStack[UpperBound],
true);
1482 LocInfo.LastKill = UpperBound;
1486 MU->setDefiningAccess(VersionStack[LocInfo.LastKill],
true);
1488 LocInfo.LowerBound = VersionStack.
size() - 1;
1489 LocInfo.LowerBoundBlock = BB;
1497 VersionStack.
push_back(MSSA->getLiveOnEntryDef());
1499 unsigned long StackEpoch = 1;
1500 unsigned long PopEpoch = 1;
1502 for (
const auto *DomNode :
depth_first(DT->getRootNode()))
1503 optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
1507void MemorySSA::placePHINodes(
1511 IDFs.setDefiningBlocks(DefiningBlocks);
1513 IDFs.calculate(IDFBlocks);
1516 for (
auto &BB : IDFBlocks)
1517 createMemoryPhi(BB);
1520template <
typename IterT>
1521void MemorySSA::buildMemorySSA(
BatchAAResults &BAA, IterT Blocks) {
1530 nullptr, &StartingPoint, NextID++));
1539 bool InsertIntoDef =
false;
1551 InsertIntoDef =
true;
1553 Defs = getOrCreateDefsList(&
B);
1554 Defs->push_back(*MUD);
1560 placePHINodes(DefiningBlocks);
1564 SmallPtrSet<BasicBlock *, 16> Visited;
1571 U.set(LiveOnEntryDef.get());
1577 L->getExitBlocks(ExitBlocks);
1579 renamePass(DT->getNode(L->getLoopPreheader()), LiveOnEntryDef.get(),
1582 renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
1587 for (
auto &BB : Blocks)
1588 if (!Visited.
count(&BB))
1589 markUnreachableAsLiveOnEntry(&BB);
1596 return Walker.get();
1599 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1601 Walker = std::make_unique<CachingWalker>(
this, WalkerBase.get());
1602 return Walker.get();
1607 return SkipWalker.get();
1610 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1612 SkipWalker = std::make_unique<SkipSelfWalker>(
this, WalkerBase.get());
1613 return SkipWalker.get();
1623 auto *
Accesses = getOrCreateAccessList(BB);
1629 auto *Defs = getOrCreateDefsList(BB);
1630 Defs->push_front(*NewAccess);
1636 auto *Defs = getOrCreateDefsList(BB);
1639 Defs->insert(DI, *NewAccess);
1645 auto *Defs = getOrCreateDefsList(BB);
1646 Defs->push_back(*NewAccess);
1649 BlockNumberingValid.erase(BB);
1655 bool WasEnd = InsertPt ==
Accesses->end();
1658 auto *Defs = getOrCreateDefsList(BB);
1664 Defs->push_back(*What);
1666 Defs->insert(InsertPt->getDefsIterator(), *What);
1672 Defs->push_back(*What);
1674 Defs->insert(InsertPt->getDefsIterator(), *What);
1677 BlockNumberingValid.erase(BB);
1698 prepareForMoveTo(What, BB);
1706 "Can only move a Phi at the beginning of the block");
1708 ValueToMemoryAccess.erase(What->
getBlock());
1709 bool Inserted = ValueToMemoryAccess.insert({BB, What}).second;
1711 assert(Inserted &&
"Cannot move a Phi to a block that already has one");
1714 prepareForMoveTo(What, BB);
1723 ValueToMemoryAccess[BB] = Phi;
1730 bool CreationMustSucceed) {
1733 if (CreationMustSucceed)
1734 assert(NewAccess !=
nullptr &&
"Tried to create a memory access for a "
1735 "non-memory touching instruction");
1738 "A use cannot be a defining access");
1749 if (!
SI->isUnordered())
1752 if (!LI->isUnordered())
1759template <
typename AliasAnalysisType>
1760MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *
I,
1761 AliasAnalysisType *AAP,
1770 switch (
II->getIntrinsicID()) {
1773 case Intrinsic::allow_runtime_check:
1774 case Intrinsic::allow_ubsan_check:
1775 case Intrinsic::assume:
1776 case Intrinsic::experimental_noalias_scope_decl:
1777 case Intrinsic::pseudoprobe:
1785 if (!
I->mayReadFromMemory() && !
I->mayWriteToMemory())
1794 bool DefCheck, UseCheck;
1799 assert((Def == DefCheck || !DefCheck) &&
1800 "Memory accesses should only be reduced");
1801 if (!Def && Use != UseCheck) {
1803 assert(!UseCheck &&
"Invalid template");
1826 MemoryUseOrDef *MUD;
1828 MUD =
new MemoryDef(
I->getContext(),
nullptr,
I,
I->getParent(), NextID++);
1830 MUD =
new MemoryUse(
I->getContext(),
nullptr,
I,
I->getParent());
1836 ValueToMemoryAccess[
I] = MUD;
1843 "Trying to remove memory access that still has uses");
1844 BlockNumbering.erase(MA);
1857 auto VMA = ValueToMemoryAccess.find(MemoryInst);
1858 if (VMA->second == MA)
1859 ValueToMemoryAccess.
erase(VMA);
1873 auto DefsIt = PerBlockDefs.find(BB);
1874 std::unique_ptr<DefsList> &Defs = DefsIt->second;
1877 PerBlockDefs.erase(DefsIt);
1882 auto AccessIt = PerBlockAccesses.find(BB);
1883 std::unique_ptr<AccessList> &
Accesses = AccessIt->second;
1890 PerBlockAccesses.erase(AccessIt);
1891 BlockNumberingValid.erase(BB);
1896 MemorySSAAnnotatedWriter Writer(
this);
1900 F->
print(OS, &Writer);
1903#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1908#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS)
1920 assert(L &&
"must either have loop or function");
1923 return *const_cast<BasicBlock *>(BB);
1943template <
typename IterT>
1947 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
1948 auto *Pred = Phi->getIncomingBlock(
I);
1949 auto *IncAcc = Phi->getIncomingValue(
I);
1953 if (
auto *DTNode = DT->getNode(Pred)) {
1955 if (
auto *DefList =
getBlockDefs(DTNode->getBlock())) {
1956 auto *LastAcc = &*(--DefList->end());
1957 assert(LastAcc == IncAcc &&
1958 "Incorrect incoming access into phi.");
1963 DTNode = DTNode->getIDom();
1980template <
typename IterT>
1982 if (BlockNumberingValid.empty())
1987 if (!ValidBlocks.
count(&BB))
1990 ValidBlocks.
erase(&BB);
1998 unsigned long LastNumber = 0;
2000 auto ThisNumberIter = BlockNumbering.find(&MA);
2001 assert(ThisNumberIter != BlockNumbering.end() &&
2002 "MemoryAccess has no domination number in a valid block!");
2004 unsigned long ThisNumber = ThisNumberIter->second;
2005 assert(ThisNumber > LastNumber &&
2006 "Domination numbers should be strictly increasing!");
2008 LastNumber = ThisNumber;
2013 "All valid BasicBlocks should exist in F -- dangling pointers?");
2022template <
typename IterT>
2039 for (
const Use &U : Phi->uses()) {
2040 assert(
dominates(Phi, U) &&
"Memory PHI does not dominate it's uses");
2046 "Incomplete MemoryPhi Node");
2047 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
2048 verifyUseInDefs(Phi->getIncomingValue(
I), Phi);
2050 "Incoming phi block not a block predecessor");
2058 "We have memory affecting instructions "
2059 "in this block but they are not in the "
2060 "access list or defs list");
2068 for (
const Use &U : MD->
uses()) {
2070 "Memory Def does not dominate it's uses");
2084 assert(AL->size() == ActualAccesses.
size() &&
2085 "We don't have the same number of accesses in the block as on the "
2088 "Either we should have a defs list, or we should have no defs");
2090 "We don't have the same number of defs in the block as on the "
2092 auto ALI = AL->begin();
2093 auto AAI = ActualAccesses.
begin();
2094 while (ALI != AL->end() && AAI != ActualAccesses.
end()) {
2095 assert(&*ALI == *AAI &&
"Not the same accesses in the same order");
2099 ActualAccesses.
clear();
2101 auto DLI =
DL->begin();
2102 auto ADI = ActualDefs.
begin();
2103 while (DLI !=
DL->end() && ADI != ActualDefs.
end()) {
2104 assert(&*DLI == *ADI &&
"Not the same defs in the same order");
2119 "Null def but use not point to live on entry def");
2122 "Did not find use in def's use list");
2131void MemorySSA::renumberBlock(
const BasicBlock *
B)
const {
2133 unsigned long CurrentNumber = 0;
2135 assert(AL !=
nullptr &&
"Asking to renumber an empty block");
2136 for (
const auto &
I : *AL)
2137 BlockNumbering[&
I] = ++CurrentNumber;
2138 BlockNumberingValid.insert(
B);
2149 "Asking for local domination when accesses are in different blocks!");
2151 if (Dominatee == Dominator)
2164 if (!BlockNumberingValid.count(DominatorBlock))
2165 renumberBlock(DominatorBlock);
2167 unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
2169 assert(DominatorNum != 0 &&
"Block was not numbered properly");
2170 unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
2171 assert(DominateeNum != 0 &&
"Block was not numbered properly");
2172 return DominatorNum < DominateeNum;
2177 if (Dominator == Dominatee)
2189 const Use &Dominatee)
const {
2191 BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
2193 if (UseBB != Dominator->
getBlock())
2194 return DT->dominates(Dominator->
getBlock(), UseBB);
2215 case MemoryPhiVal:
return static_cast<const MemoryPhi *
>(
this)->
print(OS);
2216 case MemoryDefVal:
return static_cast<const MemoryDef *
>(
this)->
print(OS);
2217 case MemoryUseVal:
return static_cast<const MemoryUse *
>(
this)->
print(OS);
2226 if (
A &&
A->getID())
2232 OS <<
getID() <<
" = MemoryDef(";
2244 OS <<
getID() <<
" = MemoryPhi(";
2255 if (
unsigned ID = MA->
getID())
2267 if (UO && UO->
getID())
2276#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2285 MemorySSAAnnotatedWriter MSSAWriter;
2289 : F(F), MSSAWriter(&MSSA) {}
2292 MemorySSAAnnotatedWriter &
getWriter() {
return MSSAWriter; }
2300 return &(CFGInfo->
getFunction()->getEntryBlock());
2335 [](std::string &S,
unsigned &
I,
unsigned Idx) ->
void {
2336 std::string Str = S.substr(
I, Idx -
I);
2338 if (SR.
count(
" = MemoryDef(") || SR.
count(
" = MemoryPhi(") ||
2339 SR.
count(
"MemoryUse("))
2359 ?
"style=filled, fillcolor=lightpink"
2366AnalysisKey MemorySSAAnalysis::Key;
2377 FunctionAnalysisManager::Invalidator &Inv) {
2387 if (EnsureOptimizedUses)
2393 OS <<
"MemorySSA for function: " <<
F.getName() <<
"\n";
2403 OS <<
"MemorySSA (walker) for function: " <<
F.getName() <<
"\n";
2404 MemorySSAWalkerAnnotatedWriter Writer(&MSSA);
2405 F.print(OS, &Writer);
2438 MSSA->verifyMemorySSA();
2457 if (
Loc.Ptr ==
nullptr)
2458 return StartingAccess;
2463 return StartingUseOrDef;
2465 I = StartingUseOrDef->getMemoryInst();
2470 return StartingUseOrDef;
2473 UpwardsMemoryQuery Q;
2474 Q.OriginalAccess = StartingAccess;
2475 Q.StartingLoc =
Loc;
2483 Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
2485 dbgs() <<
"Clobber starting at access " << *StartingAccess <<
"\n";
2487 dbgs() <<
" for instruction " << *
I <<
"\n";
2488 dbgs() <<
" is " << *Clobber <<
"\n";
2495 if (!
I.hasMetadata(LLVMContext::MD_invariant_group) ||
I.isVolatile())
2512 for (
const User *Us : PointerOperand->
users()) {
2514 if (!U || U == &
I || !DT.
dominates(U, MostDominatingInstruction))
2520 if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
2522 MostDominatingInstruction = U;
2526 return MostDominatingInstruction == &
I ? nullptr : MostDominatingInstruction;
2530 MemoryAccess *MA, BatchAAResults &BAA,
unsigned &UpwardWalkLimit,
2531 bool SkipSelf,
bool UseInvariantGroup) {
2534 if (!StartingAccess)
2537 if (UseInvariantGroup) {
2539 *StartingAccess->getMemoryInst(), MSSA->
getDomTree())) {
2545 return ClobberMA->getDefiningAccess();
2550 bool IsOptimized =
false;
2555 if (StartingAccess->isOptimized()) {
2557 return StartingAccess->getOptimized();
2561 const Instruction *
I = StartingAccess->getMemoryInst();
2566 return StartingAccess;
2568 UpwardsMemoryQuery Q(
I, StartingAccess);
2572 StartingAccess->setOptimized(LiveOnEntry);
2576 MemoryAccess *OptimizedAccess;
2579 MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
2584 StartingAccess->setOptimized(DefiningAccess);
2585 return DefiningAccess;
2589 Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
2590 StartingAccess->setOptimized(OptimizedAccess);
2592 OptimizedAccess = StartingAccess->getOptimized();
2594 LLVM_DEBUG(
dbgs() <<
"Starting Memory SSA clobber for " << *
I <<
" is ");
2596 LLVM_DEBUG(
dbgs() <<
"Optimized Memory SSA clobber for " << *
I <<
" is ");
2603 Q.SkipSelfAccess =
true;
2604 Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
2606 Result = OptimizedAccess;
2608 LLVM_DEBUG(
dbgs() <<
"Result Memory SSA clobber [SkipSelf = " << SkipSelf);
2618 return Use->getDefiningAccess();
2625 return Use->getDefiningAccess();
2626 return StartingAccess;
2637void MemoryUse::deleteMe(DerivedUser *Self) {
2638 delete static_cast<MemoryUse *
>(Self);
2641bool upward_defs_iterator::IsGuaranteedLoopInvariant(
const Value *Ptr)
const {
2642 auto IsGuaranteedLoopInvariantBase = [](
const Value *Ptr) {
2651 if (
I->getParent()->isEntryBlock())
2655 return IsGuaranteedLoopInvariantBase(
GEP->getPointerOperand()) &&
2656 GEP->hasAllConstantIndices();
2658 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)
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)