32#include "llvm/Config/llvm-config.h"
63#define DEBUG_TYPE "memoryssa"
73#ifdef EXPENSIVE_CHECKS
93 MemorySSAAnnotatedWriter(
const MemorySSA *M) : MSSA(M) {}
95 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
98 OS <<
"; " << *MA <<
"\n";
104 OS <<
"; " << *MA <<
"\n";
116 MemorySSAWalkerAnnotatedWriter(
MemorySSA *M)
117 : MSSA(M), Walker(M->getWalker()), BAA(M->getAA()) {}
119 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
122 OS <<
"; " << *MA <<
"\n";
131 OS <<
" - clobbered by ";
151class MemoryLocOrCall {
155 MemoryLocOrCall(MemoryUseOrDef *MUD)
156 : MemoryLocOrCall(MUD->getMemoryInst()) {}
157 MemoryLocOrCall(
const MemoryUseOrDef *MUD)
158 : MemoryLocOrCall(MUD->getMemoryInst()) {}
160 MemoryLocOrCall(Instruction *Inst) {
173 explicit MemoryLocOrCall(
const MemoryLocation &Loc) : Loc(Loc) {}
175 const CallBase *getCall()
const {
180 MemoryLocation getLoc()
const {
186 if (IsCall !=
Other.IsCall)
190 return Loc ==
Other.Loc;
197 Other.Call->arg_begin());
202 const CallBase *
Call;
220 MLOC.getCall()->getCalledOperand()));
222 for (
const Value *Arg : MLOC.getCall()->args())
227 static bool isEqual(
const MemoryLocOrCall &LHS,
const MemoryLocOrCall &RHS) {
242 bool VolatileUse =
Use->isVolatile();
243 bool VolatileClobber = MayClobber->
isVolatile();
245 if (VolatileUse && VolatileClobber)
261 return !(SeqCstUse || MayClobberIsAcquire);
264template <
typename AliasAnalysisType>
269 assert(DefInst &&
"Defining instruction not actually an instruction");
279 switch (
II->getIntrinsicID()) {
280 case Intrinsic::allow_runtime_check:
281 case Intrinsic::allow_ubsan_check:
282 case Intrinsic::invariant_start:
283 case Intrinsic::invariant_end:
284 case Intrinsic::assume:
285 case Intrinsic::experimental_noalias_scope_decl:
286 case Intrinsic::pseudoprobe:
306template <
typename AliasAnalysisType>
308 const MemoryLocOrCall &UseMLOC,
309 AliasAnalysisType &
AA) {
327struct UpwardsMemoryQuery {
337 bool SkipSelfAccess =
false;
339 UpwardsMemoryQuery() =
default;
350template <
typename AliasAnalysisType>
355 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
376[[maybe_unused]]
static void
380 bool AllowImpreciseClobber =
false) {
381 assert(MSSA.
dominates(ClobberAt, Start) &&
"Clobber doesn't dominate start?");
385 "liveOnEntry must clobber itself");
389 bool FoundClobber =
false;
392 Worklist.
push_back({Start, StartLoc,
false});
395 while (!Worklist.
empty()) {
403 if (MA == ClobberAt) {
430 "Found clobber before reaching ClobberAt!");
437 "Can only find use in def chain if Start is a use");
458 if (AllowImpreciseClobber)
464 "ClobberAt never acted as a clobber");
473 using ListIndex = unsigned;
483 std::optional<ListIndex> Previous;
484 bool MayBeCrossIteration;
486 DefPath(
const MemoryLocation &Loc, MemoryAccess *
First, MemoryAccess *
Last,
487 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
489 MayBeCrossIteration(MayBeCrossIteration) {}
491 DefPath(
const MemoryLocation &Loc, MemoryAccess *Init,
492 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
493 : DefPath(Loc, Init, Init, MayBeCrossIteration, Previous) {}
499 UpwardsMemoryQuery *Query;
500 unsigned *UpwardWalkLimit;
507 DenseSet<UpwardDefsElem> VisitedPhis;
510 const MemoryAccess *getWalkTarget(
const MemoryPhi *From)
const {
516 while ((Node =
Node->getIDom())) {
525 struct UpwardsWalkResult {
538 walkToPhiOrClobber(DefPath &
Desc,
const MemoryAccess *StopAt =
nullptr,
539 const MemoryAccess *SkipStopAt =
nullptr)
const {
541 assert(UpwardWalkLimit &&
"Need a valid walk limit");
542 bool LimitAlreadyReached =
false;
547 if (!*UpwardWalkLimit) {
548 *UpwardWalkLimit = 1;
549 LimitAlreadyReached =
true;
554 if (Current == StopAt || Current == SkipStopAt)
555 return {Current,
false};
561 if (!--*UpwardWalkLimit)
562 return {Current,
true};
564 BatchAACrossIterationScope
_(*AA,
Desc.MayBeCrossIteration);
570 if (LimitAlreadyReached)
571 *UpwardWalkLimit = 0;
574 "Ended at a non-clobber that's not a phi?");
575 return {
Desc.Last,
false};
578 void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
579 ListIndex PriorNode,
bool MayBeCrossIteration) {
580 auto UpwardDefsBegin =
583 for (
const UpwardDefsElem &
E : UpwardDefs) {
592 struct TerminatedPath {
593 MemoryAccess *Clobber;
606 std::optional<TerminatedPath>
607 getBlockingAccess(
const MemoryAccess *StopWhere,
608 SmallVectorImpl<ListIndex> &PausedSearches,
609 SmallVectorImpl<ListIndex> &NewPaused,
610 SmallVectorImpl<TerminatedPath> &Terminated) {
611 assert(!PausedSearches.
empty() &&
"No searches to continue?");
615 while (!PausedSearches.
empty()) {
617 DefPath &
Node = Paths[PathIndex];
637 if (!VisitedPhis.
insert({Node.Last, Node.Loc, Node.MayBeCrossIteration})
641 const MemoryAccess *SkipStopWhere =
nullptr;
642 if (Query->SkipSelfAccess &&
Node.Loc == Query->StartingLoc) {
644 SkipStopWhere = Query->OriginalAccess;
647 UpwardsWalkResult Res = walkToPhiOrClobber(Node,
650 if (Res.IsKnownClobber) {
651 assert(Res.Result != StopWhere && Res.Result != SkipStopWhere);
655 TerminatedPath
Term{Res.Result, PathIndex};
656 if (!MSSA.
dominates(Res.Result, StopWhere))
664 if (Res.Result == StopWhere || Res.Result == SkipStopWhere) {
669 if (Res.Result != SkipStopWhere)
676 Node.MayBeCrossIteration);
682 template <
typename T,
typename Walker>
683 struct generic_def_path_iterator
684 :
public iterator_facade_base<generic_def_path_iterator<T, Walker>,
685 std::forward_iterator_tag, T *> {
686 generic_def_path_iterator() =
default;
687 generic_def_path_iterator(Walker *W, ListIndex
N) :
W(
W),
N(
N) {}
691 generic_def_path_iterator &operator++() {
692 N = curNode().Previous;
696 bool operator==(
const generic_def_path_iterator &O)
const {
697 if (
N.has_value() !=
O.N.has_value())
699 return !
N || *
N == *
O.N;
703 T &curNode()
const {
return W->Paths[*
N]; }
706 std::optional<ListIndex>
N;
709 using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
712 return make_range(def_path_iterator(
this, From), def_path_iterator());
717 TerminatedPath PrimaryClobber;
723 ListIndex defPathIndex(
const DefPath &
N)
const {
725 const DefPath *NP = &
N;
727 "Out of bounds DefPath!");
728 return NP - &Paths.
front();
744 OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
745 const MemoryLocation &Loc) {
747 "Reset the optimization state.");
753 auto PriorPathsSize = Paths.
size();
759 addSearches(Phi, PausedSearches, 0,
false);
763 auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
765 auto Dom = Paths.
begin();
766 for (
auto I = std::next(Dom),
E = Paths.
end();
I !=
E; ++
I)
767 if (!MSSA.
dominates(
I->Clobber, Dom->Clobber))
771 std::iter_swap(
Last, Dom);
774 MemoryPhi *Current =
Phi;
777 "liveOnEntry wasn't treated as a clobber?");
779 const auto *
Target = getWalkTarget(Current);
782 assert(
all_of(TerminatedPaths, [&](
const TerminatedPath &
P) {
789 if (std::optional<TerminatedPath> Blocker = getBlockingAccess(
790 Target, PausedSearches, NewPaused, TerminatedPaths)) {
794 auto Iter =
find_if(def_path(Blocker->LastNode), [&](
const DefPath &
N) {
795 return defPathIndex(N) < PriorPathsSize;
797 assert(Iter != def_path_iterator());
799 DefPath &CurNode = *Iter;
800 assert(CurNode.Last == Current);
827 TerminatedPath
Result{CurNode.Last, defPathIndex(CurNode)};
834 if (NewPaused.
empty()) {
835 MoveDominatedPathToEnd(TerminatedPaths);
837 return {
Result, std::move(TerminatedPaths)};
840 MemoryAccess *DefChainEnd =
nullptr;
842 for (ListIndex Paused : NewPaused) {
843 UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
844 if (WR.IsKnownClobber)
848 DefChainEnd = WR.Result;
851 if (!TerminatedPaths.
empty()) {
855 for (
auto *MA :
def_chain(
const_cast<MemoryAccess *
>(Target)))
857 assert(DefChainEnd &&
"Failed to find dominating phi/liveOnEntry");
862 for (
const TerminatedPath &TP : TerminatedPaths) {
865 if (DT.
dominates(ChainBB, TP.Clobber->getBlock()))
872 if (!Clobbers.
empty()) {
873 MoveDominatedPathToEnd(Clobbers);
875 return {
Result, std::move(Clobbers)};
879 [&](ListIndex
I) {
return Paths[
I].Last == DefChainEnd; }));
884 PriorPathsSize = Paths.
size();
885 PausedSearches.
clear();
886 for (ListIndex
I : NewPaused)
887 addSearches(DefChainPhi, PausedSearches,
I,
888 Paths[
I].MayBeCrossIteration);
891 Current = DefChainPhi;
895 void verifyOptResult(
const OptznResult &R)
const {
897 return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
901 void resetPhiOptznState() {
907 ClobberWalker(
const MemorySSA &MSSA, DominatorTree &DT)
908 : MSSA(MSSA), DT(DT) {}
912 MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
913 UpwardsMemoryQuery &Q,
unsigned &UpWalkLimit) {
916 UpwardWalkLimit = &UpWalkLimit;
921 MemoryAccess *Current =
Start;
925 Current = MU->getDefiningAccess();
927 DefPath FirstDesc(Q.StartingLoc, Current, Current,
928 false, std::nullopt);
931 UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
933 if (WalkResult.IsKnownClobber) {
934 Result = WalkResult.Result;
937 Current, Q.StartingLoc);
938 verifyOptResult(OptRes);
939 resetPhiOptznState();
940 Result = OptRes.PrimaryClobber.Clobber;
943#ifdef EXPENSIVE_CHECKS
944 if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
951struct RenamePassData {
953 DomTreeNode::const_iterator ChildIt;
954 MemoryAccess *IncomingVal;
956 RenamePassData(
DomTreeNode *
D, DomTreeNode::const_iterator It,
958 : DTN(
D), ChildIt(It), IncomingVal(
M) {}
960 void swap(RenamePassData &
RHS) {
972 ClobberWalker Walker;
989 bool UseInvariantGroup =
true);
1007 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false);
1012 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1017 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false,
false);
1022 unsigned UpwardWalkLimit =
MSSA->Opts.memssa_check_limit;
1028 unsigned UpwardWalkLimit =
MSSA->Opts.memssa_check_limit;
1034 MUD->resetOptimized();
1050 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
true);
1055 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1060 unsigned UpwardWalkLimit =
MSSA->Opts.memssa_check_limit;
1066 unsigned UpwardWalkLimit =
MSSA->Opts.memssa_check_limit;
1072 MUD->resetOptimized();
1079 bool RenameAllUses) {
1082 auto It = PerBlockAccesses.find(S);
1084 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1088 if (RenameAllUses) {
1089 bool ReplacementDone =
false;
1090 for (
unsigned I = 0,
E = Phi->getNumIncomingValues();
I !=
E; ++
I)
1091 if (Phi->getIncomingBlock(
I) == BB) {
1092 Phi->setIncomingValue(
I, IncomingVal);
1093 ReplacementDone =
true;
1095 (void) ReplacementDone;
1096 assert(ReplacementDone &&
"Incomplete phi during partial rename");
1098 Phi->addIncoming(IncomingVal, BB);
1106 bool RenameAllUses) {
1107 auto It = PerBlockAccesses.find(BB);
1109 if (It != PerBlockAccesses.end()) {
1111 for (MemoryAccess &L : *
Accesses) {
1113 if (MUD->getDefiningAccess() ==
nullptr || RenameAllUses)
1114 MUD->setDefiningAccess(IncomingVal);
1131 bool SkipVisited,
bool RenameAllUses) {
1132 assert(Root &&
"Trying to rename accesses in an unreachable block");
1139 if (SkipVisited && AlreadyVisited)
1142 IncomingVal = renameBlock(Root->
getBlock(), IncomingVal, RenameAllUses);
1143 renameSuccessorPhis(Root->
getBlock(), IncomingVal, RenameAllUses);
1146 while (!WorkStack.
empty()) {
1148 DomTreeNode::const_iterator ChildIt = WorkStack.
back().ChildIt;
1149 IncomingVal = WorkStack.
back().IncomingVal;
1151 if (ChildIt ==
Node->end()) {
1155 ++WorkStack.
back().ChildIt;
1159 AlreadyVisited = !Visited.
insert(BB).second;
1160 if (SkipVisited && AlreadyVisited) {
1167 IncomingVal = &*BlockDefs->rbegin();
1169 IncomingVal = renameBlock(BB, IncomingVal, RenameAllUses);
1170 renameSuccessorPhis(BB, IncomingVal, RenameAllUses);
1179void MemorySSA::markUnreachableAsLiveOnEntry(
BasicBlock *BB) {
1180 assert(!DT->isReachableFromEntry(BB) &&
1181 "Reachable block found while handling unreachable blocks");
1188 if (!DT->isReachableFromEntry(S))
1190 auto It = PerBlockAccesses.find(S);
1192 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1196 Phi->addIncoming(LiveOnEntryDef.get(), BB);
1199 auto It = PerBlockAccesses.find(BB);
1200 if (It == PerBlockAccesses.end())
1205 auto Next = std::next(AI);
1209 UseOrDef->setDefiningAccess(LiveOnEntryDef.get());
1218 Walker(nullptr), SkipWalker(nullptr) {
1224 assert(AA &&
"No alias analysis?");
1236 Walker(nullptr), SkipWalker(nullptr) {
1242 assert(AA &&
"No alias analysis?");
1246 return *const_cast<BasicBlock *>(BB);
1257 for (
const auto &Pair : PerBlockAccesses)
1263 auto Res = PerBlockAccesses.try_emplace(BB);
1266 Res.first->second = std::make_unique<AccessList>();
1267 return Res.first->second.get();
1271 auto Res = PerBlockDefs.try_emplace(BB);
1274 Res.first->second = std::make_unique<DefsList>();
1275 return Res.first->second.get();
1291 : MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
1297 struct MemlocStackInfo {
1300 unsigned long StackEpoch;
1301 unsigned long PopEpoch;
1306 unsigned long LowerBound;
1309 unsigned long LastKill;
1313 void optimizeUsesInBlock(
const BasicBlock *,
unsigned long &,
unsigned long &,
1318 CachingWalker *Walker;
1337void MemorySSA::OptimizeUses::optimizeUsesInBlock(
1338 const BasicBlock *BB,
unsigned long &StackEpoch,
unsigned long &PopEpoch,
1351 !VersionStack.
empty() &&
1352 "Version stack should have liveOnEntry sentinel dominating everything");
1354 if (DT->dominates(BackBlock, BB))
1356 while (VersionStack.
back()->getBlock() == BackBlock)
1361 for (MemoryAccess &MA : *
Accesses) {
1369 if (MU->isOptimized())
1372 MemoryLocOrCall UseMLOC(MU);
1373 auto &LocInfo = LocStackInfo[UseMLOC];
1377 if (LocInfo.PopEpoch != PopEpoch) {
1378 LocInfo.PopEpoch = PopEpoch;
1379 LocInfo.StackEpoch = StackEpoch;
1391 if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
1392 !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
1396 LocInfo.LowerBound = 0;
1397 LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
1398 LocInfo.LastKillValid =
false;
1400 }
else if (LocInfo.StackEpoch != StackEpoch) {
1404 LocInfo.PopEpoch = PopEpoch;
1405 LocInfo.StackEpoch = StackEpoch;
1407 if (!LocInfo.LastKillValid) {
1408 LocInfo.LastKill = VersionStack.
size() - 1;
1409 LocInfo.LastKillValid =
true;
1414 assert(LocInfo.LowerBound < VersionStack.
size() &&
1415 "Lower bound out of range");
1416 assert(LocInfo.LastKill < VersionStack.
size() &&
1417 "Last kill info out of range");
1419 unsigned long UpperBound = VersionStack.
size() - 1;
1421 if (UpperBound - LocInfo.LowerBound > MSSA->Opts.memssa_check_limit) {
1422 LLVM_DEBUG(
dbgs() <<
"MemorySSA skipping optimization of " << *MU <<
" ("
1423 << *(MU->getMemoryInst()) <<
")"
1424 <<
" because there are "
1425 << UpperBound - LocInfo.LowerBound
1426 <<
" stores to disambiguate\n");
1429 LocInfo.LastKillValid =
false;
1432 bool FoundClobberResult =
false;
1433 unsigned UpwardWalkLimit = MSSA->Opts.memssa_check_limit;
1434 while (UpperBound > LocInfo.LowerBound) {
1440 Walker->getClobberingMemoryAccessWithoutInvariantGroup(
1441 MU, *AA, UpwardWalkLimit);
1443 while (VersionStack[UpperBound] != Result) {
1447 FoundClobberResult =
true;
1453 FoundClobberResult =
true;
1461 if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
1462 MU->setDefiningAccess(VersionStack[UpperBound],
true);
1463 LocInfo.LastKill = UpperBound;
1467 MU->setDefiningAccess(VersionStack[LocInfo.LastKill],
true);
1469 LocInfo.LowerBound = VersionStack.
size() - 1;
1470 LocInfo.LowerBoundBlock = BB;
1478 VersionStack.
push_back(MSSA->getLiveOnEntryDef());
1480 unsigned long StackEpoch = 1;
1481 unsigned long PopEpoch = 1;
1483 for (
const auto *DomNode :
depth_first(DT->getRootNode()))
1484 optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
1488void MemorySSA::placePHINodes(
1492 IDFs.setDefiningBlocks(DefiningBlocks);
1494 IDFs.calculate(IDFBlocks);
1497 for (
auto &BB : IDFBlocks)
1498 createMemoryPhi(BB);
1501template <
typename IterT>
1502void MemorySSA::buildMemorySSA(
BatchAAResults &BAA, IterT Blocks) {
1511 nullptr, &StartingPoint, NextID++));
1520 bool InsertIntoDef =
false;
1532 InsertIntoDef =
true;
1534 Defs = getOrCreateDefsList(&
B);
1535 Defs->push_back(*MUD);
1541 placePHINodes(DefiningBlocks);
1545 SmallPtrSet<BasicBlock *, 16> Visited;
1552 U.set(LiveOnEntryDef.get());
1558 L->getExitBlocks(ExitBlocks);
1560 renamePass(DT->getNode(L->getLoopPreheader()), LiveOnEntryDef.get(),
1563 renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
1568 for (
auto &BB : Blocks)
1569 if (!Visited.
count(&BB))
1570 markUnreachableAsLiveOnEntry(&BB);
1577 return Walker.get();
1580 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1582 Walker = std::make_unique<CachingWalker>(
this, WalkerBase.get());
1583 return Walker.get();
1588 return SkipWalker.get();
1591 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1593 SkipWalker = std::make_unique<SkipSelfWalker>(
this, WalkerBase.get());
1594 return SkipWalker.get();
1604 auto *
Accesses = getOrCreateAccessList(BB);
1610 auto *Defs = getOrCreateDefsList(BB);
1611 Defs->push_front(*NewAccess);
1617 auto *Defs = getOrCreateDefsList(BB);
1620 Defs->insert(DI, *NewAccess);
1626 auto *Defs = getOrCreateDefsList(BB);
1627 Defs->push_back(*NewAccess);
1630 BlockNumberingValid.erase(BB);
1636 bool WasEnd = InsertPt ==
Accesses->end();
1639 auto *Defs = getOrCreateDefsList(BB);
1645 Defs->push_back(*What);
1647 Defs->insert(InsertPt->getDefsIterator(), *What);
1653 Defs->push_back(*What);
1655 Defs->insert(InsertPt->getDefsIterator(), *What);
1658 BlockNumberingValid.erase(BB);
1679 prepareForMoveTo(What, BB);
1687 "Can only move a Phi at the beginning of the block");
1689 ValueToMemoryAccess.erase(What->
getBlock());
1690 bool Inserted = ValueToMemoryAccess.insert({BB, What}).second;
1692 assert(Inserted &&
"Cannot move a Phi to a block that already has one");
1695 prepareForMoveTo(What, BB);
1704 ValueToMemoryAccess[BB] = Phi;
1711 bool CreationMustSucceed) {
1714 if (CreationMustSucceed)
1715 assert(NewAccess !=
nullptr &&
"Tried to create a memory access for a "
1716 "non-memory touching instruction");
1719 "A use cannot be a defining access");
1730 if (!
SI->isUnordered())
1733 if (!LI->isUnordered())
1740template <
typename AliasAnalysisType>
1741MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *
I,
1742 AliasAnalysisType *AAP,
1751 switch (
II->getIntrinsicID()) {
1754 case Intrinsic::allow_runtime_check:
1755 case Intrinsic::allow_ubsan_check:
1756 case Intrinsic::assume:
1757 case Intrinsic::experimental_noalias_scope_decl:
1758 case Intrinsic::pseudoprobe:
1766 if (!
I->mayReadFromMemory() && !
I->mayWriteToMemory())
1775 bool DefCheck, UseCheck;
1780 assert((Def == DefCheck || !DefCheck) &&
1781 "Memory accesses should only be reduced");
1782 if (!Def && Use != UseCheck) {
1784 assert(!UseCheck &&
"Invalid template");
1807 MemoryUseOrDef *MUD;
1809 MUD =
new MemoryDef(
I->getContext(),
nullptr,
I,
I->getParent(), NextID++);
1811 MUD =
new MemoryUse(
I->getContext(),
nullptr,
I,
I->getParent());
1817 ValueToMemoryAccess[
I] = MUD;
1824 "Trying to remove memory access that still has uses");
1825 BlockNumbering.erase(MA);
1838 auto VMA = ValueToMemoryAccess.find(MemoryInst);
1839 if (VMA->second == MA)
1840 ValueToMemoryAccess.
erase(VMA);
1854 auto DefsIt = PerBlockDefs.find(BB);
1855 std::unique_ptr<DefsList> &Defs = DefsIt->second;
1858 PerBlockDefs.erase(DefsIt);
1863 auto AccessIt = PerBlockAccesses.find(BB);
1864 std::unique_ptr<AccessList> &
Accesses = AccessIt->second;
1871 PerBlockAccesses.erase(AccessIt);
1872 BlockNumberingValid.erase(BB);
1877 MemorySSAAnnotatedWriter Writer(
this);
1881 F->
print(OS, &Writer);
1884#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1889#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS)
1901 assert(L &&
"must either have loop or function");
1904 return *const_cast<BasicBlock *>(BB);
1924template <
typename IterT>
1928 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
1929 auto *Pred = Phi->getIncomingBlock(
I);
1930 auto *IncAcc = Phi->getIncomingValue(
I);
1934 if (
auto *DTNode = DT->getNode(Pred)) {
1936 if (
auto *DefList =
getBlockDefs(DTNode->getBlock())) {
1937 auto *LastAcc = &*(--DefList->end());
1938 assert(LastAcc == IncAcc &&
1939 "Incorrect incoming access into phi.");
1944 DTNode = DTNode->getIDom();
1961template <
typename IterT>
1963 if (BlockNumberingValid.empty())
1968 if (!ValidBlocks.
count(&BB))
1971 ValidBlocks.
erase(&BB);
1979 unsigned long LastNumber = 0;
1981 auto ThisNumberIter = BlockNumbering.find(&MA);
1982 assert(ThisNumberIter != BlockNumbering.end() &&
1983 "MemoryAccess has no domination number in a valid block!");
1985 unsigned long ThisNumber = ThisNumberIter->second;
1986 assert(ThisNumber > LastNumber &&
1987 "Domination numbers should be strictly increasing!");
1989 LastNumber = ThisNumber;
1994 "All valid BasicBlocks should exist in F -- dangling pointers?");
2003template <
typename IterT>
2020 for (
const Use &U : Phi->uses()) {
2021 assert(
dominates(Phi, U) &&
"Memory PHI does not dominate it's uses");
2027 "Incomplete MemoryPhi Node");
2028 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
2029 verifyUseInDefs(Phi->getIncomingValue(
I), Phi);
2031 "Incoming phi block not a block predecessor");
2039 "We have memory affecting instructions "
2040 "in this block but they are not in the "
2041 "access list or defs list");
2049 for (
const Use &U : MD->
uses()) {
2051 "Memory Def does not dominate it's uses");
2065 assert(AL->size() == ActualAccesses.
size() &&
2066 "We don't have the same number of accesses in the block as on the "
2069 "Either we should have a defs list, or we should have no defs");
2071 "We don't have the same number of defs in the block as on the "
2073 auto ALI = AL->begin();
2074 auto AAI = ActualAccesses.
begin();
2075 while (ALI != AL->end() && AAI != ActualAccesses.
end()) {
2076 assert(&*ALI == *AAI &&
"Not the same accesses in the same order");
2080 ActualAccesses.
clear();
2082 auto DLI =
DL->begin();
2083 auto ADI = ActualDefs.
begin();
2084 while (DLI !=
DL->end() && ADI != ActualDefs.
end()) {
2085 assert(&*DLI == *ADI &&
"Not the same defs in the same order");
2100 "Null def but use not point to live on entry def");
2103 "Did not find use in def's use list");
2112void MemorySSA::renumberBlock(
const BasicBlock *
B)
const {
2114 unsigned long CurrentNumber = 0;
2116 assert(AL !=
nullptr &&
"Asking to renumber an empty block");
2117 for (
const auto &
I : *AL)
2118 BlockNumbering[&
I] = ++CurrentNumber;
2119 BlockNumberingValid.insert(
B);
2130 "Asking for local domination when accesses are in different blocks!");
2132 if (Dominatee == Dominator)
2145 if (!BlockNumberingValid.count(DominatorBlock))
2146 renumberBlock(DominatorBlock);
2148 unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
2150 assert(DominatorNum != 0 &&
"Block was not numbered properly");
2151 unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
2152 assert(DominateeNum != 0 &&
"Block was not numbered properly");
2153 return DominatorNum < DominateeNum;
2158 if (Dominator == Dominatee)
2170 const Use &Dominatee)
const {
2172 BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
2174 if (UseBB != Dominator->
getBlock())
2175 return DT->dominates(Dominator->
getBlock(), UseBB);
2196 case MemoryPhiVal:
return static_cast<const MemoryPhi *
>(
this)->
print(OS);
2197 case MemoryDefVal:
return static_cast<const MemoryDef *
>(
this)->
print(OS);
2198 case MemoryUseVal:
return static_cast<const MemoryUse *
>(
this)->
print(OS);
2207 if (
A &&
A->getID())
2213 OS <<
getID() <<
" = MemoryDef(";
2225 OS <<
getID() <<
" = MemoryPhi(";
2236 if (
unsigned ID = MA->
getID())
2248 if (UO && UO->
getID())
2257#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2266 MemorySSAAnnotatedWriter MSSAWriter;
2270 : F(F), MSSAWriter(&MSSA) {}
2273 MemorySSAAnnotatedWriter &
getWriter() {
return MSSAWriter; }
2281 return &(CFGInfo->
getFunction()->getEntryBlock());
2316 [](std::string &S,
unsigned &
I,
unsigned Idx) ->
void {
2317 std::string Str = S.substr(
I, Idx -
I);
2319 if (SR.
count(
" = MemoryDef(") || SR.
count(
" = MemoryPhi(") ||
2320 SR.
count(
"MemoryUse("))
2340 ?
"style=filled, fillcolor=lightpink"
2347AnalysisKey MemorySSAAnalysis::Key;
2358 FunctionAnalysisManager::Invalidator &Inv) {
2368 if (EnsureOptimizedUses)
2371 if (!DotCFGMSSA.
empty()) {
2375 OS <<
"MemorySSA for function: " <<
F.getName() <<
"\n";
2385 OS <<
"MemorySSA (walker) for function: " <<
F.getName() <<
"\n";
2386 MemorySSAWalkerAnnotatedWriter Writer(&MSSA);
2387 F.print(OS, &Writer);
2420 MSSA->verifyMemorySSA();
2439 if (
Loc.Ptr ==
nullptr)
2440 return StartingAccess;
2445 return StartingUseOrDef;
2447 I = StartingUseOrDef->getMemoryInst();
2452 return StartingUseOrDef;
2455 UpwardsMemoryQuery Q;
2456 Q.OriginalAccess = StartingAccess;
2457 Q.StartingLoc =
Loc;
2465 Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
2467 dbgs() <<
"Clobber starting at access " << *StartingAccess <<
"\n";
2469 dbgs() <<
" for instruction " << *
I <<
"\n";
2470 dbgs() <<
" is " << *Clobber <<
"\n";
2477 if (!
I.hasMetadata(LLVMContext::MD_invariant_group) ||
I.isVolatile())
2494 for (
const User *Us : PointerOperand->
users()) {
2496 if (!U || U == &
I || !DT.
dominates(U, MostDominatingInstruction))
2502 if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
2504 MostDominatingInstruction = U;
2508 return MostDominatingInstruction == &
I ? nullptr : MostDominatingInstruction;
2512 MemoryAccess *MA, BatchAAResults &BAA,
unsigned &UpwardWalkLimit,
2513 bool SkipSelf,
bool UseInvariantGroup) {
2516 if (!StartingAccess)
2519 if (UseInvariantGroup) {
2521 *StartingAccess->getMemoryInst(), MSSA->
getDomTree())) {
2527 return ClobberMA->getDefiningAccess();
2532 bool IsOptimized =
false;
2537 if (StartingAccess->isOptimized()) {
2539 return StartingAccess->getOptimized();
2543 const Instruction *
I = StartingAccess->getMemoryInst();
2548 return StartingAccess;
2550 UpwardsMemoryQuery Q(
I, StartingAccess);
2554 StartingAccess->setOptimized(LiveOnEntry);
2558 MemoryAccess *OptimizedAccess;
2561 MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
2566 StartingAccess->setOptimized(DefiningAccess);
2567 return DefiningAccess;
2571 Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
2572 StartingAccess->setOptimized(OptimizedAccess);
2574 OptimizedAccess = StartingAccess->getOptimized();
2576 LLVM_DEBUG(
dbgs() <<
"Starting Memory SSA clobber for " << *
I <<
" is ");
2578 LLVM_DEBUG(
dbgs() <<
"Optimized Memory SSA clobber for " << *
I <<
" is ");
2585 Q.SkipSelfAccess =
true;
2586 Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
2588 Result = OptimizedAccess;
2590 LLVM_DEBUG(
dbgs() <<
"Result Memory SSA clobber [SkipSelf = " << SkipSelf);
2600 return Use->getDefiningAccess();
2607 return Use->getDefiningAccess();
2608 return StartingAccess;
2619void MemoryUse::deleteMe(DerivedUser *Self) {
2620 delete static_cast<MemoryUse *
>(Self);
2623bool upward_defs_iterator::IsGuaranteedLoopInvariant(
const Value *Ptr)
const {
2624 auto IsGuaranteedLoopInvariantBase = [](
const Value *Ptr) {
2633 if (
I->getParent()->isEntryBlock())
2637 return IsGuaranteedLoopInvariantBase(
GEP->getPointerOperand()) &&
2638 GEP->hasAllConstantIndices();
2640 return IsGuaranteedLoopInvariantBase(Ptr);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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)
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 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.
constexpr bool empty() const
Check if the string is empty.
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.
@ BasicBlock
Various leaf nodes.
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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
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)
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
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.
upward_defs_iterator upward_defs_end()
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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)