13#ifndef CIRCT_SUPPORT_INSTANCEGRAPH_H
14#define CIRCT_SUPPORT_INSTANCEGRAPH_H
17#include "mlir/IR/OpDefinition.h"
18#include "llvm/ADT/GraphTraits.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/iterator.h"
21#include "llvm/Support/DOTGraphTraits.h"
34 :
public llvm::mapped_iterator<It, typename It::pointer (*)(
35 typename It::reference)> {
39 static typename Iterator::value_type *
40 addrOf(
typename Iterator::value_type &v)
noexcept {
41 return std::addressof(v);
44 :
llvm::mapped_iterator<It, typename
Iterator::pointer (*)(
45 typename
Iterator::reference)>(iterator,
50class InstanceGraphNode;
55 :
public llvm::ilist_node_with_parent<InstanceRecord, InstanceGraphNode> {
58 template <
typename TTarget = InstanceOpInterface>
60 if constexpr (std::is_same<TTarget, InstanceOpInterface>::value)
62 return dyn_cast_or_null<TTarget>(
instance.getOperation());
108 template <
typename TTarget = ModuleOpInterface>
110 if constexpr (std::is_same<TTarget, ModuleOpInterface>::value)
112 return cast<TTarget>(module.getOperation());
131 :
public llvm::iterator_facade_base<
132 UseIterator, std::forward_iterator_tag, InstanceRecord *> {
136 using llvm::iterator_facade_base<
UseIterator, std::forward_iterator_tag,
154 llvm::iterator_range<UseIterator>
uses() {
172 ModuleOpInterface
module;
214 ModuleOpInterface child, ModuleOpInterface
parent,
257 InstanceOpInterface newInst);
273 llvm::DenseMap<Attribute, InstanceGraphNode *>
nodeMap;
288 InstanceOpInterface
top()
const {
293 InstanceOpInterface
leaf()
const {
303 ArrayRef<InstanceOpInterface>::iterator
begin()
const {
return path.begin(); }
304 ArrayRef<InstanceOpInterface>::iterator
end()
const {
return path.end(); }
311 void print(llvm::raw_ostream &into)
const;
318 ArrayRef<InstanceOpInterface>
path;
340 void replaceInstance(InstanceOpInterface oldOp, InstanceOpInterface newOp);
361struct llvm::GraphTraits<
circt::igraph::InstanceGraphNode *> {
375 return {node->
begin(), &getChild};
378 return {node->
end(), &getChild};
384struct llvm::GraphTraits<
llvm::Inverse<circt::igraph::InstanceGraphNode *>> {
397 return inverse.Graph;
403 return {node->
usesEnd(), &getParent};
409struct llvm::GraphTraits<
circt::igraph::InstanceGraph *>
410 :
public llvm::GraphTraits<circt::igraph::InstanceGraphNode *> {
418 return graph->
begin();
428struct llvm::DOTGraphTraits<
circt::igraph::InstanceGraph *>
429 :
public llvm::DefaultDOTGraphTraits {
430 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
435 return node->
getModule().getModuleName().str();
438 template <
typename Iterator>
443 auto *instanceRecord = *it.getCurrent();
444 auto instanceOp = instanceRecord->getInstance();
445 return (
"label=" + instanceOp.getInstanceName()).str();
assert(baseType &&"element must be base type")
This is a Node in the InstanceGraph.
llvm::iterator_range< UseIterator > uses()
InstanceRecord * firstUse
List of instances which instantiate this module.
bool noUses()
Return true if there are no more instances of this module.
InstanceRecord * addInstance(InstanceOpInterface instance, InstanceGraphNode *target)
Record a new instance op in the body of this module.
InstanceGraphNode(const InstanceGraphNode &)=delete
auto getModule()
Get the module that this node is tracking.
ModuleOpInterface InstanceList instances
The module.
UseIterator usesBegin()
Iterate the instance records which instantiate this module.
llvm::iplist< InstanceRecord > InstanceList
size_t getNumUses()
Get the number of direct instantiations of this module.
bool hasOneUse()
Return true if this module has exactly one use.
void recordUse(InstanceRecord *record)
Record that a module instantiates this module.
This graph tracks modules and where they are instantiated.
virtual ~InstanceGraph()=default
Operation * getParent()
Return the parent under which all nodes are nested.
virtual InstanceGraphNode * addModule(ModuleOpInterface module)
Add a newly created module to the instance graph.
Operation * parent
The node under which all modules are nested.
llvm::DenseMap< Attribute, InstanceGraphNode * > nodeMap
This maps each operation to its graph node.
virtual void replaceInstance(InstanceOpInterface inst, InstanceOpInterface newInst)
Replaces an instance of a module with another instance.
virtual InstanceGraphNode * getTopLevelNode()
Get the node corresponding to the top-level module of a circuit.
FailureOr< llvm::ArrayRef< InstanceGraphNode * > > getInferredTopLevelNodes()
Get the nodes corresponding to the inferred top-level modules of a circuit.
llvm::SmallVector< InstanceGraphNode * > inferredTopLevelNodes
A caching of the inferred top level module(s).
NodeList nodes
The storage for graph nodes, with deterministic iteration.
virtual void erase(InstanceGraphNode *node)
Remove this module from the instance graph.
bool isAncestor(ModuleOpInterface child, ModuleOpInterface parent, llvm::function_ref< bool(InstanceRecord *)> skipInstance=[](InstanceRecord *_) { return false;})
Check if child is instantiated by a parent.
InstanceGraphNode * lookup(ModuleOpInterface op)
Look up an InstanceGraphNode for a module.
detail::AddressIterator< NodeList::iterator > iterator
Iterate through all modules.
InstanceGraph(const InstanceGraph &)=delete
InstanceGraphNode * getOrAddNode(StringAttr name)
Get the node corresponding to the module.
InstanceGraphNode * operator[](ModuleOpInterface op)
Lookup an InstanceGraphNode for a module.
llvm::iplist< InstanceGraphNode > NodeList
This is the list of InstanceGraphNodes in the graph.
InstanceGraph(Operation *parent)
Create a new module graph of a circuit.
static NodeList InstanceGraph::* getSublistAccess(Operation *)
Returns pointer to member of operation list.
ModuleOpInterface getReferencedModuleImpl(InstanceOpInterface op)
An instance path composed of a series of instances.
InstanceOpInterface leaf() const
bool operator==(const InstancePath &that) const
InstanceOpInterface operator[](size_t idx) const
ArrayRef< InstanceOpInterface > path
InstancePath(ArrayRef< InstanceOpInterface > path)
void print(llvm::raw_ostream &into) const
Print the path to any stream-like object.
ArrayRef< InstanceOpInterface >::iterator begin() const
ArrayRef< InstanceOpInterface >::iterator end() const
InstancePath dropFront() const
InstancePath dropBack() const
InstanceOpInterface top() const
This is an edge in the InstanceGraph.
InstanceGraphNode * getParent() const
Get the module where the instantiation lives.
auto getInstance()
Get the instance-like op that this is tracking.
void erase()
Erase this instance record, removing it from the parent module and the target's use-list.
InstanceGraphNode * target
This is the module which the instance-like is instantiating.
InstanceRecord * nextUse
Intrusive linked list for other uses.
InstanceOpInterface instance
The InstanceLike that this is tracking.
InstanceGraphNode * getTarget() const
Get the module which the instance-like is instantiating.
InstanceRecord(InstanceGraphNode *parent, InstanceOpInterface instance, InstanceGraphNode *target)
InstanceGraphNode * parent
This is the module where the instantiation lives.
InstanceRecord(const InstanceRecord &)=delete
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const InstancePath &path)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Iterator for module uses.
UseIterator(InstanceGraphNode *node)
bool operator==(const UseIterator &other) const
UseIterator & operator++()
InstanceRecord * operator*() const
A data structure that caches and provides absolute paths to module instances in the IR.
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)
void replaceInstance(InstanceOpInterface oldOp, InstanceOpInterface newOp)
Replace an InstanceOp. This is required to keep the cache updated.
DenseMap< Operation *, ArrayRef< InstancePath > > absolutePathsCache
Cached absolute instance paths.
InstancePath prependInstance(InstanceOpInterface inst, InstancePath path)
Prepend an instance to a path.
InstancePath appendInstance(InstancePath path, InstanceOpInterface inst)
Append an instance to a path.
llvm::BumpPtrAllocator allocator
An allocator for individual instance paths and entire path lists.
InstanceGraph & instanceGraph
The instance graph of the IR.
InstancePathCache(InstanceGraph &instanceGraph)
This just maps a iterator of references to an iterator of addresses.
static Iterator::value_type * addrOf(typename Iterator::value_type &v) noexcept
AddressIterator(Iterator iterator)
static std::string getEdgeAttributes(const circt::igraph::InstanceGraphNode *node, Iterator it, circt::igraph::InstanceGraph *)
static std::string getNodeLabel(circt::igraph::InstanceGraphNode *node, circt::igraph::InstanceGraph *)
static NodeRef getEntryNode(NodeRef node)
static ChildIteratorType child_begin(NodeRef node)
static NodeRef getChild(const circt::igraph::InstanceRecord *record)
llvm::mapped_iterator< NodeType::iterator, decltype(&getChild)> ChildIteratorType
static ChildIteratorType child_end(NodeRef node)
static nodes_iterator nodes_begin(circt::igraph::InstanceGraph *graph)
static NodeRef getEntryNode(circt::igraph::InstanceGraph *graph)
static nodes_iterator nodes_end(circt::igraph::InstanceGraph *graph)
llvm::mapped_iterator< NodeType::UseIterator, decltype(&getParent)> ChildIteratorType
static NodeRef getParent(const circt::igraph::InstanceRecord *record)
static ChildIteratorType child_end(NodeRef node)
static ChildIteratorType child_begin(NodeRef node)
static NodeRef getEntryNode(Inverse< NodeRef > inverse)