14#include <mlir/IR/BuiltinOps.h>
15#include <mlir/IR/SymbolTable.h>
17#include <llvm/ADT/GraphTraits.h>
18#include <llvm/ADT/MapVector.h>
19#include <llvm/ADT/SetVector.h>
20#include <llvm/ADT/SmallPtrSet.h>
21#include <llvm/Support/DOTGraphTraits.h>
27class SymbolUseGraphNode {
28 using OpSet = llvm::SmallPtrSet<mlir::Operation *, 3>;
30 mlir::ModuleOp symbolPathRoot;
31 mlir::SymbolRefAttr symbolPath;
32 OpSet opsThatUseTheSymbol;
33 bool isStructConstParam;
37 mlir::SetVector<SymbolUseGraphNode *> predecessors;
39 mlir::SetVector<SymbolUseGraphNode *> successors;
41 SymbolUseGraphNode(mlir::ModuleOp pathRoot, mlir::SymbolRefAttr path)
42 : symbolPathRoot(pathRoot), symbolPath(path), isStructConstParam(
false) {
43 assert(pathRoot &&
"'pathRoot' cannot be nullptr");
44 assert(path &&
"'path' cannot be nullptr");
48 SymbolUseGraphNode() : symbolPathRoot(
nullptr), symbolPath(
nullptr), isStructConstParam(
false) {}
51 static bool isRealNodeImpl(
const SymbolUseGraphNode *node) {
return node->symbolPath !=
nullptr; }
54 void addSuccessor(SymbolUseGraphNode *node);
57 void removeSuccessor(SymbolUseGraphNode *node);
74 const OpSet &
getUserOps()
const {
return opsThatUseTheSymbol; }
81 return llvm::find_if(predecessors, isRealNodeImpl) != predecessors.end();
83 size_t numPredecessors()
const {
return llvm::count_if(predecessors, isRealNodeImpl); }
87 return llvm::find_if(successors, isRealNodeImpl) != successors.end();
89 size_t numSuccessors()
const {
return llvm::count_if(successors, isRealNodeImpl); }
93 mlir::SetVector<SymbolUseGraphNode *>::const_iterator, bool (*)(
const SymbolUseGraphNode *)>;
102 return llvm::make_filter_range(predecessors, isRealNodeImpl);
107 return llvm::make_filter_range(successors, isRealNodeImpl);
110 mlir::FailureOr<SymbolLookupResultUntyped>
111 lookupSymbol(mlir::SymbolTableCollection &tables,
bool reportMissing =
true)
const;
114 std::string
toString(
bool showLocations =
false)
const;
115 void print(llvm::raw_ostream &os,
bool showLocations =
false, std::string locationLinePrefix =
"")
123 using NodeMapKeyT = std::pair<mlir::ModuleOp, mlir::SymbolRefAttr>;
125 using NodeMapT = llvm::MapVector<NodeMapKeyT, std::unique_ptr<SymbolUseGraphNode>>;
141 class NodeIterator final
142 :
public llvm::mapped_iterator<
143 NodeMapT::const_iterator, SymbolUseGraphNode *(*)(const NodeMapT::value_type &)> {
145 return value.second.get();
150 NodeIterator(NodeMapT::const_iterator it)
151 : llvm::mapped_iterator<
159 mlir::ModuleOp pathRoot, mlir::SymbolRefAttr path,
SymbolUseGraphNode *predecessorNode
163 void buildGraph(mlir::SymbolOpInterface symbolOp);
179 size_t
size() const {
return nodes.size(); }
187 inline llvm::iterator_range<roots_iterator>
rootsIter()
const {
197 inline llvm::iterator_range<iterator>
nodesIter()
const {
198 return llvm::make_range(
begin(),
end());
203 void print(llvm::raw_ostream &os)
const;
226 :
public GraphTraits<const llzk::SymbolUseGraphNode *> {
253 :
public GraphTraits<Inverse<const llzk::SymbolUseGraphNode *>> {
254 using GraphType = Inverse<const llzk::SymbolUseGraph *>;
This file defines methods symbol lookup across LLZK operations and included files.
size_t numSuccessors() const
mlir::FailureOr< SymbolLookupResultUntyped > lookupSymbol(mlir::SymbolTableCollection &tables, bool reportMissing=true) const
bool isRealNode() const
Return 'false' iff this node is an artificial node created for the graph head/tail.
bool hasSuccessor() const
Return true if this node has any successors.
iterator predecessors_begin() const
size_t numPredecessors() const
void print(llvm::raw_ostream &os, bool showLocations=false, std::string locationLinePrefix="") const
iterator predecessors_end() const
bool isStructParam() const
Return true iff the symbol is a struct constant parameter name.
bool hasPredecessor() const
Return true if this node has any predecessors.
std::string toString(bool showLocations=false) const
Print the node in a human readable format.
iterator successors_begin() const
llvm::iterator_range< iterator > predecessorIter() const
Range over predecessor nodes.
mlir::SymbolRefAttr getSymbolPath() const
The symbol path+name relative to the closest root ModuleOp.
const OpSet & getUserOps() const
The set of operations that use the symbol.
iterator successors_end() const
mlir::ModuleOp getSymbolPathRoot() const
Return the root ModuleOp for the path.
friend class SymbolUseGraph
llvm::iterator_range< iterator > successorIter() const
Range over successor nodes.
llvm::filter_iterator< mlir::SetVector< SymbolUseGraphNode * >::const_iterator, bool(*)(const SymbolUseGraphNode *)> iterator
Iterator over predecessors/successors.
Builds a graph structure representing the relationships between symbols and their uses.
size_t size() const
Return the total number of nodes in the graph.
void dump() const
Dump the graph in a human readable format.
roots_iterator roots_end() const
SymbolUseGraphNode::iterator roots_iterator
Iterator over the root nodes (i.e., nodes that have no predecessors).
llvm::iterator_range< roots_iterator > rootsIter() const
Range over root nodes (i.e., nodes that have no predecessors).
void dumpToDotFile(std::string filename="") const
Dump the graph to file in dot graph format.
roots_iterator roots_begin() const
NodeIterator iterator
An iterator over the nodes of the graph.
SymbolUseGraph(mlir::SymbolOpInterface rootSymbolOp)
llvm::iterator_range< iterator > nodesIter() const
Range over all nodes in the graph.
void print(llvm::raw_ostream &os) const
const SymbolUseGraphNode * lookupNode(mlir::ModuleOp pathRoot, mlir::SymbolRefAttr path) const
Return the existing node for the symbol reference relative to the given module, else nullptr.
DOTGraphTraits(bool isSimple=false)
std::string getNodeLabel(NodeRef n, GraphType)
const llzk::SymbolUseGraphNode * NodeRef
const llzk::SymbolUseGraph * GraphType
static std::string getGraphName(GraphType)
DOTGraphTraits(bool isSimple=false)
std::string getNodeLabel(NodeRef n, GraphType g)
const llzk::SymbolUseGraphNode * NodeRef
llzk::SymbolUseGraphNode::iterator ChildIteratorType
static ChildIteratorType child_begin(NodeRef node)
static ChildIteratorType child_end(NodeRef node)
static NodeRef getEntryNode(Inverse< NodeRef > node)
static nodes_iterator nodes_begin(GraphType g)
static nodes_iterator nodes_end(GraphType g)
llzk::SymbolUseGraph::iterator nodes_iterator
nodes_iterator/begin/end - Allow iteration over all nodes in the graph.
static NodeRef getEntryNode(GraphType g)
The entry node into the inverse graph is the tail node.
Inverse< const llzk::SymbolUseGraph * > GraphType
static unsigned size(GraphType g)
Return total number of nodes in the graph.
static ChildIteratorType child_end(NodeRef node)
const llzk::SymbolUseGraphNode * NodeRef
llzk::SymbolUseGraphNode::iterator ChildIteratorType
ChildIteratorType/begin/end - Allow iteration over all nodes in the graph.
static NodeRef getEntryNode(NodeRef node)
static ChildIteratorType child_begin(NodeRef node)
static nodes_iterator nodes_begin(GraphType g)
llzk::SymbolUseGraph::iterator nodes_iterator
nodes_iterator/begin/end - Allow iteration over all nodes in the graph.
static unsigned size(GraphType g)
Return total number of nodes in the graph.
const llzk::SymbolUseGraph * GraphType
static NodeRef getEntryNode(GraphType g)
The entry node into the graph is the root node.
static nodes_iterator nodes_end(GraphType g)