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  const auto json = rvsdg::Region::toJson(rvsdgModule.Rvsdg().GetRootRegion(), annotationMap);
60 
61  auto file = statisticsCollector.createOutputFile("rvsdgTree.txt", true);
62  file.open("w");
63  fprintf(file.fd(), "%s\n", json.c_str());
64  file.close();
65 
66  statistics->Stop();
67  statisticsCollector.CollectDemandedStatistics(std::move(statistics));
68 }
69 
72 {
73  util::AnnotationMap annotationMap;
74  for (const auto annotation : Configuration_.RequiredAnnotations().Items())
75  {
76  switch (annotation)
77  {
79  {
80  AnnotateDebugIds(rvsdg, annotationMap);
81  break;
82  }
84  {
85  const auto matchNode = [](const rvsdg::Node &)
86  {
87  return true;
88  };
89  AnnotateNumNodes(rvsdg, matchNode, "NumRvsdgNodes", annotationMap);
90  break;
91  }
93  {
94  const auto matchAggregateAlloca = [](const rvsdg::Node & node)
95  {
96  const auto allocaOperation = dynamic_cast<const AllocaOperation *>(&node.GetOperation());
97  return allocaOperation && IsAggregateType(*allocaOperation->allocatedType());
98  };
99  AnnotateNumNodes(rvsdg, matchAggregateAlloca, "NumAggregateAllocaNodes", annotationMap);
100  break;
101  }
103  {
104  const auto matchAlloca = [](const rvsdg::Node & node)
105  {
106  return rvsdg::is<AllocaOperation>(&node);
107  };
108  AnnotateNumNodes(rvsdg, matchAlloca, "NumAllocaNodes", annotationMap);
109  break;
110  }
112  {
113  const auto matchLoad = [](const rvsdg::Node & node)
114  {
115  return rvsdg::is<LoadOperation>(&node);
116  };
117  AnnotateNumNodes(rvsdg, matchLoad, "NumLoadNodes", annotationMap);
118  break;
119  }
121  {
122  const auto matchStore = [](const rvsdg::Node & node)
123  {
124  return rvsdg::is<StoreOperation>(&node);
125  };
126  AnnotateNumNodes(rvsdg, matchStore, "NumStoreNodes", annotationMap);
127  break;
128  }
130  {
131  AnnotateNumMemoryStateInputsOutputs(rvsdg, annotationMap);
132  break;
133  }
134  default:
135  JLM_UNREACHABLE("Unhandled RVSDG tree annotation.");
136  }
137  }
138 
139  return annotationMap;
140 }
141 
142 void
144  const rvsdg::Graph & rvsdg,
145  const std::function<bool(const rvsdg::Node &)> & match,
146  const std::string_view & label,
147  util::AnnotationMap & annotationMap)
148 {
149  std::function<size_t(const rvsdg::Region &)> annotateRegion = [&](const rvsdg::Region & region)
150  {
151  size_t numNodes = 0;
152  for (auto & node : region.Nodes())
153  {
154  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
155  {
156  size_t numSubregionNodes = 0;
157  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
158  {
159  auto subregion = structuralNode->subregion(n);
160  numSubregionNodes += annotateRegion(*subregion);
161  }
162 
163  annotationMap.AddAnnotation(
164  structuralNode,
165  { label, static_cast<uint64_t>(numSubregionNodes) });
166  }
167 
168  if (match(node))
169  {
170  numNodes++;
171  }
172  }
173 
174  annotationMap.AddAnnotation(&region, { label, static_cast<uint64_t>(numNodes) });
175 
176  return numNodes;
177  };
178 
179  annotateRegion(rvsdg.GetRootRegion());
180 }
181 
182 void
184  const rvsdg::Graph & rvsdg,
185  util::AnnotationMap & annotationMap)
186 {
187  std::string_view argumentLabel("NumMemoryStateTypeArguments");
188  std::string_view resultLabel("NumMemoryStateTypeResults");
189  std::string_view inputLabel("NumMemoryStateTypeInputs");
190  std::string_view outputLabel("NumMemoryStateTypeOutputs");
191 
192  std::function<void(const rvsdg::Region &)> annotateRegion = [&](const rvsdg::Region & region)
193  {
194  auto argumentRange = region.Arguments();
195  auto numMemoryStateArguments =
196  std::count_if(argumentRange.begin(), argumentRange.end(), IsMemoryStateOutput);
197  annotationMap.AddAnnotation(
198  &region,
199  { argumentLabel, static_cast<uint64_t>(numMemoryStateArguments) });
200 
201  auto resultRange = region.Results();
202  auto numMemoryStateResults =
203  std::count_if(resultRange.begin(), resultRange.end(), IsMemoryStateInput);
204  annotationMap.AddAnnotation(
205  &region,
206  { resultLabel, static_cast<uint64_t>(numMemoryStateResults) });
207 
208  for (auto & node : region.Nodes())
209  {
210  if (auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
211  {
212  size_t numMemoryStateInputs = 0;
213  for (size_t n = 0; n < structuralNode->ninputs(); n++)
214  {
215  auto input = structuralNode->input(n);
216  if (rvsdg::is<MemoryStateType>(input->Type()))
217  {
218  numMemoryStateInputs++;
219  }
220  }
221  annotationMap.AddAnnotation(
222  structuralNode,
223  { inputLabel, static_cast<uint64_t>(numMemoryStateInputs) });
224 
225  size_t numMemoryStateOutputs = 0;
226  for (size_t n = 0; n < structuralNode->noutputs(); n++)
227  {
228  auto output = structuralNode->output(n);
229  if (rvsdg::is<MemoryStateType>(output->Type()))
230  {
231  numMemoryStateOutputs++;
232  }
233  }
234  annotationMap.AddAnnotation(
235  structuralNode,
236  { outputLabel, static_cast<uint64_t>(numMemoryStateOutputs) });
237 
238  for (size_t n = 0; n < structuralNode->nsubregions(); n++)
239  {
240  auto subregion = structuralNode->subregion(n);
241  annotateRegion(*subregion);
242  }
243  }
244  }
245  };
246 
247  annotateRegion(rvsdg.GetRootRegion());
248 }
249 
250 void
252 {
253  std::string_view nodeIdLabel("NodeId");
254  std::string_view regionIdLabel("RegionId");
255 
256  std::function<void(const rvsdg::Region &)> annotateRegion = [&](const rvsdg::Region & region)
257  {
258  for (auto & node : region.Nodes())
259  {
260  if (const auto structuralNode = dynamic_cast<const rvsdg::StructuralNode *>(&node))
261  {
262  for (auto & subregion : structuralNode->Subregions())
263  annotateRegion(subregion);
264 
265  annotationMap.AddAnnotation(
266  structuralNode,
267  { nodeIdLabel, static_cast<uint64_t>(structuralNode->GetNodeId()) });
268  }
269  }
270 
271  annotationMap.AddAnnotation(
272  &region,
273  { regionIdLabel, static_cast<uint64_t>(region.getRegionId()) });
274  };
275 
276  annotateRegion(rvsdg.GetRootRegion());
277 }
278 
279 bool
281 {
282  return rvsdg::is<MemoryStateType>(input->Type());
283 }
284 
285 bool
287 {
288  return rvsdg::is<MemoryStateType>(output->Type());
289 }
290 
291 }
static jlm::util::StatisticsCollector statisticsCollector
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 AnnotateDebugIds(const rvsdg::Graph &rvsdg, util::AnnotationMap &annotationMap)
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 toJson(const Region &region, const util::AnnotationMap &annotationMap) noexcept
Definition: region.cpp:487
void AddAnnotation(const void *key, Annotation annotation)
void open(const char *mode)
Definition: file.hpp:374
IteratorRange< ItemConstIterator > Items() const noexcept
Definition: HashSet.hpp:223
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Definition: Statistics.hpp:574
File createOutputFile(std::string fileNameSuffix, bool includeCount=false)
Definition: Statistics.cpp:182
Statistics Interface.
Definition: Statistics.hpp:31
util::Timer & GetTimer(const std::string &name)
Definition: Statistics.cpp:137
util::Timer & AddTimer(std::string name)
Definition: Statistics.cpp:158
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.
bool IsAggregateType(const jlm::rvsdg::Type &type)
Definition: types.hpp:531
static const char * Timer
Definition: Statistics.hpp:251