Jlm
RvsdgTreePrinter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2024 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
12 #include <jlm/util/Statistics.hpp>
13 
14 #include <algorithm>
15 #include <fstream>
16 
17 namespace jlm::llvm
18 {
19 
21 {
22 public:
23  ~Statistics() override = default;
24 
25  explicit Statistics(const util::FilePath & sourceFile)
26  : util::Statistics(util::Statistics::Id::RvsdgTreePrinter, sourceFile)
27  {}
28 
29  void
30  Start() noexcept
31  {
33  }
34 
35  void
36  Stop() noexcept
37  {
39  }
40 
41  static std::unique_ptr<Statistics>
42  Create(const util::FilePath & sourceFile)
43  {
44  return std::make_unique<Statistics>(sourceFile);
45  }
46 };
47 
48 RvsdgTreePrinter::~RvsdgTreePrinter() noexcept = default;
49 
50 void
52  rvsdg::RvsdgModule & rvsdgModule,
53  util::StatisticsCollector & statisticsCollector)
54 {
55  auto statistics = Statistics::Create(rvsdgModule.SourceFilePath().value());
56  statistics->Start();
57 
58  auto annotationMap = ComputeAnnotationMap(rvsdgModule.Rvsdg());
59  auto tree = rvsdg::Region::ToTree(rvsdgModule.Rvsdg().GetRootRegion(), annotationMap);
60 
61  auto file = statisticsCollector.createOutputFile("rvsdgTree.txt", true);
62  file.open("w");
63  fprintf(file.fd(), "%s\n", tree.c_str());
64  file.close();
65 
66  statistics->Stop();
67  statisticsCollector.CollectDemandedStatistics(std::move(statistics));
68 }
69 
72 {
73  util::AnnotationMap annotationMap;
74  for (auto annotation : Configuration_.RequiredAnnotations().Items())
75  {
76  switch (annotation)
77  {
79  {
80  const auto matchNode = [](const rvsdg::Node &)
81  {
82  return true;
83  };
84  AnnotateNumNodes(rvsdg, matchNode, "NumRvsdgNodes", annotationMap);
85  break;
86  }
88  {
89  const auto matchAlloca = [](const rvsdg::Node & node)
90  {
91  return rvsdg::is<AllocaOperation>(&node);
92  };
93  AnnotateNumNodes(rvsdg, matchAlloca, "NumAllocaNodes", annotationMap);
94  break;
95  }
97  {
98  const auto matchLoad = [](const rvsdg::Node & node)
99  {
100  return rvsdg::is<LoadOperation>(&node);
101  };
102  AnnotateNumNodes(rvsdg, matchLoad, "NumLoadNodes", annotationMap);
103  break;
104  }
106  {
107  const auto matchStore = [](const rvsdg::Node & node)
108  {
109  return rvsdg::is<StoreOperation>(&node);
110  };
111  AnnotateNumNodes(rvsdg, matchStore, "NumStoreNodes", annotationMap);
112  break;
113  }
115  {
116  AnnotateNumMemoryStateInputsOutputs(rvsdg, annotationMap);
117  break;
118  }
119  default:
120  JLM_UNREACHABLE("Unhandled RVSDG tree annotation.");
121  }
122  }
123 
124  return annotationMap;
125 }
126 
127 void
129  const rvsdg::Graph & rvsdg,
130  const std::function<bool(const rvsdg::Node &)> & match,
131  const std::string_view & label,
132  util::AnnotationMap & annotationMap)
133 {
134  std::function<size_t(const rvsdg::Region &)> annotateRegion = [&](const rvsdg::Region & region)
135  {
136  size_t numNodes = 0;
137  for (auto & node : region.Nodes())
138  {
139  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
140  {
141  size_t numSubregionNodes = 0;
142  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
143  {
144  auto subregion = structuralNode->subregion(n);
145  numSubregionNodes += annotateRegion(*subregion);
146  }
147 
148  annotationMap.AddAnnotation(
149  structuralNode,
150  { label, static_cast<uint64_t>(numSubregionNodes) });
151  }
152 
153  if (match(node))
154  {
155  numNodes++;
156  }
157  }
158 
159  annotationMap.AddAnnotation(&region, { label, static_cast<uint64_t>(numNodes) });
160 
161  return numNodes;
162  };
163 
164  annotateRegion(rvsdg.GetRootRegion());
165 }
166 
167 void
169  const rvsdg::Graph & rvsdg,
170  util::AnnotationMap & annotationMap)
171 {
172  std::string_view argumentLabel("NumMemoryStateTypeArguments");
173  std::string_view resultLabel("NumMemoryStateTypeResults");
174  std::string_view inputLabel("NumMemoryStateTypeInputs");
175  std::string_view outputLabel("NumMemoryStateTypeOutputs");
176 
177  std::function<void(const rvsdg::Region &)> annotateRegion = [&](const rvsdg::Region & region)
178  {
179  auto argumentRange = region.Arguments();
180  auto numMemoryStateArguments =
181  std::count_if(argumentRange.begin(), argumentRange.end(), IsMemoryStateOutput);
182  annotationMap.AddAnnotation(
183  &region,
184  { argumentLabel, static_cast<uint64_t>(numMemoryStateArguments) });
185 
186  auto resultRange = region.Results();
187  auto numMemoryStateResults =
188  std::count_if(resultRange.begin(), resultRange.end(), IsMemoryStateInput);
189  annotationMap.AddAnnotation(
190  &region,
191  { resultLabel, static_cast<uint64_t>(numMemoryStateResults) });
192 
193  for (auto & node : region.Nodes())
194  {
195  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
196  {
197  size_t numMemoryStateInputs = 0;
198  for (size_t n = 0; n < structuralNode->ninputs(); n++)
199  {
200  auto input = structuralNode->input(n);
201  if (rvsdg::is<MemoryStateType>(input->Type()))
202  {
203  numMemoryStateInputs++;
204  }
205  }
206  annotationMap.AddAnnotation(
207  structuralNode,
208  { inputLabel, static_cast<uint64_t>(numMemoryStateInputs) });
209 
210  size_t numMemoryStateOutputs = 0;
211  for (size_t n = 0; n < structuralNode->noutputs(); n++)
212  {
213  auto output = structuralNode->output(n);
214  if (rvsdg::is<MemoryStateType>(output->Type()))
215  {
216  numMemoryStateOutputs++;
217  }
218  }
219  annotationMap.AddAnnotation(
220  structuralNode,
221  { outputLabel, static_cast<uint64_t>(numMemoryStateOutputs) });
222 
223  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
224  {
225  auto subregion = structuralNode->subregion(n);
226  annotateRegion(*subregion);
227  }
228  }
229  }
230  };
231 
232  annotateRegion(rvsdg.GetRootRegion());
233 }
234 
235 bool
237 {
238  return rvsdg::is<MemoryStateType>(input->Type());
239 }
240 
241 bool
243 {
244  return rvsdg::is<MemoryStateType>(output->Type());
245 }
246 
247 }
const util::HashSet< Annotation > & RequiredAnnotations() const noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
Statistics(const util::FilePath &sourceFile)
RVSDG tree printer debug pass.
util::AnnotationMap ComputeAnnotationMap(const rvsdg::Graph &rvsdg) const
static bool IsMemoryStateOutput(const rvsdg::Output *output) noexcept
~RvsdgTreePrinter() noexcept override
static void AnnotateNumMemoryStateInputsOutputs(const rvsdg::Graph &rvsdg, util::AnnotationMap &annotationMap)
static bool IsMemoryStateInput(const rvsdg::Input *input) noexcept
static void AnnotateNumNodes(const rvsdg::Graph &rvsdg, const std::function< bool(const rvsdg::Node &)> &match, const std::string_view &label, util::AnnotationMap &annotationMap)
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
static std::string ToTree(const rvsdg::Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition: region.cpp:471
void AddAnnotation(const void *key, Annotation annotation)
IteratorRange< ItemConstIterator > Items() const noexcept
Definition: HashSet.hpp:223
Statistics Interface.
Definition: Statistics.hpp:31
util::Timer & GetTimer(const std::string &name)
Definition: Statistics.cpp:134
util::Timer & AddTimer(std::string name)
Definition: Statistics.cpp:155
void start() noexcept
Definition: time.hpp:54
void stop() noexcept
Definition: time.hpp:67
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
jlm::rvsdg::Output * match(size_t nbits, const std::unordered_map< uint64_t, uint64_t > &mapping, uint64_t default_alternative, size_t nalternatives, jlm::rvsdg::Output *operand)
Definition: control.cpp:179
static const char * Timer
Definition: Statistics.hpp:240