35 #ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H
36 #define LLVM_ANALYSIS_LAZYCALLGRAPH_H
57 class PreservedAnalyses;
151 explicit operator bool()
const;
188 void setKind(
Kind K) {
Value.setInt(K); }
230 void removeEdgeInternal(
Function &ChildF);
234 EdgeIndexMap.clear();
257 assert(EdgeIndexMap.find(&F) != EdgeIndexMap.end() &&
"No such edge!");
258 return Edges[EdgeIndexMap.find(&F)->second];
263 auto EI = EdgeIndexMap.find(&F);
264 return EI != EdgeIndexMap.end() ? &Edges[EI->second] :
nullptr;
291 std::forward_iterator_tag> {
301 while (
I != E && !*
I)
308 using iterator_adaptor_base::operator++;
312 }
while (
I != E && !*
I);
323 EdgeVectorImplT::iterator,
324 std::forward_iterator_tag> {
331 void advanceToNextEdge() {
332 while (
I !=
E && (!*
I || !
I->isCall()))
346 using iterator_adaptor_base::operator++;
372 template <
typename NodeRangeT>
373 SCC(
RefSCC &OuterRefSCC, NodeRangeT &&Nodes)
374 : OuterRefSCC(&OuterRefSCC), Nodes(std::forward<NodeRangeT>(Nodes)) {}
377 OuterRefSCC =
nullptr;
396 OS <<
"..., " << *C.Nodes.back();
425 int size()
const {
return Nodes.size(); }
519 OS <<
"..., " << *RC.SCCs.back();
547 void handleTrivialEdgeInsertion(
Node &SourceN,
Node &TargetN);
558 ssize_t
size()
const {
return SCCs.size(); }
563 return SCCs.begin() + SCCIndices.find(&C)->second;
581 return Parents.count(const_cast<RefSCC *>(&C));
807 std::forward_iterator_tag, RefSCC> {
822 : G(&G), RC(nullptr) {}
827 if (Index == (
int)G.PostOrderRefSCCs.size())
828 if (!G.buildNextRefSCCInPostOrder())
832 assert(Index < (
int)G.PostOrderRefSCCs.size() &&
833 "Built the next post-order RefSCC without growing list!");
834 return G.PostOrderRefSCCs[Index];
839 return G == Arg.G && RC == Arg.RC;
844 using iterator_facade_base::operator++;
846 assert(RC &&
"Cannot increment the end iterator!");
847 RC = getRC(*G, G->RefSCCIndices.find(RC)->second + 1);
874 postorder_ref_scc_iterator::IsAtEndT());
896 return &
C->getOuterRefSCC();
908 return insertInto(
F, N);
976 template <
typename CallbackT>
979 CallbackT Callback) {
980 while (!Worklist.
empty()) {
983 if (
Function *
F = dyn_cast<Function>(C)) {
984 if (!
F->isDeclaration())
993 if (Visited.
insert(BA->getFunction()).second)
999 if (Visited.
insert(cast<Constant>(
Op)).second)
1062 Node &insertInto(
Function &
F, Node *&MappedN);
1065 void updateGraphPtrs();
1070 template <
typename... Ts> SCC *createSCC(Ts &&...
Args) {
1071 return new (SCCBPA.Allocate()) SCC(std::forward<Ts>(
Args)...);
1077 template <
typename... Ts> RefSCC *createRefSCC(Ts &&...
Args) {
1078 return new (RefSCCBPA.Allocate()) RefSCC(std::forward<Ts>(
Args)...);
1082 void buildSCCs(RefSCC &RC, node_stack_range Nodes);
1088 void connectRefSCC(RefSCC &RC);
1094 int getRefSCCIndex(RefSCC &RC) {
1095 auto IndexIt = RefSCCIndices.find(&RC);
1096 assert(IndexIt != RefSCCIndices.end() &&
"RefSCC doesn't have an index!");
1097 assert(PostOrderRefSCCs[IndexIt->second] == &RC &&
1098 "Index does not point back at RC!");
1099 return IndexIt->second;
1107 bool buildNextRefSCCInPostOrder();
1114 inline LazyCallGraph::Edge::operator
bool()
const {
1115 return !
Value.getPointer().isNull();
1119 assert(*
this &&
"Queried a null edge!");
1120 return Value.getInt();
1124 assert(*
this &&
"Queried a null edge!");
1125 return getKind() ==
Call;
1129 assert(*
this &&
"Queried a null edge!");
1130 auto P =
Value.getPointer();
1134 return P.get<
Node *>()->getFunction();
1138 assert(*
this &&
"Queried a null edge!");
1139 auto P =
Value.getPointer();
1140 if (
auto *
N =
P.dyn_cast<
Node *>())
1147 assert(*
this &&
"Queried a null edge!");
1148 auto P =
Value.getPointer();
1149 if (
auto *
N =
P.dyn_cast<
Node *>())
1153 Value.setPointer(&N);
SuperClass::iterator iterator
EdgeVectorImplT::iterator I
std::reverse_iterator< iterator > reverse_iterator
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
void push_back(const T &Elt)
pointee_iterator< SmallPtrSetImpl< RefSCC * >::const_iterator > parent_iterator
bool isChildOf(const RefSCC &C) const
Test if this RefSCC is a child of C.
Kind getKind() const
Returnss the Kind of the edge.
void removeOutgoingEdge(Node &SourceN, Node &TargetN)
Remove an edge whose source is in this RefSCC and target is not.
bool isDescendantOf(const SCC &C) const
Test if this SCC is a descendant of C.
const Edge & operator[](Function &F) const
A Module instance is used to store all the information related to an LLVM module. ...
friend raw_ostream & operator<<(raw_ostream &OS, const RefSCC &RC)
Print a short description useful for debugging or logging.
Kind
The kind of edge in the graph.
Function & getFunction() const
Get the function referenced by this edge.
pointee_iterator< SmallVectorImpl< Node * >::const_iterator > iterator
SmallVectorImpl< Edge > EdgeVectorImplT
static NodeRef getEntryNode(NodeRef N)
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
A pass which prints the call graph as a DOT file to a raw_ostream.
iterator_range< iterator > range
static void dump(StringRef Title, SpillInfo const &Spills)
std::string getName() const
Provide a short name by printing this RefSCC to a std::string.
parent_iterator parent_end() const
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
edge_iterator begin() const
pointee_iterator< SmallVectorImpl< SCC * >::const_iterator > iterator
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
StringRef getName() const
Return a constant reference to the value's name.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
friend raw_ostream & operator<<(raw_ostream &OS, const Node &N)
Print the name of this node's function.
The address of a basic block.
SmallVector< SCC *, 1 > switchInternalEdgeToCall(Node &SourceN, Node &TargetN)
Make an existing internal ref edge into a call edge.
LazyCallGraph run(Module &M, ModuleAnalysisManager &)
Compute the LazyCallGraph for the module M.
bool isAncestorOf(const SCC &C) const
Test if this SCC is an ancestor of C.
postorder_ref_scc_iterator postorder_ref_scc_begin()
void insertEdge(Function &Caller, Function &Callee, Edge::Kind EK)
Update the call graph after inserting a new edge.
bool isParentOf(const RefSCC &C) const
Test if this RefSCC is a parent of C.
bool isDescendantOf(const RefSCC &C) const
Test if this RefSCC is a descendant of C.
LLVM_NODISCARD bool empty() const
edge_iterator end() const
static ChildIteratorType child_begin(NodeRef N)
A RefSCC of the call graph.
bool isCall() const
Test whether the edge represents a direct call to a function.
void insertTrivialCallEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new call edge...
A CRTP mix-in to automatically provide informational APIs needed for passes.
edge_iterator & operator++()
A lazily constructed view of the call graph of a module.
iterator_range< parent_iterator > parents() const
LazyCallGraph & operator=(LazyCallGraph &&RHS)
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
void removeEdge(Node &Caller, Function &Callee)
Update the call graph after deleting an edge.
LazyCallGraph::edge_iterator ChildIteratorType
void switchOutgoingEdgeToCall(Node &SourceN, Node &TargetN)
Make an existing outgoing ref edge into a call edge.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
std::string getName() const
Provide a short name by printing this SCC to a std::string.
friend raw_ostream & operator<<(raw_ostream &OS, const SCC &C)
Print a short descrtiption useful for debugging or logging.
void insertEdge(Node &Caller, Function &Callee, Edge::Kind EK)
Update the call graph after inserting a new edge.
A set of analyses that are preserved following a run of a transformation pass.
parent_iterator parent_begin() const
PointerIntPair - This class implements a pair of a pointer and small integer.
CRTP base class for adapting an iterator to a different type.
This is an important base class in LLVM.
call_edge_iterator & operator++()
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
void switchOutgoingEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing outgoing call edge into a ref edge.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
reference operator*() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
A CRTP mix-in that provides informational APIs needed for analysis passes.
void insertInternalRefEdge(Node &SourceN, Node &TargetN)
Insert a ref edge from one node in this RefSCC to another in this RefSCC.
SmallVector< RefSCC *, 1 > removeInternalRefEdge(Node &SourceN, Node &TargetN)
Remove a ref edge which is entirely within this RefSCC.
SmallVector< RefSCC *, 1 > insertIncomingRefEdge(Node &SourceN, Node &TargetN)
Insert an edge whose source is in a descendant RefSCC and target is in this RefSCC.
RefSCC & getOuterRefSCC() const
A node in the call graph.
SCC & operator[](int Idx)
A class used to represent edges in the call graph.
Node * getNode() const
Get the call graph node referenced by this edge if one exists.
A lazy iterator used for both the entry nodes and child nodes.
bool operator==(const Node &N) const
Equality is defined as address equality.
LazyCallGraph Result
Inform generic clients of the result type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Function & getFunction() const
void removeEdge(Function &Caller, Function &Callee)
Update the call graph after deleting an edge.
postorder_ref_scc_iterator & operator++()
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void removeDeadFunction(Function &F)
Remove a dead function from the call graph (typically to delete it).
iterator find(SCC &C) const
Module.h This file contains the declarations for the Module class.
An iterator type that allows iterating over the pointees via some other iterator. ...
SmallVector< Edge, 4 > EdgeVectorT
const Edge & operator[](int i) const
LLVM_NODISCARD T pop_back_val()
LazyCallGraph & getGraph() const
bool isAncestorOf(const RefSCC &C) const
Test if this RefSCC is an ancestor of C.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
LazyCallGraph::Node * NodeRef
A range adaptor for a pair of iterators.
LazyCallGraph::edge_iterator ChildIteratorType
const Edge * lookup(Function &F) const
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.
static void visitReferences(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, CallbackT Callback)
Recursively visits the defined functions whose address is reachable from every constant in the Workli...
static void clear(coro::Shape &Shape)
void switchTrivialInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge between separate SCCs into a ref edge.
iterator_range< iterator > switchInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge within a single SCC into a ref edge.
A post-order depth-first RefSCC iterator over the call graph.
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
const Edge & operator[](Node &N) const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
static NodeRef getEntryNode(NodeRef N)
A pass which prints the call graph to a raw_ostream.
call_edge_iterator call_end() const
bool operator!=(const Node &N) const
iterator_range< value_op_iterator > operand_values()
static ChildIteratorType child_end(NodeRef N)
An analysis pass which computes the call graph for a module.
bool isChildOf(const SCC &C) const
Test if this SCC is a child of C.
void insertTrivialRefEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new ref edge...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A lazy iterator over specifically call edges.
A raw_ostream that writes to an std::string.
LLVM Value Representation.
LazyCallGraph::Node * NodeRef
An SCC of the call graph.
friend class LazyCallGraph
This class implements an extremely fast bulk output stream that can only output to a stream...
A container for analyses that lazily runs them and caches their results.
bool isParentOf(const SCC &C) const
Test if this SCC is a parent of C.
RefSCC * lookupRefSCC(Node &N) const
Lookup a function's RefSCC in the graph.
This header defines various interfaces for pass management in LLVM.
postorder_ref_scc_iterator postorder_ref_scc_end()
bool operator==(const postorder_ref_scc_iterator &Arg) const
LazyCallGraph(Module &M)
Construct a graph for the given module.
static ChildIteratorType child_begin(NodeRef N)
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
A special type used by analysis passes to provide an address that identifies that particular analysis...
call_edge_iterator call_begin() const
static ChildIteratorType child_end(NodeRef N)
iterator_range< call_edge_iterator > calls() const