Jlm
gamma.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2010 2011 2012 2013 2014 Helge Bahmann <hcb@chaoticmind.net>
3  * Copyright 2013 2014 2015 2016 Nico Reißmann <nico.reissmann@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
7 #include <algorithm>
8 
9 #include <jlm/rvsdg/control.hpp>
10 #include <jlm/rvsdg/gamma.hpp>
12 #include <jlm/rvsdg/UnitType.hpp>
13 
14 namespace jlm::rvsdg
15 {
16 
17 /* gamma normal form */
18 
19 static bool
21 {
22  auto constant = rvsdg::TryGetOwnerNode<SimpleNode>(*gamma->predicate()->origin());
23  return constant && is<ControlConstantOperation>(constant->GetOperation());
24 }
25 
26 static void
28 {
29  auto origin = gamma->predicate()->origin();
30  auto & constant = AssertGetOwnerNode<SimpleNode>(*origin);
31  auto cop = static_cast<const ControlConstantOperation *>(&constant.GetOperation());
32  auto alternative = cop->value().alternative();
33 
35  for (const auto & ev : gamma->GetEntryVars())
36  smap.insert(ev.branchArgument[alternative], ev.input->origin());
37 
38  gamma->subregion(alternative)->copy(gamma->region(), smap);
39 
40  for (auto exitvar : gamma->GetExitVars())
41  exitvar.output->divert_users(&smap.lookup(*exitvar.branchResult[alternative]->origin()));
42 
43  remove(gamma);
44 }
45 
46 static bool
48 {
49  bool was_normalized = true;
50  for (auto exitvar : gamma->GetExitVars())
51  {
52  auto argument = dynamic_cast<const rvsdg::RegionArgument *>(exitvar.branchResult[0]->origin());
53  if (!argument)
54  continue;
55 
56  size_t n = 0;
57  auto input = argument->input();
58  for (n = 1; n < exitvar.branchResult.size(); n++)
59  {
60  auto argument =
61  dynamic_cast<const rvsdg::RegionArgument *>(exitvar.branchResult[n]->origin());
62  if (!argument && argument->input() != input)
63  break;
64  }
65 
66  if (n == exitvar.branchResult.size())
67  {
68  exitvar.output->divert_users(argument->input()->origin());
69  was_normalized = false;
70  }
71  }
72 
73  return was_normalized;
74 }
75 
76 static std::unordered_set<jlm::rvsdg::Output *>
78 {
79  // check gamma predicate
80  auto match = rvsdg::TryGetOwnerNode<SimpleNode>(*gamma->predicate()->origin());
81  if (!match || !is<MatchOperation>(match->GetOperation()))
82  return {};
83 
84  /* check number of alternatives */
85  auto match_op = static_cast<const MatchOperation *>(&match->GetOperation());
86  std::unordered_set<uint64_t> set({ match_op->default_alternative() });
87  for (const auto & pair : *match_op)
88  set.insert(pair.second);
89 
90  if (set.size() != gamma->nsubregions())
91  return {};
92 
93  /* check for constants */
94  std::unordered_set<jlm::rvsdg::Output *> outputs;
95  for (const auto & exitvar : gamma->GetExitVars())
96  {
97  if (!is<ControlType>(*exitvar.output->Type()))
98  continue;
99 
100  size_t n = 0;
101  for (n = 0; n < exitvar.branchResult.size(); n++)
102  {
103  auto node = rvsdg::TryGetOwnerNode<SimpleNode>(*exitvar.branchResult[n]->origin());
104  if (!node || !is<ControlConstantOperation>(node->GetOperation()))
105  break;
106 
107  auto op = static_cast<const ControlConstantOperation *>(&node->GetOperation());
108  if (op->value().nalternatives() != 2)
109  break;
110  }
111  if (n == exitvar.branchResult.size())
112  outputs.insert(exitvar.output);
113  }
114 
115  return outputs;
116 }
117 
118 static void
119 perform_control_constant_reduction(std::unordered_set<jlm::rvsdg::Output *> & outputs)
120 {
121  auto & gamma = rvsdg::AssertGetOwnerNode<GammaNode>(**outputs.begin());
122  auto origin = gamma.predicate()->origin();
123  auto [matchNode, matchOperation] = TryGetSimpleNodeAndOptionalOp<MatchOperation>(*origin);
124  JLM_ASSERT(matchNode && matchOperation);
125 
126  std::unordered_map<uint64_t, uint64_t> map;
127  for (const auto & pair : *matchOperation)
128  map[pair.second] = pair.first;
129 
130  for (const auto & xv : gamma.GetExitVars())
131  {
132  if (outputs.find(xv.output) == outputs.end())
133  continue;
134 
135  size_t defalt = 0;
136  size_t nalternatives = 0;
137  std::unordered_map<uint64_t, uint64_t> new_mapping;
138  for (size_t n = 0; n < xv.branchResult.size(); n++)
139  {
140  auto origin = xv.branchResult[n]->origin();
141  auto [ctlConstantNode, ctlConstantOperation] =
142  TryGetSimpleNodeAndOptionalOp<ControlConstantOperation>(*origin);
143  auto & value = ctlConstantOperation->value();
144  nalternatives = value.nalternatives();
145  if (map.find(n) != map.end())
146  new_mapping[map[n]] = value.alternative();
147  else
148  defalt = value.alternative();
149  }
150 
151  auto origin = matchNode->input(0)->origin();
152  auto & matchNode = MatchOperation::CreateNode(*origin, new_mapping, defalt, nalternatives);
153  xv.output->divert_users(matchNode.output(0));
154  }
155 }
156 
157 bool
159 {
160  auto gammaNode = dynamic_cast<GammaNode *>(&node);
161  if (gammaNode && is_predicate_reducible(gammaNode))
162  {
163  perform_predicate_reduction(gammaNode);
164  return true;
165  }
166 
167  return false;
168 }
169 
170 bool
172 {
173  auto gammaNode = dynamic_cast<GammaNode *>(&node);
174  if (gammaNode == nullptr)
175  return false;
176 
177  auto outputs = is_control_constant_reducible(gammaNode);
178  if (outputs.empty())
179  return false;
180 
182  return true;
183 }
184 
185 bool
187 {
188  const auto gammaNode = dynamic_cast<GammaNode *>(&node);
189  if (gammaNode == nullptr)
190  return false;
191 
192  return !perform_invariant_reduction(gammaNode);
193 }
194 
196 {}
197 
198 std::string
200 {
201  return "GAMMA";
202 }
203 
204 std::unique_ptr<Operation>
206 {
207  return std::make_unique<GammaOperation>(*this);
208 }
209 
210 bool
211 GammaOperation::operator==(const Operation & other) const noexcept
212 {
213  auto op = dynamic_cast<const GammaOperation *>(&other);
214  return op && op->numAlternatives_ == numAlternatives_;
215 }
216 
217 std::shared_ptr<const Type>
218 GammaOperation::GetMatchContentType(std::size_t alternative) const
219 {
220  return alternative < MatchContentTypes_.size() ? MatchContentTypes_[alternative]
221  : UnitType::Create();
222 }
223 
224 /* gamma node */
225 
226 GammaNode::~GammaNode() noexcept = default;
227 
228 GammaNode::GammaNode(rvsdg::Output & predicate, std::unique_ptr<GammaOperation> op)
229  : StructuralNode(predicate.region(), op->nalternatives()),
230  Operation_(std::move(op))
231 {
232  addInput(
233  std::make_unique<StructuralInput>(
234  this,
235  &predicate,
236  ControlType::Create(Operation_->nalternatives())),
237  false);
238  for (std::size_t n = 0; n < Operation_->nalternatives(); ++n)
239  {
240  RegionArgument::Create(*subregion(n), nullptr, Operation_->GetMatchContentType(n));
241  }
242 }
243 
245  rvsdg::Output & predicate,
246  size_t nalternatives,
247  std::vector<std::shared_ptr<const Type>> match_content_types)
248  : GammaNode(
249  predicate,
250  std::make_unique<GammaOperation>(nalternatives, std::move(match_content_types)))
251 {}
252 
253 [[nodiscard]] const GammaOperation &
254 GammaNode::GetOperation() const noexcept
255 {
256  return *Operation_;
257 }
258 
261 {
262  auto gammaInput = new StructuralInput(this, origin, origin->Type());
263  addInput(std::unique_ptr<StructuralInput>(gammaInput), true);
264 
265  EntryVar ev;
266  ev.input = gammaInput;
267 
268  for (size_t n = 0; n < nsubregions(); n++)
269  {
270  ev.branchArgument.push_back(
271  &RegionArgument::Create(*subregion(n), gammaInput, gammaInput->Type()));
272  }
273 
274  return ev;
275 }
276 
278 GammaNode::GetEntryVar(std::size_t index) const
279 {
280  JLM_ASSERT(index <= ninputs() - 1);
281  EntryVar ev;
282  ev.input = input(index + 1);
283  ev.branchArgument.resize(nsubregions());
284  for (size_t n = 0; n < nsubregions(); ++n)
285  {
286  ev.branchArgument[n] = subregion(n)->argument(index + 1);
287  }
288  return ev;
289 }
290 
293 {
294  MatchVar mv;
295  mv.input = input(0);
296  mv.matchContent.resize(nsubregions());
297  for (size_t n = 0; n < nsubregions(); ++n)
298  {
299  mv.matchContent[n] = subregion(n)->argument(0);
300  }
301  return mv;
302 }
303 
304 std::vector<GammaNode::EntryVar>
306 {
307  std::vector<GammaNode::EntryVar> vars(ninputs() - 1);
308  for (size_t n = 0; n < vars.size(); ++n)
309  {
310  vars[n] = GetEntryVar(n);
311  }
312  return vars;
313 }
314 
315 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
316 GammaNode::MapInput(const rvsdg::Input & input) const
317 {
318  JLM_ASSERT(rvsdg::TryGetOwnerNode<GammaNode>(input) == this);
319  if (input.index() == 0)
320  {
321  return GetMatchVar();
322  }
323  else
324  {
325  return GetEntryVar(input.index() - 1);
326  }
327 }
328 
329 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
331 {
332  JLM_ASSERT(rvsdg::TryGetRegionParentNode<GammaNode>(output) == this);
333  if (output.index() == 0)
334  {
335  return GetMatchVar();
336  }
337  else
338  {
339  return GetEntryVar(output.index() - 1);
340  }
341 }
342 
343 const rvsdg::Input &
345 {
346  JLM_ASSERT(rvsdg::TryGetRegionParentNode<GammaNode>(output) == this);
347  auto & in = *input(output.index());
348  JLM_ASSERT(*in.Type() == *output.Type());
349  return in;
350 }
351 
352 Input &
354 {
355  JLM_ASSERT(rvsdg::TryGetRegionParentNode<GammaNode>(output) == this);
356  auto & in = *input(output.index());
357  JLM_ASSERT(*in.Type() == *output.Type());
358  return in;
359 }
360 
362 GammaNode::AddExitVar(const std::vector<jlm::rvsdg::Output *> & values)
363 {
364  if (values.size() != nsubregions())
365  throw util::Error("Incorrect number of values.");
366 
367  const auto & type = values[0]->Type();
368  auto output = addOutput(std::make_unique<StructuralOutput>(this, type));
369 
370  std::vector<rvsdg::Input *> branchResults;
371  for (size_t n = 0; n < nsubregions(); n++)
372  {
373  branchResults.push_back(
374  &rvsdg::RegionResult::Create(*subregion(n), *values[n], output, output->Type()));
375  }
376 
377  return ExitVar{ std::move(branchResults), std::move(output) };
378 }
379 
380 std::vector<GammaNode::ExitVar>
382 {
383  std::vector<GammaNode::ExitVar> vars;
384  for (size_t n = 0; n < noutputs(); ++n)
385  {
386  std::vector<rvsdg::Input *> branchResults;
387  for (size_t k = 0; k < nsubregions(); ++k)
388  {
389  branchResults.push_back(subregion(k)->result(n));
390  }
391  vars.push_back(ExitVar{ std::move(branchResults), output(n) });
392  }
393  return vars;
394 }
395 
398 {
399  JLM_ASSERT(TryGetOwnerNode<GammaNode>(output) == this);
400  std::vector<rvsdg::Input *> branchResults;
401  for (size_t k = 0; k < nsubregions(); ++k)
402  {
403  branchResults.push_back(subregion(k)->result(output.index()));
404  }
405  return ExitVar{ std::move(branchResults), Node::output(output.index()) };
406 }
407 
410 {
411  JLM_ASSERT(TryGetRegionParentNode<GammaNode>(input) == this);
412  std::vector<rvsdg::Input *> branchResults;
413  for (size_t k = 0; k < nsubregions(); ++k)
414  {
415  branchResults.push_back(subregion(k)->result(input.index()));
416  }
417  return ExitVar{ std::move(branchResults), Node::output(input.index()) };
418 }
419 
420 const Output &
422 {
423  JLM_ASSERT(TryGetRegionParentNode<GammaNode>(input) == this);
424  auto & out = *output(input.index());
425  JLM_ASSERT(*out.Type() == *input.Type());
426  return out;
427 }
428 
429 Output &
431 {
432  JLM_ASSERT(TryGetRegionParentNode<GammaNode>(input) == this);
433  auto & out = *output(input.index());
434  JLM_ASSERT(*out.Type() == *input.Type());
435  return out;
436 }
437 
438 void
439 GammaNode::RemoveExitVars(const std::vector<Output *> & gammaOutputs)
440 {
441  util::HashSet<size_t> indices;
442  for (const auto output : gammaOutputs)
443  {
445  JLM_ASSERT(TryGetOwnerNode<GammaNode>(*output) == this);
446  indices.insert(output->index());
447  }
448 
449  for (auto & subregion : Subregions())
450  {
451  [[maybe_unused]] const auto numRemovedResults = subregion.RemoveResults(indices);
452  JLM_ASSERT(numRemovedResults == indices.Size());
453  }
454  [[maybe_unused]] const auto numRemovedOutputs = RemoveOutputs(indices);
455  JLM_ASSERT(numRemovedOutputs == indices.Size());
456 }
457 
458 void
459 GammaNode::RemoveEntryVars(const std::vector<EntryVar> & entryVars)
460 {
461  util::HashSet<size_t> indices;
462  for (const auto & [input, _] : entryVars)
463  {
464  JLM_ASSERT(TryGetOwnerNode<GammaNode>(*input) == this);
465  indices.insert(input->index());
466  }
467 
468  for (auto & subregion : Subregions())
469  {
470  [[maybe_unused]] const auto numRemovedArguments = subregion.RemoveArguments(indices);
471  JLM_ASSERT(numRemovedArguments == indices.Size());
472  }
473  [[maybe_unused]] const auto numRemovedInputs = RemoveInputs(indices);
474  JLM_ASSERT(numRemovedInputs == indices.Size());
475 }
476 
477 GammaNode *
479 {
480  auto gamma = create(&smap.lookup(*predicate()->origin()), nsubregions());
481 
482  /* add entry variables to new gamma */
483  std::vector<SubstitutionMap> rmap(nsubregions());
484  for (const auto & oev : GetEntryVars())
485  {
486  auto nev = gamma->AddEntryVar(&smap.lookup(*oev.input->origin()));
487  for (size_t n = 0; n < nsubregions(); n++)
488  rmap[n].insert(oev.branchArgument[n], nev.branchArgument[n]);
489  }
490 
491  /* copy subregions */
492  for (size_t r = 0; r < nsubregions(); r++)
493  subregion(r)->copy(gamma->subregion(r), rmap[r]);
494 
495  /* add exit variables to new gamma */
496  for (const auto & oex : GetExitVars())
497  {
498  std::vector<jlm::rvsdg::Output *> operands;
499  for (size_t n = 0; n < oex.branchResult.size(); n++)
500  operands.push_back(&rmap[n].lookup(*oex.branchResult[n]->origin()));
501  auto nex = gamma->AddExitVar(std::move(operands));
502  smap.insert(oex.output, nex.output);
503  }
504 
505  return gamma;
506 }
507 
508 std::optional<rvsdg::Output *>
509 GetGammaInvariantOrigin(const GammaNode & gamma, const GammaNode::ExitVar & exitvar)
510 {
511  // For any region result, check if it directly maps to a
512  // gamma entry variable, and returns the origin of its
513  // corresponding value (the def site preceding the gamma node).
514  auto GetExternalOriginOf = [&gamma](rvsdg::Input * use) -> std::optional<rvsdg::Output *>
515  {
516  // Test whether origin of this is a region entry argument of
517  // this gamma node.
518  auto def = use->origin();
519  if (rvsdg::TryGetRegionParentNode<GammaNode>(*def) != &gamma)
520  {
521  return std::nullopt;
522  }
523  auto rolevar = gamma.MapBranchArgument(*def);
524  if (auto entryvar = std::get_if<GammaNode::EntryVar>(&rolevar))
525  {
526  return entryvar->input->origin();
527  }
528  else
529  {
530  return std::nullopt;
531  }
532  };
533 
534  auto firstOrigin = GetExternalOriginOf(exitvar.branchResult[0]);
535  if (!firstOrigin)
536  {
537  return std::nullopt;
538  }
539 
540  for (size_t n = 1; n < exitvar.branchResult.size(); ++n)
541  {
542  auto currentOrigin = GetExternalOriginOf(exitvar.branchResult[n]);
543  if (!currentOrigin || *firstOrigin != *currentOrigin)
544  {
545  return std::nullopt;
546  }
547  }
548 
549  return firstOrigin;
550 }
551 
552 }
const ControlValueRepresentation & value() const noexcept
Definition: control.hpp:116
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
size_t alternative() const noexcept
Definition: control.hpp:83
Conditional operator / pattern matching.
Definition: gamma.hpp:99
void RemoveEntryVars(const std::vector< EntryVar > &entryVars)
Removes the given entry variables.
Definition: gamma.cpp:459
const GammaOperation & GetOperation() const noexcept override
Definition: gamma.cpp:254
ExitVar MapOutputExitVar(const rvsdg::Output &output) const
Maps gamma output to exit variable description.
Definition: gamma.cpp:397
const rvsdg::Input & mapBranchArgumentToInput(const rvsdg::Output &output) const
Maps branch subregion entry argument to its corresponding gamma input.
Definition: gamma.cpp:344
std::unique_ptr< GammaOperation > Operation_
Definition: gamma.hpp:459
std::variant< MatchVar, EntryVar > MapInput(const rvsdg::Input &input) const
Maps gamma input to its role (match variable or entry variable).
Definition: gamma.cpp:316
GammaNode * copy(jlm::rvsdg::Region *region, SubstitutionMap &smap) const override
Copy a node with substitutions.
Definition: gamma.cpp:478
EntryVar AddEntryVar(rvsdg::Output *origin)
Routes a variable into the gamma branches.
Definition: gamma.cpp:260
EntryVar GetEntryVar(std::size_t index) const
Gets entry variable by index.
Definition: gamma.cpp:278
GammaNode(rvsdg::Output &predicate, std::unique_ptr< GammaOperation > op)
Definition: gamma.cpp:228
std::variant< MatchVar, EntryVar > MapBranchArgument(const rvsdg::Output &output) const
Maps branch subregion entry argument to its role (pattern match or entry variable).
Definition: gamma.cpp:330
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
Definition: gamma.cpp:381
const Output & mapBranchResultToOutput(const Input &input) const
Maps branch subregion exit result to its corresponding gamma output.
Definition: gamma.cpp:421
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Definition: gamma.cpp:305
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
Definition: gamma.hpp:161
void RemoveExitVars(const std::vector< Output * > &gammaOutputs)
Removes the exit variables corresponding to the given gammaOutputs.
Definition: gamma.cpp:439
ExitVar MapBranchResultExitVar(const rvsdg::Input &input) const
Maps gamma region exit result to exit variable description.
Definition: gamma.cpp:409
rvsdg::Input * predicate() const noexcept
Definition: gamma.hpp:487
~GammaNode() noexcept override
ExitVar AddExitVar(const std::vector< rvsdg::Output * > &values)
Routes per-branch result of gamma to output.
Definition: gamma.cpp:362
MatchVar GetMatchVar() const
Definition: gamma.cpp:292
std::shared_ptr< const Type > GetMatchContentType(std::size_t alternative) const
Returns the type of pattern matching content produced in a branch.
Definition: gamma.cpp:218
std::unique_ptr< Operation > copy() const override
Definition: gamma.cpp:205
bool operator==(const Operation &other) const noexcept override
Definition: gamma.cpp:211
std::vector< std::shared_ptr< const Type > > MatchContentTypes_
Definition: gamma.hpp:61
std::string debug_string() const override
Definition: gamma.cpp:199
~GammaOperation() noexcept override
Definition: gamma.cpp:195
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
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:226
rvsdg::Region * region() const noexcept
Definition: node.hpp:761
size_t RemoveInputs(const util::HashSet< size_t > &indices)
Definition: node.cpp:306
NodeOutput * output(size_t index) const noexcept
Definition: node.hpp:650
size_t ninputs() const noexcept
Definition: node.hpp:609
size_t noutputs() const noexcept
Definition: node.hpp:644
size_t RemoveOutputs(const util::HashSet< size_t > &indices)
Definition: node.cpp:342
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
size_t index() const noexcept
Definition: node.hpp:274
void divert_users(jlm::rvsdg::Output *new_origin)
Definition: node.hpp:301
bool IsDead() const noexcept
Definition: node.hpp:295
Represents the argument of a region.
Definition: region.hpp:41
StructuralInput * input() const noexcept
Definition: region.hpp:69
static RegionArgument & Create(rvsdg::Region &region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
Definition: region.cpp:62
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
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition: region.cpp:314
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
size_t RemoveArguments(const util::HashSet< size_t > &indices)
Definition: region.cpp:210
StructuralInput * addInput(std::unique_ptr< StructuralInput > input, bool notifyRegion)
StructuralOutput * addOutput(std::unique_ptr< StructuralOutput > input)
SubregionIteratorRange Subregions()
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(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
static std::shared_ptr< const UnitType > Create()
Definition: UnitType.cpp:33
bool insert(ItemType item)
Definition: HashSet.hpp:210
std::size_t Size() const noexcept
Definition: HashSet.hpp:187
#define JLM_ASSERT(x)
Definition: common.hpp:16
static bool perform_invariant_reduction(GammaNode *gamma)
Definition: gamma.cpp:47
static std::unordered_set< jlm::rvsdg::Output * > is_control_constant_reducible(GammaNode *gamma)
Definition: gamma.cpp:77
bool ReduceGammaControlConstant(Node &node)
Definition: gamma.cpp:171
static void perform_predicate_reduction(GammaNode *gamma)
Definition: gamma.cpp:27
bool ReduceGammaWithStaticallyKnownPredicate(Node &node)
Definition: gamma.cpp:158
static bool is_predicate_reducible(const GammaNode *gamma)
Definition: gamma.cpp:20
static void remove(Node *node)
Definition: region.hpp:978
static void perform_control_constant_reduction(std::unordered_set< jlm::rvsdg::Output * > &outputs)
Definition: gamma.cpp:119
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058
std::optional< rvsdg::Output * > GetGammaInvariantOrigin(const GammaNode &gamma, const GammaNode::ExitVar &exitvar)
Determines whether a gamma exit var is path-invariant.
Definition: gamma.cpp:509
bool ReduceGammaInvariantVariables(Node &node)
Definition: gamma.cpp:186
A variable routed into all gamma regions.
Definition: gamma.hpp:131
rvsdg::Input * input
Variable at entry point (input to gamma node).
Definition: gamma.hpp:135
std::vector< rvsdg::Output * > branchArgument
Variable inside each of the branch regions (argument per subregion).
Definition: gamma.hpp:139
A variable routed out of all gamma regions as result.
Definition: gamma.hpp:146
std::vector< rvsdg::Input * > branchResult
Variable exit points (results per subregion).
Definition: gamma.hpp:150
The match/discriminator variable of this gamma node.
Definition: gamma.hpp:116
rvsdg::Input * input
The variable matched over (i.e. the "selector" of the gamma branch).
Definition: gamma.hpp:120
std::vector< rvsdg::Output * > matchContent
The content of the match per branch.
Definition: gamma.hpp:124