34#ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H
35#define LLVM_ANALYSIS_LAZYCALLGRAPH_H
60template <
class GraphType>
struct GraphTraits;
141 explicit operator bool()
const;
167 void setKind(
Kind K) {
Value.setInt(K); }
192 std::forward_iterator_tag> {
201 while (
I !=
E && !*
I)
208 using iterator_adaptor_base::operator++;
212 }
while (
I !=
E && !*
I);
223 std::forward_iterator_tag> {
230 void advanceToNextEdge() {
231 while (
I !=
E && (!*
I || !
I->isCall()))
244 using iterator_adaptor_base::operator++;
256 assert(EdgeIndexMap.contains(&
N) &&
"No such edge!");
257 auto &
E = Edges[EdgeIndexMap.find(&
N)->second];
258 assert(
E &&
"Dead or null edge!");
263 auto EI = EdgeIndexMap.find(&
N);
264 if (EI == EdgeIndexMap.end())
266 auto &
E = Edges[EI->second];
267 return E ? &
E :
nullptr;
280 for (
auto &
E : Edges)
294 void insertEdgeInternal(
Node &ChildN, Edge::Kind EK);
297 void setEdgeKind(
Node &ChildN, Edge::Kind EK);
300 bool removeEdgeInternal(
Node &ChildN);
338 "Both graph and function pointers should be null or non-null.");
366 return populateSlow();
379 std::optional<EdgeSequence> Edges;
386 LLVM_ABI EdgeSequence &populateSlow();
393 void replaceFunction(
Function &NewF);
395 void clear() { Edges.reset(); }
399 return OS <<
N.F->getName();
424 template <
typename NodeRangeT>
425 SCC(
RefSCC &OuterRefSCC, NodeRangeT &&Nodes)
426 : OuterRefSCC(&OuterRefSCC), Nodes(
std::forward<NodeRangeT>(Nodes)) {}
429 OuterRefSCC =
nullptr;
448 OS <<
"..., " << *
C.Nodes.back();
461#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
486 bool isParentOf(
const SCC &
C)
const;
494 bool isAncestorOf(
const SCC &
C)
const;
578 OS <<
"..., " << *RC.SCCs.back();
591#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
618 return SCCs.
begin() + SCCIndices.
find(&
C)->second;
880 std::forward_iterator_tag, RefSCC> {
892 incrementUntilNonEmptyRefSCC();
901 if (
Index == (
int)
G.PostOrderRefSCCs.size())
905 return G.PostOrderRefSCCs[
Index];
909 void incrementUntilNonEmptyRefSCC() {
910 while (RC && RC->
size() == 0)
915 assert(RC &&
"Cannot increment the end iterator!");
916 RC = getRC(*G,
G->RefSCCIndices.find(RC)->second + 1);
921 return G == Arg.G && RC == Arg.RC;
926 using iterator_facade_base::operator++;
929 incrementUntilNonEmptyRefSCC();
945#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
959 if (!EntryEdges.
empty())
960 assert(!PostOrderRefSCCs.empty() &&
961 "Must form RefSCCs before iterating them!");
965 if (!EntryEdges.
empty())
966 assert(!PostOrderRefSCCs.empty() &&
967 "Must form RefSCCs before iterating them!");
969 postorder_ref_scc_iterator::IsAtEndT());
991 return &
C->getOuterRefSCC();
1003 return insertInto(
F,
N);
1011 return LibFunctions.getArrayRef();
1133 EdgeSequence EntryEdges;
1168 void updateGraphPtrs();
1173 template <
typename... Ts> SCC *createSCC(Ts &&...Args) {
1174 return new (SCCBPA.
Allocate()) SCC(std::forward<Ts>(Args)...);
1180 template <
typename... Ts> RefSCC *createRefSCC(Ts &&...Args) {
1181 return new (RefSCCBPA.
Allocate()) RefSCC(std::forward<Ts>(Args)...);
1195 template <
typename RootsT,
typename GetBeginT,
typename GetEndT,
1196 typename GetNodeT,
typename FormSCCCallbackT>
1197 static void buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
1198 GetEndT &&GetEnd, GetNodeT &&GetNode,
1199 FormSCCCallbackT &&FormSCC);
1202 void buildSCCs(RefSCC &RC, node_stack_range Nodes);
1208 int getRefSCCIndex(RefSCC &RC) {
1209 auto IndexIt = RefSCCIndices.
find(&RC);
1210 assert(IndexIt != RefSCCIndices.
end() &&
"RefSCC doesn't have an index!");
1211 assert(PostOrderRefSCCs[IndexIt->second] == &RC &&
1212 "Index does not point back at RC!");
1213 return IndexIt->second;
1217inline LazyCallGraph::Edge::Edge() =
default;
1220inline LazyCallGraph::Edge::operator
bool()
const {
1221 return Value.getPointer() && !
Value.getPointer()->isDead();
1224inline LazyCallGraph::Edge::Kind LazyCallGraph::Edge::getKind()
const {
1225 assert(*
this &&
"Queried a null edge!");
1226 return Value.getInt();
1229inline bool LazyCallGraph::Edge::isCall()
const {
1230 assert(*
this &&
"Queried a null edge!");
1231 return getKind() == Call;
1235 assert(*
this &&
"Queried a null edge!");
1236 return *
Value.getPointer();
1239inline Function &LazyCallGraph::Edge::getFunction()
const {
1240 assert(*
this &&
"Queried a null edge!");
1241 return getNode().getFunction();
1317 Any::TypeId<const LazyCallGraph::SCC *>;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file defines the BumpPtrAllocator interface.
This file provides Any, a non-template class modeled in the spirit of std::any.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_TEMPLATE_ABI
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
FunctionAnalysisManager FAM
This file defines the PointerIntPair class.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
An analysis pass which computes the call graph for a module.
LazyCallGraph run(Module &M, ModuleAnalysisManager &AM)
Compute the LazyCallGraph for the module M.
A pass which prints the call graph as a DOT file to a raw_ostream.
A pass which prints the call graph to a raw_ostream.
An iterator over specifically call edges.
call_iterator & operator++()
An iterator used for the edges to both entry nodes and child nodes.
The edge sequence object.
Edge & operator[](Node &N)
call_iterator call_begin()
iterator_range< call_iterator > calls()
A class used to represent edges in the call graph.
Function & getFunction() const
Get the function referenced by this edge.
bool isCall() const
Test whether the edge represents a direct call to a function.
Kind
The kind of edge in the graph.
Kind getKind() const
Returns the Kind of the edge.
Node & getNode() const
Get the call graph node referenced by this edge.
A node in the call graph.
LazyCallGraph & getGraph() const
EdgeSequence & populate()
Populate the edges of this node if necessary.
bool isDead() const
Tests whether this is actually a dead node and no longer valid.
bool operator!=(const Node &N) const
bool isPopulated() const
Tests whether the node has been populated with edges.
bool operator==(const Node &N) const
Equality is defined as address equality.
friend raw_ostream & operator<<(raw_ostream &OS, const Node &N)
Print the name of this node's function.
EdgeSequence * operator->() const
StringRef getName() const
EdgeSequence & operator*() const
Function & getFunction() const
A RefSCC of the call graph.
LLVM_ABI SmallVector< RefSCC *, 1 > insertIncomingRefEdge(Node &SourceN, Node &TargetN)
Insert an edge whose source is in a descendant RefSCC and target is in this RefSCC.
LLVM_ABI bool switchInternalEdgeToCall(Node &SourceN, Node &TargetN, function_ref< void(ArrayRef< SCC * > MergedSCCs)> MergeCB={})
Make an existing internal ref edge into a call edge.
LLVM_ABI bool isAncestorOf(const RefSCC &RC) const
Test if this RefSCC is an ancestor of RC.
LLVM_ABI void insertTrivialRefEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new ref edge.
iterator find(SCC &C) const
SCC & operator[](int Idx)
bool isDescendantOf(const RefSCC &RC) const
Test if this RefSCC is a descendant of RC.
bool isChildOf(const RefSCC &RC) const
Test if this RefSCC is a child of RC.
LLVM_ABI void switchOutgoingEdgeToCall(Node &SourceN, Node &TargetN)
Make an existing outgoing ref edge into a call edge.
LLVM_ABI void replaceNodeFunction(Node &N, Function &NewF)
Directly replace a node's function with a new function.
LLVM_ABI void insertOutgoingEdge(Node &SourceN, Node &TargetN, Edge::Kind EK)
Insert an edge whose parent is in this RefSCC and child is in some child RefSCC.
LLVM_ABI SmallVector< RefSCC *, 1 > removeInternalRefEdges(ArrayRef< std::pair< Node *, Node * > > Edges)
Remove a list of ref edges which are entirely within this RefSCC.
LLVM_ABI iterator_range< iterator > switchInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge within a single SCC into a ref edge.
LLVM_ABI void insertInternalRefEdge(Node &SourceN, Node &TargetN)
Insert a ref edge from one node in this RefSCC to another in this RefSCC.
LLVM_ABI void insertTrivialCallEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new call edge.
LLVM_ABI void removeOutgoingEdge(Node &SourceN, Node &TargetN)
Remove an edge whose source is in this RefSCC and target is not.
std::string getName() const
Provide a short name by printing this RefSCC to a std::string.
LLVM_ABI void switchOutgoingEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing outgoing call edge into a ref edge.
friend raw_ostream & operator<<(raw_ostream &OS, const RefSCC &RC)
Print a short description useful for debugging or logging.
LLVM_ABI void switchTrivialInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge between separate SCCs into a ref edge.
LLVM_ABI bool isParentOf(const RefSCC &RC) const
Test if this RefSCC is a parent of RC.
An SCC of the call graph.
bool isChildOf(const SCC &C) const
Test if this SCC is a child of C.
friend raw_ostream & operator<<(raw_ostream &OS, const SCC &C)
Print a short description useful for debugging or logging.
bool isDescendantOf(const SCC &C) const
Test if this SCC is a descendant of C.
std::string getName() const
Provide a short name by printing this SCC to a std::string.
RefSCC & getOuterRefSCC() const
A post-order depth-first RefSCC iterator over the call graph.
reference operator*() const
friend class LazyCallGraph
postorder_ref_scc_iterator & operator++()
bool operator==(const postorder_ref_scc_iterator &Arg) const
A lazily constructed view of the call graph of a module.
bool isLibFunction(Function &F) const
Test whether a function is a known and defined library function tracked by the call graph.
EdgeSequence::iterator begin()
RefSCC * lookupRefSCC(Node &N) const
Lookup a function's RefSCC in the graph.
LLVM_ABI void insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK)
Update the call graph after inserting a new edge.
LLVM_ABI void buildRefSCCs()
static LLVM_ABI void visitReferences(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, function_ref< void(Function &)> Callback)
Recursively visits the defined functions whose address is reachable from every constant in the Workli...
LLVM_ABI void markDeadFunction(Function &F)
Mark a function as dead to be removed later by removeDeadFunctions().
LLVM_ABI void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
LLVM_ABI void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
LLVM_ABI void removeDeadFunctions(ArrayRef< Function * > DeadFs)
Remove dead functions from the call graph.
postorder_ref_scc_iterator postorder_ref_scc_begin()
ArrayRef< Function * > getLibFunctions() const
Get the sequence of known and defined library functions.
postorder_ref_scc_iterator postorder_ref_scc_end()
LLVM_ABI void removeEdge(Node &SourceN, Node &TargetN)
Update the call graph after deleting an edge.
void removeEdge(Function &Source, Function &Target)
Update the call graph after deleting an edge.
void insertEdge(Function &Source, Function &Target, Edge::Kind EK)
Update the call graph after inserting a new edge.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
LLVM_ABI LazyCallGraph & operator=(LazyCallGraph &&RHS)
LLVM_ABI bool invalidate(Module &, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &)
void verify()
Verify that every RefSCC is valid.
EdgeSequence::iterator end()
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
A Module instance is used to store all the information related to an LLVM module.
PointerIntPair - This class implements a pair of a pointer and small integer.
A set of analyses that are preserved following a run of a transformation pass.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
A SetVector that performs no allocations if smaller than a certain size.
typename SuperClass::iterator iterator
std::reverse_iterator< iterator > reverse_iterator
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Target - Wrapper for Target specific information.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
CRTP base class for adapting an iterator to a different type.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
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.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Implement std::hash so that hash_code can be used in STL containers.
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
static ChildIteratorType child_begin(NodeRef N)
static ChildIteratorType child_end(NodeRef N)
static NodeRef getEntryNode(NodeRef N)
static NodeRef getEntryNode(NodeRef N)
static ChildIteratorType child_end(NodeRef N)
static ChildIteratorType child_begin(NodeRef N)
A CRTP mix-in to automatically provide informational APIs needed for passes.
An iterator type that allows iterating over the pointees via some other iterator.