Jlm
GammaConversion.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2021 David Metz <david.c.metz@ntnu.no>
3  * See COPYING for terms of redistribution.
4  */
5 
7 #include <jlm/hls/ir/hls.hpp>
8 #include <jlm/rvsdg/gamma.hpp>
10 #include <jlm/rvsdg/theta.hpp>
11 #include <jlm/rvsdg/traverser.hpp>
12 
13 namespace jlm::hls
14 {
15 
16 static void
18 {
19  rvsdg::SubstitutionMap substitutionMap;
20 
21  // create a branch for each gamma input and map the corresponding argument of each subregion to an
22  // output of the branch
23  for (const auto & entryvar : gammaNode.GetEntryVars())
24  {
25  auto branchResults =
26  BranchOperation::create(*gammaNode.predicate()->origin(), *entryvar.input->origin());
27 
28  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
29  {
30  substitutionMap.insert(entryvar.branchArgument[s], branchResults[s]);
31  }
32  }
33 
34  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
35  {
36  gammaNode.subregion(s)->copy(gammaNode.region(), substitutionMap);
37  }
38 
39  for (const auto & ex : gammaNode.GetExitVars())
40  {
41  std::vector<rvsdg::Output *> alternatives;
42  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
43  {
44  alternatives.push_back(&substitutionMap.lookup(*ex.branchResult[s]->origin()));
45  }
46  // create mux nodes for each gamma output
47  // use mux instead of merge in case of paths with different delay - otherwise one could overtake
48  // the other see https://ieeexplore.ieee.org/abstract/document/9515491
49  auto mux = MuxOperation::create(*gammaNode.predicate()->origin(), alternatives, false);
50 
51  ex.output->divert_users(mux[0]);
52  }
53 
54  remove(&gammaNode);
55 }
56 
57 static void
59 {
60  rvsdg::SubstitutionMap substitutionMap;
61 
62  // Map arguments to origins of inputs. Forks will automatically be created later
63  for (const auto & entryvar : gammaNode.GetEntryVars())
64  {
65  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
66  {
67  substitutionMap.insert(entryvar.branchArgument[s], entryvar.input->origin());
68  }
69  }
70 
71  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
72  {
73  gammaNode.subregion(s)->copy(gammaNode.region(), substitutionMap);
74  }
75 
76  for (const auto & ex : gammaNode.GetExitVars())
77  {
78  std::vector<rvsdg::Output *> alternatives;
79  for (size_t s = 0; s < gammaNode.nsubregions(); s++)
80  {
81  alternatives.push_back(&substitutionMap.lookup(*ex.branchResult[s]->origin()));
82  }
83 
84  // create discarding mux for each gamma output
85  auto merge = MuxOperation::create(*gammaNode.predicate()->origin(), alternatives, true);
86 
87  ex.output->divert_users(merge[0]);
88  }
89 
90  remove(&gammaNode);
91 }
92 
93 static bool
95 {
96  for (size_t i = 0; i < gammaNode.noutputs(); ++i)
97  {
98  auto gammaOutput = gammaNode.output(i);
99  if (gammaOutput->Type()->Kind() == rvsdg::TypeKind::State)
100  {
101  // don't allow state outputs since they imply operations with side effects
102  return false;
103  }
104  }
105 
106  for (size_t i = 0; i < gammaNode.nsubregions(); ++i)
107  {
108  for (auto & node : gammaNode.subregion(i)->Nodes())
109  {
110  if (dynamic_cast<const rvsdg::ThetaNode *>(&node) || dynamic_cast<const LoopNode *>(&node))
111  {
112  // don't allow thetas or loops since they could potentially block forever
113  return false;
114  }
115  else if (auto innerGammaNode = dynamic_cast<rvsdg::GammaNode *>(&node))
116  {
117  if (!CanGammaNodeBeSpeculative(*innerGammaNode))
118  {
119  // only allow gammas that can also be speculated on
120  return false;
121  }
122  }
123  else if (rvsdg::is<rvsdg::StructuralOperation>(&node))
124  {
125  throw util::Error("Unexpected structural node: " + node.DebugString());
126  }
127  }
128  }
129 
130  return true;
131 }
132 
133 static void
135 
136 static void
138 {
139  for (size_t n = 0; n < structuralNode.nsubregions(); n++)
140  {
141  ConvertGammaNodesInRegion(*structuralNode.subregion(n));
142  }
143 
144  if (auto gammaNode = dynamic_cast<rvsdg::GammaNode *>(&structuralNode))
145  {
146  if (CanGammaNodeBeSpeculative(*gammaNode))
147  {
149  }
150  else
151  {
153  }
154  }
155 }
156 
157 static void
159 {
160  for (auto & node : rvsdg::TopDownTraverser(&region))
161  {
162  if (auto structuralNode = dynamic_cast<rvsdg::StructuralNode *>(node))
163  {
164  ConvertGammaNodesInStructuralNode(*structuralNode);
165  }
166  }
167 }
168 
169 GammaNodeConversion::~GammaNodeConversion() noexcept = default;
170 
173 {}
174 
175 void
177 {
179 }
180 
181 }
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &predicate, jlm::rvsdg::Output &value, bool loop=false)
Definition: hls.hpp:68
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
~GammaNodeConversion() noexcept override
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &predicate, const std::vector< jlm::rvsdg::Output * > &alternatives, bool discarding, bool loop=false)
Definition: hls.hpp:235
Conditional operator / pattern matching.
Definition: gamma.hpp:99
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
Definition: gamma.cpp:361
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Definition: gamma.cpp:303
rvsdg::Input * predicate() const noexcept
Definition: gamma.hpp:398
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Output * origin() const noexcept
Definition: node.hpp:58
rvsdg::Region * region() const noexcept
Definition: node.hpp:761
size_t noutputs() const noexcept
Definition: node.hpp:644
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition: region.cpp:314
NodeRange Nodes() noexcept
Definition: region.hpp:328
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
void insert(const Output *original, Output *substitute)
Output & lookup(const Output &original) const
Represents an RVSDG transformation.
static void ConvertGammaNodeWithoutSpeculation(rvsdg::GammaNode &gammaNode)
static void ConvertGammaNodeWithSpeculation(rvsdg::GammaNode &gammaNode)
static void ConvertGammaNodesInStructuralNode(rvsdg::StructuralNode &structuralNode)
static bool CanGammaNodeBeSpeculative(const rvsdg::GammaNode &gammaNode)
static void ConvertGammaNodesInRegion(rvsdg::Region &region)
static void remove(Node *node)
Definition: region.hpp:932
@ State
Designate a state type.