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;
236 MLOC.getCall()->getCalledOperand()));
238 for (
const Value *Arg : MLOC.getCall()->args())
243 static bool isEqual(
const MemoryLocOrCall &LHS,
const MemoryLocOrCall &RHS) {
258 bool VolatileUse =
Use->isVolatile();
259 bool VolatileClobber = MayClobber->
isVolatile();
261 if (VolatileUse && VolatileClobber)
277 return !(SeqCstUse || MayClobberIsAcquire);
280template <
typename AliasAnalysisType>
285 assert(DefInst &&
"Defining instruction not actually an instruction");
295 switch (
II->getIntrinsicID()) {
296 case Intrinsic::allow_runtime_check:
297 case Intrinsic::allow_ubsan_check:
298 case Intrinsic::invariant_start:
299 case Intrinsic::invariant_end:
300 case Intrinsic::assume:
301 case Intrinsic::experimental_noalias_scope_decl:
302 case Intrinsic::pseudoprobe:
304 case Intrinsic::dbg_declare:
305 case Intrinsic::dbg_label:
306 case Intrinsic::dbg_value:
326template <
typename AliasAnalysisType>
328 const MemoryLocOrCall &UseMLOC,
329 AliasAnalysisType &
AA) {
347struct UpwardsMemoryQuery {
357 bool SkipSelfAccess =
false;
359 UpwardsMemoryQuery() =
default;
370template <
typename AliasAnalysisType>
376 return I->hasMetadata(LLVMContext::MD_invariant_load) ||
396[[maybe_unused]]
static void
400 bool AllowImpreciseClobber =
false) {
401 assert(MSSA.
dominates(ClobberAt, Start) &&
"Clobber doesn't dominate start?");
405 "liveOnEntry must clobber itself");
409 bool FoundClobber =
false;
412 Worklist.
push_back({Start, StartLoc,
false});
415 while (!Worklist.
empty()) {
423 if (MA == ClobberAt) {
450 "Found clobber before reaching ClobberAt!");
457 "Can only find use in def chain if Start is a use");
478 if (AllowImpreciseClobber)
484 "ClobberAt never acted as a clobber");
493 using ListIndex = unsigned;
503 std::optional<ListIndex> Previous;
504 bool MayBeCrossIteration;
506 DefPath(
const MemoryLocation &Loc, MemoryAccess *
First, MemoryAccess *
Last,
507 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
509 MayBeCrossIteration(MayBeCrossIteration) {}
511 DefPath(
const MemoryLocation &Loc, MemoryAccess *Init,
512 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
513 : DefPath(Loc, Init, Init, MayBeCrossIteration, Previous) {}
519 UpwardsMemoryQuery *Query;
520 unsigned *UpwardWalkLimit;
527 DenseSet<UpwardDefsElem> VisitedPhis;
530 const MemoryAccess *getWalkTarget(
const MemoryPhi *From)
const {
536 while ((Node =
Node->getIDom())) {
545 struct UpwardsWalkResult {
558 walkToPhiOrClobber(DefPath &
Desc,
const MemoryAccess *
StopAt =
nullptr,
559 const MemoryAccess *SkipStopAt =
nullptr)
const {
561 assert(UpwardWalkLimit &&
"Need a valid walk limit");
562 bool LimitAlreadyReached =
false;
567 if (!*UpwardWalkLimit) {
568 *UpwardWalkLimit = 1;
569 LimitAlreadyReached =
true;
574 if (Current ==
StopAt || Current == SkipStopAt)
575 return {Current,
false};
581 if (!--*UpwardWalkLimit)
582 return {Current,
true};
584 BatchAACrossIterationScope
_(*AA,
Desc.MayBeCrossIteration);
590 if (LimitAlreadyReached)
591 *UpwardWalkLimit = 0;
594 "Ended at a non-clobber that's not a phi?");
595 return {
Desc.Last,
false};
598 void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
599 ListIndex PriorNode,
bool MayBeCrossIteration) {
600 auto UpwardDefsBegin =
603 for (
const UpwardDefsElem &
E : UpwardDefs) {
612 struct TerminatedPath {
613 MemoryAccess *Clobber;
626 std::optional<TerminatedPath>
627 getBlockingAccess(
const MemoryAccess *StopWhere,
628 SmallVectorImpl<ListIndex> &PausedSearches,
629 SmallVectorImpl<ListIndex> &NewPaused,
630 SmallVectorImpl<TerminatedPath> &Terminated) {
631 assert(!PausedSearches.
empty() &&
"No searches to continue?");
635 while (!PausedSearches.
empty()) {
637 DefPath &
Node = Paths[PathIndex];
657 if (!VisitedPhis.
insert({Node.Last, Node.Loc, Node.MayBeCrossIteration})
661 const MemoryAccess *SkipStopWhere =
nullptr;
662 if (Query->SkipSelfAccess &&
Node.Loc == Query->StartingLoc) {
664 SkipStopWhere = Query->OriginalAccess;
667 UpwardsWalkResult Res = walkToPhiOrClobber(Node,
670 if (Res.IsKnownClobber) {
671 assert(Res.Result != StopWhere && Res.Result != SkipStopWhere);
675 TerminatedPath
Term{Res.Result, PathIndex};
676 if (!MSSA.
dominates(Res.Result, StopWhere))
684 if (Res.Result == StopWhere || Res.Result == SkipStopWhere) {
689 if (Res.Result != SkipStopWhere)
696 Node.MayBeCrossIteration);
702 template <
typename T,
typename Walker>
703 struct generic_def_path_iterator
704 :
public iterator_facade_base<generic_def_path_iterator<T, Walker>,
705 std::forward_iterator_tag, T *> {
706 generic_def_path_iterator() =
default;
707 generic_def_path_iterator(Walker *W, ListIndex
N) :
W(
W),
N(
N) {}
711 generic_def_path_iterator &operator++() {
712 N = curNode().Previous;
716 bool operator==(
const generic_def_path_iterator &O)
const {
717 if (
N.has_value() !=
O.N.has_value())
719 return !
N || *
N == *
O.N;
723 T &curNode()
const {
return W->Paths[*
N]; }
726 std::optional<ListIndex>
N;
729 using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
730 using const_def_path_iterator =
731 generic_def_path_iterator<const DefPath, const ClobberWalker>;
734 return make_range(def_path_iterator(
this, From), def_path_iterator());
738 return make_range(const_def_path_iterator(
this, From),
739 const_def_path_iterator());
744 TerminatedPath PrimaryClobber;
750 ListIndex defPathIndex(
const DefPath &
N)
const {
752 const DefPath *NP = &
N;
754 "Out of bounds DefPath!");
755 return NP - &Paths.
front();
771 OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
772 const MemoryLocation &Loc) {
774 "Reset the optimization state.");
780 auto PriorPathsSize = Paths.
size();
786 addSearches(Phi, PausedSearches, 0,
false);
790 auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
792 auto Dom = Paths.
begin();
793 for (
auto I = std::next(Dom),
E = Paths.
end();
I !=
E; ++
I)
794 if (!MSSA.
dominates(
I->Clobber, Dom->Clobber))
798 std::iter_swap(
Last, Dom);
801 MemoryPhi *Current =
Phi;
804 "liveOnEntry wasn't treated as a clobber?");
806 const auto *
Target = getWalkTarget(Current);
809 assert(
all_of(TerminatedPaths, [&](
const TerminatedPath &
P) {
816 if (std::optional<TerminatedPath> Blocker = getBlockingAccess(
817 Target, PausedSearches, NewPaused, TerminatedPaths)) {
821 auto Iter =
find_if(def_path(Blocker->LastNode), [&](
const DefPath &
N) {
822 return defPathIndex(N) < PriorPathsSize;
824 assert(Iter != def_path_iterator());
826 DefPath &CurNode = *Iter;
827 assert(CurNode.Last == Current);
854 TerminatedPath
Result{CurNode.Last, defPathIndex(CurNode)};
861 if (NewPaused.
empty()) {
862 MoveDominatedPathToEnd(TerminatedPaths);
864 return {
Result, std::move(TerminatedPaths)};
867 MemoryAccess *DefChainEnd =
nullptr;
869 for (ListIndex Paused : NewPaused) {
870 UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
871 if (WR.IsKnownClobber)
875 DefChainEnd = WR.Result;
878 if (!TerminatedPaths.
empty()) {
882 for (
auto *MA :
def_chain(
const_cast<MemoryAccess *
>(Target)))
884 assert(DefChainEnd &&
"Failed to find dominating phi/liveOnEntry");
889 for (
const TerminatedPath &TP : TerminatedPaths) {
892 if (DT.
dominates(ChainBB, TP.Clobber->getBlock()))
899 if (!Clobbers.
empty()) {
900 MoveDominatedPathToEnd(Clobbers);
902 return {
Result, std::move(Clobbers)};
906 [&](ListIndex
I) {
return Paths[
I].Last == DefChainEnd; }));
911 PriorPathsSize = Paths.
size();
912 PausedSearches.
clear();
913 for (ListIndex
I : NewPaused)
914 addSearches(DefChainPhi, PausedSearches,
I,
915 Paths[
I].MayBeCrossIteration);
918 Current = DefChainPhi;
922 void verifyOptResult(
const OptznResult &R)
const {
924 return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
928 void resetPhiOptznState() {
934 ClobberWalker(
const MemorySSA &MSSA, DominatorTree &DT)
935 : MSSA(MSSA), DT(DT) {}
939 MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
940 UpwardsMemoryQuery &Q,
unsigned &UpWalkLimit) {
943 UpwardWalkLimit = &UpWalkLimit;
948 MemoryAccess *Current =
Start;
952 Current = MU->getDefiningAccess();
954 DefPath FirstDesc(Q.StartingLoc, Current, Current,
955 false, std::nullopt);
958 UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
960 if (WalkResult.IsKnownClobber) {
961 Result = WalkResult.Result;
964 Current, Q.StartingLoc);
965 verifyOptResult(OptRes);
966 resetPhiOptznState();
967 Result = OptRes.PrimaryClobber.Clobber;
970#ifdef EXPENSIVE_CHECKS
971 if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
978struct RenamePassData {
980 DomTreeNode::const_iterator ChildIt;
981 MemoryAccess *IncomingVal;
983 RenamePassData(
DomTreeNode *
D, DomTreeNode::const_iterator It,
985 : DTN(
D), ChildIt(It), IncomingVal(
M) {}
987 void swap(RenamePassData &
RHS) {
999 ClobberWalker Walker;
1016 bool UseInvariantGroup =
true);
1034 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false);
1039 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1044 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false,
false);
1061 MUD->resetOptimized();
1077 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
true);
1082 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1099 MUD->resetOptimized();
1106 bool RenameAllUses) {
1109 auto It = PerBlockAccesses.find(S);
1111 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1115 if (RenameAllUses) {
1116 bool ReplacementDone =
false;
1117 for (
unsigned I = 0,
E = Phi->getNumIncomingValues();
I !=
E; ++
I)
1118 if (Phi->getIncomingBlock(
I) == BB) {
1119 Phi->setIncomingValue(
I, IncomingVal);
1120 ReplacementDone =
true;
1122 (void) ReplacementDone;
1123 assert(ReplacementDone &&
"Incomplete phi during partial rename");
1125 Phi->addIncoming(IncomingVal, BB);
1133 bool RenameAllUses) {
1134 auto It = PerBlockAccesses.find(BB);
1136 if (It != PerBlockAccesses.end()) {
1138 for (MemoryAccess &L : *
Accesses) {
1140 if (MUD->getDefiningAccess() ==
nullptr || RenameAllUses)
1141 MUD->setDefiningAccess(IncomingVal);
1158 bool SkipVisited,
bool RenameAllUses) {
1159 assert(Root &&
"Trying to rename accesses in an unreachable block");
1166 if (SkipVisited && AlreadyVisited)
1169 IncomingVal = renameBlock(Root->
getBlock(), IncomingVal, RenameAllUses);
1170 renameSuccessorPhis(Root->
getBlock(), IncomingVal, RenameAllUses);
1173 while (!WorkStack.
empty()) {
1175 DomTreeNode::const_iterator ChildIt = WorkStack.
back().ChildIt;
1176 IncomingVal = WorkStack.
back().IncomingVal;
1178 if (ChildIt ==
Node->end()) {
1182 ++WorkStack.
back().ChildIt;
1186 AlreadyVisited = !Visited.
insert(BB).second;
1187 if (SkipVisited && AlreadyVisited) {
1194 IncomingVal = &*BlockDefs->rbegin();
1196 IncomingVal = renameBlock(BB, IncomingVal, RenameAllUses);
1197 renameSuccessorPhis(BB, IncomingVal, RenameAllUses);
1206void MemorySSA::markUnreachableAsLiveOnEntry(
BasicBlock *BB) {
1207 assert(!DT->isReachableFromEntry(BB) &&
1208 "Reachable block found while handling unreachable blocks");
1215 if (!DT->isReachableFromEntry(S))
1217 auto It = PerBlockAccesses.find(S);
1219 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1223 Phi->addIncoming(LiveOnEntryDef.get(), BB);
1226 auto It = PerBlockAccesses.find(BB);
1227 if (It == PerBlockAccesses.end())
1232 auto Next = std::next(AI);
1236 UseOrDef->setDefiningAccess(LiveOnEntryDef.get());
1244 : DT(DT), F(&Func), LiveOnEntryDef(nullptr), Walker(nullptr),
1245 SkipWalker(nullptr) {
1251 assert(AA &&
"No alias analysis?");
1262 : DT(DT), L(&L), LiveOnEntryDef(nullptr), Walker(nullptr),
1263 SkipWalker(nullptr) {
1269 assert(AA &&
"No alias analysis?");
1273 return *const_cast<BasicBlock *>(BB);
1284 for (
const auto &Pair : PerBlockAccesses)
1290 auto Res = PerBlockAccesses.try_emplace(BB);
1293 Res.first->second = std::make_unique<AccessList>();
1294 return Res.first->second.get();
1298 auto Res = PerBlockDefs.try_emplace(BB);
1301 Res.first->second = std::make_unique<DefsList>();
1302 return Res.first->second.get();
1318 : MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
1324 struct MemlocStackInfo {
1327 unsigned long StackEpoch;
1328 unsigned long PopEpoch;
1333 unsigned long LowerBound;
1336 unsigned long LastKill;
1340 void optimizeUsesInBlock(
const BasicBlock *,
unsigned long &,
unsigned long &,
1345 CachingWalker *Walker;
1364void MemorySSA::OptimizeUses::optimizeUsesInBlock(
1365 const BasicBlock *BB,
unsigned long &StackEpoch,
unsigned long &PopEpoch,
1378 !VersionStack.
empty() &&
1379 "Version stack should have liveOnEntry sentinel dominating everything");
1381 if (DT->dominates(BackBlock, BB))
1383 while (VersionStack.
back()->getBlock() == BackBlock)
1388 for (MemoryAccess &MA : *
Accesses) {
1396 if (MU->isOptimized())
1399 MemoryLocOrCall UseMLOC(MU);
1400 auto &LocInfo = LocStackInfo[UseMLOC];
1404 if (LocInfo.PopEpoch != PopEpoch) {
1405 LocInfo.PopEpoch = PopEpoch;
1406 LocInfo.StackEpoch = StackEpoch;
1418 if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
1419 !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
1423 LocInfo.LowerBound = 0;
1424 LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
1425 LocInfo.LastKillValid =
false;
1427 }
else if (LocInfo.StackEpoch != StackEpoch) {
1431 LocInfo.PopEpoch = PopEpoch;
1432 LocInfo.StackEpoch = StackEpoch;
1434 if (!LocInfo.LastKillValid) {
1435 LocInfo.LastKill = VersionStack.
size() - 1;
1436 LocInfo.LastKillValid =
true;
1441 assert(LocInfo.LowerBound < VersionStack.
size() &&
1442 "Lower bound out of range");
1443 assert(LocInfo.LastKill < VersionStack.
size() &&
1444 "Last kill info out of range");
1446 unsigned long UpperBound = VersionStack.
size() - 1;
1449 LLVM_DEBUG(
dbgs() <<
"MemorySSA skipping optimization of " << *MU <<
" ("
1450 << *(MU->getMemoryInst()) <<
")"
1451 <<
" because there are "
1452 << UpperBound - LocInfo.LowerBound
1453 <<
" stores to disambiguate\n");
1456 LocInfo.LastKillValid =
false;
1459 bool FoundClobberResult =
false;
1461 while (UpperBound > LocInfo.LowerBound) {
1467 Walker->getClobberingMemoryAccessWithoutInvariantGroup(
1468 MU, *AA, UpwardWalkLimit);
1470 while (VersionStack[UpperBound] != Result) {
1474 FoundClobberResult =
true;
1480 FoundClobberResult =
true;
1488 if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
1489 MU->setDefiningAccess(VersionStack[UpperBound],
true);
1490 LocInfo.LastKill = UpperBound;
1494 MU->setDefiningAccess(VersionStack[LocInfo.LastKill],
true);
1496 LocInfo.LowerBound = VersionStack.
size() - 1;
1497 LocInfo.LowerBoundBlock = BB;
1505 VersionStack.
push_back(MSSA->getLiveOnEntryDef());
1507 unsigned long StackEpoch = 1;
1508 unsigned long PopEpoch = 1;
1510 for (
const auto *DomNode :
depth_first(DT->getRootNode()))
1511 optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
1515void MemorySSA::placePHINodes(
1519 IDFs.setDefiningBlocks(DefiningBlocks);
1521 IDFs.calculate(IDFBlocks);
1524 for (
auto &BB : IDFBlocks)
1525 createMemoryPhi(BB);
1528template <
typename IterT>
1529void MemorySSA::buildMemorySSA(
BatchAAResults &BAA, IterT Blocks) {
1538 nullptr, &StartingPoint, NextID++));
1547 bool InsertIntoDef =
false;
1559 InsertIntoDef =
true;
1561 Defs = getOrCreateDefsList(&
B);
1562 Defs->push_back(*MUD);
1568 placePHINodes(DefiningBlocks);
1572 SmallPtrSet<BasicBlock *, 16> Visited;
1579 U.set(LiveOnEntryDef.get());
1585 L->getExitBlocks(ExitBlocks);
1587 renamePass(DT->getNode(L->getLoopPreheader()), LiveOnEntryDef.get(),
1590 renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
1595 for (
auto &BB : Blocks)
1596 if (!Visited.
count(&BB))
1597 markUnreachableAsLiveOnEntry(&BB);
1604 return Walker.get();
1607 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1609 Walker = std::make_unique<CachingWalker>(
this, WalkerBase.get());
1610 return Walker.get();
1615 return SkipWalker.get();
1618 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1620 SkipWalker = std::make_unique<SkipSelfWalker>(
this, WalkerBase.get());
1621 return SkipWalker.get();
1631 auto *
Accesses = getOrCreateAccessList(BB);
1637 auto *Defs = getOrCreateDefsList(BB);
1638 Defs->push_front(*NewAccess);
1644 auto *Defs = getOrCreateDefsList(BB);
1647 Defs->insert(DI, *NewAccess);
1653 auto *Defs = getOrCreateDefsList(BB);
1654 Defs->push_back(*NewAccess);
1657 BlockNumberingValid.erase(BB);
1663 bool WasEnd = InsertPt ==
Accesses->end();
1666 auto *Defs = getOrCreateDefsList(BB);
1672 Defs->push_back(*What);
1674 Defs->insert(InsertPt->getDefsIterator(), *What);
1680 Defs->push_back(*What);
1682 Defs->insert(InsertPt->getDefsIterator(), *What);
1685 BlockNumberingValid.erase(BB);
1706 prepareForMoveTo(What, BB);
1714 "Can only move a Phi at the beginning of the block");
1716 ValueToMemoryAccess.erase(What->
getBlock());
1717 bool Inserted = ValueToMemoryAccess.insert({BB, What}).second;
1719 assert(Inserted &&
"Cannot move a Phi to a block that already has one");
1722 prepareForMoveTo(What, BB);
1731 ValueToMemoryAccess[BB] = Phi;
1738 bool CreationMustSucceed) {
1741 if (CreationMustSucceed)
1742 assert(NewAccess !=
nullptr &&
"Tried to create a memory access for a "
1743 "non-memory touching instruction");
1746 "A use cannot be a defining access");
1757 if (!
SI->isUnordered())
1760 if (!LI->isUnordered())
1767template <
typename AliasAnalysisType>
1768MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *
I,
1769 AliasAnalysisType *AAP,
1778 switch (
II->getIntrinsicID()) {
1781 case Intrinsic::allow_runtime_check:
1782 case Intrinsic::allow_ubsan_check:
1783 case Intrinsic::assume:
1784 case Intrinsic::experimental_noalias_scope_decl:
1785 case Intrinsic::pseudoprobe:
1793 if (!
I->mayReadFromMemory() && !
I->mayWriteToMemory())
1802 bool DefCheck, UseCheck;
1807 assert((Def == DefCheck || !DefCheck) &&
1808 "Memory accesses should only be reduced");
1809 if (!Def && Use != UseCheck) {
1811 assert(!UseCheck &&
"Invalid template");
1834 MemoryUseOrDef *MUD;
1836 MUD =
new MemoryDef(
I->getContext(),
nullptr,
I,
I->getParent(), NextID++);
1838 MUD =
new MemoryUse(
I->getContext(),
nullptr,
I,
I->getParent());
1844 ValueToMemoryAccess[
I] = MUD;
1851 "Trying to remove memory access that still has uses");
1852 BlockNumbering.erase(MA);
1865 auto VMA = ValueToMemoryAccess.find(MemoryInst);
1866 if (VMA->second == MA)
1867 ValueToMemoryAccess.
erase(VMA);
1881 auto DefsIt = PerBlockDefs.find(BB);
1882 std::unique_ptr<DefsList> &Defs = DefsIt->second;
1885 PerBlockDefs.erase(DefsIt);
1890 auto AccessIt = PerBlockAccesses.find(BB);
1891 std::unique_ptr<AccessList> &
Accesses = AccessIt->second;
1898 PerBlockAccesses.erase(AccessIt);
1899 BlockNumberingValid.erase(BB);
1904 MemorySSAAnnotatedWriter Writer(
this);
1908 F->
print(OS, &Writer);
1911#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1916#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS)
1928 assert(L &&
"must either have loop or function");
1931 return *const_cast<BasicBlock *>(BB);
1951template <
typename IterT>
1955 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
1956 auto *Pred = Phi->getIncomingBlock(
I);
1957 auto *IncAcc = Phi->getIncomingValue(
I);
1961 if (
auto *DTNode = DT->getNode(Pred)) {
1963 if (
auto *DefList =
getBlockDefs(DTNode->getBlock())) {
1964 auto *LastAcc = &*(--DefList->end());
1965 assert(LastAcc == IncAcc &&
1966 "Incorrect incoming access into phi.");
1971 DTNode = DTNode->getIDom();
1988template <
typename IterT>
1990 if (BlockNumberingValid.empty())
1995 if (!ValidBlocks.
count(&BB))
1998 ValidBlocks.
erase(&BB);
2006 unsigned long LastNumber = 0;
2008 auto ThisNumberIter = BlockNumbering.find(&MA);
2009 assert(ThisNumberIter != BlockNumbering.end() &&
2010 "MemoryAccess has no domination number in a valid block!");
2012 unsigned long ThisNumber = ThisNumberIter->second;
2013 assert(ThisNumber > LastNumber &&
2014 "Domination numbers should be strictly increasing!");
2016 LastNumber = ThisNumber;
2021 "All valid BasicBlocks should exist in F -- dangling pointers?");
2030template <
typename IterT>
2047 for (
const Use &U : Phi->uses()) {
2048 assert(
dominates(Phi, U) &&
"Memory PHI does not dominate it's uses");
2054 "Incomplete MemoryPhi Node");
2055 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
2056 verifyUseInDefs(Phi->getIncomingValue(
I), Phi);
2058 "Incoming phi block not a block predecessor");
2066 "We have memory affecting instructions "
2067 "in this block but they are not in the "
2068 "access list or defs list");
2076 for (
const Use &U : MD->
uses()) {
2078 "Memory Def does not dominate it's uses");
2092 assert(AL->size() == ActualAccesses.
size() &&
2093 "We don't have the same number of accesses in the block as on the "
2096 "Either we should have a defs list, or we should have no defs");
2098 "We don't have the same number of defs in the block as on the "
2100 auto ALI = AL->begin();
2101 auto AAI = ActualAccesses.
begin();
2102 while (ALI != AL->end() && AAI != ActualAccesses.
end()) {
2103 assert(&*ALI == *AAI &&
"Not the same accesses in the same order");
2107 ActualAccesses.
clear();
2109 auto DLI =
DL->begin();
2110 auto ADI = ActualDefs.
begin();
2111 while (DLI !=
DL->end() && ADI != ActualDefs.
end()) {
2112 assert(&*DLI == *ADI &&
"Not the same defs in the same order");
2127 "Null def but use not point to live on entry def");
2130 "Did not find use in def's use list");
2139void MemorySSA::renumberBlock(
const BasicBlock *
B)
const {
2141 unsigned long CurrentNumber = 0;
2143 assert(AL !=
nullptr &&
"Asking to renumber an empty block");
2144 for (
const auto &
I : *AL)
2145 BlockNumbering[&
I] = ++CurrentNumber;
2146 BlockNumberingValid.insert(
B);
2157 "Asking for local domination when accesses are in different blocks!");
2159 if (Dominatee == Dominator)
2172 if (!BlockNumberingValid.count(DominatorBlock))
2173 renumberBlock(DominatorBlock);
2175 unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
2177 assert(DominatorNum != 0 &&
"Block was not numbered properly");
2178 unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
2179 assert(DominateeNum != 0 &&
"Block was not numbered properly");
2180 return DominatorNum < DominateeNum;
2185 if (Dominator == Dominatee)
2197 const Use &Dominatee)
const {
2199 BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
2201 if (UseBB != Dominator->
getBlock())
2202 return DT->dominates(Dominator->
getBlock(), UseBB);
2223 case MemoryPhiVal:
return static_cast<const MemoryPhi *
>(
this)->
print(OS);
2224 case MemoryDefVal:
return static_cast<const MemoryDef *
>(
this)->
print(OS);
2225 case MemoryUseVal:
return static_cast<const MemoryUse *
>(
this)->
print(OS);
2234 if (
A &&
A->getID())
2240 OS <<
getID() <<
" = MemoryDef(";
2252 OS <<
getID() <<
" = MemoryPhi(";
2263 if (
unsigned ID = MA->
getID())
2275 if (UO && UO->
getID())
2284#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2293 MemorySSAAnnotatedWriter MSSAWriter;
2297 : F(F), MSSAWriter(&MSSA) {}
2300 MemorySSAAnnotatedWriter &
getWriter() {
return MSSAWriter; }
2308 return &(CFGInfo->
getFunction()->getEntryBlock());
2343 [](std::string &S,
unsigned &
I,
unsigned Idx) ->
void {
2344 std::string Str = S.substr(
I, Idx -
I);
2346 if (SR.
count(
" = MemoryDef(") || SR.
count(
" = MemoryPhi(") ||
2347 SR.
count(
"MemoryUse("))
2367 ?
"style=filled, fillcolor=lightpink"
2374AnalysisKey MemorySSAAnalysis::Key;
2385 FunctionAnalysisManager::Invalidator &Inv) {
2395 if (EnsureOptimizedUses)
2401 OS <<
"MemorySSA for function: " <<
F.getName() <<
"\n";
2411 OS <<
"MemorySSA (walker) for function: " <<
F.getName() <<
"\n";
2412 MemorySSAWalkerAnnotatedWriter Writer(&MSSA);
2413 F.print(OS, &Writer);
2446 MSSA->verifyMemorySSA();
2465 if (
Loc.Ptr ==
nullptr)
2466 return StartingAccess;
2471 return StartingUseOrDef;
2473 I = StartingUseOrDef->getMemoryInst();
2478 return StartingUseOrDef;
2481 UpwardsMemoryQuery Q;
2482 Q.OriginalAccess = StartingAccess;
2483 Q.StartingLoc =
Loc;
2491 Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
2493 dbgs() <<
"Clobber starting at access " << *StartingAccess <<
"\n";
2495 dbgs() <<
" for instruction " << *
I <<
"\n";
2496 dbgs() <<
" is " << *Clobber <<
"\n";
2503 if (!
I.hasMetadata(LLVMContext::MD_invariant_group) ||
I.isVolatile())
2520 for (
const User *Us : PointerOperand->
users()) {
2522 if (!U || U == &
I || !DT.
dominates(U, MostDominatingInstruction))
2528 if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
2530 MostDominatingInstruction = U;
2534 return MostDominatingInstruction == &
I ? nullptr : MostDominatingInstruction;
2538 MemoryAccess *MA, BatchAAResults &BAA,
unsigned &UpwardWalkLimit,
2539 bool SkipSelf,
bool UseInvariantGroup) {
2542 if (!StartingAccess)
2545 if (UseInvariantGroup) {
2547 *StartingAccess->getMemoryInst(), MSSA->
getDomTree())) {
2553 return ClobberMA->getDefiningAccess();
2558 bool IsOptimized =
false;
2563 if (StartingAccess->isOptimized()) {
2565 return StartingAccess->getOptimized();
2569 const Instruction *
I = StartingAccess->getMemoryInst();
2574 return StartingAccess;
2576 UpwardsMemoryQuery Q(
I, StartingAccess);
2580 StartingAccess->setOptimized(LiveOnEntry);
2584 MemoryAccess *OptimizedAccess;
2587 MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
2592 StartingAccess->setOptimized(DefiningAccess);
2593 return DefiningAccess;
2597 Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
2598 StartingAccess->setOptimized(OptimizedAccess);
2600 OptimizedAccess = StartingAccess->getOptimized();
2602 LLVM_DEBUG(
dbgs() <<
"Starting Memory SSA clobber for " << *
I <<
" is ");
2604 LLVM_DEBUG(
dbgs() <<
"Optimized Memory SSA clobber for " << *
I <<
" is ");
2611 Q.SkipSelfAccess =
true;
2612 Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
2614 Result = OptimizedAccess;
2616 LLVM_DEBUG(
dbgs() <<
"Result Memory SSA clobber [SkipSelf = " << SkipSelf);
2626 return Use->getDefiningAccess();
2633 return Use->getDefiningAccess();
2634 return StartingAccess;
2645void MemoryUse::deleteMe(DerivedUser *Self) {
2646 delete static_cast<MemoryUse *
>(Self);
2649bool upward_defs_iterator::IsGuaranteedLoopInvariant(
const Value *Ptr)
const {
2650 auto IsGuaranteedLoopInvariantBase = [](
const Value *Ptr) {
2659 if (
I->getParent()->isEntryBlock())
2663 return IsGuaranteedLoopInvariantBase(
GEP->getPointerOperand()) &&
2664 GEP->hasAllConstantIndices();
2666 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.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
size_t count(char C) const
Return the number of occurrences of C in the string.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
void dropAllReferences()
Drop all references to operands.
unsigned getNumOperands() const
LLVM Value Representation.
iterator_range< user_iterator > users()
unsigned getValueID() const
Return an ID for the concrete type of this object.
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
An opaque object representing a hash code.
typename base_list_type::iterator iterator
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
reverse_iterator rbegin()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
This namespace contains all of the command line option processing machinery.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static cl::opt< unsigned long > StopAt("sbvec-stop-at", cl::init(StopAtDisabled), cl::Hidden, cl::desc("Vectorize if the invocation count is < than this. 0 " "disables vectorization."))
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
auto successors(const MachineBasicBlock *BB)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto pred_size(const MachineBasicBlock *BB)
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
DomTreeNodeBase< BasicBlock > DomTreeNode
auto dyn_cast_or_null(const Y &Val)
iterator_range< def_chain_iterator< T > > def_chain(T MA, MemoryAccess *UpTo=nullptr)
bool isModSet(const ModRefInfo MRI)
auto find_if_not(R &&Range, UnaryPredicate P)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IDFCalculator< false > ForwardIDFCalculator
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
upward_defs_iterator upward_defs_end()
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Instruction::const_succ_iterator const_succ_iterator
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
upward_defs_iterator upward_defs_begin(const UpwardDefsElem &Pair, DominatorTree &DT)
bool isRefSet(const ModRefInfo MRI)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
std::string getEdgeAttributes(const BasicBlock *Node, const_succ_iterator I, DOTFuncMSSAInfo *CFGInfo)
Display the raw branch weights from PGO.
std::string getNodeAttributes(const BasicBlock *Node, DOTFuncMSSAInfo *CFGInfo)
static std::string getEdgeSourceLabel(const BasicBlock *Node, const_succ_iterator I)
std::string getNodeLabel(const BasicBlock *Node, DOTFuncMSSAInfo *CFGInfo)
static std::string getGraphName(DOTFuncMSSAInfo *CFGInfo)
DOTGraphTraits(bool IsSimple=false)
DefaultDOTGraphTraits(bool simple=false)
static std::string getEdgeSourceLabel(const void *, EdgeIter)
getEdgeSourceLabel - If you want to label the edge source itself, implement this method.
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS)
static unsigned getHashValue(const MemoryLocOrCall &MLOC)
static MemoryLocOrCall getEmptyKey()
static MemoryLocOrCall getTombstoneKey()
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)