Jlm
Loading...
Searching...
No Matches
region.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2010 2011 2012 Helge Bahmann <hcb@chaoticmind.net>
3 * Copyright 2012 2013 2014 2015 2016 Nico Reißmann <nico.reissmann@gmail.com>
4 * See COPYING for terms of redistribution.
5 */
6
8#include <jlm/rvsdg/graph.hpp>
13#include <jlm/util/file.hpp>
14#include <jlm/util/Program.hpp>
15#include <jlm/util/strfmt.hpp>
16
17#include <algorithm>
18#include <fstream>
19
20namespace jlm::rvsdg
21{
22
28
30 rvsdg::Region * region,
31 StructuralInput * input,
32 std::shared_ptr<const rvsdg::Type> type)
33 : Output(region, std::move(type)),
34 input_(input)
35{
36 if (input)
37 {
38 if (input->node() != region->node())
39 throw util::Error("Argument cannot be added to input.");
40
41 if (*input->Type() != *Type())
42 {
43 throw util::TypeError(Type()->debug_string(), input->Type()->debug_string());
44 }
45
47 }
48}
49
50std::string
52{
53 return util::strfmt("a", index());
54}
55
58{
59 return Create(region, input, Type());
60}
61
64 rvsdg::Region & region,
65 StructuralInput * input,
66 std::shared_ptr<const rvsdg::Type> type)
67{
68 return region.addArgument(std::make_unique<RegionArgument>(&region, input, std::move(type)));
69}
70
76
78 rvsdg::Region * region,
79 jlm::rvsdg::Output * origin,
80 StructuralOutput * output,
81 std::shared_ptr<const rvsdg::Type> type)
82 : Input(*region, *origin, std::move(type)),
83 output_(output)
84{
85 if (output)
86 {
87 if (output->node() != region->node())
88 throw util::Error("Result cannot be added to output.");
89
90 if (*Type() != *output->Type())
91 {
92 throw jlm::util::TypeError(Type()->debug_string(), output->Type()->debug_string());
93 }
94
96 }
97}
98
99std::string
101{
102 return util::strfmt("r", index());
103}
104
107{
108 return Create(*origin.region(), origin, output, origin.Type());
109}
110
113 rvsdg::Region & region,
114 rvsdg::Output & origin,
115 StructuralOutput * output,
116 std::shared_ptr<const rvsdg::Type> type)
117{
118 return region.addResult(
119 std::make_unique<RegionResult>(&region, &origin, output, std::move(type)));
120}
121
123{
124 util::HashSet<size_t> indices;
125 for (size_t n = 0; n < nresults(); n++)
126 indices.insert(n);
127 RemoveResults(indices);
128 JLM_ASSERT(nresults() == 0);
129
130 prune(false);
131 JLM_ASSERT(numNodes() == 0);
132 JLM_ASSERT(numTopNodes() == 0);
134
136 JLM_ASSERT(narguments() == 0);
137
138 // Disconnect observers
139 while (observers_)
140 {
143 head->pprev_ = &head->next_;
144 head->next_ = nullptr;
145 }
146}
147
149 : graph_(graph),
150 id_(graph->generateRegionId()),
151 depth_(0),
152 node_(nullptr),
153 index_(0),
154 nextNodeId_(0),
155 numTopNodes_(0),
156 numBottomNodes_(0),
157 numNodes_(0)
158{}
159
160Region::Region(StructuralNode * node, const size_t index)
161 : graph_(node->graph()),
162 id_(node->graph()->generateRegionId()),
163 depth_(node->region()->getDepth() + 1),
164 node_(node),
165 index_(index),
166 nextNodeId_(0),
167 numTopNodes_(0),
168 numBottomNodes_(0),
169 numNodes_(0)
170{}
171
172bool
174{
175 return &this->graph()->GetRootRegion() == this;
176}
177
179Region::addArgument(std::unique_ptr<RegionArgument> argument)
180{
181 if (argument->region() != this)
182 throw util::Error("Appending argument to wrong region.");
183
185 arguments_.push_back(argument.release());
186 return *arguments_.back();
187}
188
190Region::insertArgument(size_t index, std::unique_ptr<RegionArgument> argument)
191{
192 if (argument->region() != this)
193 throw util::Error("Inserting argument to wrong region.");
194
195 if (index > narguments())
196 throw util::Error("Inserting argument after end of region.");
197
198 arguments_.push_back(nullptr);
199
200 // Move everything at index or above one index up
201 for (size_t n = narguments() - 1; n > index; n--)
202 {
203 arguments_[n] = arguments_[n - 1];
204 arguments_[n]->index_ = n;
205 }
206 arguments_[index] = argument.release();
208
209 return *arguments_[index];
210}
211
212size_t
214{
215 if (indices.IsEmpty())
216 return 0;
217
218 // Remove arguments
219 size_t numLiveArguments = 0;
220 size_t numRemovedArguments = 0;
221 for (size_t n = 0; n < narguments(); n++)
222 {
223 auto argument = arguments_[n];
224 if (argument->IsDead() && indices.Contains(argument->index()))
225 {
226 delete argument;
228 }
229 else
230 {
233 }
234 }
236
237 return numRemovedArguments;
238}
239
240size_t
242{
243 size_t numLiveArguments = 0;
244 size_t numRemovedArguments = 0;
245 for (size_t n = 0; n < narguments(); n++)
246 {
247 auto argument = arguments_[n];
248 if (argument->IsDead())
249 {
250 delete argument;
252 }
253 else
254 {
257 }
258 }
260
261 return numRemovedArguments;
262}
263
265Region::addResult(std::unique_ptr<RegionResult> result)
266{
267 const auto resultPtr = result.release();
268
269 if (resultPtr->region() != this)
270 throw util::Error("Appending result to wrong region.");
271
272 resultPtr->index_ = nresults();
273 results_.push_back(resultPtr);
274
276
277 return *resultPtr;
278}
279
280size_t
282{
283 if (indices.IsEmpty())
284 return 0;
285
286 size_t numLiveResults = 0;
287 size_t numRemovedResults = 0;
288 for (size_t n = 0; n < nresults(); n++)
289 {
290 const auto result = results_[n];
291 if (indices.Contains(result->index()))
292 {
294 delete result;
296 }
297 else
298 {
301 }
302 }
303 results_.resize(numLiveResults);
304
305 return numRemovedResults;
306}
307
308void
310{
311 JLM_ASSERT(node->region() == this);
312 // The node's destructor handles informing the region about removal
313 delete node;
314}
315
316void
318{
319 for (const auto node : TopDownConstTraverser(this))
320 {
321 node->copy(target, smap);
322 }
323}
324
325void
327{
328 while (bottomNodes_.first())
330
331 if (!recursive)
332 return;
333
334 for (const auto & node : Nodes())
335 {
336 if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
337 {
338 for (size_t n = 0; n < snode->nsubregions(); n++)
339 snode->subregion(n)->prune(recursive);
340 }
341 }
342}
343
344void
359
360void
362{
363 JLM_ASSERT(node.region() == this);
364 JLM_ASSERT(node.ninputs() == 0);
366 numTopNodes_++;
367}
368
369void
371{
372 JLM_ASSERT(node.region() == this);
374 numTopNodes_--;
375}
376
377void
385
386void
393
394void
396{
397 JLM_ASSERT(node.region() == this);
399 numNodes_++;
400}
401
402void
404{
405 JLM_ASSERT(node.region() == this);
406 nodes_.erase(&node);
407 numNodes_--;
408}
409
410void
412{
414 {
415 observer->onNodeCreate(node);
416 }
417}
418
419void
421{
423 {
424 observer->onNodeDestroy(node);
425 }
426}
427
428void
430{
432 {
433 observer->onInputCreate(input);
434 }
435}
436
437void
439{
441 {
442 observer->onInputChange(input, old_origin, new_origin);
443 }
444}
445
446void
448{
450 {
451 observer->onInputDestroy(input);
452 }
453}
454
455size_t
456Region::NumRegions(const rvsdg::Region & region) noexcept
457{
458 size_t numRegions = 1;
459 for (auto & node : region.Nodes())
460 {
461 if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
462 {
463 for (size_t n = 0; n < structuralNode->nsubregions(); n++)
464 {
465 numRegions += NumRegions(*structuralNode->subregion(n));
466 }
467 }
468 }
469
470 return numRegions;
471}
472
473bool
474Region::isAncestor(const Region & region, const Region & ancestor) noexcept
475{
476 const auto ancestorDepth = ancestor.getDepth();
477 // If region starts at the same level or higher than ancestor, it can not be an ancestor
478 if (region.getDepth() <= ancestorDepth)
479 return false;
480
481 // Follow the parent chain until the ancestor depth is reached
482 auto current = &region;
483 do
484 {
485 current = current->node()->region();
486 } while (current->getDepth() > ancestorDepth);
487
488 return current == &ancestor;
489}
490
491std::string
493{
494 std::stringstream stream{};
495 toJson(region, annotationMap, stream);
496 return stream.str();
497}
498
499std::string
500Region::toJson(const Region & region) noexcept
501{
502 std::stringstream stream{};
504 toJson(region, annotationMap, stream);
505 return stream.str();
506}
507
508void
510 const Region & region,
512 std::stringstream & stream) noexcept
513{
514 stream << '{';
515
516 if (annotationMap.HasAnnotations(&region))
517 {
518 auto annotations = annotationMap.GetAnnotations(&region);
519 std::sort(
520 annotations.begin(),
521 annotations.end(),
522 [](const util::Annotation & a, const util::Annotation & b)
523 {
524 return a.Label() < b.Label();
525 });
526
527 bool first = true;
528 for (const auto & annotation : annotations)
529 {
530 if (first)
531 first = false;
532 else
533 stream << ',';
534
535 stream << toJsonKeyValue(annotation);
536 }
537 }
538
539 std::vector<const StructuralNode *> structuralNodes;
540 for (auto & node : region.Nodes())
541 {
542 if (const auto structuralNode = dynamic_cast<const StructuralNode *>(&node))
543 {
545 }
546 }
547
548 if (!structuralNodes.empty())
549 {
550 if (annotationMap.HasAnnotations(&region))
551 stream << ",";
552
553 bool firstNode = true;
554 stream << "\"StructuralNodes\":[";
555 for (const auto & structuralNode : structuralNodes)
556 {
557 if (firstNode)
558 firstNode = false;
559 else
560 stream << ",";
561
563 }
564 stream << "]";
565 }
566 stream << "}";
567}
568
569void
573 std::stringstream & stream) noexcept
574{
575 stream << '{';
576 stream << "\"DebugString\":\"" << structuralNode.DebugString() << "\"";
577 if (annotationMap.HasAnnotations(&structuralNode))
578 {
579 stream << ",";
580
581 auto annotations = annotationMap.GetAnnotations(&structuralNode);
582 std::sort(
583 annotations.begin(),
584 annotations.end(),
585 [](const util::Annotation & a, const util::Annotation & b)
586 {
587 return a.Label() < b.Label();
588 });
589
590 bool first = true;
591 for (const auto & annotation : annotations)
592 {
593 if (first)
594 first = false;
595 else
596 stream << ",";
597
598 stream << toJsonKeyValue(annotation);
599 }
600 }
601 stream << ",";
602
603 if (structuralNode.nsubregions() != 0)
604 {
605 bool firstSubregion = true;
606 stream << "\"Subregions\":[";
607 for (auto & subregion : structuralNode.Subregions())
608 {
609 if (firstSubregion)
610 firstSubregion = false;
611 else
612 stream << ",";
613
614 toJson(subregion, annotationMap, stream);
615 }
616 stream << "]";
617 }
618 stream << "}";
619}
620
621std::string
623{
624 std::string value;
625 if (annotation.HasValueType<std::string>())
626 {
627 value = util::strfmt("\"", annotation.Value<std::string>(), "\"");
628 }
629 else if (annotation.HasValueType<int64_t>())
630 {
631 value = util::strfmt(annotation.Value<int64_t>());
632 }
633 else if (annotation.HasValueType<uint64_t>())
634 {
635 value = util::strfmt(annotation.Value<uint64_t>());
636 }
637 else if (annotation.HasValueType<double>())
638 {
639 value = util::strfmt(annotation.Value<double>());
640 }
641 else
642 {
643 JLM_UNREACHABLE("Unhandled annotation type.");
644 }
645
646 return util::strfmt("\"", annotation.Label(), "\":", value);
647}
648
649std::string
651{
652 std::stringstream stream;
653 ToTree(region, annotationMap, 0, stream);
654 return stream.str();
655}
656
657std::string
658Region::ToTree(const rvsdg::Region & region) noexcept
659{
660 std::stringstream stream;
662 ToTree(region, annotationMap, 0, stream);
663 return stream.str();
664}
665
666void
668 const rvsdg::Region & region,
670 size_t indentationDepth,
671 std::stringstream & stream) noexcept
672{
673 static const char indentationChar = '-';
674 static const char annotationSeparator = ' ';
675 static const char labelValueSeparator = ':';
676
677 // Convert current region to a string
679 auto regionString =
680 region.IsRootRegion() ? "RootRegion" : util::strfmt("Region[", region.index(), "]");
682 GetAnnotationString(&region, annotationMap, annotationSeparator, labelValueSeparator);
683
685
686 // Convert the region's structural nodes with their subregions to a string
689 for (auto & node : region.Nodes())
690 {
691 if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
692 {
693 auto nodeString = structuralNode->DebugString();
694 auto annotationString = GetAnnotationString(
700
701 for (size_t n = 0; n < structuralNode->nsubregions(); n++)
702 {
703 ToTree(*structuralNode->subregion(n), annotationMap, indentationDepth + 1, stream);
704 }
705 }
706 }
707}
708
709std::string
711 const void * key,
715{
716 if (!annotationMap.HasAnnotations(key))
717 return "";
718
719 auto & annotations = annotationMap.GetAnnotations(key);
721}
722
723std::string
725 const std::vector<util::Annotation> & annotations,
728{
729 std::stringstream stream;
730 for (auto & annotation : annotations)
731 {
734 }
735
736 return stream.str();
737}
738
739std::string
741{
742 std::string value;
743 if (annotation.HasValueType<std::string>())
744 {
745 value = annotation.Value<std::string>();
746 }
747 else if (annotation.HasValueType<int64_t>())
748 {
749 value = util::strfmt(annotation.Value<int64_t>());
750 }
751 else if (annotation.HasValueType<uint64_t>())
752 {
753 value = util::strfmt(annotation.Value<uint64_t>());
754 }
755 else if (annotation.HasValueType<double>())
756 {
757 value = util::strfmt(annotation.Value<double>());
758 }
759 else
760 {
761 JLM_UNREACHABLE("Unhandled annotation type.");
762 }
763
764 return util::strfmt(annotation.Label(), labelValueSeparator, value);
765}
766
768{
769 *pprev_ = next_;
770 if (next_)
771 {
773 }
774}
775
777{
778 next_ = region.observers_;
779 if (next_)
780 {
781 next_->pprev_ = &next_;
782 }
783 pprev_ = &region.observers_;
784 region.observers_ = this;
785}
786
787std::unordered_map<const Node *, size_t>
788computeDepthMap(const Region & region)
789{
790 std::unordered_map<const Node *, size_t> depthMap;
791 for (const auto node : TopDownConstTraverser(&region))
792 {
793 size_t depth = 0;
794 for (auto & input : node->Inputs())
795 {
796 if (const auto owner = TryGetOwnerNode<Node>(*input.origin()))
797 {
798 depth = std::max(depth, depthMap[owner] + 1);
799 }
800 }
801 depthMap[node] = depth;
802 }
803
804 return depthMap;
805}
806
807size_t
808nnodes(const jlm::rvsdg::Region * region) noexcept
809{
810 size_t n = region->numNodes();
811 for (const auto & node : region->Nodes())
812 {
813 if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
814 {
815 for (size_t r = 0; r < snode->nsubregions(); r++)
816 n += nnodes(snode->subregion(r));
817 }
818 }
819
820 return n;
821}
822
823size_t
824nstructnodes(const rvsdg::Region * region) noexcept
825{
826 size_t n = 0;
827 for (const auto & node : region->Nodes())
828 {
829 if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
830 {
831 for (size_t r = 0; r < snode->nsubregions(); r++)
832 n += nstructnodes(snode->subregion(r));
833 n += 1;
834 }
835 }
836
837 return n;
838}
839
840size_t
841nsimpnodes(const rvsdg::Region * region) noexcept
842{
843 size_t n = 0;
844 for (const auto & node : region->Nodes())
845 {
846 if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
847 {
848 for (size_t r = 0; r < snode->nsubregions(); r++)
849 n += nsimpnodes(snode->subregion(r));
850 }
851 else
852 {
853 n += 1;
854 }
855 }
856
857 return n;
858}
859
860size_t
861ninputs(const rvsdg::Region * region) noexcept
862{
863 size_t n = region->nresults();
864 for (const auto & node : region->Nodes())
865 {
866 if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
867 {
868 for (size_t r = 0; r < snode->nsubregions(); r++)
869 n += ninputs(snode->subregion(r));
870 }
871 n += node.ninputs();
872 }
873
874 return n;
875}
876
877} // namespace
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
size_t index() const noexcept
Definition node.hpp:52
Output * origin() const noexcept
Definition node.hpp:58
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:67
Region * region() const noexcept
Definition node.cpp:83
bool IsDead() const noexcept
Determines whether the node is dead.
Definition node.hpp:688
rvsdg::Region * region() const noexcept
Definition node.hpp:761
size_t ninputs() const noexcept
Definition node.hpp:609
virtual Node * copy(rvsdg::Region *region, const std::vector< jlm::rvsdg::Output * > &operands) const
Definition node.cpp:369
rvsdg::Region * region() const noexcept
Definition node.cpp:151
size_t index() const noexcept
Definition node.hpp:274
bool IsDead() const noexcept
Definition node.hpp:295
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
Represents the argument of a region.
Definition region.hpp:41
RegionArgument(rvsdg::Region *region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Definition region.cpp:29
std::string debug_string() const override
Definition region.cpp:51
virtual RegionArgument & Copy(Region &region, StructuralInput *input) const
Definition region.cpp:57
~RegionArgument() noexcept override
Definition region.cpp:23
static RegionArgument & Create(rvsdg::Region &region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
Definition region.cpp:63
StructuralInput * input() const noexcept
Definition region.hpp:69
Proxy object to observe changes to a region.
Definition region.hpp:886
virtual ~RegionObserver() noexcept
Definition region.cpp:767
RegionObserver ** pprev_
Definition region.hpp:939
RegionObserver * next_
Definition region.hpp:940
RegionObserver(const Region &region)
Definition region.cpp:776
Represents the result of a region.
Definition region.hpp:120
RegionResult(rvsdg::Region *region, rvsdg::Output *origin, StructuralOutput *output, std::shared_ptr< const rvsdg::Type > type)
Definition region.cpp:77
StructuralOutput * output() const noexcept
Definition region.hpp:149
~RegionResult() noexcept override
Definition region.cpp:71
virtual RegionResult & Copy(rvsdg::Output &origin, StructuralOutput *output) const
Definition region.cpp:106
std::string debug_string() const override
Definition region.cpp:100
static RegionResult & Create(rvsdg::Region &region, rvsdg::Output &origin, StructuralOutput *output, std::shared_ptr< const rvsdg::Type > type)
Create region exit result.
Definition region.cpp:112
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
size_t RemoveResults(const util::HashSet< size_t > &indices)
Definition region.cpp:281
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
RegionArgument & addArgument(std::unique_ptr< RegionArgument > argument)
Definition region.cpp:179
void notifyNodeDestroy(Node *node)
Definition region.cpp:420
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition region.cpp:317
Graph * graph() const noexcept
Definition region.hpp:267
static std::string ToString(const std::vector< util::Annotation > &annotations, char annotationSeparator, char labelValueSeparator)
Definition region.cpp:724
size_t numNodes() const noexcept
Definition region.hpp:510
region_nodes_list nodes_
Definition region.hpp:860
void view() const
Definition region.cpp:345
static std::string toJson(const Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition region.cpp:492
static std::string ToTree(const rvsdg::Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition region.cpp:650
void onNodeRemoved(Node &node)
Definition region.cpp:403
void onNodeAdded(Node &node)
Adds node to the list of nodes in the region.
Definition region.cpp:395
void notifyInputChange(Input *input, Output *old_origin, Output *new_origin)
Definition region.cpp:438
size_t numBottomNodes_
Definition region.hpp:859
size_t nresults() const noexcept
Definition region.hpp:494
RegionObserver * observers_
Definition region.hpp:867
std::vector< RegionResult * > results_
Definition region.hpp:854
RegionResult & addResult(std::unique_ptr< RegionResult > result)
Definition region.cpp:265
void prune(bool recursive)
Definition region.cpp:326
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
std::vector< RegionArgument * > arguments_
Definition region.hpp:855
void onBottomNodeRemoved(Node &node)
Definition region.cpp:387
size_t index() const noexcept
Definition region.hpp:310
static std::string GetAnnotationString(const void *key, const util::AnnotationMap &annotationMap, char annotationSeparator, char labelValueSeparator)
Definition region.cpp:710
void notifyNodeCreate(Node *node)
Definition region.cpp:411
size_t numTopNodes() const noexcept
Definition region.hpp:519
bool IsRootRegion() const noexcept
Definition region.cpp:173
static size_t NumRegions(const rvsdg::Region &region) noexcept
Definition region.cpp:456
void onTopNodeRemoved(Node &node)
Definition region.cpp:370
rvsdg::StructuralNode * node() const noexcept
Definition region.hpp:301
Region(Graph *graph)
Definition region.cpp:148
size_t numBottomNodes() const noexcept
Definition region.hpp:528
~Region() noexcept
Definition region.cpp:122
size_t RemoveArguments(const util::HashSet< size_t > &indices)
Definition region.cpp:213
void removeNode(Node *node)
Definition region.cpp:309
static bool isAncestor(const rvsdg::Region &region, const rvsdg::Region &ancestor) noexcept
Definition region.cpp:474
region_top_node_list topNodes_
Definition region.hpp:856
void onTopNodeAdded(Node &node)
Adds node to the top nodes of the region.
Definition region.cpp:361
region_bottom_node_list bottomNodes_
Definition region.hpp:858
NodeRange Nodes() noexcept
Definition region.hpp:375
void notifyInputDestroy(Input *input)
Definition region.cpp:447
void notifyInputCreate(Input *input)
Definition region.cpp:429
RegionArgument & insertArgument(size_t index, std::unique_ptr< RegionArgument > argument)
Definition region.cpp:190
static std::string toJsonKeyValue(const util::Annotation &annotation) noexcept
Definition region.cpp:622
size_t narguments() const noexcept
Definition region.hpp:460
void onBottomNodeAdded(Node &node)
Adds node to the set of bottom nodes in the region.
Definition region.cpp:378
size_t PruneArguments()
Definition region.cpp:241
StructuralNode * node() const noexcept
StructuralNode * node() const noexcept
static FilePath createUniqueFileName(const FilePath &directory, const std::string &fileNamePrefix, const std::string &fileNameSuffix)
Generates a unique file in a given directory with a prefix and suffix.
Definition file.hpp:301
static FilePath TempDirectoryPath()
Definition file.hpp:317
bool insert(ItemType item)
Definition HashSet.hpp:210
bool Contains(const ItemType &item) const noexcept
Definition HashSet.hpp:150
bool IsEmpty() const noexcept
Definition HashSet.hpp:198
ElementType * first() const noexcept
void erase(ElementType *element) noexcept
void push_back(ElementType *element) noexcept
#define JLM_ASSERT(x)
Definition common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
size_t nsimpnodes(const rvsdg::Region *region) noexcept
Definition region.cpp:841
size_t nstructnodes(const rvsdg::Region *region) noexcept
Definition region.cpp:824
std::unordered_map< const Node *, size_t > computeDepthMap(const Region &region)
Definition region.cpp:788
detail::TopDownTraverserGeneric< true > TopDownConstTraverser
Traverser for visiting every node in a const region in a top down order.
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
Definition region.cpp:808
size_t ninputs(const rvsdg::Region *region) noexcept
Definition region.cpp:861
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
std::string getDotViewer()
Definition Program.cpp:42
static std::string strfmt(Args... args)
Definition strfmt.hpp:35
int executeProgramAndWait(const std::string &programName, const std::vector< std::string > &programArguments)
Definition Program.cpp:18