Jlm
Annotation.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
9 
10 #include <algorithm>
11 #include <typeindex>
12 
13 namespace jlm::llvm
14 {
15 
16 std::string
17 VariableSet::DebugString() const noexcept
18 {
19  std::string debugString("{");
20 
21  bool isFirst = true;
22  for (auto & variable : Variables())
23  {
24  debugString += isFirst ? "" : ", ";
25  debugString += variable.name();
26  isFirst = false;
27  }
28 
29  debugString += "}";
30 
31  return debugString;
32 }
33 
34 AnnotationSet::~AnnotationSet() noexcept = default;
35 
36 EntryAnnotationSet::~EntryAnnotationSet() noexcept = default;
37 
38 std::string
39 EntryAnnotationSet::DebugString() const noexcept
40 {
41  return util::strfmt(
42  "ReadSet:",
43  ReadSet().DebugString(),
44  " ",
45  "AllWriteSet:",
46  AllWriteSet().DebugString(),
47  " ",
48  "FullWriteSet:",
49  FullWriteSet().DebugString(),
50  " ",
51  "TopSet:",
52  TopSet_.DebugString(),
53  " ");
54 }
55 
56 bool
58 {
59  auto otherEntryDemandSet = dynamic_cast<const EntryAnnotationSet *>(&other);
60  return otherEntryDemandSet && AnnotationSet::operator==(other)
61  && TopSet_ == otherEntryDemandSet->TopSet_;
62 }
63 
64 ExitAnnotationSet::~ExitAnnotationSet() noexcept = default;
65 
66 std::string
67 ExitAnnotationSet::DebugString() const noexcept
68 {
69  return util::strfmt(
70  "ReadSet:",
71  ReadSet().DebugString(),
72  " ",
73  "AllWriteSet:",
74  AllWriteSet().DebugString(),
75  " ",
76  "FullWriteSet:",
77  FullWriteSet().DebugString(),
78  " ");
79 }
80 
81 bool
83 {
84  auto otherExitDemandSet = dynamic_cast<const ExitAnnotationSet *>(&other);
85  return otherExitDemandSet && AnnotationSet::operator==(other);
86 }
87 
89 
90 std::string
91 BasicBlockAnnotationSet::DebugString() const noexcept
92 {
93  return util::strfmt(
94  "ReadSet:",
95  ReadSet().DebugString(),
96  " ",
97  "AllWriteSet:",
98  AllWriteSet().DebugString(),
99  " ",
100  "FullWriteSet:",
101  FullWriteSet().DebugString(),
102  " ");
103 }
104 
105 bool
107 {
108  auto otherBasicBlockDemandSet = dynamic_cast<const BasicBlockAnnotationSet *>(&other);
109  return otherBasicBlockDemandSet && AnnotationSet::operator==(other);
110 }
111 
112 LinearAnnotationSet::~LinearAnnotationSet() noexcept = default;
113 
114 std::string
115 LinearAnnotationSet::DebugString() const noexcept
116 {
117  return util::strfmt(
118  "ReadSet:",
119  ReadSet().DebugString(),
120  " ",
121  "AllWriteSet:",
122  AllWriteSet().DebugString(),
123  " ",
124  "FullWriteSet:",
125  FullWriteSet().DebugString(),
126  " ");
127 }
128 
129 bool
131 {
132  auto otherLinearDemandSet = dynamic_cast<const LinearAnnotationSet *>(&other);
133  return otherLinearDemandSet && AnnotationSet::operator==(other);
134 }
135 
136 BranchAnnotationSet::~BranchAnnotationSet() noexcept = default;
137 
138 std::string
139 BranchAnnotationSet::DebugString() const noexcept
140 {
141  return util::strfmt(
142  "ReadSet:",
143  ReadSet().DebugString(),
144  " ",
145  "AllWriteSet:",
146  AllWriteSet().DebugString(),
147  " ",
148  "FullWriteSet:",
149  FullWriteSet().DebugString(),
150  " ",
151  "TopSet:",
152  InputVariables().DebugString(),
153  " ",
154  "BottomSet:",
155  OutputVariables().DebugString(),
156  " ");
157 }
158 
159 bool
161 {
162  auto otherBranchDemandSet = dynamic_cast<const BranchAnnotationSet *>(&other);
163  return otherBranchDemandSet && AnnotationSet::operator==(other)
164  && InputVariables_ == otherBranchDemandSet->InputVariables_
165  && OutputVariables_ == otherBranchDemandSet->OutputVariables_;
166 }
167 
168 LoopAnnotationSet::~LoopAnnotationSet() noexcept = default;
169 
170 std::string
171 LoopAnnotationSet::DebugString() const noexcept
172 {
173  return util::strfmt(
174  "ReadSet:",
175  ReadSet().DebugString(),
176  " ",
177  "AllWriteSet:",
178  AllWriteSet().DebugString(),
179  " ",
180  "FullWriteSet:",
181  FullWriteSet().DebugString(),
182  " ",
183  "LoopVariables:",
184  LoopVariables_.DebugString(),
185  " ");
186 }
187 
188 bool
190 {
191  auto otherLoopDemandSet = dynamic_cast<const LoopAnnotationSet *>(&other);
192  return otherLoopDemandSet && AnnotationSet::operator==(other)
193  && LoopVariables_ == otherLoopDemandSet->LoopVariables_;
194 }
195 
196 static void
198 
199 static void
200 AnnotateReadWrite(const EntryAggregationNode & entryAggregationNode, AnnotationMap & demandMap)
201 {
202  VariableSet allWriteSet;
203  VariableSet fullWriteSet;
204  for (auto & argument : entryAggregationNode)
205  {
206  allWriteSet.Insert(argument);
207  fullWriteSet.Insert(argument);
208  }
209 
210  auto demandSet =
211  EntryAnnotationSet::Create(VariableSet(), std::move(allWriteSet), std::move(fullWriteSet));
212  demandMap.Insert(entryAggregationNode, std::move(demandSet));
213 }
214 
215 static void
216 AnnotateReadWrite(const ExitAggregationNode & exitAggregationNode, AnnotationMap & demandMap)
217 {
218  VariableSet readSet;
219  for (auto & result : exitAggregationNode)
220  readSet.Insert(*result);
221 
222  auto demandSet = ExitAnnotationSet::Create(std::move(readSet), VariableSet(), VariableSet());
223  demandMap.Insert(exitAggregationNode, std::move(demandSet));
224 }
225 
226 static void
228  const BasicBlockAggregationNode & basicBlockAggregationNode,
229  AnnotationMap & demandMap)
230 {
231  auto & threeAddressCodeList = basicBlockAggregationNode.tacs();
232 
233  VariableSet readSet;
234  VariableSet allWriteSet;
235  VariableSet fullWriteSet;
236  for (auto it = threeAddressCodeList.rbegin(); it != threeAddressCodeList.rend(); it++)
237  {
238  auto & tac = *it;
239  if (is<AssignmentOperation>(tac->operation()))
240  {
241  /*
242  We need special treatment for assignment operation, since the variable
243  they assign the value to is modeled as an argument of the three address code.
244  */
245  JLM_ASSERT(tac->noperands() == 2 && tac->nresults() == 0);
246  readSet.Remove(*tac->operand(0));
247  allWriteSet.Insert(*tac->operand(0));
248  fullWriteSet.Insert(*tac->operand(0));
249  readSet.Insert(*tac->operand(1));
250  }
251  else
252  {
253  for (size_t n = 0; n < tac->nresults(); n++)
254  {
255  readSet.Remove(*tac->result(n));
256  allWriteSet.Insert(*tac->result(n));
257  fullWriteSet.Insert(*tac->result(n));
258  }
259  for (size_t n = 0; n < tac->noperands(); n++)
260  readSet.Insert(*tac->operand(n));
261  }
262  }
263 
264  auto demandSet = BasicBlockAnnotationSet::Create(
265  std::move(readSet),
266  std::move(allWriteSet),
267  std::move(fullWriteSet));
268  demandMap.Insert(basicBlockAggregationNode, std::move(demandSet));
269 }
270 
271 static void
272 AnnotateReadWrite(const LinearAggregationNode & linearAggregationNode, AnnotationMap & demandMap)
273 {
274  VariableSet readSet;
275  VariableSet allWriteSet;
276  VariableSet fullWriteSet;
277  for (size_t n = linearAggregationNode.nchildren() - 1; n != static_cast<size_t>(-1); n--)
278  {
279  auto & childDemandSet = demandMap.Lookup<AnnotationSet>(*linearAggregationNode.child(n));
280 
281  readSet.Remove(childDemandSet.FullWriteSet());
282  readSet.Insert(childDemandSet.ReadSet());
283  allWriteSet.Insert(childDemandSet.AllWriteSet());
284  fullWriteSet.Insert(childDemandSet.FullWriteSet());
285  }
286 
287  auto demandSet = LinearAnnotationSet::Create(
288  std::move(readSet),
289  std::move(allWriteSet),
290  std::move(fullWriteSet));
291  demandMap.Insert(linearAggregationNode, std::move(demandSet));
292 }
293 
294 static void
295 AnnotateReadWrite(const BranchAggregationNode & branchAggregationNode, AnnotationMap & demandMap)
296 {
297  auto & case0DemandSet = demandMap.Lookup<AnnotationSet>(*branchAggregationNode.child(0));
298  auto & case0ReadSet = case0DemandSet.ReadSet();
299  auto & case0AllWriteSet = case0DemandSet.AllWriteSet();
300  auto & case0FullWriteSet = case0DemandSet.FullWriteSet();
301 
302  VariableSet branchReadSet(case0ReadSet);
303  VariableSet branchAllWriteSet(case0AllWriteSet);
304  VariableSet branchFullWriteSet(case0FullWriteSet);
305  for (size_t n = 1; n < branchAggregationNode.nchildren(); n++)
306  {
307  auto & caseDemandSet = demandMap.Lookup<AnnotationSet>(*branchAggregationNode.child(n));
308 
309  branchAllWriteSet.Insert(caseDemandSet.AllWriteSet());
310  branchFullWriteSet.Intersect(caseDemandSet.FullWriteSet());
311  branchReadSet.Insert(caseDemandSet.ReadSet());
312  }
313 
314  auto branchDemandSet = BranchAnnotationSet::Create(
315  std::move(branchReadSet),
316  std::move(branchAllWriteSet),
317  std::move(branchFullWriteSet));
318  demandMap.Insert(branchAggregationNode, std::move(branchDemandSet));
319 }
320 
321 static void
322 AnnotateReadWrite(const LoopAggregationNode & loopAggregationNode, AnnotationMap & demandMap)
323 {
324  auto & loopBody = *loopAggregationNode.child(0);
325  auto & bodyDemandSet = demandMap.Lookup<AnnotationSet>(loopBody);
326 
327  auto demandSet = LoopAnnotationSet::Create(
328  bodyDemandSet.ReadSet(),
329  bodyDemandSet.AllWriteSet(),
330  bodyDemandSet.FullWriteSet());
331  demandMap.Insert(loopAggregationNode, std::move(demandSet));
332 }
333 
334 static void
335 AnnotateReadWrite(const AggregationNode & aggregationNode, AnnotationMap & demandMap)
336 {
337  for (size_t n = 0; n < aggregationNode.nchildren(); n++)
338  AnnotateReadWrite(*aggregationNode.child(n), demandMap);
339 
340  if (auto entryNode = dynamic_cast<const EntryAggregationNode *>(&aggregationNode))
341  {
342  AnnotateReadWrite(*entryNode, demandMap);
343  }
344  else if (auto exitNode = dynamic_cast<const ExitAggregationNode *>(&aggregationNode))
345  {
346  AnnotateReadWrite(*exitNode, demandMap);
347  }
348  else if (auto blockNode = dynamic_cast<const BasicBlockAggregationNode *>(&aggregationNode))
349  {
350  AnnotateReadWrite(*blockNode, demandMap);
351  }
352  else if (const auto linearNode = dynamic_cast<const LinearAggregationNode *>(&aggregationNode))
353  {
354  AnnotateReadWrite(*linearNode, demandMap);
355  }
356  else if (auto branchNode = dynamic_cast<const BranchAggregationNode *>(&aggregationNode))
357  {
358  AnnotateReadWrite(*branchNode, demandMap);
359  }
360  else if (auto loopNode = dynamic_cast<const LoopAggregationNode *>(&aggregationNode))
361  {
362  AnnotateReadWrite(*loopNode, demandMap);
363  }
364  else
365  {
366  JLM_UNREACHABLE("Unhandled aggregation node type");
367  }
368 }
369 
370 static void
371 AnnotateDemandSet(const AggregationNode &, VariableSet &, AnnotationMap &);
372 
373 static void
375  const EntryAggregationNode & entryAggregationNode,
376  VariableSet & workingSet,
377  AnnotationMap & demandMap)
378 {
379  auto & demandSet = demandMap.Lookup<EntryAnnotationSet>(entryAggregationNode);
380 
381  workingSet.Remove(demandSet.FullWriteSet());
382 
383  demandSet.TopSet_ = workingSet;
384 }
385 
386 static void
388  const ExitAggregationNode & exitAggregationNode,
389  VariableSet & workingSet,
390  AnnotationMap & demandMap)
391 {
392  auto & demandSet = demandMap.Lookup<ExitAnnotationSet>(exitAggregationNode);
393  workingSet.Insert(demandSet.ReadSet());
394 }
395 
396 static void
398  const BasicBlockAggregationNode & basicBlockAggregationNode,
399  VariableSet & workingSet,
400  AnnotationMap & demandMap)
401 {
402  auto & demandSet = demandMap.Lookup<BasicBlockAnnotationSet>(basicBlockAggregationNode);
403  workingSet.Remove(demandSet.FullWriteSet());
404  workingSet.Insert(demandSet.ReadSet());
405 }
406 
407 static void
409  const LinearAggregationNode & linearAggregationNode,
410  VariableSet & workingSet,
411  AnnotationMap & demandMap)
412 {
413  auto & demandSet = demandMap.Lookup<LinearAnnotationSet>(linearAggregationNode);
414 
415  for (size_t n = linearAggregationNode.nchildren() - 1; n != static_cast<size_t>(-1); n--)
416  AnnotateDemandSet(*linearAggregationNode.child(n), workingSet, demandMap);
417 
418  workingSet.Remove(demandSet.FullWriteSet());
419  workingSet.Insert(demandSet.ReadSet());
420 }
421 
422 static void
424  const BranchAggregationNode & branchAggregationNode,
425  VariableSet & workingSet,
426  AnnotationMap & demandMap)
427 {
428  auto & demandSet = demandMap.Lookup<BranchAnnotationSet>(branchAggregationNode);
429 
430  VariableSet branchWorkingSet = workingSet;
431  branchWorkingSet.Intersect(demandSet.AllWriteSet());
432  demandSet.SetOutputVariables(branchWorkingSet);
433 
434  for (size_t n = 0; n < branchAggregationNode.nchildren(); n++)
435  {
436  auto caseWorkingSet = branchWorkingSet;
437  AnnotateDemandSet(*branchAggregationNode.child(n), caseWorkingSet, demandMap);
438  }
439 
440  branchWorkingSet.Remove(demandSet.FullWriteSet());
441  branchWorkingSet.Insert(demandSet.ReadSet());
442  demandSet.SetInputVariables(branchWorkingSet);
443 
444  workingSet.Insert(branchWorkingSet);
445 }
446 
447 static void
449  const LoopAggregationNode & loopAggregationNode,
450  VariableSet & workingSet,
451  AnnotationMap & demandMap)
452 {
453  auto & demandSet = demandMap.Lookup<LoopAnnotationSet>(loopAggregationNode);
454 
455  workingSet.Insert(demandSet.ReadSet());
456  demandSet.SetLoopVariables(workingSet);
457  AnnotateDemandSet(*loopAggregationNode.child(0), workingSet, demandMap);
458 }
459 
460 template<class T>
461 static void
463  const AggregationNode * aggregationNode,
464  VariableSet & workingSet,
465  AnnotationMap & demandMap)
466 {
467  JLM_ASSERT(is<T>(aggregationNode));
468  AnnotateDemandSet(*static_cast<const T *>(aggregationNode), workingSet, demandMap);
469 }
470 
471 static void
473  const AggregationNode & aggregationNode,
474  VariableSet & workingSet,
475  AnnotationMap & demandMap)
476 {
477  static std::unordered_map<
478  std::type_index,
479  void (*)(const AggregationNode *, VariableSet &, AnnotationMap &)>
480  map({ { typeid(EntryAggregationNode), AnnotateDemandSet<EntryAggregationNode> },
481  { typeid(ExitAggregationNode), AnnotateDemandSet<ExitAggregationNode> },
482  { typeid(BasicBlockAggregationNode), AnnotateDemandSet<BasicBlockAggregationNode> },
483  { typeid(LinearAggregationNode), AnnotateDemandSet<LinearAggregationNode> },
484  { typeid(BranchAggregationNode), AnnotateDemandSet<BranchAggregationNode> },
485  { typeid(LoopAggregationNode), AnnotateDemandSet<LoopAggregationNode> } });
486 
487  JLM_ASSERT(map.find(typeid(aggregationNode)) != map.end());
488  return map[typeid(aggregationNode)](&aggregationNode, workingSet, demandMap);
489 }
490 
491 std::unique_ptr<AnnotationMap>
492 Annotate(const AggregationNode & aggregationTreeRoot)
493 {
494  auto demandMap = AnnotationMap::Create();
495  AnnotateReadWrite(aggregationTreeRoot, *demandMap);
496 
497  VariableSet workingSet;
498  AnnotateDemandSet(aggregationTreeRoot, workingSet, *demandMap);
499 
500  return demandMap;
501 }
502 
503 }
size_t nchildren() const noexcept
Definition: aggregation.hpp:69
AggregationNode * child(size_t n) const noexcept
Definition: aggregation.hpp:84
T & Lookup(const AggregationNode &aggregationNode) const noexcept
Definition: Annotation.hpp:504
static std::unique_ptr< AnnotationMap > Create()
Definition: Annotation.hpp:519
void Insert(const AggregationNode &aggregationNode, std::unique_ptr< AnnotationSet > annotationSet)
Definition: Annotation.hpp:512
virtual ~AnnotationSet() noexcept
const VariableSet & ReadSet() const noexcept
Definition: Annotation.hpp:218
virtual bool operator==(const AnnotationSet &other) const
Definition: Annotation.hpp:236
const ThreeAddressCodeList & tacs() const noexcept
~BasicBlockAnnotationSet() noexcept override
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:106
static std::unique_ptr< BasicBlockAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:328
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:160
static std::unique_ptr< BranchAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:389
~BranchAnnotationSet() noexcept override
static std::unique_ptr< EntryAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:276
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:57
~ExitAnnotationSet() noexcept override
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:82
static std::unique_ptr< ExitAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:303
~LinearAnnotationSet() noexcept override
static std::unique_ptr< LinearAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:353
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:130
~LoopAnnotationSet() noexcept override
static std::unique_ptr< LoopAnnotationSet > Create(VariableSet readSet, VariableSet allWriteSet, VariableSet fullWriteSet)
Definition: Annotation.hpp:451
bool operator==(const AnnotationSet &other) const override
Definition: Annotation.cpp:189
void Insert(const Variable &v)
Definition: Annotation.hpp:132
std::string DebugString() const noexcept
Definition: Annotation.cpp:17
ConstRange Variables() const noexcept
Definition: Annotation.hpp:99
void Remove(const Variable &v)
Definition: Annotation.hpp:144
void Intersect(const VariableSet &variableSet)
Definition: Annotation.hpp:157
#define JLM_ASSERT(x)
Definition: common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
static void AnnotateReadWrite(const AggregationNode &, AnnotationMap &)
Definition: Annotation.cpp:335
static void AnnotateDemandSet(const AggregationNode &, VariableSet &, AnnotationMap &)
Definition: Annotation.cpp:472
std::unique_ptr< AnnotationMap > Annotate(const AggregationNode &aggregationTreeRoot)
Definition: Annotation.cpp:492
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35