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 isTemplateSymBinding;
37 mlir::SetVector<SymbolUseGraphNode *> predecessors;
39 mlir::SetVector<SymbolUseGraphNode *> successors;
41 SymbolUseGraphNode(mlir::ModuleOp pathRoot, mlir::SymbolRefAttr path)
42 : symbolPathRoot(pathRoot), symbolPath(path), isTemplateSymBinding(
false) {
43 assert(pathRoot &&
"'pathRoot' cannot be nullptr");
44 assert(path &&
"'path' cannot be nullptr");
49 : symbolPathRoot(
nullptr), symbolPath(
nullptr), isTemplateSymBinding(
false) {}
52 static bool isRealNodeImpl(
const SymbolUseGraphNode *node) {
return node->symbolPath !=
nullptr; }
55 void addSuccessor(SymbolUseGraphNode *node);
58 void removeSuccessor(SymbolUseGraphNode *node);
75 const OpSet &
getUserOps()
const {
return opsThatUseTheSymbol; }
82 return llvm::find_if(predecessors, isRealNodeImpl) != predecessors.end();
84 size_t numPredecessors()
const {
return llvm::count_if(predecessors, isRealNodeImpl); }
88 return llvm::find_if(successors, isRealNodeImpl) != successors.end();
90 size_t numSuccessors()
const {
return llvm::count_if(successors, isRealNodeImpl); }
94 mlir::SetVector<SymbolUseGraphNode *>::const_iterator, bool (*)(
const SymbolUseGraphNode *)>;
103 return llvm::make_filter_range(predecessors, isRealNodeImpl);
108 return llvm::make_filter_range(successors, isRealNodeImpl);
111 mlir::FailureOr<SymbolLookupResultUntyped>
112 lookupSymbol(mlir::SymbolTableCollection &tables,
bool reportMissing =
true)
const;
115 std::string
toString(
bool showLocations =
false)
const;
117 llvm::raw_ostream &os,
bool showLocations =
false,
const std::string &locationLinePrefix =
""
125 using NodeMapKeyT = std::pair<mlir::ModuleOp, mlir::SymbolRefAttr>;
127 using NodeMapT = llvm::MapVector<NodeMapKeyT, std::unique_ptr<SymbolUseGraphNode>>;
143 class NodeIterator final
144 :
public llvm::mapped_iterator<
145 NodeMapT::const_iterator, SymbolUseGraphNode *(*)(const NodeMapT::value_type &)> {
147 return value.second.get();
152 NodeIterator(NodeMapT::const_iterator it)
153 : llvm::mapped_iterator<
161 mlir::ModuleOp pathRoot, mlir::SymbolRefAttr path,
SymbolUseGraphNode *predecessorNode
165 void buildGraph(mlir::SymbolOpInterface symbolOp);
169 friend struct llvm::GraphTraits<llvm::Inverse<const llzk::SymbolUseGraph *>>;
181 size_t
size() const {
return nodes.size(); }
189 inline llvm::iterator_range<roots_iterator>
rootsIter()
const {
199 inline llvm::iterator_range<iterator>
nodesIter()
const {
200 return llvm::make_range(
begin(),
end());
205 void print(llvm::raw_ostream &os)
const;
216template <>
struct GraphTraits<const
llzk::SymbolUseGraphNode *> {
227struct GraphTraits<const
llzk::SymbolUseGraph *>
228 :
public GraphTraits<const llzk::SymbolUseGraphNode *> {
244template <>
struct GraphTraits<Inverse<const
llzk::SymbolUseGraphNode *>> {
254struct GraphTraits<Inverse<const
llzk::SymbolUseGraph *>>
255 :
public GraphTraits<Inverse<const llzk::SymbolUseGraphNode *>> {
256 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
iterator predecessors_end() const
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.
bool isTemplateSymbolBinding() const
Return true iff the symbol is a defined by a TemplateSymbolBindingOpInterface.
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.
void print(llvm::raw_ostream &os, bool showLocations=false, const std::string &locationLinePrefix="") const
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)