CIRCT 22.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");
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> {
590 return circt::igraph::InstancePath(ArrayRefInfo::getEmptyKey());
591 }
592
594 return circt::igraph::InstancePath(ArrayRefInfo::getTombstoneKey());
595 }
596
597 static llvm::hash_code getHashValue(circt::igraph::InstancePath path) {
598 auto range =
599 llvm::map_range(path, [](auto op) { return op.getAsOpaquePointer(); });
600 return llvm::hash_combine_range(range.begin(), range.end());
601 }
602
605 return ArrayRefInfo::isEqual(lhs.getPath(), rhs.getPath());
606 }
607};
608
609#endif // CIRCT_SUPPORT_INSTANCEGRAPH_H
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
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.
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)
DenseMap< Operation *, ArrayRef< InstancePath > > PathsCache
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)
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 circt::igraph::InstancePath getTombstoneKey()
static bool isEqual(circt::igraph::InstancePath lhs, circt::igraph::InstancePath rhs)
static llvm::hash_code getHashValue(circt::igraph::InstancePath path)
static circt::igraph::InstancePath getEmptyKey()
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)