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 bool
471 Region::isAncestor(const Region & region, const Region & ancestor) noexcept
472 {
473  auto current = &region;
474 
475  while (!current->IsRootRegion())
476  {
477  current = current->node()->region();
478 
479  if (current == &ancestor)
480  return true;
481  }
482 
483  return false;
484 }
485 
486 std::string
487 Region::toJson(const Region & region, const util::AnnotationMap & annotationMap) noexcept
488 {
489  std::stringstream stream{};
490  toJson(region, annotationMap, stream);
491  return stream.str();
492 }
493 
494 std::string
495 Region::toJson(const Region & region) noexcept
496 {
497  std::stringstream stream{};
498  const util::AnnotationMap annotationMap;
499  toJson(region, annotationMap, stream);
500  return stream.str();
501 }
502 
503 void
505  const Region & region,
506  const util::AnnotationMap & annotationMap,
507  std::stringstream & stream) noexcept
508 {
509  stream << '{';
510 
511  if (annotationMap.HasAnnotations(&region))
512  {
513  bool first = true;
514  for (auto & annotation : annotationMap.GetAnnotations(&region))
515  {
516  if (first)
517  first = false;
518  else
519  stream << ',';
520 
521  stream << toJsonKeyValue(annotation);
522  }
523  }
524 
525  std::vector<const StructuralNode *> structuralNodes;
526  for (auto & node : region.Nodes())
527  {
528  if (const auto structuralNode = dynamic_cast<const StructuralNode *>(&node))
529  {
530  structuralNodes.push_back(structuralNode);
531  }
532  }
533 
534  if (!structuralNodes.empty())
535  {
536  if (annotationMap.HasAnnotations(&region))
537  stream << ",";
538 
539  bool firstNode = true;
540  stream << "\"StructuralNodes\":[";
541  for (const auto & structuralNode : structuralNodes)
542  {
543  if (firstNode)
544  firstNode = false;
545  else
546  stream << ",";
547 
548  toJson(*structuralNode, annotationMap, stream);
549  }
550  stream << "]";
551  }
552  stream << "}";
553 }
554 
555 void
557  const StructuralNode & structuralNode,
558  const util::AnnotationMap & annotationMap,
559  std::stringstream & stream) noexcept
560 {
561  stream << '{';
562  stream << "\"DebugString\":\"" << structuralNode.DebugString() << "\"";
563  if (annotationMap.HasAnnotations(&structuralNode))
564  {
565  stream << ",";
566 
567  bool first = true;
568  for (auto & annotation : annotationMap.GetAnnotations(&structuralNode))
569  {
570  if (first)
571  first = false;
572  else
573  stream << ",";
574 
575  stream << toJsonKeyValue(annotation);
576  }
577  }
578  stream << ",";
579 
580  if (structuralNode.nsubregions() != 0)
581  {
582  bool firstSubregion = true;
583  stream << "\"Subregions\":[";
584  for (auto & subregion : structuralNode.Subregions())
585  {
586  if (firstSubregion)
587  firstSubregion = false;
588  else
589  stream << ",";
590 
591  toJson(subregion, annotationMap, stream);
592  }
593  stream << "]";
594  }
595  stream << "}";
596 }
597 
598 std::string
599 Region::toJsonKeyValue(const util::Annotation & annotation) noexcept
600 {
601  std::string value;
602  if (annotation.HasValueType<std::string>())
603  {
604  value = util::strfmt("\"", annotation.Value<std::string>(), "\"");
605  }
606  else if (annotation.HasValueType<int64_t>())
607  {
608  value = util::strfmt(annotation.Value<int64_t>());
609  }
610  else if (annotation.HasValueType<uint64_t>())
611  {
612  value = util::strfmt(annotation.Value<uint64_t>());
613  }
614  else if (annotation.HasValueType<double>())
615  {
616  value = util::strfmt(annotation.Value<double>());
617  }
618  else
619  {
620  JLM_UNREACHABLE("Unhandled annotation type.");
621  }
622 
623  return util::strfmt("\"", annotation.Label(), "\":", value);
624 }
625 
626 std::string
627 Region::ToTree(const rvsdg::Region & region, const util::AnnotationMap & annotationMap) noexcept
628 {
629  std::stringstream stream;
630  ToTree(region, annotationMap, 0, stream);
631  return stream.str();
632 }
633 
634 std::string
635 Region::ToTree(const rvsdg::Region & region) noexcept
636 {
637  std::stringstream stream;
638  util::AnnotationMap annotationMap;
639  ToTree(region, annotationMap, 0, stream);
640  return stream.str();
641 }
642 
643 void
645  const rvsdg::Region & region,
646  const util::AnnotationMap & annotationMap,
647  size_t indentationDepth,
648  std::stringstream & stream) noexcept
649 {
650  static const char indentationChar = '-';
651  static const char annotationSeparator = ' ';
652  static const char labelValueSeparator = ':';
653 
654  // Convert current region to a string
655  auto indentationString = std::string(indentationDepth, indentationChar);
656  auto regionString =
657  region.IsRootRegion() ? "RootRegion" : util::strfmt("Region[", region.index(), "]");
658  auto regionAnnotationString =
659  GetAnnotationString(&region, annotationMap, annotationSeparator, labelValueSeparator);
660 
661  stream << indentationString << regionString << regionAnnotationString << '\n';
662 
663  // Convert the region's structural nodes with their subregions to a string
664  indentationDepth++;
665  indentationString = std::string(indentationDepth, indentationChar);
666  for (auto & node : region.Nodes())
667  {
668  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
669  {
670  auto nodeString = structuralNode->DebugString();
671  auto annotationString = GetAnnotationString(
672  structuralNode,
673  annotationMap,
674  annotationSeparator,
675  labelValueSeparator);
676  stream << indentationString << nodeString << annotationString << '\n';
677 
678  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
679  {
680  ToTree(*structuralNode->subregion(n), annotationMap, indentationDepth + 1, stream);
681  }
682  }
683  }
684 }
685 
686 std::string
688  const void * key,
689  const util::AnnotationMap & annotationMap,
690  char annotationSeparator,
691  char labelValueSeparator)
692 {
693  if (!annotationMap.HasAnnotations(key))
694  return "";
695 
696  auto & annotations = annotationMap.GetAnnotations(key);
697  return ToString(annotations, annotationSeparator, labelValueSeparator);
698 }
699 
700 std::string
702  const std::vector<util::Annotation> & annotations,
703  char annotationSeparator,
704  char labelValueSeparator)
705 {
706  std::stringstream stream;
707  for (auto & annotation : annotations)
708  {
709  auto annotationString = ToString(annotation, labelValueSeparator);
710  stream << annotationSeparator << annotationString;
711  }
712 
713  return stream.str();
714 }
715 
716 std::string
717 Region::ToString(const util::Annotation & annotation, char labelValueSeparator)
718 {
719  std::string value;
720  if (annotation.HasValueType<std::string>())
721  {
722  value = annotation.Value<std::string>();
723  }
724  else if (annotation.HasValueType<int64_t>())
725  {
726  value = util::strfmt(annotation.Value<int64_t>());
727  }
728  else if (annotation.HasValueType<uint64_t>())
729  {
730  value = util::strfmt(annotation.Value<uint64_t>());
731  }
732  else if (annotation.HasValueType<double>())
733  {
734  value = util::strfmt(annotation.Value<double>());
735  }
736  else
737  {
738  JLM_UNREACHABLE("Unhandled annotation type.");
739  }
740 
741  return util::strfmt(annotation.Label(), labelValueSeparator, value);
742 }
743 
745 {
746  *pprev_ = next_;
747  if (next_)
748  {
749  next_->pprev_ = pprev_;
750  }
751 }
752 
754 {
755  next_ = region.observers_;
756  if (next_)
757  {
758  next_->pprev_ = &next_;
759  }
760  pprev_ = &region.observers_;
761  region.observers_ = this;
762 }
763 
764 std::unordered_map<const Node *, size_t>
765 computeDepthMap(const Region & region)
766 {
767  std::unordered_map<const Node *, size_t> depthMap;
768  for (const auto node : TopDownConstTraverser(&region))
769  {
770  size_t depth = 0;
771  for (auto & input : node->Inputs())
772  {
773  if (const auto owner = TryGetOwnerNode<Node>(*input.origin()))
774  {
775  depth = std::max(depth, depthMap[owner] + 1);
776  }
777  }
778  depthMap[node] = depth;
779  }
780 
781  return depthMap;
782 }
783 
784 size_t
785 nnodes(const jlm::rvsdg::Region * region) noexcept
786 {
787  size_t n = region->numNodes();
788  for (const auto & node : region->Nodes())
789  {
790  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
791  {
792  for (size_t r = 0; r < snode->nsubregions(); r++)
793  n += nnodes(snode->subregion(r));
794  }
795  }
796 
797  return n;
798 }
799 
800 size_t
801 nstructnodes(const rvsdg::Region * region) noexcept
802 {
803  size_t n = 0;
804  for (const auto & node : region->Nodes())
805  {
806  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
807  {
808  for (size_t r = 0; r < snode->nsubregions(); r++)
809  n += nstructnodes(snode->subregion(r));
810  n += 1;
811  }
812  }
813 
814  return n;
815 }
816 
817 size_t
818 nsimpnodes(const rvsdg::Region * region) noexcept
819 {
820  size_t n = 0;
821  for (const auto & node : region->Nodes())
822  {
823  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
824  {
825  for (size_t r = 0; r < snode->nsubregions(); r++)
826  n += nsimpnodes(snode->subregion(r));
827  }
828  else
829  {
830  n += 1;
831  }
832  }
833 
834  return n;
835 }
836 
837 size_t
838 ninputs(const rvsdg::Region * region) noexcept
839 {
840  size_t n = region->nresults();
841  for (const auto & node : region->Nodes())
842  {
843  if (auto snode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
844  {
845  for (size_t r = 0; r < snode->nsubregions(); r++)
846  n += ninputs(snode->subregion(r));
847  }
848  n += node.ninputs();
849  }
850 
851  return n;
852 }
853 
854 } // 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:829
virtual ~RegionObserver() noexcept
Definition: region.cpp:744
RegionObserver ** pprev_
Definition: region.hpp:882
RegionObserver * next_
Definition: region.hpp:883
RegionObserver(const Region &region)
Definition: region.cpp:753
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:701
size_t numNodes() const noexcept
Definition: region.hpp:481
region_nodes_list nodes_
Definition: region.hpp:806
void view() const
Definition: region.cpp:342
static std::string toJson(const Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition: region.cpp:487
static std::string ToTree(const rvsdg::Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition: region.cpp:627
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:805
size_t nresults() const noexcept
Definition: region.hpp:465
RegionObserver * observers_
Definition: region.hpp:810
std::vector< RegionResult * > results_
Definition: region.hpp:800
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:801
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:687
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
static bool isAncestor(const rvsdg::Region &region, const rvsdg::Region &ancestor) noexcept
Definition: region.cpp:471
Region(rvsdg::Region *parent, Graph *graph)
Definition: region.cpp:147
region_top_node_list topNodes_
Definition: region.hpp:802
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:804
NodeRange Nodes() noexcept
Definition: region.hpp:328
size_t numTopNodes_
Definition: region.hpp:803
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
static std::string toJsonKeyValue(const util::Annotation &annotation) noexcept
Definition: region.cpp:599
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:818
size_t nstructnodes(const rvsdg::Region *region) noexcept
Definition: region.cpp:801
std::unordered_map< const Node *, size_t > computeDepthMap(const Region &region)
Definition: region.cpp:765
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:785
size_t ninputs(const rvsdg::Region *region) noexcept
Definition: region.cpp:838
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