CIRCT 24.0.0git
Loading...
Searching...
No Matches
InstanceGraph.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 defines a generic instance graph for module- and instance-likes.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CIRCT_SUPPORT_INSTANCEGRAPH_H
14#define CIRCT_SUPPORT_INSTANCEGRAPH_H
15
16#include "circt/Support/LLVM.h"
17#include "mlir/IR/OpDefinition.h"
18#include "llvm/ADT/GraphTraits.h"
19#include "llvm/ADT/PostOrderIterator.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/iterator.h"
22#include "llvm/Support/DOTGraphTraits.h"
23
24/// The InstanceGraph op interface, see InstanceGraphInterface.td for more
25/// details.
27
28namespace circt {
29namespace igraph {
30
31namespace detail {
32/// This just maps a iterator of references to an iterator of addresses.
33template <typename It>
35 : public llvm::mapped_iterator<It, typename It::pointer (*)(
36 typename It::reference)> {
37 // This using statement is to get around a bug in MSVC. Without it, it
38 // tries to look up "It" as a member type of the parent class.
39 using Iterator = It;
40 static typename Iterator::value_type *
41 addrOf(typename Iterator::value_type &v) noexcept {
42 return std::addressof(v);
43 }
44 /* implicit */ AddressIterator(Iterator iterator)
45 : llvm::mapped_iterator<It, typename Iterator::pointer (*)(
46 typename Iterator::reference)>(iterator,
47 addrOf) {}
48};
49} // namespace detail
50
51//===----------------------------------------------------------------------===//
52// Instance Node
53//===----------------------------------------------------------------------===//
54
55class InstanceGraphNode;
56
57/// This is an edge in the InstanceGraph. This tracks a specific instantiation
58/// of a module.
60 : public llvm::ilist_node_with_parent<InstanceRecord, InstanceGraphNode> {
61public:
62 /// Get the instance-like op that this is tracking.
63 template <typename TTarget = InstanceOpInterface>
64 auto getInstance() {
65 if constexpr (std::is_same<TTarget, InstanceOpInterface>::value)
66 return instance;
67 return dyn_cast_or_null<TTarget>(instance.getOperation());
68 }
69
70 /// Get the module where the instantiation lives.
71 InstanceGraphNode *getParent() const { return parent; }
72
73 /// Get the module which the instance-like is instantiating.
74 InstanceGraphNode *getTarget() const { return target; }
75
76 /// Erase this instance record, removing it from the parent module and the
77 /// target's use-list.
78 void erase();
79
80private:
81 friend class InstanceGraph;
82 friend class InstanceGraphNode;
83
87 InstanceRecord(const InstanceRecord &) = delete;
88
89 /// This is the module where the instantiation lives.
91
92 /// The InstanceLike that this is tracking.
93 InstanceOpInterface instance;
94
95 /// This is the module which the instance-like is instantiating.
97 /// Intrusive linked list for other uses.
100};
101
102//===----------------------------------------------------------------------===//
103// Module Node
104//===----------------------------------------------------------------------===//
105
106/// This is a Node in the InstanceGraph. Each node represents a Module in a
107/// Circuit. Both external modules and regular modules can be represented by
108/// this class. It is possible to efficiently iterate all modules instantiated
109/// by this module, as well as all instantiations of this module.
110class InstanceGraphNode : public llvm::ilist_node<InstanceGraphNode> {
111 using InstanceList = llvm::iplist<InstanceRecord>;
112
113public:
114 InstanceGraphNode() : module(nullptr) {}
115
116 /// Get the module that this node is tracking.
117 template <typename TTarget = ModuleOpInterface>
118 auto getModule() {
119 if constexpr (std::is_same<TTarget, ModuleOpInterface>::value)
120 return module;
121 return cast<TTarget>(module.getOperation());
122 }
123
124 /// Iterate the instance records in this module.
126 iterator begin() { return instances.begin(); }
127 iterator end() { return instances.end(); }
128
129 /// Return true if there are no more instances of this module.
130 bool noUses() { return !firstUse; }
131
132 /// Return true if this module has exactly one use.
133 bool hasOneUse() { return llvm::hasSingleElement(uses()); }
134
135 /// Get the number of direct instantiations of this module.
136 size_t getNumUses() { return std::distance(usesBegin(), usesEnd()); }
137
138 /// Iterator for module uses.
140 : public llvm::iterator_facade_base<
141 UseIterator, std::forward_iterator_tag, InstanceRecord *> {
142 UseIterator() : current(nullptr) {}
144 InstanceRecord *operator*() const { return current; }
145 using llvm::iterator_facade_base<UseIterator, std::forward_iterator_tag,
146 InstanceRecord *>::operator++;
148 assert(current && "incrementing past end");
149 current = current->nextUse;
150 return *this;
151 }
152 bool operator==(const UseIterator &other) const {
153 return current == other.current;
154 }
155
156 private:
158 };
159
160 /// Iterate the instance records which instantiate this module.
161 UseIterator usesBegin() { return {this}; }
162 UseIterator usesEnd() { return {}; }
163 llvm::iterator_range<UseIterator> uses() {
164 return llvm::make_range(usesBegin(), usesEnd());
165 }
166
167 /// Record a new instance op in the body of this module. Returns a newly
168 /// allocated InstanceRecord which will be owned by this node.
169 InstanceRecord *addInstance(InstanceOpInterface instance,
170 InstanceGraphNode *target);
171
172private:
173 friend class InstanceRecord;
174
176
177 /// Record that a module instantiates this module.
178 void recordUse(InstanceRecord *record);
179
180 /// The module.
181 ModuleOpInterface module;
182
183 /// List of instance operations in this module. This member owns the
184 /// InstanceRecords, which may be pointed to by other InstanceGraphNode's use
185 /// lists.
187
188 /// List of instances which instantiate this module.
190
191 // Provide access to the constructor.
192 friend class InstanceGraph;
193};
194
195//===----------------------------------------------------------------------===//
196// Instance Graph
197//===----------------------------------------------------------------------===//
198
199/// This graph tracks modules and where they are instantiated. This is intended
200/// to be used as a cached analysis on circuits. This class can be used
201/// to walk the modules efficiently in a bottom-up or top-down order.
202///
203/// To use this class, retrieve a cached copy from the analysis manager:
204/// auto &instanceGraph = getAnalysis<InstanceGraph>(getOperation());
206 /// This is the list of InstanceGraphNodes in the graph.
207 using NodeList = llvm::iplist<InstanceGraphNode>;
208
209public:
210 /// Create a new module graph of a circuit. Must be called on the parent
211 /// operation of ModuleOpInterface ops.
213 InstanceGraph(const InstanceGraph &) = delete;
214 virtual ~InstanceGraph() = default;
215
216 /// Lookup an module by name. Returns null if no module with the given name
217 /// exists in the instance graph.
218 InstanceGraphNode *lookupOrNull(StringAttr name);
219
220 /// Look up an InstanceGraphNode for a module. Returns null if the module has
221 /// not been added to the instance graph.
222 InstanceGraphNode *lookupOrNull(ModuleOpInterface op) {
223 return lookup(op.getModuleNameAttr());
224 }
225
226 /// Look up an InstanceGraphNode for a module. Aborts if the module does not
227 /// exist.
228 InstanceGraphNode *lookup(ModuleOpInterface op) {
229 auto *node = lookupOrNull(op);
230 assert(node != nullptr && "Module not in InstanceGraph!");
231 return node;
232 }
233
234 /// Lookup an module by name. Aborts if the module does not exist.
235 InstanceGraphNode *lookup(StringAttr name) {
236 auto *node = lookupOrNull(name);
237 assert(node != nullptr && "Module not in InstanceGraph!");
238 return node;
239 }
240
241 /// Lookup an InstanceGraphNode for a module.
242 InstanceGraphNode *operator[](ModuleOpInterface op) { return lookup(op); }
243
244 /// Check if child is instantiated by a parent.
245 bool isAncestor(
246 ModuleOpInterface child, ModuleOpInterface parent,
247 llvm::function_ref<bool(InstanceRecord *)> skipInstance =
248 [](InstanceRecord *_) { return false; });
249
250 /// Get the node corresponding to the top-level module of a circuit.
251 virtual InstanceGraphNode *getTopLevelNode() { return nullptr; }
252
253 /// Get the nodes corresponding to the inferred top-level modules of a
254 /// circuit.
255 FailureOr<llvm::ArrayRef<InstanceGraphNode *>> getInferredTopLevelNodes();
256
257 /// Return the parent under which all nodes are nested.
258 Operation *getParent() { return parent; }
259
260 /// Returns pointer to member of operation list.
262 return &InstanceGraph::nodes;
263 }
264
265 /// Iterate through all modules.
267 iterator begin() { return nodes.begin(); }
268 iterator end() { return nodes.end(); }
269
270 /// Perform a post-order walk across the modules. Guaranteed to visit all
271 /// modules. Child modules are visited before their parent modules. If `Fn`
272 /// returns a `LogicalResult`, the walk can be interrupted by returning
273 /// `failure()` from the callback, in which case the overall walk will return
274 /// `failure()`.
275 template <typename Fn>
276 decltype(auto) walkPostOrder(Fn &&fn);
277
278 /// Perform an inverse-post-order walk across the modules. Guaranteed to visit
279 /// all modules. Child modules are visited before their parent modules. If
280 /// `Fn` returns a `LogicalResult`, the walk can be interrupted by returning
281 /// `failure()` from the callback, in which case the overall walk will return
282 /// `failure()`.
283 template <typename Fn>
284 decltype(auto) walkInversePostOrder(Fn &&fn);
285
286 //===-------------------------------------------------------------------------
287 // Methods to keep an InstanceGraph up to date.
288 //
289 // These methods are not thread safe. Make sure that modifications are
290 // properly synchronized or performed in a serial context. When the
291 // InstanceGraph is used as an analysis, this is only safe when the pass is
292 // on a CircuitOp or a ModuleOp.
293
294 /// Add a newly created module to the instance graph.
295 virtual InstanceGraphNode *addModule(ModuleOpInterface module);
296
297 /// Remove this module from the instance graph. This will also remove all
298 /// InstanceRecords in this module. All instances of this module must have
299 /// been removed from the graph.
300 virtual void erase(InstanceGraphNode *node);
301
302 /// Replaces an instance of a module with another instance. The target module
303 /// of both InstanceOps must be the same.
304 virtual void replaceInstance(InstanceOpInterface inst,
305 InstanceOpInterface newInst);
306
307protected:
308 ModuleOpInterface getReferencedModuleImpl(InstanceOpInterface op);
309
310 /// Get the node corresponding to the module. If the node has does not exist
311 /// yet, it will be created.
312 InstanceGraphNode *getOrAddNode(StringAttr name);
313
314 /// The node under which all modules are nested.
315 Operation *parent;
316
317 /// The storage for graph nodes, with deterministic iteration.
319
320 /// This maps each operation to its graph node.
321 llvm::DenseMap<Attribute, InstanceGraphNode *> nodeMap;
322
323 /// A caching of the inferred top level module(s).
324 llvm::SmallVector<InstanceGraphNode *> inferredTopLevelNodes;
325};
326
327//===----------------------------------------------------------------------===//
328// Instance Paths
329//===----------------------------------------------------------------------===//
330
331struct InstancePathCache;
332
333/// An instance path composed of a series of instances.
334class InstancePath final {
335public:
336 InstancePath() = default;
337
338 InstanceOpInterface top() const {
339 assert(!empty() && "instance path is empty");
340 return path[0];
341 }
342
343 InstanceOpInterface leaf() const {
344 assert(!empty() && "instance path is empty");
345 return path.back();
346 }
347
348 InstancePath dropFront() const { return InstancePath(path.drop_front()); }
349
350 InstancePath dropBack() const { return InstancePath(path.drop_back()); }
351
352 InstanceOpInterface operator[](size_t idx) const { return path[idx]; }
353 ArrayRef<InstanceOpInterface>::iterator begin() const { return path.begin(); }
354 ArrayRef<InstanceOpInterface>::iterator end() const { return path.end(); }
355 ArrayRef<InstanceOpInterface> getPath() const { return path; }
356 size_t size() const { return path.size(); }
357 bool empty() const { return path.empty(); }
358
359 bool operator==(const InstancePath &that) const { return path == that.path; }
360
361 /// Print the path to any stream-like object.
362 void print(llvm::raw_ostream &into) const;
363
364private:
365 // Either path cache or DenseMapInfo is allowed to create paths.
366 friend struct InstancePathCache;
367 friend struct llvm::DenseMapInfo<InstancePath>;
368 InstancePath(ArrayRef<InstanceOpInterface> path) : path(path) {}
369
370 ArrayRef<InstanceOpInterface> path;
371};
372
373inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
374 const InstancePath &path) {
375 path.print(os);
376 return os;
377}
378
379/// A data structure that caches and provides paths to module
380/// instances in the IR.
382 /// The instance graph of the IR.
384
387
388 // Return all absolute paths from the top-level node to the given module.
389 ArrayRef<InstancePath> getAbsolutePaths(ModuleOpInterface op);
390
391 // Return all relative paths from the given node to the given module.
392 ArrayRef<InstancePath> getRelativePaths(ModuleOpInterface op,
393 InstanceGraphNode *node);
394
395 /// Replace an InstanceOp. This is required to keep the cache updated.
396 void replaceInstance(InstanceOpInterface oldOp, InstanceOpInterface newOp);
397
398 /// Append an instance to a path.
399 InstancePath appendInstance(InstancePath path, InstanceOpInterface inst);
400
401 /// Prepend an instance to a path.
402 InstancePath prependInstance(InstanceOpInterface inst, InstancePath path);
403
404 /// Concatenate two paths.
406
407private:
408 using PathsCache = DenseMap<Operation *, ArrayRef<InstancePath>>;
409 ArrayRef<InstancePath> getPaths(ModuleOpInterface op, InstanceGraphNode *top,
410 PathsCache &cache);
411
412 /// An allocator for individual instance paths and entire path lists.
413 llvm::BumpPtrAllocator allocator;
414
415 /// Cached absolute instance paths.
417
418 /// Cached relative instance paths.
419 DenseMap<InstanceGraphNode *, PathsCache> relativePathsCache;
420};
421
422} // namespace igraph
423} // namespace circt
424
425//===----------------------------------------------------------------------===//
426// Graph Traits
427//===----------------------------------------------------------------------===//
428
429/// Graph traits for modules.
430template <>
431struct llvm::GraphTraits<circt::igraph::InstanceGraphNode *> {
433 using NodeRef = NodeType *;
434
435 // Helper for getting the module referenced by the instance op.
437 return record->getTarget();
438 }
439
441 llvm::mapped_iterator<NodeType::iterator, decltype(&getChild)>;
442
443 static NodeRef getEntryNode(NodeRef node) { return node; }
445 return {node->begin(), &getChild};
446 }
448 return {node->end(), &getChild};
449 }
450};
451
452/// Graph traits for iterating modules in inverse order.
453template <>
454struct llvm::GraphTraits<llvm::Inverse<circt::igraph::InstanceGraphNode *>> {
456 using NodeRef = NodeType *;
457
458 // Helper for getting the module containing the instance op.
460 return record->getParent();
461 }
462
464 llvm::mapped_iterator<NodeType::UseIterator, decltype(&getParent)>;
465
466 static NodeRef getEntryNode(Inverse<NodeRef> inverse) {
467 return inverse.Graph;
468 }
470 return {node->usesBegin(), &getParent};
471 }
473 return {node->usesEnd(), &getParent};
474 }
475};
476
477/// Graph traits for the instance graph.
478///
479/// **Deprecated:** This uses `getTopLevelNode()` as the root node of the graph,
480/// which does not contain all modules in the instance graph. Instead, the
481/// behaviour is dependent on concrete subclasses of the instance graph. The HW
482/// and FIRRTL dialects define this to be variants of "the top module" and "all
483/// public modules", which is usually not what you want in a pass. You are more
484/// likely to want to visit _all_ modules in the IR in post order (children
485/// before parents), not just a subset of the modules depending on whether
486/// things are transitively instantiated. Use `walkPostOrder` or
487/// `walkInversePostOrder` on `InstanceGraph` instead.
488template <>
489struct llvm::GraphTraits<circt::igraph::InstanceGraph *>
490 : public llvm::GraphTraits<circt::igraph::InstanceGraphNode *> {
492
494 return graph->getTopLevelNode();
495 }
496 // NOLINTNEXTLINE(readability-identifier-naming)
498 return graph->begin();
499 }
500 // NOLINTNEXTLINE(readability-identifier-naming)
502 return graph->end();
503 }
504};
505
506// Graph traits for DOT labeling.
507template <>
508struct llvm::DOTGraphTraits<circt::igraph::InstanceGraph *>
509 : public llvm::DefaultDOTGraphTraits {
510 using DefaultDOTGraphTraits::DefaultDOTGraphTraits;
511
514 // The name of the graph node is the module name.
515 return node->getModule().getModuleName().str();
516 }
517
518 template <typename Iterator>
519 static std::string
522 // Set an edge label that is the name of the instance.
523 auto *instanceRecord = *it.getCurrent();
524 auto instanceOp = instanceRecord->getInstance();
525 return ("label=" + instanceOp.getInstanceName()).str();
526 }
527};
528
529//===----------------------------------------------------------------------===//
530// Graph Iterators
531//===----------------------------------------------------------------------===//
532
533namespace circt {
534namespace igraph {
535
536// These are defined out-of-line here since they need the graph traits to have
537// been defined.
538
539template <typename Fn>
540decltype(auto) InstanceGraph::walkPostOrder(Fn &&fn) {
541 constexpr bool fallible =
542 std::is_invocable_r_v<LogicalResult, Fn &, InstanceGraphNode &>;
543 DenseSet<InstanceGraphNode *> visited;
544 for (auto &root : nodes) {
545 for (auto *node : llvm::post_order_ext(&root, visited)) {
546 if constexpr (fallible) {
547 if (failed(fn(*node)))
548 return failure();
549 } else {
550 fn(*node);
551 }
552 }
553 }
554 if constexpr (fallible)
555 return success();
556}
557
558template <typename Fn>
559decltype(auto) InstanceGraph::walkInversePostOrder(Fn &&fn) {
560 constexpr bool fallible =
561 std::is_invocable_r_v<LogicalResult, Fn &, InstanceGraphNode &>;
562 DenseSet<InstanceGraphNode *> visited;
563 for (auto &root : nodes) {
564 for (auto *node : llvm::inverse_post_order_ext(&root, visited)) {
565 if constexpr (fallible) {
566 if (failed(fn(*node)))
567 return failure();
568 } else {
569 fn(*node);
570 }
571 }
572 }
573 if constexpr (fallible)
574 return success();
575}
576
577} // namespace igraph
578} // namespace circt
579
580//===----------------------------------------------------------------------===//
581// Dense Map Traits
582//===----------------------------------------------------------------------===//
583
584/// DenseMap traits for InstancePath.
585template <>
586struct llvm::DenseMapInfo<circt::igraph::InstancePath> {
589
590 static llvm::hash_code getHashValue(circt::igraph::InstancePath path) {
591 auto range =
592 llvm::map_range(path, [](auto op) { return op.getAsOpaquePointer(); });
593 return llvm::hash_combine_range(range.begin(), range.end());
594 }
595
598 return ArrayRefInfo::isEqual(lhs.getPath(), rhs.getPath());
599 }
600};
601
602#endif // CIRCT_SUPPORT_INSTANCEGRAPH_H
assert(baseType &&"element must be base type")
false return failure()
Parse an optional keyword or string and set instance into 'result'.
return success()
This is a Node in the InstanceGraph.
llvm::iterator_range< UseIterator > uses()
detail::AddressIterator< InstanceList::iterator > iterator
Iterate the instance records in this module.
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.
InstanceList instances
List of instance operations in this module.
UseIterator usesBegin()
Iterate the instance records which instantiate this module.
llvm::iplist< InstanceRecord > InstanceList
friend class InstanceGraph
Iterates over the handshake::FuncOp's in the program to build an instance graph.
size_t getNumUses()
Get the number of direct instantiations of this module.
ModuleOpInterface module
The 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
InstanceGraphNode * lookupOrNull(StringAttr name)
Lookup an module by name.
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.
decltype(auto) walkPostOrder(Fn &&fn)
Perform a post-order walk across the modules.
InstanceGraphNode * lookup(ModuleOpInterface op)
Look up an InstanceGraphNode for a module.
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(StringAttr name)
Lookup an module by name. Aborts if the module does not exist.
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.
InstanceGraphNode * lookupOrNull(ModuleOpInterface op)
Look up an InstanceGraphNode for a module.
decltype(auto) walkInversePostOrder(Fn &&fn)
Perform an inverse-post-order walk across the modules.
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
ArrayRef< InstanceOpInterface > getPath() const
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.
friend class InstanceGraph
Iterates over the handshake::FuncOp's in the program to build an instance graph.
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.
bool operator==(const UseIterator &other) const
A data structure that caches and provides paths to module instances in the IR.
ArrayRef< InstancePath > getPaths(ModuleOpInterface op, InstanceGraphNode *top, PathsCache &cache)
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)
DenseMap< Operation *, ArrayRef< InstancePath > > PathsCache
ArrayRef< InstancePath > getRelativePaths(ModuleOpInterface op, InstanceGraphNode *node)
DenseMap< InstanceGraphNode *, PathsCache > relativePathsCache
Cached relative instance paths.
void replaceInstance(InstanceOpInterface oldOp, InstanceOpInterface newOp)
Replace an InstanceOp. This is required to keep the cache updated.
InstancePath prependInstance(InstanceOpInterface inst, InstancePath path)
Prepend an instance to a path.
InstancePath appendInstance(InstancePath path, InstanceOpInterface inst)
Append an instance to a path.
InstancePath concatPath(InstancePath path1, InstancePath path2)
Concatenate two paths.
llvm::BumpPtrAllocator allocator
An allocator for individual instance paths and entire path lists.
InstanceGraph & instanceGraph
The instance graph of the IR.
PathsCache absolutePathsCache
Cached absolute instance paths.
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
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 bool isEqual(circt::igraph::InstancePath lhs, circt::igraph::InstancePath rhs)
static llvm::hash_code getHashValue(circt::igraph::InstancePath path)
llvm::DenseMapInfo< ArrayRef< circt::igraph::InstanceOpInterface > > ArrayRefInfo
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)
circt::igraph::InstanceGraph::iterator nodes_iterator
static nodes_iterator nodes_end(circt::igraph::InstanceGraph *graph)
static NodeRef getParent(const circt::igraph::InstanceRecord *record)
llvm::mapped_iterator< NodeType::UseIterator, decltype(&getParent)> ChildIteratorType