29 std::vector<jlm::rvsdg::SimpleNode *> & load_nodes,
30 std::vector<jlm::rvsdg::SimpleNode *> & store_nodes,
31 std::unordered_set<jlm::rvsdg::Output *> & visited)
33 if (!jlm::rvsdg::is<jlm::llvm::MemoryStateType>(op->
Type()))
37 if (visited.count(op))
43 for (
auto & user : op->
Users())
45 if (
auto simplenode = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(user))
49 store_nodes.push_back(simplenode);
52 &simplenode->GetOperation()))
54 load_nodes.push_back(simplenode);
56 for (
size_t i = 0; i < simplenode->noutputs(); ++i)
58 find_load_store(simplenode->output(i), load_nodes, store_nodes, visited);
63 for (
auto & arg : sti->arguments)
91 auto & user = *sti_arg->Users().begin();
92 auto [muxNode, muxOperation] =
93 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::hls::MuxOperation>(user);
95 for (
size_t i = 1; i < 3; ++i)
97 auto arg = muxNode->input(i)->origin();
100 auto res = ba->result();
102 auto [bufferNode, bufferOperation] =
103 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::hls::BufferOperation>(*res->origin());
105 auto [branchNode, branchOperation] =
106 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::hls::BranchOperation>(
107 *bufferNode->input(0)->origin());
109 for (
size_t j = 0; j < 2; ++j)
111 JLM_ASSERT(branchNode->output(j)->nusers() == 1);
130 std::vector<jlm::rvsdg::Output *> & store_addresses,
131 std::vector<jlm::rvsdg::Output *> & store_dequeues,
132 std::vector<bool> & store_precedes,
133 bool * load_encountered)
146 auto & addr_edge_user = *addr_edge->
Users().
begin();
154 auto loop_node = jlm::util::assertedCast<jlm::hls::LoopNode>(sti->node());
156 auto addr_edge_before_loop = addr_edge;
157 addr_edge = loop_node->AddLoopVar(addr_edge, &buffer);
158 addr_edge_user.divert_to(addr_edge);
160 auto sti_arg = sti->arguments.first();
162 auto & user = *sti_arg->Users().begin();
163 auto [muxNode, muxOperation] =
164 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::hls::MuxOperation>(user);
168 std::vector<jlm::rvsdg::Output *> loop_store_addresses;
174 loop_store_addresses,
178 if (loop_store_addresses.empty())
184 store_addresses.insert(
185 store_addresses.cend(),
186 loop_store_addresses.begin(),
187 loop_store_addresses.end());
190 else if (
auto sn = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*user))
192 auto op = &sn->GetOperation();
199 auto load_branch_out =
201 for (
size_t i = 0; i < sn->noutputs(); ++i)
209 auto dummy_user = &jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::SimpleNode>(
210 *load_branch_out[i]->Users().begin());
221 JLM_ASSERT(load_branch_out[i]->nusers() == 1);
222 JLM_ASSERT(dummy_user->input(0)->origin() == load_branch_out[i]);
227 auto [muxNode, muxOperation] =
228 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::hls::MuxOperation>(
232 *muxNode->input(0)->origin(),
234 muxOperation->discarding,
236 addr_edge_user.divert_to(addr_edge);
237 mem_edge = muxNode->output(0);
242 JLM_ASSERT(jlm::rvsdg::IsOwnerNodeOperation<jlm::hls::BranchOperation>(addr_edge_user));
251 *new_mem_edge = mem_edge;
257 addr_edge = sg_out[1];
258 addr_edge_user.divert_to(addr_edge);
260 store_precedes.push_back(!*load_encountered);
261 mem_edge = sn->output(0);
264 auto [mssNode, msso] =
265 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<jlm::llvm::MemoryStateSplitOperation>(*user);
272 for (
size_t i = 0; i < msso->nresults(); ++i)
274 mssNode->output(i)->divert_users(store_split[i]);
277 mem_edge = store_split[0];
278 store_dequeues.push_back(
284 mem_edge = store_split[0];
285 user->divert_to(mem_edge);
286 store_dequeues.push_back(
298 addr_edge = addr_sg_out[1];
299 addr_edge_user.divert_to(addr_edge);
301 addr_edge = addr_sg_out2[1];
302 addr_edge_user.divert_to(addr_edge);
312 mem_edge = mem_sg_out[1];
315 user->divert_to(addr_edge);
316 sn->output(1)->divert_users(mem_edge);
318 *load = &jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::SimpleNode>(*new_load_outputs[0]);
319 *load_encountered =
true;
323 mem_edge = sn->output(1);
328 mem_edge = sn->output(1);
332 JLM_ASSERT(
"Decoupled nodes not implemented yet");
336 auto si_load_user = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(addr_edge_user);
337 auto & userNode = jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::SimpleNode>(*user);
338 if (si_load_user && &userNode == sn)
368 return user.origin();
370 else if (
auto sn = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(user))
372 auto op = &sn->GetOperation();
377 for (
size_t i = 0; i < sn->noutputs(); ++i)
382 else if (jlm::rvsdg::is<jlm::hls::MuxOperation>(*op))
386 return sn->output(0);
392 return sn->output(0);
398 state_edge = sn->output(1);
402 state_edge = sn->output(sn->noutputs() - 1);
407 state_edge = sn->output(0);
415 JLM_ASSERT(mem_edge_after_loop->nusers() == 1);
416 auto & common_user = *mem_edge_after_loop->Users().begin();
418 std::vector<jlm::rvsdg::SimpleNode *> load_nodes;
419 std::vector<jlm::rvsdg::SimpleNode *> store_nodes;
420 std::unordered_set<jlm::rvsdg::Output *> visited;
422 visited.insert(mem_edge_after_loop);
423 find_load_store(&*sti->arguments.begin(), load_nodes, store_nodes, visited);
427 auto mem_edge = split_states[0];
428 sti->divert_to(mem_edge);
429 split_states[0] = mem_edge_after_loop;
431 common_user.divert_to(state_edge);
432 for (
size_t i = 0; i < load_nodes.size(); ++i)
434 auto load = load_nodes[i];
435 auto addr_edge = split_states[1 + i];
436 std::vector<jlm::rvsdg::Output *> store_addresses;
437 std::vector<jlm::rvsdg::Output *> store_dequeues;
438 std::vector<bool> store_precedes;
439 bool load_encountered =
false;
450 JLM_ASSERT(store_nodes.size() == store_addresses.size());
451 JLM_ASSERT(store_nodes.size() == store_dequeues.size());
452 auto state_gate_addr_in =
453 jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::SimpleNode>(*load->input(0)->origin())
455 for (
size_t j = 0; j < store_nodes.size(); ++j)
457 JLM_ASSERT(state_gate_addr_in->origin()->region() == store_addresses[j]->region());
458 JLM_ASSERT(store_dequeues[j]->region() == store_addresses[j]->region());
460 *state_gate_addr_in->origin(),
477 const auto & graph = rvsdgModule.
Rvsdg();
479 if (rootRegion->numNodes() != 1)
481 throw std::logic_error(
"Root should have only one node now");
484 const auto lambda =
dynamic_cast<const rvsdg::LambdaNode *
>(rootRegion->Nodes().begin().ptr());
487 throw std::logic_error(
"Node needs to be a lambda");
509 if (state_arg->nusers() == 1)
511 auto entryNode = rvsdg::TryGetOwnerNode<rvsdg::Node>(*state_arg->Users().begin());
512 if (jlm::rvsdg::is<const jlm::llvm::LambdaEntryMemoryStateSplitOperation>(
513 entryNode->GetOperation()))
515 for (
size_t i = 0; i < entryNode->noutputs(); ++i)
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
~AddressQueueInsertion() noexcept override
static jlm::rvsdg::Output * create(jlm::rvsdg::Output &check, jlm::rvsdg::Output &enq, jlm::rvsdg::Output &deq, bool combinatorial, size_t capacity=10)
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &predicate, jlm::rvsdg::Output &value, bool loop=false)
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &predicate, const std::vector< jlm::rvsdg::Output * > &alternatives, bool discarding, bool loop=false)
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &value)
static std::vector< jlm::rvsdg::Output * > create(jlm::rvsdg::Output &addr, const std::vector< jlm::rvsdg::Output * > &states)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
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
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
size_t nusers() const noexcept
Represents the result of a region.
StructuralOutput * output() const noexcept
ElementType * first() const noexcept
#define JLM_UNREACHABLE(msg)
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)
static void find_load_store(jlm::rvsdg::Output *op, std::vector< jlm::rvsdg::SimpleNode * > &load_nodes, std::vector< jlm::rvsdg::SimpleNode * > &store_nodes, std::unordered_set< jlm::rvsdg::Output * > &visited)
rvsdg::Output * route_to_region_rhls(rvsdg::Region *target, rvsdg::Output *out)
static rvsdg::StructuralOutput * find_loop_output(jlm::rvsdg::StructuralInput *sti)
jlm::rvsdg::Output * process_loops(jlm::rvsdg::Output *state_edge)
static void mem_queue(rvsdg::RvsdgModule &rvsdgModule)
void convert_loop_state_to_lcb(rvsdg::Input *loop_state_input)
rvsdg::Output & GetMemoryStateRegionArgument(const rvsdg::LambdaNode &lambdaNode) noexcept
static void remove(Node *node)