22 auto constant = rvsdg::TryGetOwnerNode<SimpleNode>(*gamma->
predicate()->
origin());
23 return constant && is<ControlConstantOperation>(constant->GetOperation());
30 auto & constant = AssertGetOwnerNode<SimpleNode>(*origin);
36 smap.
insert(ev.branchArgument[alternative], ev.input->origin());
41 exitvar.output->divert_users(&smap.
lookup(*exitvar.branchResult[alternative]->origin()));
49 bool was_normalized =
true;
57 auto input = argument->
input();
58 for (n = 1; n < exitvar.branchResult.size(); n++)
62 if (!argument && argument->input() != input)
66 if (n == exitvar.branchResult.size())
68 exitvar.output->
divert_users(argument->input()->origin());
69 was_normalized =
false;
73 return was_normalized;
76 static std::unordered_set<jlm::rvsdg::Output *>
81 if (!
match || !is<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);
94 std::unordered_set<jlm::rvsdg::Output *>
outputs;
97 if (!is<ControlType>(*exitvar.output->Type()))
101 for (n = 0; n < exitvar.branchResult.size(); n++)
103 auto node = rvsdg::TryGetOwnerNode<SimpleNode>(*exitvar.branchResult[n]->origin());
104 if (!node || !is<ControlConstantOperation>(node->GetOperation()))
108 if (op->value().nalternatives() != 2)
111 if (n == exitvar.branchResult.size())
112 outputs.insert(exitvar.output);
121 auto & gamma = rvsdg::AssertGetOwnerNode<GammaNode>(**
outputs.begin());
122 auto origin = gamma.predicate()->origin();
123 auto [matchNode, matchOperation] = TryGetSimpleNodeAndOptionalOp<MatchOperation>(*origin);
126 std::unordered_map<uint64_t, uint64_t> map;
127 for (
const auto & pair : *matchOperation)
128 map[pair.second] = pair.first;
130 for (
const auto & xv : gamma.GetExitVars())
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++)
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();
148 defalt = value.alternative();
151 auto origin = matchNode->input(0)->origin();
152 auto m =
match(matchOperation->nbits(), new_mapping, defalt, nalternatives, origin);
153 xv.output->divert_users(m);
160 auto gammaNode =
dynamic_cast<GammaNode *
>(&node);
173 auto gammaNode =
dynamic_cast<GammaNode *
>(&node);
174 if (gammaNode ==
nullptr)
188 const auto gammaNode =
dynamic_cast<GammaNode *
>(&node);
189 if (gammaNode ==
nullptr)
204 std::unique_ptr<Operation>
207 return std::make_unique<GammaOperation>(*
this);
217 std::shared_ptr<const Type>
230 Operation_(std::move(op))
233 std::make_unique<StructuralInput>(
238 for (std::size_t n = 0; n < Operation_->nalternatives(); ++n)
246 size_t nalternatives,
247 std::vector<std::shared_ptr<const Type>> match_content_types)
250 std::make_unique<
GammaOperation>(nalternatives, std::move(match_content_types)))
263 addInput(std::unique_ptr<StructuralInput>(gammaInput),
true);
266 ev.
input = gammaInput;
302 std::vector<GammaNode::EntryVar>
305 std::vector<GammaNode::EntryVar> vars;
306 for (
size_t n = 0; n <
ninputs() - 1; ++n)
313 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
327 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
347 const auto &
type = values[0]->Type();
350 std::vector<rvsdg::Input *> branchResults;
353 branchResults.push_back(
357 return ExitVar{ std::move(branchResults), std::move(
output) };
360 std::vector<GammaNode::ExitVar>
363 std::vector<GammaNode::ExitVar> vars;
364 for (
size_t n = 0; n <
noutputs(); ++n)
366 std::vector<rvsdg::Input *> branchResults;
371 vars.push_back(
ExitVar{ std::move(branchResults),
output(n) });
380 std::vector<rvsdg::Input *> branchResults;
392 std::vector<rvsdg::Input *> branchResults;
404 for (
const auto & [_,
output] : exitVars)
415 [[maybe_unused]]
const auto numRemovedOutputs =
RemoveOutputs(indices);
423 for (
const auto & [
input, _] : entryVars)
434 [[maybe_unused]]
const auto numRemovedInputs =
RemoveInputs(indices);
447 auto nev = gamma->AddEntryVar(&smap.
lookup(*oev.input->origin()));
449 rmap[n].insert(oev.branchArgument[n], nev.branchArgument[n]);
459 std::vector<jlm::rvsdg::Output *>
operands;
460 for (
size_t n = 0; n < oex.branchResult.size(); n++)
461 operands.push_back(&rmap[n].lookup(*oex.branchResult[n]->origin()));
462 auto nex = gamma->AddExitVar(std::move(
operands));
463 smap.
insert(oex.output, nex.output);
469 std::optional<rvsdg::Output *>
475 auto GetExternalOriginOf = [&gamma](
rvsdg::Input * use) -> std::optional<rvsdg::Output *>
479 auto def = use->origin();
480 if (rvsdg::TryGetRegionParentNode<GammaNode>(*def) != &gamma)
485 if (
auto entryvar = std::get_if<GammaNode::EntryVar>(&rolevar))
487 return entryvar->input->origin();
495 auto firstOrigin = GetExternalOriginOf(exitvar.
branchResult[0]);
501 for (
size_t n = 1; n < exitvar.
branchResult.size(); ++n)
503 auto currentOrigin = GetExternalOriginOf(exitvar.
branchResult[n]);
504 if (!currentOrigin || *firstOrigin != *currentOrigin)
const ControlValueRepresentation & value() const noexcept
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
size_t alternative() const noexcept
Conditional operator / pattern matching.
void RemoveEntryVars(const std::vector< EntryVar > &entryVars)
Removes the given entry variables.
const GammaOperation & GetOperation() const noexcept override
ExitVar MapOutputExitVar(const rvsdg::Output &output) const
Maps gamma output to exit variable description.
std::unique_ptr< GammaOperation > Operation_
std::variant< MatchVar, EntryVar > MapInput(const rvsdg::Input &input) const
Maps gamma input to its role (match variable or entry variable).
GammaNode * copy(jlm::rvsdg::Region *region, SubstitutionMap &smap) const override
Copy a node with substitutions.
EntryVar AddEntryVar(rvsdg::Output *origin)
Routes a variable into the gamma branches.
EntryVar GetEntryVar(std::size_t index) const
Gets entry variable by index.
GammaNode(rvsdg::Output &predicate, std::unique_ptr< GammaOperation > op)
void RemoveExitVars(const std::vector< ExitVar > &exitVars)
Removes the given exit variables.
std::variant< MatchVar, EntryVar > MapBranchArgument(const rvsdg::Output &output) const
Maps branch subregion entry argument to its role (pattern match or entry variable).
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
ExitVar AddExitVar(std::vector< rvsdg::Output * > values)
Routes per-branch result of gamma to output.
ExitVar MapBranchResultExitVar(const rvsdg::Input &input) const
Maps gamma region exit result to exit variable description.
rvsdg::Input * predicate() const noexcept
~GammaNode() noexcept override
MatchVar GetMatchVar() const
std::shared_ptr< const Type > GetMatchContentType(std::size_t alternative) const
Returns the type of pattern matching content produced in a branch.
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
std::vector< std::shared_ptr< const Type > > MatchContentTypes_
std::string debug_string() const override
~GammaOperation() noexcept override
rvsdg::Region * region() const noexcept
size_t RemoveInputs(const util::HashSet< size_t > &indices)
NodeOutput * output(size_t index) const noexcept
size_t ninputs() const noexcept
size_t noutputs() const noexcept
size_t RemoveOutputs(const util::HashSet< size_t > &indices)
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
size_t index() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
Represents the argument of a region.
StructuralInput * input() const noexcept
static RegionArgument & Create(rvsdg::Region ®ion, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
static RegionResult & Create(rvsdg::Region ®ion, rvsdg::Output &origin, StructuralOutput *output, std::shared_ptr< const rvsdg::Type > type)
Create region exit result.
Represent acyclic RVSDG subgraphs.
RegionResult * result(size_t index) const noexcept
size_t RemoveResults(const util::HashSet< size_t > &indices)
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
RegionArgument * argument(size_t index) const noexcept
size_t RemoveArguments(const util::HashSet< size_t > &indices)
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()
bool insert(ItemType item)
std::size_t Size() const noexcept
static bool perform_invariant_reduction(GammaNode *gamma)
static std::unordered_set< jlm::rvsdg::Output * > is_control_constant_reducible(GammaNode *gamma)
bool ReduceGammaControlConstant(Node &node)
static void perform_predicate_reduction(GammaNode *gamma)
bool ReduceGammaWithStaticallyKnownPredicate(Node &node)
static bool is_predicate_reducible(const GammaNode *gamma)
static void remove(Node *node)
static void perform_control_constant_reduction(std::unordered_set< jlm::rvsdg::Output * > &outputs)
static std::string type(const Node *n)
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)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
std::optional< rvsdg::Output * > GetGammaInvariantOrigin(const GammaNode &gamma, const GammaNode::ExitVar &exitvar)
Determines whether a gamma exit var is path-invariant.
bool ReduceGammaInvariantVariables(Node &node)
A variable routed into all gamma regions.
rvsdg::Input * input
Variable at entry point (input to gamma node).
std::vector< rvsdg::Output * > branchArgument
Variable inside each of the branch regions (argument per subregion).
A variable routed out of all gamma regions as result.
std::vector< rvsdg::Input * > branchResult
Variable exit points (results per subregion).
The match/discriminator variable of this gamma node.
rvsdg::Input * input
The variable matched over (i.e. the "selector" of the gamma branch).
std::vector< rvsdg::Output * > matchContent
The content of the match per branch.