21 const auto subregion = loopNode->
subregion();
22 for (
const auto argument : subregion->Arguments())
25 || argument->IsDead())
27 auto & user = *argument->Users().begin();
30 resultIndices.
insert(result->index());
31 argumentIndices.
insert(argument->index());
36 [[maybe_unused]]
const auto numRemovedResults = subregion->RemoveResults(resultIndices);
39 [[maybe_unused]]
const auto numRemovedArguments = subregion->RemoveArguments(argumentIndices);
42 return numRemovedArguments != 0;
48 bool any_changed =
false;
50 for (
int i = ln->
noutputs() - 1; i >= 0; --i)
52 const auto out = ln->
output(i);
53 if (out->nusers() == 0)
65 bool any_changed =
false;
67 for (
int i = ln->
ninputs() - 1; i >= 0; --i)
69 const auto in = ln->
input(i);
71 const auto arg = in->arguments.begin();
72 if (arg->nusers() != 1)
75 auto & user = *arg->Users().begin();
78 result->output()->divert_users(in->origin());
90 bool any_changed =
false;
93 for (
int i = ln->
ninputs() - 1; i >= 0; --i)
95 auto in = ln->
input(i);
97 auto arg = in->arguments.begin();
98 if (arg->nusers() == 0)
106 for (
int i = sr->narguments() - 1; i >= 0; --i)
108 auto arg = sr->argument(i);
111 auto result = ba->result();
113 if (arg->nusers() == 0 || (arg->nusers() == 1 && result->origin() == arg))
115 sr->RemoveResults({ result->index() });
116 sr->RemoveArguments({ arg->index() });
130 const auto mux_op = util::assertedCast<const MuxOperation>(&dmux_node->
GetOperation());
133 bool all_inputs_same =
true;
135 for (
size_t i = 2; i < dmux_node->
ninputs(); ++i)
139 all_inputs_same =
false;
155 auto mux_op = util::assertedCast<const MuxOperation>(&ndmux_node->
GetOperation());
158 bool all_inputs_same_branch =
true;
160 for (
size_t i = 1; i < ndmux_node->
ninputs(); ++i)
162 if (
auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*ndmux_node->
input(i)->
origin()))
169 origin_branch = node;
172 else if (origin_branch == node)
178 all_inputs_same_branch =
false;
196 const auto mux_op = util::assertedCast<const MuxOperation>(&ndmux_node->
GetOperation());
209 auto branch_in_node =
210 rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*ndmux_node->
output(0)->
Users().
begin());
211 if (!branch_in_node || !
dynamic_cast<const BranchOperation *
>(&branch_in_node->GetOperation()))
216 if (branch_in_node->output(1)->nusers() != 1)
221 rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*branch_in_node->output(1)->Users().begin());
222 if (!buf_in_node || !
dynamic_cast<const BufferOperation *
>(&buf_in_node->GetOperation()))
226 auto buf_out = buf_in_node->output(0);
227 if (buf_out != backedge_arg->result()->origin())
233 auto branch_cond_origin = branch_in_node->input(0)->origin();
234 auto pred_buf_out_node =
235 rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*ndmux_node->
input(0)->
origin());
236 if (!pred_buf_out_node
241 auto pred_buf_cond_origin = pred_buf_out_node->input(0)->origin();
243 auto extra_buf_out_node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*pred_buf_cond_origin);
244 if (!extra_buf_out_node
245 || !
dynamic_cast<const BufferOperation *
>(&extra_buf_out_node->GetOperation()))
249 auto extra_buf_cond_origin = extra_buf_out_node->input(0)->origin();
253 extra_buf_cond_origin = pred_be->result()->origin();
255 if (extra_buf_cond_origin != branch_cond_origin)
260 branch_in_node->output(0)->divert_users(ndmux_node->
input(1)->
origin());
261 buf_out->divert_users(backedge_arg);
264 auto region = ndmux_node->
region();
266 region->RemoveResults({ backedge_arg->result()->index() });
267 region->RemoveArguments({ backedge_arg->index() });
274 JLM_ASSERT(jlm::rvsdg::is<LoopConstantBufferOperation>(lcb_node));
281 auto [branchNode, branchOperation] =
282 rvsdg::TryGetSimpleNodeAndOptionalOp<BranchOperation>(*lcb_node->
output(0)->
Users().
begin());
283 if (!branchNode || !branchOperation || !branchOperation->loop)
288 if (branchNode->output(1)->nusers())
293 auto branch_cond_origin = branchNode->input(0)->origin();
304 || !
dynamic_cast<const BufferOperation *
>(&extra_buf_out->node()->GetOperation()))
308 auto extra_buf_cond_origin = extra_buf_out->
node()->
input(0)->
origin();
312 extra_buf_cond_origin = pred_be->result()->origin();
314 if (extra_buf_cond_origin != branch_cond_origin)
337 std::vector<rvsdg::Output *> combined_outputs;
338 for (
size_t i = 0; i < split_node->
noutputs(); ++i)
343 if (rvsdg::IsOwnerNodeOperation<llvm::MemoryStateSplitOperation>(*user))
345 auto sub_split = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*user);
346 for (
size_t j = 0; j < sub_split->noutputs(); ++j)
348 combined_outputs.push_back(sub_split->output(j));
353 combined_outputs.push_back(split_node->
output(i));
356 if (combined_outputs.size() != split_node->
noutputs())
360 combined_outputs.size());
361 for (
size_t i = 0; i < combined_outputs.size(); ++i)
363 combined_outputs[i]->divert_users(new_outputs[i]);
374 if (merge_node->
ninputs() == 1)
381 std::vector<rvsdg::Output *> combined_origins;
382 std::unordered_set<rvsdg::SimpleNode *> splits;
383 for (
size_t i = 0; i < merge_node->
ninputs(); ++i)
386 if (rvsdg::IsOwnerNodeOperation<llvm::MemoryStateMergeOperation>(*origin))
388 auto sub_merge = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*origin);
389 for (
size_t j = 0; j < sub_merge->ninputs(); ++j)
391 combined_origins.push_back(sub_merge->input(j)->origin());
394 else if (rvsdg::IsOwnerNodeOperation<llvm::MemoryStateSplitOperation>(*origin))
398 auto split = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*origin);
399 if (!splits.count(split))
401 splits.insert(split);
402 combined_origins.push_back(origin);
407 combined_origins.push_back(merge_node->
input(i)->
origin());
410 if (combined_origins.empty())
413 combined_origins.push_back(merge_node->
input(0)->
origin());
415 if (combined_origins.size() != merge_node->
ninputs())
430 bool any_changed =
false;
431 bool changed =
false;
439 if (rvsdg::is<MemoryRequestOperation>(node))
444 if (rvsdg::is<LocalMemoryRequestOperation>(node))
448 if (rvsdg::is<LocalMemoryResponseOperation>(node))
460 else if (
auto ln =
dynamic_cast<LoopNode *
>(node))
466 changed |=
Run(*ln->subregion(), statisticsCollector);
468 else if (
const auto mux =
dynamic_cast<const MuxOperation *
>(&node->GetOperation()))
479 else if (rvsdg::is<LoopConstantBufferOperation>(node))
503 any_changed |= changed;
520 auto & graph = rvsdgModule.
Rvsdg();
522 if (rootRegion->numNodes() != 1)
524 throw util::Error(
"Root should have only one node now");
526 const auto lambdaNode =
532 Run(*lambdaNode->subregion(), statisticsCollector);
rvsdg::Region * subregion() const noexcept
void removeLoopOutput(rvsdg::StructuralOutput *output)
void removeLoopInput(rvsdg::StructuralInput *input)
~RhlsDeadNodeElimination() noexcept override
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::vector< rvsdg::Output * > Create(rvsdg::Output &operand, const size_t numResults)
Region & GetRootRegion() const noexcept
Node * node() const noexcept
virtual const Operation & GetOperation() const noexcept=0
bool IsDead() const noexcept
Determines whether the node is dead.
rvsdg::Region * region() const noexcept
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
size_t ninputs() const noexcept
size_t noutputs() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
bool IsDead() const noexcept
size_t nusers() const noexcept
Represents the result of a region.
Represent acyclic RVSDG subgraphs.
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
bool insert(ItemType item)
std::size_t Size() const noexcept
#define JLM_UNREACHABLE(msg)
static bool remove_loop_passthrough(LoopNode *ln)
static bool dead_loop_lcb(rvsdg::Node *lcb_node)
static bool dead_loop(rvsdg::Node *ndmux_node)
static bool remove_unused_loop_outputs(LoopNode *ln)
static bool fix_mem_split(rvsdg::Node *split_node)
static bool dead_spec_gamma(rvsdg::Node *dmux_node)
static bool remove_unused_loop_inputs(LoopNode *ln)
static bool remove_unused_loop_backedges(LoopNode *loopNode)
static bool fix_mem_merge(rvsdg::Node *merge_node)
rvsdg::Input * get_mem_state_user(rvsdg::Output *state_edge)
static bool dead_nonspec_gamma(rvsdg::Node *ndmux_node)
static void remove(Node *node)