32 std::vector<jlm::rvsdg::SimpleNode *> & load_nodes,
33 std::vector<jlm::rvsdg::SimpleNode *> & store_nodes,
34 std::unordered_set<jlm::rvsdg::Output *> & visited)
40 if (visited.count(
op))
46 for (
auto &
user :
op->Users())
52 rvsdg::MatchTypeOrFail(
54 [&](rvsdg::SimpleNode & simplenode)
57 simplenode.GetOperation(),
58 [&](const jlm::llvm::StoreNonVolatileOperation &)
60 store_nodes.push_back(&simplenode);
62 [&](const jlm::llvm::LoadNonVolatileOperation &)
64 load_nodes.push_back(&simplenode);
66 for (auto & output : simplenode.Outputs())
68 find_load_store(&output, load_nodes, store_nodes, visited);
73 find_load_store(loop.mapInput(user).inner, load_nodes, store_nodes, visited);
77 find_load_store(theta.MapInputLoopVar(user).pre, load_nodes, store_nodes, visited);
83 [&](const rvsdg::GammaNode::MatchVar &)
88 for (auto out : evar.branchArgument)
90 find_load_store(out, load_nodes, store_nodes, visited);
95 [&](rvsdg::Region * region)
97 rvsdg::MatchTypeOrFail(
102 loop.mapResult(user),
103 [&](const LoopNode::BackEdgeVar & backedge)
105 find_load_store(backedge.pre, load_nodes, store_nodes, visited);
107 [&](
const LoopNode::ExitVar & exit)
109 find_load_store(exit.output, load_nodes, store_nodes, visited);
112 [&](rvsdg::ThetaNode & theta)
115 theta.mapResult(user),
116 [&](
const rvsdg::ThetaNode::LoopVar & loopvar)
118 find_load_store(loopvar.pre, load_nodes, store_nodes, visited);
119 find_load_store(loopvar.output, load_nodes, store_nodes, visited);
121 [&](
const rvsdg::ThetaNode::PredicateVar &)
125 [&](rvsdg::GammaNode & gamma)
128 gamma.MapBranchResultExitVar(user).output,
142 auto & user = *sti_arg->Users().begin();
143 auto [muxNode, muxOperation] =
146 for (
size_t i = 1; i < 3; ++i)
148 auto arg = muxNode->input(i)->origin();
149 auto loopNode = rvsdg::TryGetRegionParentNode<LoopNode>(*arg);
154 auto var = loopNode->mapArgument(*arg);
155 if (
auto ba = std::get_if<LoopNode::BackEdgeVar>(&var))
159 auto [bufferNode, bufferOperation] =
162 auto [branchNode, branchOperation] =
164 *bufferNode->input(0)->origin());
166 for (
size_t j = 0; j < 2; ++j)
168 JLM_ASSERT(branchNode->output(j)->nusers() == 1);
187 std::vector<jlm::rvsdg::Output *> & store_addresses,
188 std::vector<jlm::rvsdg::Output *> & store_dequeues,
189 std::vector<bool> & store_precedes,
190 bool * load_encountered)
203 auto & addr_edge_user = *addr_edge->
Users().
begin();
211 auto loop_node = jlm::util::assertedCast<jlm::hls::LoopNode>(sti->node());
213 auto addr_edge_before_loop = addr_edge;
214 addr_edge = loop_node->AddLoopVar(addr_edge, &buffer);
215 addr_edge_user.divert_to(addr_edge);
217 auto sti_arg = sti->arguments.first();
219 auto & user = *sti_arg->Users().begin();
220 auto [muxNode, muxOperation] =
225 std::vector<jlm::rvsdg::Output *> loop_store_addresses;
231 loop_store_addresses,
235 if (loop_store_addresses.empty())
241 store_addresses.insert(
242 store_addresses.cend(),
243 loop_store_addresses.begin(),
244 loop_store_addresses.end());
249 auto op = &sn->GetOperation();
256 auto load_branch_out =
258 for (
size_t i = 0; i < sn->noutputs(); ++i)
267 *load_branch_out[i]->Users().begin());
278 JLM_ASSERT(load_branch_out[i]->nusers() == 1);
279 JLM_ASSERT(dummy_user->input(0)->origin() == load_branch_out[i]);
284 auto [muxNode, muxOperation] =
289 *muxNode->input(0)->origin(),
291 muxOperation->discarding,
293 addr_edge_user.divert_to(addr_edge);
294 mem_edge = muxNode->output(0);
308 *new_mem_edge = mem_edge;
314 addr_edge = sg_out[1];
315 addr_edge_user.divert_to(addr_edge);
317 store_precedes.push_back(!*load_encountered);
318 mem_edge = sn->output(0);
321 auto [mssNode, msso] =
329 for (
size_t i = 0; i < msso->nresults(); ++i)
331 mssNode->output(i)->divert_users(store_split[i]);
334 mem_edge = store_split[0];
335 store_dequeues.push_back(
341 mem_edge = store_split[0];
342 user->divert_to(mem_edge);
343 store_dequeues.push_back(
355 addr_edge = addr_sg_out[1];
356 addr_edge_user.divert_to(addr_edge);
358 addr_edge = addr_sg_out2[1];
359 addr_edge_user.divert_to(addr_edge);
369 mem_edge = mem_sg_out[1];
372 user->divert_to(addr_edge);
373 sn->output(1)->divert_users(mem_edge);
376 *load_encountered =
true;
380 mem_edge = sn->output(1);
385 mem_edge = sn->output(1);
389 JLM_ASSERT(
"Decoupled nodes not implemented yet");
395 if (si_load_user && &userNode == sn)
425 return user.origin();
429 auto op = &sn->GetOperation();
434 for (
size_t i = 0; i < sn->noutputs(); ++i)
443 return sn->output(0);
449 return sn->output(0);
455 state_edge = sn->output(1);
459 state_edge = sn->output(sn->noutputs() - 1);
464 state_edge = sn->output(0);
472 JLM_ASSERT(mem_edge_after_loop->nusers() == 1);
473 auto & common_user = *mem_edge_after_loop->Users().begin();
475 std::vector<jlm::rvsdg::SimpleNode *> load_nodes;
476 std::vector<jlm::rvsdg::SimpleNode *> store_nodes;
477 std::unordered_set<jlm::rvsdg::Output *> visited;
479 visited.insert(mem_edge_after_loop);
480 find_load_store(&*sti->arguments.begin(), load_nodes, store_nodes, visited);
484 auto mem_edge = split_states[0];
485 sti->divert_to(mem_edge);
486 split_states[0] = mem_edge_after_loop;
488 common_user.divert_to(state_edge);
489 for (
size_t i = 0; i < load_nodes.size(); ++i)
491 auto load = load_nodes[i];
492 auto addr_edge = split_states[1 + i];
493 std::vector<jlm::rvsdg::Output *> store_addresses;
494 std::vector<jlm::rvsdg::Output *> store_dequeues;
495 std::vector<bool> store_precedes;
496 bool load_encountered =
false;
507 JLM_ASSERT(store_nodes.size() == store_addresses.size());
508 JLM_ASSERT(store_nodes.size() == store_dequeues.size());
509 auto state_gate_addr_in =
512 for (
size_t j = 0; j < store_nodes.size(); ++j)
514 JLM_ASSERT(state_gate_addr_in->origin()->region() == store_addresses[j]->region());
515 JLM_ASSERT(store_dequeues[j]->region() == store_addresses[j]->region());
517 *state_gate_addr_in->origin(),
static rvsdg::Output * separate_load_edge(jlm::rvsdg::Output *mem_edge, jlm::rvsdg::Output *addr_edge, jlm::rvsdg::SimpleNode **load, jlm::rvsdg::Output **new_mem_edge, std::vector< jlm::rvsdg::Output * > &store_addresses, std::vector< jlm::rvsdg::Output * > &store_dequeues, std::vector< bool > &store_precedes, bool *load_encountered)
A variable routed into all gamma regions.