11 #include <unordered_map>
35 std::unique_ptr<StronglyConnectedComponentStructure>
38 auto sccStructure = std::make_unique<StronglyConnectedComponentStructure>();
40 for (
auto & node : scc)
42 for (
auto & inEdge : node.InEdges())
46 sccStructure->EntryEdges_.insert(&inEdge);
47 if (!sccStructure->EntryNodes_.Contains(&node))
48 sccStructure->EntryNodes_.insert(&node);
52 for (
auto & outEdge : node.OutEdges())
56 sccStructure->ExitEdges_.insert(&outEdge);
57 if (!sccStructure->ExitNodes_.Contains(outEdge.sink()))
58 sccStructure->ExitNodes_.insert(outEdge.sink());
63 for (
auto & node : scc)
65 for (
auto & outEdge : node.OutEdges())
67 if (sccStructure->EntryNodes_.Contains(outEdge.sink()))
68 sccStructure->RepetitionEdges_.insert(&outEdge);
83 std::vector<ControlFlowGraphNode *> & node_stack,
85 std::vector<StronglyConnectedComponent> & sccs)
87 map.emplace(node, std::make_pair(index, index));
88 node_stack.push_back(node);
95 auto successor = edge.sink();
96 if (map.find(successor) == map.end())
100 map[node].second = std::min(map[node].second, map[successor].second);
102 else if (std::find(node_stack.begin(), node_stack.end(), successor) != node_stack.end())
105 map[node].second = std::min(map[node].second, map[successor].first);
110 if (map[node].second == map[node].first)
112 std::unordered_set<ControlFlowGraphNode *> set;
116 w = node_stack.back();
117 node_stack.pop_back();
121 if (set.size() != 1 || (*set.begin())->has_selfloop_edge())
126 std::vector<StronglyConnectedComponent>
134 std::vector<StronglyConnectedComponent>
138 std::vector<StronglyConnectedComponent> sccs;
139 std::vector<ControlFlowGraphNode *> node_stack;
140 std::unordered_map<ControlFlowGraphNode *, std::pair<size_t, size_t>> map;
146 static std::unique_ptr<ControlFlowGraph>
152 out->entry()->remove_outedge(0);
155 std::unordered_map<const jlm::llvm::ControlFlowGraphNode *, jlm::llvm::ControlFlowGraphNode *>
156 node_map({ { in.
entry(), out->entry() }, { in.
exit(), out->exit() } });
158 for (
const auto & node : in)
160 JLM_ASSERT(jlm::llvm::is<jlm::llvm::BasicBlock>(&node));
166 for (
const auto & node : in)
168 for (
auto & outedge : node.OutEdges())
169 node_map[&node]->add_outedge(node_map[outedge.sink()]);
178 return node->NumInEdges() == 2 && node->NumOutEdges() == 2 && node->has_selfloop_edge();
184 if (node->NumOutEdges() != 1)
187 if (node->OutEdge(0)->sink()->NumInEdges() != 1)
197 auto s1 = split->OutEdge(0)->sink();
198 auto s2 = split->OutEdge(1)->sink();
201 if (s1->NumOutEdges() == 1 && s1->OutEdge(0)->sink() == s2)
203 else if (s2->NumOutEdges() == 1 && s2->OutEdge(0)->sink() == s1)
206 s1->NumOutEdges() == 1 && s2->NumOutEdges() == 1
207 && (s1->OutEdge(0)->sink() == s2->OutEdge(0)->sink()))
216 if (split->NumOutEdges() < 2)
220 if (join ==
nullptr || join->NumInEdges() != split->NumOutEdges())
223 for (
auto & outedge : split->OutEdges())
225 if (outedge.sink() == join)
228 auto node = outedge.sink();
229 if (node->NumInEdges() != 1)
231 if (node->NumOutEdges() != 1 || node->OutEdge(0)->sink() != join)
241 if (split->NumOutEdges() < 2)
244 if (split->OutEdge(0)->sink()->NumOutEdges() != 1)
247 auto join = split->OutEdge(0)->sink()->OutEdge(0)->sink();
248 for (
auto & outedge : split->OutEdges())
250 if (outedge.sink()->NumInEdges() != 1)
252 if (outedge.sink()->NumOutEdges() != 1)
254 if (outedge.sink()->OutEdge(0)->sink() != join)
264 for (
auto & outedge : node->OutEdges())
266 if (outedge.source() == outedge.sink())
276 if (node->NumInEdges() == 0)
279 auto source = node->InEdges().begin()->source();
280 for (
auto & inedge : node->InEdges())
282 if (inedge.source() != source)
292 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
295 auto & cfg = node->
cfg();
298 for (
auto & outedge : node->
OutEdges())
300 if (outedge.is_selfloop())
311 to_visit.erase(node);
312 to_visit.insert(reduction);
318 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
322 auto & cfg = entry->
cfg();
326 for (
auto & outedge : exit->OutEdges())
327 reduction->add_outedge(outedge.sink());
328 exit->remove_outedges();
330 to_visit.erase(entry);
331 to_visit.erase(exit);
332 to_visit.insert(reduction);
338 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
342 auto & cfg = split->
cfg();
346 reduction->add_outedge(join);
347 for (
auto & outedge : split->
OutEdges())
349 if (outedge.sink() != join)
351 outedge.sink()->remove_outedges();
352 to_visit.erase(outedge.sink());
357 to_visit.erase(split);
358 to_visit.insert(reduction);
364 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
371 join->remove_inedges();
372 reduction->add_outedge(join);
373 for (
auto & outedge : split->
OutEdges())
374 to_visit.erase(outedge.sink());
376 to_visit.erase(split);
377 to_visit.insert(reduction);
385 for (
auto & outedge : node->
OutEdges())
387 if (outedge.source() == outedge.sink())
398 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
403 p->divert_inedges(node);
404 p->remove_outedges();
411 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
437 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
463 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
483 for (
auto it = bb.
begin(); it != bb.
end(); it++)
485 const auto tac = *it;
486 const auto phi =
dynamic_cast<const SsaPhiOperation *
>(&tac->operation());
491 if (tac != bb.
first() && !is<SsaPhiOperation>(*std::prev(it)))
496 for (
size_t i = 0; i < phi->narguments(); i++)
498 phiIncoming.
insert(phi->GetIncomingNode(i));
500 if (phiIncoming.
Size() != phi->narguments())
505 for (
auto & inEdge : bb.
InEdges())
507 predecessors.
insert(inEdge.source());
509 if (phiIncoming != predecessors)
556 for (
const auto & bb : cfg)
570 for (
const auto & node : cfg)
572 if (node.no_predecessor())
584 for (
const auto & node : cfg)
586 if (!node.single_successor() || !node.single_predecessor())
602 std::unordered_set<ControlFlowGraphNode *> to_visit({ c->entry(), c->exit() });
603 for (
auto & node : *c)
604 to_visit.insert(&node);
606 auto it = to_visit.begin();
607 while (it != to_visit.end())
609 bool reduced = f(*it, to_visit);
610 it = reduced ? to_visit.begin() : std::next(it);
613 return to_visit.size() == 1;
637 auto it = cfg.
begin();
638 while (it != cfg.
end())
649 auto successor =
dynamic_cast<BasicBlock *
>(it->OutEdge(0)->sink());
650 if (!successor || successor->HasSsaPhiOperation())
668 auto it = cfg.
begin();
669 while (it != cfg.
end())
676 if (bb->ntacs() != 0)
683 auto outedge = bb->OutEdge(0);
687 if (outedge->sink() == bb)
693 bb->divert_inedges(outedge->sink());
703 static std::unordered_set<const ControlFlowGraphNode *>
706 std::unordered_set<const ControlFlowGraphNode *> visited;
707 std::unordered_set<ControlFlowGraphNode *> to_visit({ cfg.
entry() });
708 while (!to_visit.empty())
710 auto node = *to_visit.begin();
711 to_visit.erase(to_visit.begin());
712 JLM_ASSERT(visited.find(node) == visited.end());
713 visited.insert(node);
714 for (
auto & outedge : node->OutEdges())
716 if (visited.find(outedge.sink()) == visited.end()
717 && to_visit.find(outedge.sink()) == to_visit.end())
718 to_visit.insert(outedge.sink());
728 static std::unordered_set<ControlFlowGraphNode *>
733 std::unordered_set<ControlFlowGraphNode *> deadnodes;
734 for (
auto & node : cfg)
736 if (livenodes.find(&node) == livenodes.end())
737 deadnodes.insert(&node);
749 static std::unordered_set<BasicBlock *>
752 std::unordered_set<BasicBlock *> sinks;
753 for (
auto & node : deadnodes)
755 for (
size_t n = 0; n < node->NumOutEdges(); n++)
757 auto sink =
dynamic_cast<BasicBlock *
>(node->OutEdge(n)->sink());
758 if (sink && deadnodes.find(sink) == deadnodes.end())
769 const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
771 const auto phi = util::assertedCast<const SsaPhiOperation>(&phitac.
operation());
773 std::vector<ControlFlowGraphNode *> incomingNodes;
774 std::vector<const Variable *>
operands;
775 for (
size_t n = 0; n < phitac.
noperands(); n++)
777 if (deadnodes.find(phi->GetIncomingNode(n)) == deadnodes.end())
780 incomingNodes.push_back(phi->GetIncomingNode(n));
789 const std::unordered_set<BasicBlock *> & sinks,
790 const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
792 for (
auto & sink : sinks)
794 for (
auto & tac : *sink)
796 if (!is<SsaPhiOperation>(tac))
807 for (
auto & node : deadnodes)
809 node->remove_inedges();
811 node->cfg().remove_node(
static_cast<BasicBlock *
>(node));
ThreeAddressCodeList::const_iterator end() const noexcept
const ThreeAddressCodeList & tacs() const noexcept
llvm::ThreeAddressCode * append_first(std::unique_ptr< llvm::ThreeAddressCode > tac)
ThreeAddressCode * first() const noexcept
static BasicBlock * create(ControlFlowGraph &cfg)
ThreeAddressCodeList::const_iterator begin() const noexcept
ControlFlowGraphNode * sink() const noexcept
inedge_iterator_range InEdges() const
ControlFlowGraphEdge * OutEdge(size_t n) const
bool no_predecessor() const noexcept
ControlFlowGraph & cfg() const noexcept
outedge_iterator_range OutEdges() const
void remove_outedge(size_t n)
bool no_successor() const noexcept
size_t NumOutEdges() const noexcept
void divert_inedges(llvm::ControlFlowGraphNode *new_successor)
const_iterator begin() const
EntryNode * entry() const noexcept
static ControlFlowGraph::iterator remove_node(ControlFlowGraph::iterator &it)
ExitNode * exit() const noexcept
const_iterator end() const
InterProceduralGraphModule & module() const noexcept
bool IsTailControlledLoop() const noexcept
EdgeIteratorRange ExitEdges() const
size_t NumExitEdges() const noexcept
size_t NumEntryNodes() const noexcept
EdgeIteratorRange RepetitionEdges() const
static std::unique_ptr< StronglyConnectedComponentStructure > Create(const StronglyConnectedComponent &scc)
size_t NumRepetitionEdges() const noexcept
Strongly Connected Component.
constiterator end() const
constiterator begin() const
std::unordered_set< ControlFlowGraphNode * > nodes_
bool contains(ControlFlowGraphNode *node) const
util::PtrIterator< ControlFlowGraphNode, std::unordered_set< ControlFlowGraphNode * >::const_iterator > constiterator
void replace(const rvsdg::SimpleOperation &operation, const std::vector< const Variable * > &operands)
const Variable * operand(size_t index) const noexcept
const rvsdg::SimpleOperation & operation() const noexcept
size_t noperands() const noexcept
bool insert(ItemType item)
std::size_t Size() const noexcept
Global memory state passed between functions.
std::vector< StronglyConnectedComponent > find_sccs(const ControlFlowGraph &cfg)
static bool is_loop(const jlm::llvm::ControlFlowGraphNode *node) noexcept
static void reduce_loop(const StronglyConnectedComponentStructure &sccstruct, AggregationMap &map)
bool is_structured(const ControlFlowGraph &cfg)
static std::unordered_set< const ControlFlowGraphNode * > compute_livenodes(const ControlFlowGraph &cfg)
static bool is_linear(const ControlFlowGraphNode *node) noexcept
static void reduce_proper_branch(jlm::llvm::ControlFlowGraphNode *split, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
static jlm::llvm::ControlFlowGraphNode * find_join(const jlm::llvm::ControlFlowGraphNode *split) noexcept
static void remove_deadnodes(const std::unordered_set< ControlFlowGraphNode * > &deadnodes)
bool is_reducible(const ControlFlowGraph &cfg)
static void reduce_T1(jlm::llvm::ControlFlowGraphNode *node)
static bool reduce_reducible(jlm::llvm::ControlFlowGraphNode *node, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
static bool reduce(const ControlFlowGraph &cfg, const std::function< bool(llvm::ControlFlowGraphNode *, std::unordered_set< llvm::ControlFlowGraphNode * > &)> &f)
static ControlFlowGraphNode * reduce_branch(ControlFlowGraphNode *split, ControlFlowGraphNode **entry, AggregationMap &map)
static bool is_proper_branch(const jlm::llvm::ControlFlowGraphNode *split) noexcept
static std::unordered_set< BasicBlock * > compute_live_sinks(const std::unordered_set< ControlFlowGraphNode * > &deadnodes)
static bool has_valid_entry(const ControlFlowGraph &cfg)
bool is_valid(const ControlFlowGraph &cfg)
static std::unordered_set< ControlFlowGraphNode * > compute_deadnodes(ControlFlowGraph &cfg)
static bool has_valid_phis(const BasicBlock &bb)
static bool is_branch(const ControlFlowGraphNode *split) noexcept
static bool is_T2(const jlm::llvm::ControlFlowGraphNode *node) noexcept
static bool reduce_proper_structured(jlm::llvm::ControlFlowGraphNode *node, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
static void strongconnect(ControlFlowGraphNode *node, ControlFlowGraphNode *exit, std::unordered_map< ControlFlowGraphNode *, std::pair< size_t, size_t >> &map, std::vector< ControlFlowGraphNode * > &node_stack, size_t &index, std::vector< StronglyConnectedComponent > &sccs)
static void update_phi_operands(llvm::ThreeAddressCode &phitac, const std::unordered_set< ControlFlowGraphNode * > &deadnodes)
static bool is_valid_basic_block(const BasicBlock &bb)
void straighten(ControlFlowGraph &cfg)
static ControlFlowGraphNode * reduce_linear(ControlFlowGraphNode *source, ControlFlowGraphNode **entry, ControlFlowGraphNode **exit, AggregationMap &map)
bool is_proper_structured(const ControlFlowGraph &cfg)
static void reduce_T2(jlm::llvm::ControlFlowGraphNode *node, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
static bool reduce_structured(jlm::llvm::ControlFlowGraphNode *node, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
static std::unique_ptr< ControlFlowGraph > copy_structural(const ControlFlowGraph &in)
void purge(ControlFlowGraph &cfg)
Remove all basic blocks without instructions.
bool is_closed(const ControlFlowGraph &cfg)
static bool has_valid_exit(const ControlFlowGraph &cfg)
static bool is_linear_reduction(const jlm::llvm::ControlFlowGraphNode *node) noexcept
static bool is_T1(const jlm::llvm::ControlFlowGraphNode *node) noexcept
void prune(ControlFlowGraph &cfg)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)