23 std::unique_ptr<Operation>
26 return std::make_unique<PhiOperation>(*
this);
42 auto input =
addInput(std::make_unique<StructuralInput>(
this, &origin, origin.
Type()),
true);
49 [[nodiscard]] std::vector<PhiNode::ContextVar>
52 std::vector<PhiNode::ContextVar> vars;
54 for (
size_t n = 0; n <
ninputs(); ++n)
62 [[nodiscard]] std::vector<PhiNode::FixVar>
65 std::vector<PhiNode::FixVar> vars;
67 for (std::size_t n = 0; n <
noutputs(); ++n)
75 [[nodiscard]] std::optional<PhiNode::FixVar>
78 JLM_ASSERT(rvsdg::TryGetRegionParentNode<PhiNode>(argument) ==
this);
79 if (argument.index() < subregion()->nresults())
81 size_t n = argument.index();
82 return FixVar{ subregion()->argument(n), subregion()->
result(n), output(n) };
93 JLM_ASSERT(rvsdg::TryGetRegionParentNode<PhiNode>(result) ==
this);
94 return FixVar{ subregion()->argument(result.index()),
95 subregion()->
result(result.index()),
96 output(result.index()) };
102 JLM_ASSERT(rvsdg::TryGetOwnerNode<PhiNode>(output) ==
this);
103 return FixVar{ subregion()->argument(output.index()),
104 subregion()->
result(output.index()),
111 JLM_ASSERT(rvsdg::TryGetOwnerNode<PhiNode>(input) ==
this);
113 subregion()->argument(input.index() + subregion()->nresults()) };
116 [[nodiscard]] std::optional<PhiNode::ContextVar>
119 JLM_ASSERT(rvsdg::TryGetRegionParentNode<PhiNode>(argument) ==
this);
120 if (argument.index() >= subregion()->nresults())
122 size_t n = argument.index();
123 return ContextVar{ input(n - subregion()->nresults()), subregion()->argument(n) };
131 [[nodiscard]] std::variant<PhiNode::FixVar, PhiNode::ContextVar>
134 JLM_ASSERT(rvsdg::TryGetRegionParentNode<PhiNode>(argument) ==
this);
135 if (
auto ctxvar = MapArgumentContextVar(argument))
139 else if (
auto fixvar = MapArgumentFixVar(argument))
145 JLM_UNREACHABLE(
"phi binder is neither context nor fixpoint variable");
154 for (
const auto [
input, argument] : vars)
156 argumentIndices.
insert(argument->index());
163 [[maybe_unused]]
const auto numRemovedInputs =
RemoveInputs(inputIndices);
173 for (
const auto & [argument, result,
output] : vars)
175 resultIndices.
insert(result->index());
176 argumentIndices.
insert(argument->index());
186 [[maybe_unused]]
const auto numRemovedOutputs =
RemoveOutputs(outputIndices);
200 auto & origin = smap.
lookup(*var.input->origin());
202 subregionmap.
insert(var.inner, newcv.inner);
208 auto newrv = pb.
AddFixVar(var.recref->Type());
209 subregionmap.
insert(var.recref, newrv.recref);
218 auto neworigin = &subregionmap.
lookup(*var.result->origin());
219 var.result->divert_to(neworigin);
225 std::vector<rvsdg::LambdaNode *>
228 std::function<void(
const PhiNode &, std::vector<rvsdg::LambdaNode *> &)> extractLambdaNodes =
229 [&](
auto & phiNode,
auto & lambdaNodes)
235 lambdaNodes.push_back(lambdaNode);
237 else if (
auto innerPhiNode =
dynamic_cast<const PhiNode *
>(&node))
239 extractLambdaNodes(*innerPhiNode, lambdaNodes);
244 std::vector<rvsdg::LambdaNode *> lambdaNodes;
245 extractLambdaNodes(phiNode, lambdaNodes);
262 std::make_unique<RegionArgument>(
subregion(),
nullptr,
type));
277 if (var.result->origin() == var.recref)
278 throw util::Error(
"Recursion variable not properly set.");
rvsdg::Region * region() const noexcept
size_t RemoveInputs(const util::HashSet< size_t > &indices)
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
rvsdg::Region * subregion() const noexcept
PhiNode::ContextVar AddContextVar(jlm::rvsdg::Output &origin)
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
void begin(rvsdg::Region *parent)
A phi node represents the fixpoint of mutually recursive definitions.
rvsdg::Region * subregion() const noexcept
FixVar MapResultFixVar(const rvsdg::Input &result) const noexcept
Maps region result to fixpoint variable.
PhiNode * copy(rvsdg::Region *region, rvsdg::SubstitutionMap &smap) const override
Copy a node with substitutions.
ContextVar MapInputContextVar(const rvsdg::Input &input) const noexcept
Maps input to context variable.
std::optional< ContextVar > MapArgumentContextVar(const rvsdg::Output &argument) const noexcept
Attempts to map bound variable reference to context variable.
static std::vector< rvsdg::LambdaNode * > ExtractLambdaNodes(const PhiNode &phiNode)
std::vector< FixVar > GetFixVars() const noexcept
Gets all fixpoint variables.
void RemoveContextVars(std::vector< ContextVar > vars)
Removes context variables from phi node.
FixVar MapOutputFixVar(const rvsdg::Output &output) const noexcept
Maps output to fixpoint variable.
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
std::optional< FixVar > MapArgumentFixVar(const rvsdg::Output &argument) const noexcept
Tries to map region argument to fixpoint variable.
std::variant< FixVar, ContextVar > MapArgument(const rvsdg::Output &argument) const noexcept
Maps region argument to its function.
ContextVar AddContextVar(jlm::rvsdg::Output &origin)
Adds a context variable to the phi node.
void RemoveFixVars(std::vector< FixVar > vars)
Removes fixpoint variables from the phi node.
const PhiOperation & GetOperation() const noexcept override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
Represent acyclic RVSDG subgraphs.
RegionResult * result(size_t index) const noexcept
size_t RemoveResults(const util::HashSet< size_t > &indices)
RegionArgument & addArgument(std::unique_ptr< RegionArgument > argument)
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
RegionResult & addResult(std::unique_ptr< RegionResult > result)
RegionArgument * argument(size_t index) const noexcept
size_t RemoveArguments(const util::HashSet< size_t > &indices)
NodeRange Nodes() noexcept
RegionArgument & insertArgument(size_t index, std::unique_ptr< RegionArgument > argument)
StructuralInput * addInput(std::unique_ptr< StructuralInput > input, bool notifyRegion)
StructuralOutput * addOutput(std::unique_ptr< StructuralOutput > input)
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
void insert(const Output *original, Output *substitute)
Output & lookup(const Output &original) const
bool insert(ItemType item)
std::size_t Size() const noexcept
#define JLM_UNREACHABLE(msg)
static std::string type(const Node *n)
Description of a recursively defined variable.
rvsdg::Input * result
Definition result of a variable within the phi region.