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 *>
80 auto match = rvsdg::TryGetOwnerNode<SimpleNode>(*gamma->
predicate()->
origin());
81 if (!match || !is<MatchOperation>(match->GetOperation()))
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);
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();
153 xv.output->divert_users(matchNode.output(0));
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;
304 std::vector<GammaNode::EntryVar>
307 std::vector<GammaNode::EntryVar> vars(
ninputs() - 1);
308 for (
size_t n = 0; n < vars.size(); ++n)
315 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
329 std::variant<GammaNode::MatchVar, GammaNode::EntryVar>
367 const auto & type = values[0]->Type();
368 auto output =
addOutput(std::make_unique<StructuralOutput>(
this, type));
370 std::vector<rvsdg::Input *> branchResults;
373 branchResults.push_back(
377 return ExitVar{ std::move(branchResults), std::move(
output) };
380 std::vector<GammaNode::ExitVar>
383 std::vector<GammaNode::ExitVar> vars;
384 for (
size_t n = 0; n <
noutputs(); ++n)
386 std::vector<rvsdg::Input *> branchResults;
391 vars.push_back(
ExitVar{ std::move(branchResults),
output(n) });
400 std::vector<rvsdg::Input *> branchResults;
412 std::vector<rvsdg::Input *> branchResults;
442 for (
const auto output : gammaOutputs)
454 [[maybe_unused]]
const auto numRemovedOutputs =
RemoveOutputs(indices);
462 for (
const auto & [
input, _] : entryVars)
473 [[maybe_unused]]
const auto numRemovedInputs =
RemoveInputs(indices);
486 auto nev = gamma->AddEntryVar(&smap.
lookup(*oev.input->origin()));
488 rmap[n].insert(oev.branchArgument[n], nev.branchArgument[n]);
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);
508 std::optional<rvsdg::Output *>
514 auto GetExternalOriginOf = [&gamma](
rvsdg::Input * use) -> std::optional<rvsdg::Output *>
518 auto def = use->origin();
519 if (rvsdg::TryGetRegionParentNode<GammaNode>(*def) != &gamma)
524 if (
auto entryvar = std::get_if<GammaNode::EntryVar>(&rolevar))
526 return entryvar->input->origin();
534 auto firstOrigin = GetExternalOriginOf(exitvar.
branchResult[0]);
540 for (
size_t n = 1; n < exitvar.
branchResult.size(); ++n)
542 auto currentOrigin = GetExternalOriginOf(exitvar.
branchResult[n]);
543 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.
const rvsdg::Input & mapBranchArgumentToInput(const rvsdg::Output &output) const
Maps branch subregion entry argument to its corresponding gamma input.
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)
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.
const Output & mapBranchResultToOutput(const Input &input) const
Maps branch subregion exit result to its corresponding gamma output.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
void RemoveExitVars(const std::vector< Output * > &gammaOutputs)
Removes the exit variables corresponding to the given gammaOutputs.
ExitVar MapBranchResultExitVar(const rvsdg::Input &input) const
Maps gamma region exit result to exit variable description.
rvsdg::Input * predicate() const noexcept
~GammaNode() noexcept override
ExitVar AddExitVar(const std::vector< rvsdg::Output * > &values)
Routes per-branch result of gamma to output.
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
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
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)
bool IsDead() const noexcept
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::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.