MLIR 23.0.0git
CallGraph.h
Go to the documentation of this file.
1//===- CallGraph.h - CallGraph analysis for MLIR ----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains an analysis for computing the multi-level callgraph from a
10// given top-level operation. This nodes within this callgraph are defined by
11// the `CallOpInterface` and `CallableOpInterface` operation interfaces defined
12// in CallInterface.td.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef MLIR_ANALYSIS_CALLGRAPH_H
17#define MLIR_ANALYSIS_CALLGRAPH_H
18
19#include "mlir/Support/LLVM.h"
20#include "llvm/ADT/GraphTraits.h"
21#include "llvm/ADT/MapVector.h"
22#include "llvm/ADT/PointerIntPair.h"
23#include "llvm/ADT/SetVector.h"
24
25namespace mlir {
26class CallOpInterface;
28class Operation;
29class Region;
31
32//===----------------------------------------------------------------------===//
33// CallGraphNode
34//===----------------------------------------------------------------------===//
35
36/// This class represents a single callable in the callgraph. Aside from the
37/// external node, each node represents a callable node in the graph and
38/// contains a valid corresponding Region. The external node is a virtual node
39/// used to represent external edges into, and out of, the callgraph.
40class CallGraphNode {
41public:
42 /// This class represents a directed edge between two nodes in the callgraph.
43 class Edge {
44 enum class Kind {
45 // An 'Abstract' edge represents an opaque, non-operation, reference
46 // between this node and the target. Edges of this type are only valid
47 // from the external node, as there is no valid connection to an operation
48 // in the module.
49 Abstract,
50
51 // A 'Call' edge represents a direct reference to the target node via a
52 // call-like operation within the callable region of this node.
53 Call,
54
55 // A 'Child' edge is used when the region of target node is defined inside
56 // of the callable region of this node. This means that the region of this
57 // node is an ancestor of the region for the target node. As such, this
58 // edge cannot be used on the 'external' node.
59 Child,
60 };
61
62 public:
63 /// Returns true if this edge represents an `Abstract` edge.
64 bool isAbstract() const { return targetAndKind.getInt() == Kind::Abstract; }
65
66 /// Returns true if this edge represents a `Call` edge.
67 bool isCall() const { return targetAndKind.getInt() == Kind::Call; }
68
69 /// Returns true if this edge represents a `Child` edge.
70 bool isChild() const { return targetAndKind.getInt() == Kind::Child; }
71
72 /// Returns the target node for this edge.
73 CallGraphNode *getTarget() const { return targetAndKind.getPointer(); }
74
75 bool operator==(const Edge &edge) const {
76 return targetAndKind == edge.targetAndKind;
77 }
78
79 private:
80 Edge(CallGraphNode *node, Kind kind) : targetAndKind(node, kind) {}
81 explicit Edge(llvm::PointerIntPair<CallGraphNode *, 2, Kind> targetAndKind)
82 : targetAndKind(targetAndKind) {}
83
84 /// The target node of this edge, as well as the edge kind.
85 llvm::PointerIntPair<CallGraphNode *, 2, Kind> targetAndKind;
86
87 // Provide access to the constructor and Kind.
88 friend class CallGraphNode;
89 };
90
91 /// Returns true if this node is an external node.
92 bool isExternal() const;
93
94 /// Returns the callable region this node represents. This can only be called
95 /// on non-external nodes.
97
98 /// Adds an abstract reference edge to the given node. An abstract edge does
99 /// not come from any observable operations, so this is only valid on the
100 /// external node.
101 void addAbstractEdge(CallGraphNode *node);
102
103 /// Add an outgoing call edge from this node.
104 void addCallEdge(CallGraphNode *node);
105
106 /// Adds a reference edge to the given child node.
107 void addChildEdge(CallGraphNode *child);
108
109 /// Iterator over the outgoing edges of this node.
111 iterator begin() const { return edges.begin(); }
112 iterator end() const { return edges.end(); }
113
114 /// Returns true if this node has any child edges.
115 bool hasChildren() const;
116
117private:
118 /// DenseMap info for callgraph edges.
119 struct EdgeKeyInfo {
120 using BaseInfo =
122
123 static Edge getEmptyKey() { return Edge(BaseInfo::getEmptyKey()); }
124 static unsigned getHashValue(const Edge &edge) {
125 return BaseInfo::getHashValue(edge.targetAndKind);
126 }
127 static bool isEqual(const Edge &lhs, const Edge &rhs) { return lhs == rhs; }
128 };
129
130 CallGraphNode(Region *callableRegion) : callableRegion(callableRegion) {}
131
132 /// Add an edge to 'node' with the given kind.
133 void addEdge(CallGraphNode *node, Edge::Kind kind);
134
135 /// The callable region defines the boundary of the call graph node. This is
136 /// the region referenced by 'call' operations. This is at a per-region
137 /// boundary as operations may define multiple callable regions.
138 Region *callableRegion;
139
140 /// A set of out-going edges from this node to other nodes in the graph.
142 llvm::SmallDenseSet<Edge, 4, EdgeKeyInfo>>
143 edges;
144
145 // Provide access to private methods.
146 friend class CallGraph;
147};
148
149//===----------------------------------------------------------------------===//
150// CallGraph
151//===----------------------------------------------------------------------===//
152
154 using NodeMapT = llvm::MapVector<Region *, std::unique_ptr<CallGraphNode>>;
155
156 /// This class represents an iterator over the internal call graph nodes. This
157 /// class unwraps the map iterator to access the raw node.
158 class NodeIterator final
159 : public llvm::mapped_iterator<
160 NodeMapT::const_iterator,
161 CallGraphNode *(*)(const NodeMapT::value_type &)> {
162 static CallGraphNode *unwrap(const NodeMapT::value_type &value) {
163 return value.second.get();
164 }
165
166 public:
167 /// Initializes the result type iterator to the specified result iterator.
168 NodeIterator(NodeMapT::const_iterator it)
169 : llvm::mapped_iterator<
170 NodeMapT::const_iterator,
171 CallGraphNode *(*)(const NodeMapT::value_type &)>(it, &unwrap) {}
172 };
173
174public:
175 CallGraph(Operation *op);
176
177 /// Get or add a call graph node for the given region. `parentNode`
178 /// corresponds to the direct node in the callgraph that contains the parent
179 /// operation of `region`, or nullptr if there is no parent node.
180 CallGraphNode *getOrAddNode(Region *region, CallGraphNode *parentNode);
181
182 /// Lookup a call graph node for the given region, or nullptr if none is
183 /// registered.
184 CallGraphNode *lookupNode(Region *region) const;
185
186 /// Return the callgraph node representing an external caller.
188 return const_cast<CallGraphNode *>(&externalCallerNode);
189 }
190
191 /// Return the callgraph node representing an indirect callee.
193 return const_cast<CallGraphNode *>(&unknownCalleeNode);
194 }
195
196 /// Resolve the callable for given callee to a node in the callgraph, or the
197 /// external node if a valid node was not resolved. The provided symbol table
198 /// is used when resolving calls that reference callables via a symbol
199 /// reference.
200 CallGraphNode *resolveCallable(CallOpInterface call,
201 SymbolTableCollection &symbolTable) const;
202
203 /// Erase the given node from the callgraph.
204 void eraseNode(CallGraphNode *node);
205
206 /// An iterator over the nodes of the graph.
207 using iterator = NodeIterator;
208 iterator begin() const { return nodes.begin(); }
209 iterator end() const { return nodes.end(); }
210
211 /// Dump the graph in a human readable format.
212 void dump() const;
213 void print(raw_ostream &os) const;
214
215private:
216 /// The set of nodes within the callgraph.
217 NodeMapT nodes;
218
219 /// A special node used to indicate an external caller.
220 CallGraphNode externalCallerNode;
221
222 /// A special node used to indicate an unknown callee.
223 CallGraphNode unknownCalleeNode;
224};
225
226} // namespace mlir
227
228namespace llvm {
229// Provide graph traits for traversing call graphs using standard graph
230// traversals.
231template <>
232struct GraphTraits<const mlir::CallGraphNode *> {
234 static NodeRef getEntryNode(NodeRef node) { return node; }
235
237 return edge.getTarget();
238 }
239
240 // ChildIteratorType/begin/end - Allow iteration over all nodes in the graph.
242 mapped_iterator<mlir::CallGraphNode::iterator, decltype(&unwrap)>;
244 return {node->begin(), &unwrap};
245 }
247 return {node->end(), &unwrap};
248 }
249};
250
251template <>
252struct GraphTraits<const mlir::CallGraph *>
253 : public GraphTraits<const mlir::CallGraphNode *> {
254 /// The entry node into the graph is the external node.
256 return cg->getExternalCallerNode();
257 }
258
259 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
261 static nodes_iterator nodes_begin(mlir::CallGraph *cg) { return cg->begin(); }
262 static nodes_iterator nodes_end(mlir::CallGraph *cg) { return cg->end(); }
263};
264} // namespace llvm
265
266#endif // MLIR_ANALYSIS_CALLGRAPH_H
lhs
This class represents a directed edge between two nodes in the callgraph.
Definition CallGraph.h:43
bool isChild() const
Returns true if this edge represents a Child edge.
Definition CallGraph.h:70
bool isCall() const
Returns true if this edge represents a Call edge.
Definition CallGraph.h:67
bool operator==(const Edge &edge) const
Definition CallGraph.h:75
friend class CallGraphNode
Definition CallGraph.h:88
CallGraphNode * getTarget() const
Returns the target node for this edge.
Definition CallGraph.h:73
bool isAbstract() const
Returns true if this edge represents an Abstract edge.
Definition CallGraph.h:64
This class represents a single callable in the callgraph.
Definition CallGraph.h:40
friend class CallGraph
Definition CallGraph.h:146
bool isExternal() const
Returns true if this node is an external node.
Definition CallGraph.cpp:32
void addAbstractEdge(CallGraphNode *node)
Adds an abstract reference edge to the given node.
Definition CallGraph.cpp:43
void addChildEdge(CallGraphNode *child)
Adds a reference edge to the given child node.
Definition CallGraph.cpp:54
bool hasChildren() const
Returns true if this node has any child edges.
Definition CallGraph.cpp:59
void addCallEdge(CallGraphNode *node)
Add an outgoing call edge from this node.
Definition CallGraph.cpp:49
iterator end() const
Definition CallGraph.h:112
Region * getCallableRegion() const
Returns the callable region this node represents.
Definition CallGraph.cpp:36
SmallVectorImpl< Edge >::const_iterator iterator
Iterator over the outgoing edges of this node.
Definition CallGraph.h:110
iterator begin() const
Definition CallGraph.h:111
CallGraphNode * getUnknownCalleeNode() const
Return the callgraph node representing an indirect callee.
Definition CallGraph.h:192
void eraseNode(CallGraphNode *node)
Erase the given node from the callgraph.
CallGraphNode * resolveCallable(CallOpInterface call, SymbolTableCollection &symbolTable) const
Resolve the callable for given callee to a node in the callgraph, or the external node if a valid nod...
iterator end() const
Definition CallGraph.h:209
CallGraphNode * getExternalCallerNode() const
Return the callgraph node representing an external caller.
Definition CallGraph.h:187
CallGraph(Operation *op)
Definition CallGraph.cpp:99
NodeIterator iterator
An iterator over the nodes of the graph.
Definition CallGraph.h:207
CallGraphNode * lookupNode(Region *region) const
Lookup a call graph node for the given region, or nullptr if none is registered.
iterator begin() const
Definition CallGraph.h:208
void dump() const
Dump the graph in a human readable format.
CallGraphNode * getOrAddNode(Region *region, CallGraphNode *parentNode)
Get or add a call graph node for the given region.
void print(raw_ostream &os) const
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
This class represents a collection of SymbolTables.
mlir::Diagnostic & unwrap(MlirDiagnostic diagnostic)
Definition Diagnostics.h:19
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:228
Include the generated interface declarations.
llvm::DenseMapInfo< T, Enable > DenseMapInfo
Definition LLVM.h:116
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:125
static ChildIteratorType child_begin(NodeRef node)
Definition CallGraph.h:243
mapped_iterator< mlir::CallGraphNode::iterator, decltype(&unwrap)> ChildIteratorType
Definition CallGraph.h:241
static NodeRef unwrap(const mlir::CallGraphNode::Edge &edge)
Definition CallGraph.h:236
static NodeRef getEntryNode(NodeRef node)
Definition CallGraph.h:234
static ChildIteratorType child_end(NodeRef node)
Definition CallGraph.h:246
static nodes_iterator nodes_begin(mlir::CallGraph *cg)
Definition CallGraph.h:261
static NodeRef getEntryNode(const mlir::CallGraph *cg)
The entry node into the graph is the external node.
Definition CallGraph.h:255
static nodes_iterator nodes_end(mlir::CallGraph *cg)
Definition CallGraph.h:262
mlir::CallGraph::iterator nodes_iterator
Definition CallGraph.h:260
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.