Jlm
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>
11 #include <jlm/rvsdg/traverser.hpp>
13 #include <jlm/util/file.hpp>
14 #include <jlm/util/Program.hpp>
15 #include <jlm/util/strfmt.hpp>
16 
17 #include <fstream>
18 
19 namespace jlm::rvsdg
20 {
21 
23 {
24  if (input())
25  input()->arguments.erase(this);
26 }
27 
29  rvsdg::Region * region,
30  StructuralInput * input,
31  std::shared_ptr<const rvsdg::Type> type)
32  : Output(region, std::move(type)),
33  input_(input)
34 {
35  if (input)
36  {
37  if (input->node() != region->node())
38  throw util::Error("Argument cannot be added to input.");
39 
40  if (*input->Type() != *Type())
41  {
42  throw util::TypeError(Type()->debug_string(), input->Type()->debug_string());
43  }
44 
45  input->arguments.push_back(this);
46  }
47 }
48 
49 std::string
51 {
52  return util::strfmt("a", index());
53 }
54 
57 {
58  return Create(region, input, Type());
59 }
60 
63  rvsdg::Region & region,
64  StructuralInput * input,
65  std::shared_ptr<const rvsdg::Type> type)
66 {
67  return region.addArgument(std::make_unique<RegionArgument>(&region, input, std::move(type)));
68 }
69 
71 {
72  if (output())
73  output()->results.erase(this);
74 }
75 
77  rvsdg::Region * region,
78  jlm::rvsdg::Output * origin,
79  StructuralOutput * output,
80  std::shared_ptr<const rvsdg::Type> type)
81  : Input(*region, *origin, std::move(type)),
82  output_(output)
83 {
84  if (output)
85  {
86  if (output->node() != region->node())
87  throw util::Error("Result cannot be added to output.");
88 
89  if (*Type() != *output->Type())
90  {
91  throw jlm::util::TypeError(Type()->debug_string(), output->Type()->debug_string());
92  }
93 
94  output->results.push_back(this);
95  }
96 }
97 
98 std::string
100 {
101  return util::strfmt("r", index());
102 }
103 
104 RegionResult &
106 {
107  return Create(*origin.region(), origin, output, origin.Type());
108 }
109 
110 RegionResult &
112  rvsdg::Region & region,
113  rvsdg::Output & origin,
114  StructuralOutput * output,
115  std::shared_ptr<const rvsdg::Type> type)
116 {
117  return region.addResult(
118  std::make_unique<RegionResult>(&region, &origin, output, std::move(type)));
119 }
120 
121 Region::~Region() noexcept
122 {
123  util::HashSet<size_t> indices;
124  for (size_t n = 0; n < nresults(); n++)
125  indices.insert(n);
126  RemoveResults(indices);
127  JLM_ASSERT(nresults() == 0);
128 
129  prune(false);
130  JLM_ASSERT(numNodes() == 0);
131  JLM_ASSERT(numTopNodes() == 0);
132  JLM_ASSERT(numBottomNodes() == 0);
133 
134  PruneArguments();
135  JLM_ASSERT(narguments() == 0);
136 
137  // Disconnect observers
138  while (observers_)
139  {
140  RegionObserver * head = observers_;
141  observers_ = head->next_;
142  head->pprev_ = &head->next_;
143  head->next_ = nullptr;
144  }
145 }
146 
148  : id_(graph->generateRegionId()),
149  index_(0),
150  graph_(graph),
151  nextNodeId_(0),
152  node_(nullptr),
153  numTopNodes_(0),
154  numBottomNodes_(0),
155  numNodes_(0)
156 {}
157 
158 Region::Region(StructuralNode * node, const size_t index)
159  : id_(node->graph()->generateRegionId()),
160  index_(index),
161  graph_(node->graph()),
162  nextNodeId_(0),
163  node_(node),
164  numTopNodes_(0),
165  numBottomNodes_(0),
166  numNodes_(0)
167 {}
168 
169 bool
170 Region::IsRootRegion() const noexcept
171 {
172  return &this->graph()->GetRootRegion() == this;
173 }
174 
176 Region::addArgument(std::unique_ptr<RegionArgument> argument)
177 {
178  if (argument->region() != this)
179  throw util::Error("Appending argument to wrong region.");
180 
182  arguments_.push_back(argument.release());
183  return *arguments_.back();
184 }
185 
187 Region::insertArgument(size_t index, std::unique_ptr<RegionArgument> argument)
188 {
189  if (argument->region() != this)
190  throw util::Error("Inserting argument to wrong region.");
191 
192  if (index > narguments())
193  throw util::Error("Inserting argument after end of region.");
194 
195  arguments_.push_back(nullptr);
196 
197  // Move everything at index or above one index up
198  for (size_t n = narguments() - 1; n > index; n--)
199  {
200  arguments_[n] = arguments_[n - 1];
201  arguments_[n]->index_ = n;
202  }
203  arguments_[index] = argument.release();
204  arguments_[index]->index_ = index;
205 
206  return *arguments_[index];
207 }
208 
209 size_t
211 {
212  if (indices.IsEmpty())
213  return 0;
214 
215  // Remove arguments
216  size_t numLiveArguments = 0;
217  size_t numRemovedArguments = 0;
218  for (size_t n = 0; n < narguments(); n++)
219  {
220  auto argument = arguments_[n];
221  if (argument->IsDead() && indices.Contains(argument->index()))
222  {
223  delete argument;
224  numRemovedArguments++;
225  }
226  else
227  {
228  argument->index_ = numLiveArguments;
229  arguments_[numLiveArguments++] = argument;
230  }
231  }
232  arguments_.resize(numLiveArguments);
233 
234  return numRemovedArguments;
235 }
236 
237 size_t
239 {
240  size_t numLiveArguments = 0;
241  size_t numRemovedArguments = 0;
242  for (size_t n = 0; n < narguments(); n++)
243  {
244  auto argument = arguments_[n];
245  if (argument->IsDead())
246  {
247  delete argument;
248  numRemovedArguments++;
249  }
250  else
251  {
252  argument->index_ = numLiveArguments;
253  arguments_[numLiveArguments++] = argument;
254  }
255  }
256  arguments_.resize(numLiveArguments);
257 
258  return numRemovedArguments;
259 }
260 
261 RegionResult &
262 Region::addResult(std::unique_ptr<RegionResult> result)
263 {
264  const auto resultPtr = result.release();
265 
266  if (resultPtr->region() != this)
267  throw util::Error("Appending result to wrong region.");
268 
269  resultPtr->index_ = nresults();
270  results_.push_back(resultPtr);
271 
272  notifyInputCreate(resultPtr);
273 
274  return *resultPtr;
275 }
276 
277 size_t
279 {
280  if (indices.IsEmpty())
281  return 0;
282 
283  size_t numLiveResults = 0;
284  size_t numRemovedResults = 0;
285  for (size_t n = 0; n < nresults(); n++)
286  {
287  const auto result = results_[n];
288  if (indices.Contains(result->index()))
289  {
291  delete result;
292  numRemovedResults++;
293  }
294  else
295  {
296  result->index_ = numLiveResults;
297  results_[numLiveResults++] = result;
298  }
299  }
300  results_.resize(numLiveResults);
301 
302  return numRemovedResults;
303 }
304 
305 void
307 {
308  JLM_ASSERT(node->region() == this);
309  // The node's destructor handles informing the region about removal
310  delete node;
311 }
312 
313 void
314 Region::copy(Region * target, SubstitutionMap & smap) const
315 {
316  for (const auto node : TopDownConstTraverser(this))
317  {
318  node->copy(target, smap);
319  }
320 }
321 
322 void
323 Region::prune(bool recursive)
324 {
325  while (bottomNodes_.first())
327 
328  if (!recursive)
329  return;
330 
331  for (const auto & node : Nodes())
332  {
333  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
334  {
335  for (size_t n = 0; n < snode->nsubregions(); n++)
336  snode->subregion(n)->prune(recursive);
337  }
338  }
339 }
340 
341 void
343 {
344  DotWriter dotWriter;
345  util::graph::Writer graphWriter;
346  dotWriter.WriteGraph(graphWriter, *this);
347 
348  const util::FilePath outputFilePath =
350 
351  std::ofstream outputFile(outputFilePath.to_str());
352  graphWriter.outputAllGraphs(outputFile, util::graph::OutputFormat::Dot);
353 
354  util::executeProgramAndWait(util::getDotViewer(), { outputFilePath.to_str() });
355 }
356 
357 void
359 {
360  JLM_ASSERT(node.region() == this);
361  JLM_ASSERT(node.ninputs() == 0);
363  numTopNodes_++;
364 }
365 
366 void
368 {
369  JLM_ASSERT(node.region() == this);
370  topNodes_.erase(&node);
371  numTopNodes_--;
372 }
373 
374 void
376 {
377  JLM_ASSERT(node.region() == this);
380  numBottomNodes_++;
381 }
382 
383 void
385 {
386  JLM_ASSERT(node.region() == this);
388  numBottomNodes_--;
389 }
390 
391 void
393 {
394  JLM_ASSERT(node.region() == this);
396  numNodes_++;
397 }
398 
399 void
401 {
402  JLM_ASSERT(node.region() == this);
403  nodes_.erase(&node);
404  numNodes_--;
405 }
406 
407 void
409 {
410  for (auto observer = observers_; observer; observer = observer->next_)
411  {
412  observer->onNodeCreate(node);
413  }
414 }
415 
416 void
418 {
419  for (auto observer = observers_; observer; observer = observer->next_)
420  {
421  observer->onNodeDestroy(node);
422  }
423 }
424 
425 void
427 {
428  for (auto observer = observers_; observer; observer = observer->next_)
429  {
430  observer->onInputCreate(input);
431  }
432 }
433 
434 void
435 Region::notifyInputChange(Input * input, Output * old_origin, Output * new_origin)
436 {
437  for (auto observer = observers_; observer; observer = observer->next_)
438  {
439  observer->onInputChange(input, old_origin, new_origin);
440  }
441 }
442 
443 void
445 {
446  for (auto observer = observers_; observer; observer = observer->next_)
447  {
448  observer->onInputDestroy(input);
449  }
450 }
451 
452 size_t
453 Region::NumRegions(const rvsdg::Region & region) noexcept
454 {
455  size_t numRegions = 1;
456  for (auto & node : region.Nodes())
457  {
458  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
459  {
460  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
461  {
462  numRegions += NumRegions(*structuralNode->subregion(n));
463  }
464  }
465  }
466 
467  return numRegions;
468 }
469 
470 std::string
471 Region::ToTree(const rvsdg::Region & region, const util::AnnotationMap & annotationMap) noexcept
472 {
473  std::stringstream stream;
474  ToTree(region, annotationMap, 0, stream);
475  return stream.str();
476 }
477 
478 std::string
479 Region::ToTree(const rvsdg::Region & region) noexcept
480 {
481  std::stringstream stream;
482  util::AnnotationMap annotationMap;
483  ToTree(region, annotationMap, 0, stream);
484  return stream.str();
485 }
486 
487 void
489  const rvsdg::Region & region,
490  const util::AnnotationMap & annotationMap,
491  size_t indentationDepth,
492  std::stringstream & stream) noexcept
493 {
494  static const char indentationChar = '-';
495  static const char annotationSeparator = ' ';
496  static const char labelValueSeparator = ':';
497 
498  // Convert current region to a string
499  auto indentationString = std::string(indentationDepth, indentationChar);
500  auto regionString =
501  region.IsRootRegion() ? "RootRegion" : util::strfmt("Region[", region.index(), "]");
502  auto regionAnnotationString =
503  GetAnnotationString(&region, annotationMap, annotationSeparator, labelValueSeparator);
504 
505  stream << indentationString << regionString << regionAnnotationString << '\n';
506 
507  // Convert the region's structural nodes with their subregions to a string
508  indentationDepth++;
509  indentationString = std::string(indentationDepth, indentationChar);
510  for (auto & node : region.Nodes())
511  {
512  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
513  {
514  auto nodeString = structuralNode->DebugString();
515  auto annotationString = GetAnnotationString(
516  structuralNode,
517  annotationMap,
518  annotationSeparator,
519  labelValueSeparator);
520  stream << indentationString << nodeString << annotationString << '\n';
521 
522  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
523  {
524  ToTree(*structuralNode->subregion(n), annotationMap, indentationDepth + 1, stream);
525  }
526  }
527  }
528 }
529 
530 std::string
532  const void * key,
533  const util::AnnotationMap & annotationMap,
534  char annotationSeparator,
535  char labelValueSeparator)
536 {
537  if (!annotationMap.HasAnnotations(key))
538  return "";
539 
540  auto & annotations = annotationMap.GetAnnotations(key);
541  return ToString(annotations, annotationSeparator, labelValueSeparator);
542 }
543 
544 std::string
546  const std::vector<util::Annotation> & annotations,
547  char annotationSeparator,
548  char labelValueSeparator)
549 {
550  std::stringstream stream;
551  for (auto & annotation : annotations)
552  {
553  auto annotationString = ToString(annotation, labelValueSeparator);
554  stream << annotationSeparator << annotationString;
555  }
556 
557  return stream.str();
558 }
559 
560 std::string
561 Region::ToString(const util::Annotation & annotation, char labelValueSeparator)
562 {
563  std::string value;
564  if (annotation.HasValueType<std::string>())
565  {
566  value = annotation.Value<std::string>();
567  }
568  else if (annotation.HasValueType<int64_t>())
569  {
570  value = util::strfmt(annotation.Value<int64_t>());
571  }
572  else if (annotation.HasValueType<uint64_t>())
573  {
574  value = util::strfmt(annotation.Value<uint64_t>());
575  }
576  else if (annotation.HasValueType<double>())
577  {
578  value = util::strfmt(annotation.Value<double>());
579  }
580  else
581  {
582  JLM_UNREACHABLE("Unhandled annotation type.");
583  }
584 
585  return util::strfmt(annotation.Label(), labelValueSeparator, value);
586 }
587 
589 {
590  *pprev_ = next_;
591  if (next_)
592  {
593  next_->pprev_ = pprev_;
594  }
595 }
596 
598 {
599  next_ = region.observers_;
600  if (next_)
601  {
602  next_->pprev_ = &next_;
603  }
604  pprev_ = &region.observers_;
605  region.observers_ = this;
606 }
607 
608 std::unordered_map<const Node *, size_t>
609 computeDepthMap(const Region & region)
610 {
611  std::unordered_map<const Node *, size_t> depthMap;
612  for (const auto node : TopDownConstTraverser(&region))
613  {
614  size_t depth = 0;
615  for (auto & input : node->Inputs())
616  {
617  if (const auto owner = TryGetOwnerNode<Node>(*input.origin()))
618  {
619  depth = std::max(depth, depthMap[owner] + 1);
620  }
621  }
622  depthMap[node] = depth;
623  }
624 
625  return depthMap;
626 }
627 
628 size_t
629 nnodes(const jlm::rvsdg::Region * region) noexcept
630 {
631  size_t n = region->numNodes();
632  for (const auto & node : region->Nodes())
633  {
634  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
635  {
636  for (size_t r = 0; r < snode->nsubregions(); r++)
637  n += nnodes(snode->subregion(r));
638  }
639  }
640 
641  return n;
642 }
643 
644 size_t
645 nstructnodes(const rvsdg::Region * region) noexcept
646 {
647  size_t n = 0;
648  for (const auto & node : region->Nodes())
649  {
650  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
651  {
652  for (size_t r = 0; r < snode->nsubregions(); r++)
653  n += nstructnodes(snode->subregion(r));
654  n += 1;
655  }
656  }
657 
658  return n;
659 }
660 
661 size_t
662 nsimpnodes(const rvsdg::Region * region) noexcept
663 {
664  size_t n = 0;
665  for (const auto & node : region->Nodes())
666  {
667  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
668  {
669  for (size_t r = 0; r < snode->nsubregions(); r++)
670  n += nsimpnodes(snode->subregion(r));
671  }
672  else
673  {
674  n += 1;
675  }
676  }
677 
678  return n;
679 }
680 
681 size_t
682 ninputs(const rvsdg::Region * region) noexcept
683 {
684  size_t n = region->nresults();
685  for (const auto & node : region->Nodes())
686  {
687  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
688  {
689  for (size_t r = 0; r < snode->nsubregions(); r++)
690  n += ninputs(snode->subregion(r));
691  }
692  n += node.ninputs();
693  }
694 
695  return n;
696 }
697 
698 } // namespace
util::graph::Graph & WriteGraph(util::graph::Writer &writer, const Region &region)
Definition: DotWriter.cpp:217
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Output * origin() const noexcept
Definition: node.hpp:58
size_t index() const noexcept
Definition: node.hpp:52
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:67
Region * region() const noexcept
Definition: node.cpp:83
size_t index_
Definition: node.hpp:223
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
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
size_t index() const noexcept
Definition: node.hpp:274
bool IsDead() const noexcept
Definition: node.hpp:295
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:28
std::string debug_string() const override
Definition: region.cpp:50
virtual RegionArgument & Copy(Region &region, StructuralInput *input) const
Definition: region.cpp:56
StructuralInput * input() const noexcept
Definition: region.hpp:69
~RegionArgument() noexcept override
Definition: region.cpp:22
static RegionArgument & Create(rvsdg::Region &region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
Definition: region.cpp:62
Proxy object to observe changes to a region.
Definition: region.hpp:783
virtual ~RegionObserver() noexcept
Definition: region.cpp:588
RegionObserver ** pprev_
Definition: region.hpp:836
RegionObserver * next_
Definition: region.hpp:837
RegionObserver(const Region &region)
Definition: region.cpp:597
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:76
StructuralOutput * output() const noexcept
Definition: region.hpp:149
~RegionResult() noexcept override
Definition: region.cpp:70
virtual RegionResult & Copy(rvsdg::Output &origin, StructuralOutput *output) const
Definition: region.cpp:105
std::string debug_string() const override
Definition: region.cpp:99
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:111
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
RegionResult * result(size_t index) const noexcept
Definition: region.hpp:471
size_t RemoveResults(const util::HashSet< size_t > &indices)
Definition: region.cpp:278
RegionArgument & addArgument(std::unique_ptr< RegionArgument > argument)
Definition: region.cpp:176
void notifyNodeDestroy(Node *node)
Definition: region.cpp:417
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition: region.cpp:314
static std::string ToString(const std::vector< util::Annotation > &annotations, char annotationSeparator, char labelValueSeparator)
Definition: region.cpp:545
size_t numNodes() const noexcept
Definition: region.hpp:481
region_nodes_list nodes_
Definition: region.hpp:760
void view() const
Definition: region.cpp:342
static std::string ToTree(const rvsdg::Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition: region.cpp:471
void onNodeRemoved(Node &node)
Definition: region.cpp:400
rvsdg::StructuralNode * node() const noexcept
Definition: region.hpp:369
void onNodeAdded(Node &node)
Adds node to the list of nodes in the region.
Definition: region.cpp:392
Graph * graph() const noexcept
Definition: region.hpp:363
void notifyInputChange(Input *input, Output *old_origin, Output *new_origin)
Definition: region.cpp:435
size_t numBottomNodes_
Definition: region.hpp:759
size_t nresults() const noexcept
Definition: region.hpp:465
RegionObserver * observers_
Definition: region.hpp:764
std::vector< RegionResult * > results_
Definition: region.hpp:754
RegionResult & addResult(std::unique_ptr< RegionResult > result)
Definition: region.cpp:262
void prune(bool recursive)
Definition: region.cpp:323
std::vector< RegionArgument * > arguments_
Definition: region.hpp:755
void onBottomNodeRemoved(Node &node)
Definition: region.cpp:384
size_t index() const noexcept
Definition: region.hpp:375
static std::string GetAnnotationString(const void *key, const util::AnnotationMap &annotationMap, char annotationSeparator, char labelValueSeparator)
Definition: region.cpp:531
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
void notifyNodeCreate(Node *node)
Definition: region.cpp:408
size_t numTopNodes() const noexcept
Definition: region.hpp:490
bool IsRootRegion() const noexcept
Definition: region.cpp:170
static size_t NumRegions(const rvsdg::Region &region) noexcept
Definition: region.cpp:453
void onTopNodeRemoved(Node &node)
Definition: region.cpp:367
size_t numBottomNodes() const noexcept
Definition: region.hpp:499
~Region() noexcept
Definition: region.cpp:121
size_t RemoveArguments(const util::HashSet< size_t > &indices)
Definition: region.cpp:210
void removeNode(Node *node)
Definition: region.cpp:306
Region(rvsdg::Region *parent, Graph *graph)
Definition: region.cpp:147
region_top_node_list topNodes_
Definition: region.hpp:756
void onTopNodeAdded(Node &node)
Adds node to the top nodes of the region.
Definition: region.cpp:358
region_bottom_node_list bottomNodes_
Definition: region.hpp:758
NodeRange Nodes() noexcept
Definition: region.hpp:328
size_t numTopNodes_
Definition: region.hpp:757
void notifyInputDestroy(Input *input)
Definition: region.cpp:444
void notifyInputCreate(Input *input)
Definition: region.cpp:426
RegionArgument & insertArgument(size_t index, std::unique_ptr< RegionArgument > argument)
Definition: region.cpp:187
size_t narguments() const noexcept
Definition: region.hpp:431
void onBottomNodeAdded(Node &node)
Adds node to the set of bottom nodes in the region.
Definition: region.cpp:375
size_t PruneArguments()
Definition: region.cpp:238
StructuralNode * node() const noexcept
StructuralNode * node() const noexcept
const std::vector< Annotation > & GetAnnotations(const void *key) const noexcept
bool HasAnnotations(const void *key) const noexcept
bool HasValueType() const noexcept
const TValue & Value() const
const std::string_view & Label() 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
const std::string & to_str() const noexcept
Definition: file.hpp:275
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
void erase(ElementType *element) noexcept
ElementType * first() const noexcept
void push_back(ElementType *element) noexcept
void outputAllGraphs(std::ostream &out, OutputFormat format)
#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:662
size_t nstructnodes(const rvsdg::Region *region) noexcept
Definition: region.cpp:645
std::unordered_map< const Node *, size_t > computeDepthMap(const Region &region)
Definition: region.cpp:609
static std::string type(const Node *n)
Definition: view.cpp:255
detail::TopDownTraverserGeneric< true > TopDownConstTraverser
Traverser for visiting every node in a const region in a top down order.
Definition: traverser.hpp:314
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
Definition: region.cpp:629
size_t ninputs(const rvsdg::Region *region) noexcept
Definition: region.cpp:682
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