31#include "llvm/Config/llvm-config.h"
62#define DEBUG_TYPE "memoryssa"
77 "memssa-check-limit",
cl::Hidden,
cl::init(100),
78 cl::desc(
"The maximum number of stores/phis MemorySSA"
79 "will consider trying to walk past (default = 100)"));
82#ifdef EXPENSIVE_CHECKS
102 MemorySSAAnnotatedWriter(
const MemorySSA *M) : MSSA(M) {}
104 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
107 OS <<
"; " << *MA <<
"\n";
113 OS <<
"; " << *MA <<
"\n";
125 MemorySSAWalkerAnnotatedWriter(
MemorySSA *M)
126 : MSSA(M), Walker(M->getWalker()), BAA(M->getAA()) {}
128 void emitBasicBlockStartAnnot(
const BasicBlock *BB,
131 OS <<
"; " << *MA <<
"\n";
140 OS <<
" - clobbered by ";
160class MemoryLocOrCall {
164 MemoryLocOrCall(MemoryUseOrDef *MUD)
165 : MemoryLocOrCall(MUD->getMemoryInst()) {}
166 MemoryLocOrCall(
const MemoryUseOrDef *MUD)
167 : MemoryLocOrCall(MUD->getMemoryInst()) {}
169 MemoryLocOrCall(Instruction *Inst) {
182 explicit MemoryLocOrCall(
const MemoryLocation &Loc) : Loc(Loc) {}
184 const CallBase *getCall()
const {
189 MemoryLocation getLoc()
const {
195 if (IsCall !=
Other.IsCall)
199 return Loc ==
Other.Loc;
206 Other.Call->arg_begin());
211 const CallBase *
Call;
229 MLOC.getCall()->getCalledOperand()));
231 for (
const Value *Arg : MLOC.getCall()->args())
236 static bool isEqual(
const MemoryLocOrCall &LHS,
const MemoryLocOrCall &RHS) {
251 bool VolatileUse =
Use->isVolatile();
252 bool VolatileClobber = MayClobber->
isVolatile();
254 if (VolatileUse && VolatileClobber)
270 return !(SeqCstUse || MayClobberIsAcquire);
273template <
typename AliasAnalysisType>
278 assert(DefInst &&
"Defining instruction not actually an instruction");
288 switch (
II->getIntrinsicID()) {
289 case Intrinsic::allow_runtime_check:
290 case Intrinsic::allow_ubsan_check:
291 case Intrinsic::invariant_start:
292 case Intrinsic::invariant_end:
293 case Intrinsic::assume:
294 case Intrinsic::experimental_noalias_scope_decl:
295 case Intrinsic::pseudoprobe:
297 case Intrinsic::dbg_declare:
298 case Intrinsic::dbg_label:
299 case Intrinsic::dbg_value:
319template <
typename AliasAnalysisType>
321 const MemoryLocOrCall &UseMLOC,
322 AliasAnalysisType &
AA) {
340struct UpwardsMemoryQuery {
350 bool SkipSelfAccess =
false;
352 UpwardsMemoryQuery() =
default;
363template <
typename AliasAnalysisType>
368 if (
I->hasMetadata(LLVMContext::MD_invariant_load))
389[[maybe_unused]]
static void
393 bool AllowImpreciseClobber =
false) {
394 assert(MSSA.
dominates(ClobberAt, Start) &&
"Clobber doesn't dominate start?");
398 "liveOnEntry must clobber itself");
402 bool FoundClobber =
false;
405 Worklist.
push_back({Start, StartLoc,
false});
408 while (!Worklist.
empty()) {
416 if (MA == ClobberAt) {
443 "Found clobber before reaching ClobberAt!");
450 "Can only find use in def chain if Start is a use");
471 if (AllowImpreciseClobber)
477 "ClobberAt never acted as a clobber");
486 using ListIndex = unsigned;
496 std::optional<ListIndex> Previous;
497 bool MayBeCrossIteration;
499 DefPath(
const MemoryLocation &Loc, MemoryAccess *
First, MemoryAccess *
Last,
500 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
502 MayBeCrossIteration(MayBeCrossIteration) {}
504 DefPath(
const MemoryLocation &Loc, MemoryAccess *Init,
505 bool MayBeCrossIteration, std::optional<ListIndex> Previous)
506 : DefPath(Loc, Init, Init, MayBeCrossIteration, Previous) {}
512 UpwardsMemoryQuery *Query;
513 unsigned *UpwardWalkLimit;
520 DenseSet<UpwardDefsElem> VisitedPhis;
523 const MemoryAccess *getWalkTarget(
const MemoryPhi *From)
const {
529 while ((Node =
Node->getIDom())) {
538 struct UpwardsWalkResult {
551 walkToPhiOrClobber(DefPath &
Desc,
const MemoryAccess *
StopAt =
nullptr,
552 const MemoryAccess *SkipStopAt =
nullptr)
const {
554 assert(UpwardWalkLimit &&
"Need a valid walk limit");
555 bool LimitAlreadyReached =
false;
560 if (!*UpwardWalkLimit) {
561 *UpwardWalkLimit = 1;
562 LimitAlreadyReached =
true;
567 if (Current ==
StopAt || Current == SkipStopAt)
568 return {Current,
false};
574 if (!--*UpwardWalkLimit)
575 return {Current,
true};
577 BatchAACrossIterationScope
_(*AA,
Desc.MayBeCrossIteration);
583 if (LimitAlreadyReached)
584 *UpwardWalkLimit = 0;
587 "Ended at a non-clobber that's not a phi?");
588 return {
Desc.Last,
false};
591 void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
592 ListIndex PriorNode,
bool MayBeCrossIteration) {
593 auto UpwardDefsBegin =
596 for (
const UpwardDefsElem &
E : UpwardDefs) {
605 struct TerminatedPath {
606 MemoryAccess *Clobber;
619 std::optional<TerminatedPath>
620 getBlockingAccess(
const MemoryAccess *StopWhere,
621 SmallVectorImpl<ListIndex> &PausedSearches,
622 SmallVectorImpl<ListIndex> &NewPaused,
623 SmallVectorImpl<TerminatedPath> &Terminated) {
624 assert(!PausedSearches.
empty() &&
"No searches to continue?");
628 while (!PausedSearches.
empty()) {
630 DefPath &
Node = Paths[PathIndex];
650 if (!VisitedPhis.
insert({Node.Last, Node.Loc, Node.MayBeCrossIteration})
654 const MemoryAccess *SkipStopWhere =
nullptr;
655 if (Query->SkipSelfAccess &&
Node.Loc == Query->StartingLoc) {
657 SkipStopWhere = Query->OriginalAccess;
660 UpwardsWalkResult Res = walkToPhiOrClobber(Node,
663 if (Res.IsKnownClobber) {
664 assert(Res.Result != StopWhere && Res.Result != SkipStopWhere);
668 TerminatedPath
Term{Res.Result, PathIndex};
669 if (!MSSA.
dominates(Res.Result, StopWhere))
677 if (Res.Result == StopWhere || Res.Result == SkipStopWhere) {
682 if (Res.Result != SkipStopWhere)
689 Node.MayBeCrossIteration);
695 template <
typename T,
typename Walker>
696 struct generic_def_path_iterator
697 :
public iterator_facade_base<generic_def_path_iterator<T, Walker>,
698 std::forward_iterator_tag, T *> {
699 generic_def_path_iterator() =
default;
700 generic_def_path_iterator(Walker *W, ListIndex
N) :
W(
W),
N(
N) {}
704 generic_def_path_iterator &operator++() {
705 N = curNode().Previous;
709 bool operator==(
const generic_def_path_iterator &O)
const {
710 if (
N.has_value() !=
O.N.has_value())
712 return !
N || *
N == *
O.N;
716 T &curNode()
const {
return W->Paths[*
N]; }
719 std::optional<ListIndex>
N;
722 using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
723 using const_def_path_iterator =
724 generic_def_path_iterator<const DefPath, const ClobberWalker>;
727 return make_range(def_path_iterator(
this, From), def_path_iterator());
731 return make_range(const_def_path_iterator(
this, From),
732 const_def_path_iterator());
737 TerminatedPath PrimaryClobber;
743 ListIndex defPathIndex(
const DefPath &
N)
const {
745 const DefPath *NP = &
N;
747 "Out of bounds DefPath!");
748 return NP - &Paths.
front();
764 OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
765 const MemoryLocation &Loc) {
767 "Reset the optimization state.");
773 auto PriorPathsSize = Paths.
size();
779 addSearches(Phi, PausedSearches, 0,
false);
783 auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
785 auto Dom = Paths.
begin();
786 for (
auto I = std::next(Dom),
E = Paths.
end();
I !=
E; ++
I)
787 if (!MSSA.
dominates(
I->Clobber, Dom->Clobber))
791 std::iter_swap(
Last, Dom);
794 MemoryPhi *Current =
Phi;
797 "liveOnEntry wasn't treated as a clobber?");
799 const auto *
Target = getWalkTarget(Current);
802 assert(
all_of(TerminatedPaths, [&](
const TerminatedPath &
P) {
809 if (std::optional<TerminatedPath> Blocker = getBlockingAccess(
810 Target, PausedSearches, NewPaused, TerminatedPaths)) {
814 auto Iter =
find_if(def_path(Blocker->LastNode), [&](
const DefPath &
N) {
815 return defPathIndex(N) < PriorPathsSize;
817 assert(Iter != def_path_iterator());
819 DefPath &CurNode = *Iter;
820 assert(CurNode.Last == Current);
847 TerminatedPath
Result{CurNode.Last, defPathIndex(CurNode)};
854 if (NewPaused.
empty()) {
855 MoveDominatedPathToEnd(TerminatedPaths);
857 return {
Result, std::move(TerminatedPaths)};
860 MemoryAccess *DefChainEnd =
nullptr;
862 for (ListIndex Paused : NewPaused) {
863 UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
864 if (WR.IsKnownClobber)
868 DefChainEnd = WR.Result;
871 if (!TerminatedPaths.
empty()) {
875 for (
auto *MA :
def_chain(
const_cast<MemoryAccess *
>(Target)))
877 assert(DefChainEnd &&
"Failed to find dominating phi/liveOnEntry");
882 for (
const TerminatedPath &TP : TerminatedPaths) {
885 if (DT.
dominates(ChainBB, TP.Clobber->getBlock()))
892 if (!Clobbers.
empty()) {
893 MoveDominatedPathToEnd(Clobbers);
895 return {
Result, std::move(Clobbers)};
899 [&](ListIndex
I) {
return Paths[
I].Last == DefChainEnd; }));
904 PriorPathsSize = Paths.
size();
905 PausedSearches.
clear();
906 for (ListIndex
I : NewPaused)
907 addSearches(DefChainPhi, PausedSearches,
I,
908 Paths[
I].MayBeCrossIteration);
911 Current = DefChainPhi;
915 void verifyOptResult(
const OptznResult &R)
const {
917 return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
921 void resetPhiOptznState() {
927 ClobberWalker(
const MemorySSA &MSSA, DominatorTree &DT)
928 : MSSA(MSSA), DT(DT) {}
932 MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
933 UpwardsMemoryQuery &Q,
unsigned &UpWalkLimit) {
936 UpwardWalkLimit = &UpWalkLimit;
941 MemoryAccess *Current =
Start;
945 Current = MU->getDefiningAccess();
947 DefPath FirstDesc(Q.StartingLoc, Current, Current,
948 false, std::nullopt);
951 UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
953 if (WalkResult.IsKnownClobber) {
954 Result = WalkResult.Result;
957 Current, Q.StartingLoc);
958 verifyOptResult(OptRes);
959 resetPhiOptznState();
960 Result = OptRes.PrimaryClobber.Clobber;
963#ifdef EXPENSIVE_CHECKS
964 if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
971struct RenamePassData {
973 DomTreeNode::const_iterator ChildIt;
974 MemoryAccess *IncomingVal;
976 RenamePassData(
DomTreeNode *
D, DomTreeNode::const_iterator It,
978 : DTN(
D), ChildIt(It), IncomingVal(
M) {}
980 void swap(RenamePassData &
RHS) {
992 ClobberWalker Walker;
1009 bool UseInvariantGroup =
true);
1027 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false);
1032 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1037 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
false,
false);
1054 MUD->resetOptimized();
1070 return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL,
true);
1075 return Walker->getClobberingMemoryAccessBase(MA,
Loc, BAA, UWL);
1092 MUD->resetOptimized();
1099 bool RenameAllUses) {
1102 auto It = PerBlockAccesses.find(S);
1104 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1108 if (RenameAllUses) {
1109 bool ReplacementDone =
false;
1110 for (
unsigned I = 0,
E = Phi->getNumIncomingValues();
I !=
E; ++
I)
1111 if (Phi->getIncomingBlock(
I) == BB) {
1112 Phi->setIncomingValue(
I, IncomingVal);
1113 ReplacementDone =
true;
1115 (void) ReplacementDone;
1116 assert(ReplacementDone &&
"Incomplete phi during partial rename");
1118 Phi->addIncoming(IncomingVal, BB);
1126 bool RenameAllUses) {
1127 auto It = PerBlockAccesses.find(BB);
1129 if (It != PerBlockAccesses.end()) {
1131 for (MemoryAccess &L : *
Accesses) {
1133 if (MUD->getDefiningAccess() ==
nullptr || RenameAllUses)
1134 MUD->setDefiningAccess(IncomingVal);
1151 bool SkipVisited,
bool RenameAllUses) {
1152 assert(Root &&
"Trying to rename accesses in an unreachable block");
1159 if (SkipVisited && AlreadyVisited)
1162 IncomingVal = renameBlock(Root->
getBlock(), IncomingVal, RenameAllUses);
1163 renameSuccessorPhis(Root->
getBlock(), IncomingVal, RenameAllUses);
1166 while (!WorkStack.
empty()) {
1168 DomTreeNode::const_iterator ChildIt = WorkStack.
back().ChildIt;
1169 IncomingVal = WorkStack.
back().IncomingVal;
1171 if (ChildIt ==
Node->end()) {
1175 ++WorkStack.
back().ChildIt;
1179 AlreadyVisited = !Visited.
insert(BB).second;
1180 if (SkipVisited && AlreadyVisited) {
1187 IncomingVal = &*BlockDefs->rbegin();
1189 IncomingVal = renameBlock(BB, IncomingVal, RenameAllUses);
1190 renameSuccessorPhis(BB, IncomingVal, RenameAllUses);
1199void MemorySSA::markUnreachableAsLiveOnEntry(
BasicBlock *BB) {
1200 assert(!DT->isReachableFromEntry(BB) &&
1201 "Reachable block found while handling unreachable blocks");
1208 if (!DT->isReachableFromEntry(S))
1210 auto It = PerBlockAccesses.find(S);
1212 if (It == PerBlockAccesses.end() || !
isa<MemoryPhi>(It->second->front()))
1216 Phi->addIncoming(LiveOnEntryDef.get(), BB);
1219 auto It = PerBlockAccesses.find(BB);
1220 if (It == PerBlockAccesses.end())
1225 auto Next = std::next(AI);
1229 UseOrDef->setDefiningAccess(LiveOnEntryDef.get());
1237 : DT(DT), F(&Func), LiveOnEntryDef(nullptr), Walker(nullptr),
1238 SkipWalker(nullptr) {
1244 assert(AA &&
"No alias analysis?");
1255 : DT(DT), L(&L), LiveOnEntryDef(nullptr), Walker(nullptr),
1256 SkipWalker(nullptr) {
1262 assert(AA &&
"No alias analysis?");
1266 return *const_cast<BasicBlock *>(BB);
1277 for (
const auto &Pair : PerBlockAccesses)
1283 auto Res = PerBlockAccesses.try_emplace(BB);
1286 Res.first->second = std::make_unique<AccessList>();
1287 return Res.first->second.get();
1291 auto Res = PerBlockDefs.try_emplace(BB);
1294 Res.first->second = std::make_unique<DefsList>();
1295 return Res.first->second.get();
1311 : MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
1317 struct MemlocStackInfo {
1320 unsigned long StackEpoch;
1321 unsigned long PopEpoch;
1326 unsigned long LowerBound;
1329 unsigned long LastKill;
1333 void optimizeUsesInBlock(
const BasicBlock *,
unsigned long &,
unsigned long &,
1338 CachingWalker *Walker;
1357void MemorySSA::OptimizeUses::optimizeUsesInBlock(
1358 const BasicBlock *BB,
unsigned long &StackEpoch,
unsigned long &PopEpoch,
1371 !VersionStack.
empty() &&
1372 "Version stack should have liveOnEntry sentinel dominating everything");
1374 if (DT->dominates(BackBlock, BB))
1376 while (VersionStack.
back()->getBlock() == BackBlock)
1381 for (MemoryAccess &MA : *
Accesses) {
1389 if (MU->isOptimized())
1392 MemoryLocOrCall UseMLOC(MU);
1393 auto &LocInfo = LocStackInfo[UseMLOC];
1397 if (LocInfo.PopEpoch != PopEpoch) {
1398 LocInfo.PopEpoch = PopEpoch;
1399 LocInfo.StackEpoch = StackEpoch;
1411 if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
1412 !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
1416 LocInfo.LowerBound = 0;
1417 LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
1418 LocInfo.LastKillValid =
false;
1420 }
else if (LocInfo.StackEpoch != StackEpoch) {
1424 LocInfo.PopEpoch = PopEpoch;
1425 LocInfo.StackEpoch = StackEpoch;
1427 if (!LocInfo.LastKillValid) {
1428 LocInfo.LastKill = VersionStack.
size() - 1;
1429 LocInfo.LastKillValid =
true;
1434 assert(LocInfo.LowerBound < VersionStack.
size() &&
1435 "Lower bound out of range");
1436 assert(LocInfo.LastKill < VersionStack.
size() &&
1437 "Last kill info out of range");
1439 unsigned long UpperBound = VersionStack.
size() - 1;
1442 LLVM_DEBUG(
dbgs() <<
"MemorySSA skipping optimization of " << *MU <<
" ("
1443 << *(MU->getMemoryInst()) <<
")"
1444 <<
" because there are "
1445 << UpperBound - LocInfo.LowerBound
1446 <<
" stores to disambiguate\n");
1449 LocInfo.LastKillValid =
false;
1452 bool FoundClobberResult =
false;
1454 while (UpperBound > LocInfo.LowerBound) {
1460 Walker->getClobberingMemoryAccessWithoutInvariantGroup(
1461 MU, *AA, UpwardWalkLimit);
1463 while (VersionStack[UpperBound] != Result) {
1467 FoundClobberResult =
true;
1473 FoundClobberResult =
true;
1481 if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
1482 MU->setDefiningAccess(VersionStack[UpperBound],
true);
1483 LocInfo.LastKill = UpperBound;
1487 MU->setDefiningAccess(VersionStack[LocInfo.LastKill],
true);
1489 LocInfo.LowerBound = VersionStack.
size() - 1;
1490 LocInfo.LowerBoundBlock = BB;
1498 VersionStack.
push_back(MSSA->getLiveOnEntryDef());
1500 unsigned long StackEpoch = 1;
1501 unsigned long PopEpoch = 1;
1503 for (
const auto *DomNode :
depth_first(DT->getRootNode()))
1504 optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
1508void MemorySSA::placePHINodes(
1512 IDFs.setDefiningBlocks(DefiningBlocks);
1514 IDFs.calculate(IDFBlocks);
1517 for (
auto &BB : IDFBlocks)
1518 createMemoryPhi(BB);
1521template <
typename IterT>
1522void MemorySSA::buildMemorySSA(
BatchAAResults &BAA, IterT Blocks) {
1531 nullptr, &StartingPoint, NextID++));
1540 bool InsertIntoDef =
false;
1552 InsertIntoDef =
true;
1554 Defs = getOrCreateDefsList(&
B);
1555 Defs->push_back(*MUD);
1561 placePHINodes(DefiningBlocks);
1565 SmallPtrSet<BasicBlock *, 16> Visited;
1572 U.set(LiveOnEntryDef.get());
1578 L->getExitBlocks(ExitBlocks);
1580 renamePass(DT->getNode(L->getLoopPreheader()), LiveOnEntryDef.get(),
1583 renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
1588 for (
auto &BB : Blocks)
1589 if (!Visited.
count(&BB))
1590 markUnreachableAsLiveOnEntry(&BB);
1597 return Walker.get();
1600 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1602 Walker = std::make_unique<CachingWalker>(
this, WalkerBase.get());
1603 return Walker.get();
1608 return SkipWalker.get();
1611 WalkerBase = std::make_unique<ClobberWalkerBase>(
this, DT);
1613 SkipWalker = std::make_unique<SkipSelfWalker>(
this, WalkerBase.get());
1614 return SkipWalker.get();
1624 auto *
Accesses = getOrCreateAccessList(BB);
1630 auto *Defs = getOrCreateDefsList(BB);
1631 Defs->push_front(*NewAccess);
1637 auto *Defs = getOrCreateDefsList(BB);
1640 Defs->insert(DI, *NewAccess);
1646 auto *Defs = getOrCreateDefsList(BB);
1647 Defs->push_back(*NewAccess);
1650 BlockNumberingValid.erase(BB);
1656 bool WasEnd = InsertPt ==
Accesses->end();
1659 auto *Defs = getOrCreateDefsList(BB);
1665 Defs->push_back(*What);
1667 Defs->insert(InsertPt->getDefsIterator(), *What);
1673 Defs->push_back(*What);
1675 Defs->insert(InsertPt->getDefsIterator(), *What);
1678 BlockNumberingValid.erase(BB);
1699 prepareForMoveTo(What, BB);
1707 "Can only move a Phi at the beginning of the block");
1709 ValueToMemoryAccess.erase(What->
getBlock());
1710 bool Inserted = ValueToMemoryAccess.insert({BB, What}).second;
1712 assert(Inserted &&
"Cannot move a Phi to a block that already has one");
1715 prepareForMoveTo(What, BB);
1724 ValueToMemoryAccess[BB] = Phi;
1731 bool CreationMustSucceed) {
1734 if (CreationMustSucceed)
1735 assert(NewAccess !=
nullptr &&
"Tried to create a memory access for a "
1736 "non-memory touching instruction");
1739 "A use cannot be a defining access");
1750 if (!
SI->isUnordered())
1753 if (!LI->isUnordered())
1760template <
typename AliasAnalysisType>
1761MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *
I,
1762 AliasAnalysisType *AAP,
1771 switch (
II->getIntrinsicID()) {
1774 case Intrinsic::allow_runtime_check:
1775 case Intrinsic::allow_ubsan_check:
1776 case Intrinsic::assume:
1777 case Intrinsic::experimental_noalias_scope_decl:
1778 case Intrinsic::pseudoprobe:
1786 if (!
I->mayReadFromMemory() && !
I->mayWriteToMemory())
1795 bool DefCheck, UseCheck;
1800 assert((Def == DefCheck || !DefCheck) &&
1801 "Memory accesses should only be reduced");
1802 if (!Def && Use != UseCheck) {
1804 assert(!UseCheck &&
"Invalid template");
1827 MemoryUseOrDef *MUD;
1829 MUD =
new MemoryDef(
I->getContext(),
nullptr,
I,
I->getParent(), NextID++);
1831 MUD =
new MemoryUse(
I->getContext(),
nullptr,
I,
I->getParent());
1837 ValueToMemoryAccess[
I] = MUD;
1844 "Trying to remove memory access that still has uses");
1845 BlockNumbering.erase(MA);
1858 auto VMA = ValueToMemoryAccess.find(MemoryInst);
1859 if (VMA->second == MA)
1860 ValueToMemoryAccess.
erase(VMA);
1874 auto DefsIt = PerBlockDefs.find(BB);
1875 std::unique_ptr<DefsList> &Defs = DefsIt->second;
1878 PerBlockDefs.erase(DefsIt);
1883 auto AccessIt = PerBlockAccesses.find(BB);
1884 std::unique_ptr<AccessList> &
Accesses = AccessIt->second;
1891 PerBlockAccesses.erase(AccessIt);
1892 BlockNumberingValid.erase(BB);
1897 MemorySSAAnnotatedWriter Writer(
this);
1901 F->
print(OS, &Writer);
1904#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1909#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS)
1921 assert(L &&
"must either have loop or function");
1924 return *const_cast<BasicBlock *>(BB);
1944template <
typename IterT>
1948 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
1949 auto *Pred = Phi->getIncomingBlock(
I);
1950 auto *IncAcc = Phi->getIncomingValue(
I);
1954 if (
auto *DTNode = DT->getNode(Pred)) {
1956 if (
auto *DefList =
getBlockDefs(DTNode->getBlock())) {
1957 auto *LastAcc = &*(--DefList->end());
1958 assert(LastAcc == IncAcc &&
1959 "Incorrect incoming access into phi.");
1964 DTNode = DTNode->getIDom();
1981template <
typename IterT>
1983 if (BlockNumberingValid.empty())
1988 if (!ValidBlocks.
count(&BB))
1991 ValidBlocks.
erase(&BB);
1999 unsigned long LastNumber = 0;
2001 auto ThisNumberIter = BlockNumbering.find(&MA);
2002 assert(ThisNumberIter != BlockNumbering.end() &&
2003 "MemoryAccess has no domination number in a valid block!");
2005 unsigned long ThisNumber = ThisNumberIter->second;
2006 assert(ThisNumber > LastNumber &&
2007 "Domination numbers should be strictly increasing!");
2009 LastNumber = ThisNumber;
2014 "All valid BasicBlocks should exist in F -- dangling pointers?");
2023template <
typename IterT>
2040 for (
const Use &U : Phi->uses()) {
2041 assert(
dominates(Phi, U) &&
"Memory PHI does not dominate it's uses");
2047 "Incomplete MemoryPhi Node");
2048 for (
unsigned I = 0, E = Phi->getNumIncomingValues();
I != E; ++
I) {
2049 verifyUseInDefs(Phi->getIncomingValue(
I), Phi);
2051 "Incoming phi block not a block predecessor");
2059 "We have memory affecting instructions "
2060 "in this block but they are not in the "
2061 "access list or defs list");
2069 for (
const Use &U : MD->
uses()) {
2071 "Memory Def does not dominate it's uses");
2085 assert(AL->size() == ActualAccesses.
size() &&
2086 "We don't have the same number of accesses in the block as on the "
2089 "Either we should have a defs list, or we should have no defs");
2091 "We don't have the same number of defs in the block as on the "
2093 auto ALI = AL->begin();
2094 auto AAI = ActualAccesses.
begin();
2095 while (ALI != AL->end() && AAI != ActualAccesses.
end()) {
2096 assert(&*ALI == *AAI &&
"Not the same accesses in the same order");
2100 ActualAccesses.
clear();
2102 auto DLI =
DL->begin();
2103 auto ADI = ActualDefs.
begin();
2104 while (DLI !=
DL->end() && ADI != ActualDefs.
end()) {
2105 assert(&*DLI == *ADI &&
"Not the same defs in the same order");
2120 "Null def but use not point to live on entry def");
2123 "Did not find use in def's use list");
2132void MemorySSA::renumberBlock(
const BasicBlock *
B)
const {
2134 unsigned long CurrentNumber = 0;
2136 assert(AL !=
nullptr &&
"Asking to renumber an empty block");
2137 for (
const auto &
I : *AL)
2138 BlockNumbering[&
I] = ++CurrentNumber;
2139 BlockNumberingValid.insert(
B);
2150 "Asking for local domination when accesses are in different blocks!");
2152 if (Dominatee == Dominator)
2165 if (!BlockNumberingValid.count(DominatorBlock))
2166 renumberBlock(DominatorBlock);
2168 unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
2170 assert(DominatorNum != 0 &&
"Block was not numbered properly");
2171 unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
2172 assert(DominateeNum != 0 &&
"Block was not numbered properly");
2173 return DominatorNum < DominateeNum;
2178 if (Dominator == Dominatee)
2190 const Use &Dominatee)
const {
2192 BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
2194 if (UseBB != Dominator->
getBlock())
2195 return DT->dominates(Dominator->
getBlock(), UseBB);
2216 case MemoryPhiVal:
return static_cast<const MemoryPhi *
>(
this)->
print(OS);
2217 case MemoryDefVal:
return static_cast<const MemoryDef *
>(
this)->
print(OS);
2218 case MemoryUseVal:
return static_cast<const MemoryUse *
>(
this)->
print(OS);
2227 if (
A &&
A->getID())
2233 OS <<
getID() <<
" = MemoryDef(";
2245 OS <<
getID() <<
" = MemoryPhi(";
2256 if (
unsigned ID = MA->
getID())
2268 if (UO && UO->
getID())
2277#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2286 MemorySSAAnnotatedWriter MSSAWriter;
2290 : F(F), MSSAWriter(&MSSA) {}
2293 MemorySSAAnnotatedWriter &
getWriter() {
return MSSAWriter; }
2301 return &(CFGInfo->
getFunction()->getEntryBlock());
2336 [](std::string &S,
unsigned &
I,
unsigned Idx) ->
void {
2337 std::string Str = S.substr(
I, Idx -
I);
2339 if (SR.
count(
" = MemoryDef(") || SR.
count(
" = MemoryPhi(") ||
2340 SR.
count(
"MemoryUse("))
2360 ?
"style=filled, fillcolor=lightpink"
2367AnalysisKey MemorySSAAnalysis::Key;
2378 FunctionAnalysisManager::Invalidator &Inv) {
2388 if (EnsureOptimizedUses)
2394 OS <<
"MemorySSA for function: " <<
F.getName() <<
"\n";
2404 OS <<
"MemorySSA (walker) for function: " <<
F.getName() <<
"\n";
2405 MemorySSAWalkerAnnotatedWriter Writer(&MSSA);
2406 F.print(OS, &Writer);
2439 MSSA->verifyMemorySSA();
2458 if (
Loc.Ptr ==
nullptr)
2459 return StartingAccess;
2464 return StartingUseOrDef;
2466 I = StartingUseOrDef->getMemoryInst();
2471 return StartingUseOrDef;
2474 UpwardsMemoryQuery Q;
2475 Q.OriginalAccess = StartingAccess;
2476 Q.StartingLoc =
Loc;
2484 Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
2486 dbgs() <<
"Clobber starting at access " << *StartingAccess <<
"\n";
2488 dbgs() <<
" for instruction " << *
I <<
"\n";
2489 dbgs() <<
" is " << *Clobber <<
"\n";
2496 if (!
I.hasMetadata(LLVMContext::MD_invariant_group) ||
I.isVolatile())
2513 for (
const User *Us : PointerOperand->
users()) {
2515 if (!U || U == &
I || !DT.
dominates(U, MostDominatingInstruction))
2521 if (U->hasMetadata(LLVMContext::MD_invariant_group) &&
2523 MostDominatingInstruction = U;
2527 return MostDominatingInstruction == &
I ? nullptr : MostDominatingInstruction;
2531 MemoryAccess *MA, BatchAAResults &BAA,
unsigned &UpwardWalkLimit,
2532 bool SkipSelf,
bool UseInvariantGroup) {
2535 if (!StartingAccess)
2538 if (UseInvariantGroup) {
2540 *StartingAccess->getMemoryInst(), MSSA->
getDomTree())) {
2546 return ClobberMA->getDefiningAccess();
2551 bool IsOptimized =
false;
2556 if (StartingAccess->isOptimized()) {
2558 return StartingAccess->getOptimized();
2562 const Instruction *
I = StartingAccess->getMemoryInst();
2567 return StartingAccess;
2569 UpwardsMemoryQuery Q(
I, StartingAccess);
2573 StartingAccess->setOptimized(LiveOnEntry);
2577 MemoryAccess *OptimizedAccess;
2580 MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
2585 StartingAccess->setOptimized(DefiningAccess);
2586 return DefiningAccess;
2590 Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
2591 StartingAccess->setOptimized(OptimizedAccess);
2593 OptimizedAccess = StartingAccess->getOptimized();
2595 LLVM_DEBUG(
dbgs() <<
"Starting Memory SSA clobber for " << *
I <<
" is ");
2597 LLVM_DEBUG(
dbgs() <<
"Optimized Memory SSA clobber for " << *
I <<
" is ");
2604 Q.SkipSelfAccess =
true;
2605 Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
2607 Result = OptimizedAccess;
2609 LLVM_DEBUG(
dbgs() <<
"Result Memory SSA clobber [SkipSelf = " << SkipSelf);
2619 return Use->getDefiningAccess();
2626 return Use->getDefiningAccess();
2627 return StartingAccess;
2638void MemoryUse::deleteMe(DerivedUser *Self) {
2639 delete static_cast<MemoryUse *
>(Self);
2642bool upward_defs_iterator::IsGuaranteedLoopInvariant(
const Value *Ptr)
const {
2643 auto IsGuaranteedLoopInvariantBase = [](
const Value *Ptr) {
2652 if (
I->getParent()->isEntryBlock())
2656 return IsGuaranteedLoopInvariantBase(
GEP->getPointerOperand()) &&
2657 GEP->hasAllConstantIndices();
2659 return IsGuaranteedLoopInvariantBase(Ptr);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
DXIL Forward Handle Accesses
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
early cse Early CSE w MemorySSA
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file provides utility analysis objects describing memory locations.
static bool instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc, const Instruction *UseInst, AliasAnalysisType &AA)
Memory static true cl::opt< unsigned > MaxCheckLimit("memssa-check-limit", cl::Hidden, cl::init(100), cl::desc("The maximum number of stores/phis MemorySSA" "will consider trying to walk past (default = 100)"))
static void checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt, const MemoryLocation &StartLoc, const MemorySSA &MSSA, const UpwardsMemoryQuery &Query, BatchAAResults &AA, bool AllowImpreciseClobber=false)
Verifies that Start is clobbered by ClobberAt, and that nothing inbetween Start and ClobberAt can clo...
static cl::opt< bool, true > VerifyMemorySSAX("verify-memoryssa", cl::location(VerifyMemorySSA), cl::Hidden, cl::desc("Enable verification of MemorySSA."))
static const char LiveOnEntryStr[]
static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA, const Instruction *I)
static bool areLoadsReorderable(const LoadInst *Use, const LoadInst *MayClobber)
This does one-way checks to see if Use could theoretically be hoisted above MayClobber.
static const Instruction * getInvariantGroupClobberingInstruction(Instruction &I, DominatorTree &DT)
static cl::opt< std::string > DotCFGMSSA("dot-cfg-mssa", cl::value_desc("file name for generated dot file"), cl::desc("file name for generated dot file"), cl::init(""))
static bool isOrdered(const Instruction *I)
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
DOTFuncMSSAInfo(const Function &F, MemorySSA &MSSA)
const Function * getFunction()
MemorySSAAnnotatedWriter & getWriter()
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
LLVM Basic Block Representation.
LLVM_ABI BasicBlock::iterator erase(BasicBlock::iterator FromIt, BasicBlock::iterator ToIt)
Erases a range of instructions from FromIt to (not including) ToIt.
iterator begin()
Instruction iterator methods.
LLVM_ABI void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW=nullptr, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the basic block to an output stream with an optional AssemblyAnnotationWriter.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
Temporarily set the cross iteration mode on a BatchAA instance.
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getCalledOperand() const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
Implements a dense probed hash-table based set.
Extension point for the Value hierarchy.
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *, BatchAAResults &) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Module * getParent()
Get the module that this global value is contained inside of...
A wrapper class for inspecting calls to intrinsic functions.
A helper class to return the specified delimiter string after the first invocation of operator String...
An instruction for reading from memory.
bool isVolatile() const
Return true if this is a load from a volatile memory location.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Represents a single loop in the control flow graph.
LLVM_ABI void dump() const
MemoryAccess(const MemoryAccess &)=delete
BasicBlock * getBlock() const
LLVM_ABI void print(raw_ostream &OS) const
unsigned getID() const
Used for debugging and tracking things about MemoryAccesses.
void setBlock(BasicBlock *BB)
Used by MemorySSA to change the block of a MemoryAccess when it is moved.
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
LLVM_ABI void print(raw_ostream &OS) const
MemoryAccess * getOptimized() const
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
Represents phi nodes for memory accesses.
BasicBlock * getIncomingBlock(unsigned I) const
Return incoming basic block number i.
LLVM_ABI void print(raw_ostream &OS) const
An analysis that produces MemorySSA for a function.
LLVM_ABI Result run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static LLVM_ABI bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU, AliasAnalysis &AA)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This is the generic walker interface for walkers of MemorySSA.
MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)
Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...
LLVM_ABI MemorySSAWalker(MemorySSA *)
virtual void invalidateInfo(MemoryAccess *)
Given a memory access, invalidate anything this walker knows about that access.
Legacy analysis pass which computes MemorySSA.
void verifyAnalysis() const override
verifyAnalysis() - This member can be implemented by a analysis pass to check state of analysis infor...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
bool runOnFunction(Function &) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void print(raw_ostream &OS, const Module *M=nullptr) const override
print - Print out the internal state of the pass.
A MemorySSAWalker that does AA walks to disambiguate accesses.
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
MemoryAccess * getClobberingMemoryAccessWithoutInvariantGroup(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA, unsigned &UWL)
void invalidateInfo(MemoryAccess *MA) override
Given a memory access, invalidate anything this walker knows about that access.
~CachingWalker() override=default
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
CachingWalker(MemorySSA *M, ClobberWalkerBase *W)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA) override
Given a potentially clobbering memory access and a new location, calling this will give you the neare...
ClobberWalkerBase(MemorySSA *M, DominatorTree *D)
MemoryAccess * getClobberingMemoryAccessBase(MemoryAccess *, BatchAAResults &, unsigned &, bool, bool UseInvariantGroup=true)
MemoryAccess * getClobberingMemoryAccessBase(MemoryAccess *, const MemoryLocation &, BatchAAResults &, unsigned &)
This class is a batch walker of all MemoryUse's in the program, and points their defining access at t...
void optimizeUses()
Optimize uses to point to their actual clobbering definitions.
OptimizeUses(MemorySSA *MSSA, CachingWalker *Walker, BatchAAResults *BAA, DominatorTree *DT)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA) override
Given a potentially clobbering memory access and a new location, calling this will give you the neare...
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, BatchAAResults &BAA, unsigned &UWL)
~SkipSelfWalker() override=default
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL)
SkipSelfWalker(MemorySSA *M, ClobberWalkerBase *W)
MemoryAccess * getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA) override
Does the same thing as getClobberingMemoryAccess(const Instruction *I), but takes a MemoryAccess inst...
void invalidateInfo(MemoryAccess *MA) override
Given a memory access, invalidate anything this walker knows about that access.
Encapsulates MemorySSA, including all data associated with memory accesses.
LLVM_ABI void dump() const
simple_ilist< MemoryAccess, ilist_tag< MSSAHelpers::DefsOnlyTag > > DefsList
LLVM_ABI void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where)
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal, SmallPtrSetImpl< BasicBlock * > &Visited)
DefsList * getBlockDefs(const BasicBlock *BB) const
Return the list of MemoryDef's and MemoryPhi's for a given basic block.
LLVM_ABI MemorySSAWalker * getSkipSelfWalker()
LLVM_ABI MemorySSA(Function &, AliasAnalysis *, DominatorTree *)
iplist< MemoryAccess, ilist_tag< MSSAHelpers::AllAccessTag > > AccessList
AccessList * getBlockAccesses(const BasicBlock *BB) const
Return the list of MemoryAccess's for a given basic block.
LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
void verifyOrderingDominationAndDefUses(IterT Blocks, VerificationLevel=VerificationLevel::Fast) const
Verify ordering: the order and existence of MemoryAccesses matches the order and existence of memory ...
LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
LLVM_ABI void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *, InsertionPlace)
LLVM_ABI MemorySSAWalker * getWalker()
InsertionPlace
Used in various insertion functions to specify whether we are talking about the beginning or end of a...
LLVM_ABI void insertIntoListsBefore(MemoryAccess *, const BasicBlock *, AccessList::iterator)
LLVM_ABI MemoryUseOrDef * createDefinedAccess(Instruction *, MemoryAccess *, const MemoryUseOrDef *Template=nullptr, bool CreationMustSucceed=true)
DominatorTree & getDomTree() const
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
MemoryAccess * getLiveOnEntryDef() const
LLVM_ABI void removeFromLookups(MemoryAccess *)
Properly remove MA from all of MemorySSA's lookup tables.
LLVM_ABI void ensureOptimizedUses()
By default, uses are not optimized during MemorySSA construction.
void verifyDominationNumbers(IterT Blocks) const
Verify that all of the blocks we believe to have valid domination numbers actually have valid dominat...
void verifyPrevDefInPhis(IterT Blocks) const
LLVM_ABI bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...
LLVM_ABI void removeFromLists(MemoryAccess *, bool ShouldDelete=true)
Properly remove MA from all of MemorySSA's lists.
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
LLVM_ABI void print(raw_ostream &) const
Class that has the common methods + fields of memory uses/defs.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
void setDefiningAccess(MemoryAccess *DMA, bool Optimized=false)
void setOptimized(MemoryAccess *)
Sets the optimized use for a MemoryDef.
Instruction * getMemoryInst() const
Get the instruction that this MemoryUse represents.
LLVM_ABI void print(raw_ostream &OS) const
A Module instance is used to store all the information related to an LLVM module.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the module to an output stream with an optional AssemblyAnnotationWriter.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
size_t count(char C) const
Return the number of occurrences of C in the string.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
void dropAllReferences()
Drop all references to operands.
unsigned getNumOperands() const
LLVM Value Representation.
iterator_range< user_iterator > users()
unsigned getValueID() const
Return an ID for the concrete type of this object.
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
An opaque object representing a hash code.
typename base_list_type::iterator iterator
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
reverse_iterator rbegin()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
This namespace contains all of the command line option processing machinery.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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()
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)