Jlm
Loading...
Searching...
No Matches
cfg-structure.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
9
10#include <algorithm>
11#include <unordered_map>
12
13namespace jlm::llvm
14{
15
18{
19 return constiterator(nodes_.begin());
20}
21
24{
25 return constiterator(nodes_.end());
26}
27
28bool
30{
31 return NumEntryNodes() == 1 && NumRepetitionEdges() == 1 && NumExitEdges() == 1
32 && (*RepetitionEdges().begin())->source() == (*ExitEdges().begin())->source();
33}
34
35std::unique_ptr<StronglyConnectedComponentStructure>
37{
38 auto sccStructure = std::make_unique<StronglyConnectedComponentStructure>();
39
40 for (auto & node : scc)
41 {
42 for (auto & inEdge : node.InEdges())
43 {
44 if (!scc.contains(inEdge.source()))
45 {
46 sccStructure->EntryEdges_.insert(&inEdge);
47 if (!sccStructure->EntryNodes_.Contains(&node))
48 sccStructure->EntryNodes_.insert(&node);
49 }
50 }
51
52 for (auto & outEdge : node.OutEdges())
53 {
54 if (!scc.contains(outEdge.sink()))
55 {
56 sccStructure->ExitEdges_.insert(&outEdge);
57 if (!sccStructure->ExitNodes_.Contains(outEdge.sink()))
58 sccStructure->ExitNodes_.insert(outEdge.sink());
59 }
60 }
61 }
62
63 for (auto & node : scc)
64 {
65 for (auto & outEdge : node.OutEdges())
66 {
67 if (sccStructure->EntryNodes_.Contains(outEdge.sink()))
68 sccStructure->RepetitionEdges_.insert(&outEdge);
69 }
70 }
71
72 return sccStructure;
73}
74
78static void
82 std::unordered_map<ControlFlowGraphNode *, std::pair<size_t, size_t>> & map,
83 std::vector<ControlFlowGraphNode *> & node_stack,
84 size_t & index,
85 std::vector<StronglyConnectedComponent> & sccs)
86{
87 map.emplace(node, std::make_pair(index, index));
88 node_stack.push_back(node);
89 index++;
90
91 if (node != exit)
92 {
93 for (auto & edge : node->OutEdges())
94 {
95 auto successor = edge.sink();
96 if (map.find(successor) == map.end())
97 {
98 /* successor has not been visited yet; recurse on it */
99 strongconnect(successor, exit, map, node_stack, index, sccs);
100 map[node].second = std::min(map[node].second, map[successor].second);
101 }
102 else if (std::find(node_stack.begin(), node_stack.end(), successor) != node_stack.end())
103 {
104 /* successor is in stack and hence in the current SCC */
105 map[node].second = std::min(map[node].second, map[successor].first);
106 }
107 }
108 }
109
110 if (map[node].second == map[node].first)
111 {
112 std::unordered_set<ControlFlowGraphNode *> set;
113 ControlFlowGraphNode * w = nullptr;
114 do
115 {
116 w = node_stack.back();
117 node_stack.pop_back();
118 set.insert(w);
119 } while (w != node);
120
121 if (set.size() != 1 || (*set.begin())->has_selfloop_edge())
122 sccs.push_back(StronglyConnectedComponent(set));
123 }
124}
125
126std::vector<StronglyConnectedComponent>
128{
129 JLM_ASSERT(is_closed(cfg));
130
131 return find_sccs(cfg.entry(), cfg.exit());
132}
133
134std::vector<StronglyConnectedComponent>
136{
137 size_t index = 0;
138 std::vector<StronglyConnectedComponent> sccs;
139 std::vector<ControlFlowGraphNode *> node_stack;
140 std::unordered_map<ControlFlowGraphNode *, std::pair<size_t, size_t>> map;
141 strongconnect(entry, exit, map, node_stack, index, sccs);
142
143 return sccs;
144}
145
146static std::unique_ptr<ControlFlowGraph>
148{
149 JLM_ASSERT(is_valid(in));
150
151 std::unique_ptr<ControlFlowGraph> out(new ControlFlowGraph(in.module()));
152 out->entry()->remove_outedge(0);
153
154 /* create all nodes */
155 std::unordered_map<const jlm::llvm::ControlFlowGraphNode *, jlm::llvm::ControlFlowGraphNode *>
156 node_map({ { in.entry(), out->entry() }, { in.exit(), out->exit() } });
157
158 for (const auto & node : in)
159 {
160 JLM_ASSERT(jlm::llvm::is<jlm::llvm::BasicBlock>(&node));
161 node_map[&node] = jlm::llvm::BasicBlock::create(*out);
162 }
163
164 /* establish control flow */
165 node_map[in.entry()]->add_outedge(node_map[in.entry()->OutEdge(0)->sink()]);
166 for (const auto & node : in)
167 {
168 for (auto & outedge : node.OutEdges())
169 node_map[&node]->add_outedge(node_map[outedge.sink()]);
170 }
171
172 return out;
173}
174
175static inline bool
177{
178 return node->NumInEdges() == 2 && node->NumOutEdges() == 2 && node->has_selfloop_edge();
179}
180
181static inline bool
183{
184 if (node->NumOutEdges() != 1)
185 return false;
186
187 if (node->OutEdge(0)->sink()->NumInEdges() != 1)
188 return false;
189
190 return true;
191}
192
195{
196 JLM_ASSERT(split->NumOutEdges() > 1);
197 auto s1 = split->OutEdge(0)->sink();
198 auto s2 = split->OutEdge(1)->sink();
199
200 jlm::llvm::ControlFlowGraphNode * join = nullptr;
201 if (s1->NumOutEdges() == 1 && s1->OutEdge(0)->sink() == s2)
202 join = s2;
203 else if (s2->NumOutEdges() == 1 && s2->OutEdge(0)->sink() == s1)
204 join = s1;
205 else if (
206 s1->NumOutEdges() == 1 && s2->NumOutEdges() == 1
207 && (s1->OutEdge(0)->sink() == s2->OutEdge(0)->sink()))
208 join = s1->OutEdge(0)->sink();
209
210 return join;
211}
212
213static inline bool
215{
216 if (split->NumOutEdges() < 2)
217 return false;
218
219 auto join = find_join(split);
220 if (join == nullptr || join->NumInEdges() != split->NumOutEdges())
221 return false;
222
223 for (auto & outedge : split->OutEdges())
224 {
225 if (outedge.sink() == join)
226 continue;
227
228 auto node = outedge.sink();
229 if (node->NumInEdges() != 1)
230 return false;
231 if (node->NumOutEdges() != 1 || node->OutEdge(0)->sink() != join)
232 return false;
233 }
234
235 return true;
236}
237
238static inline bool
240{
241 if (split->NumOutEdges() < 2)
242 return false;
243
244 if (split->OutEdge(0)->sink()->NumOutEdges() != 1)
245 return false;
246
247 auto join = split->OutEdge(0)->sink()->OutEdge(0)->sink();
248 for (auto & outedge : split->OutEdges())
249 {
250 if (outedge.sink()->NumInEdges() != 1)
251 return false;
252 if (outedge.sink()->NumOutEdges() != 1)
253 return false;
254 if (outedge.sink()->OutEdge(0)->sink() != join)
255 return false;
256 }
257
258 return true;
259}
260
261static inline bool
263{
264 for (auto & outedge : node->OutEdges())
265 {
266 if (outedge.source() == outedge.sink())
267 return true;
268 }
269
270 return false;
271}
272
273static inline bool
275{
276 if (node->NumInEdges() == 0)
277 return false;
278
279 auto source = node->InEdges().begin()->source();
280 for (auto & inedge : node->InEdges())
281 {
282 if (inedge.source() != source)
283 return false;
284 }
285
286 return true;
287}
288
289static inline void
292 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
293{
294 JLM_ASSERT(is_loop(node));
295 auto & cfg = node->cfg();
296
297 auto reduction = jlm::llvm::BasicBlock::create(cfg);
298 for (auto & outedge : node->OutEdges())
299 {
300 if (outedge.is_selfloop())
301 {
302 node->remove_outedge(outedge.index());
303 break;
304 }
305 }
306
307 reduction->add_outedge(node->OutEdge(0)->sink());
308 node->remove_outedges();
309 node->divert_inedges(reduction);
310
311 to_visit.erase(node);
312 to_visit.insert(reduction);
313}
314
315static inline void
318 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
319{
321 auto exit = entry->OutEdge(0)->sink();
322 auto & cfg = entry->cfg();
323
324 auto reduction = jlm::llvm::BasicBlock::create(cfg);
325 entry->divert_inedges(reduction);
326 for (auto & outedge : exit->OutEdges())
327 reduction->add_outedge(outedge.sink());
328 exit->remove_outedges();
329
330 to_visit.erase(entry);
331 to_visit.erase(exit);
332 to_visit.insert(reduction);
333}
334
335static inline void
338 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
339{
340 JLM_ASSERT(is_branch(split));
341 auto join = find_join(split);
342 auto & cfg = split->cfg();
343
344 auto reduction = jlm::llvm::BasicBlock::create(cfg);
345 split->divert_inedges(reduction);
346 reduction->add_outedge(join);
347 for (auto & outedge : split->OutEdges())
348 {
349 if (outedge.sink() != join)
350 {
351 outedge.sink()->remove_outedges();
352 to_visit.erase(outedge.sink());
353 }
354 }
355 split->remove_outedges();
356
357 to_visit.erase(split);
358 to_visit.insert(reduction);
359}
360
361static inline void
364 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
365{
367 auto join = split->OutEdge(0)->sink()->OutEdge(0)->sink();
368
369 auto reduction = jlm::llvm::BasicBlock::create(split->cfg());
370 split->divert_inedges(reduction);
371 join->remove_inedges();
372 reduction->add_outedge(join);
373 for (auto & outedge : split->OutEdges())
374 to_visit.erase(outedge.sink());
375
376 to_visit.erase(split);
377 to_visit.insert(reduction);
378}
379
380static inline void
382{
383 JLM_ASSERT(is_T1(node));
384
385 for (auto & outedge : node->OutEdges())
386 {
387 if (outedge.source() == outedge.sink())
388 {
389 node->remove_outedge(outedge.index());
390 break;
391 }
392 }
393}
394
395static inline void
398 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
399{
400 JLM_ASSERT(is_T2(node));
401
402 auto p = node->InEdges().begin()->source();
403 p->divert_inedges(node);
404 p->remove_outedges();
405 to_visit.erase(p);
406}
407
408static inline bool
411 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
412{
413 if (is_loop(node))
414 {
415 reduce_loop(node, to_visit);
416 return true;
417 }
418
419 if (is_proper_branch(node))
420 {
421 reduce_proper_branch(node, to_visit);
422 return true;
423 }
424
425 if (is_linear_reduction(node))
426 {
427 reduce_linear(node, to_visit);
428 return true;
429 }
430
431 return false;
432}
433
434static inline bool
437 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
438{
439 if (is_loop(node))
440 {
441 reduce_loop(node, to_visit);
442 return true;
443 }
444
445 if (is_branch(node))
446 {
447 reduce_branch(node, to_visit);
448 return true;
449 }
450
451 if (is_linear_reduction(node))
452 {
453 reduce_linear(node, to_visit);
454 return true;
455 }
456
457 return false;
458}
459
460static inline bool
463 std::unordered_set<jlm::llvm::ControlFlowGraphNode *> & to_visit)
464{
465 if (is_T1(node))
466 {
467 reduce_T1(node);
468 return true;
469 }
470
471 if (is_T2(node))
472 {
473 reduce_T2(node, to_visit);
474 return true;
475 }
476
477 return false;
478}
479
480static bool
482{
483 for (auto it = bb.begin(); it != bb.end(); it++)
484 {
485 const auto tac = *it;
486 const auto phi = dynamic_cast<const SsaPhiOperation *>(&tac->operation());
487 if (!phi)
488 continue;
489
490 // Ensure all phi nodes are at the beginning of a basic block
491 if (tac != bb.first() && !is<SsaPhiOperation>(*std::prev(it)))
492 return false;
493
494 // Ensure there are no duplicated incoming blocks in the phi node
496 for (size_t i = 0; i < phi->narguments(); i++)
497 {
498 phiIncoming.insert(phi->GetIncomingNode(i));
499 }
500 if (phiIncoming.Size() != phi->narguments())
501 return false;
502
503 // Ensure the set of incoming blocks matches the actual predecessors of this basic block
505 for (auto & inEdge : bb.InEdges())
506 {
507 predecessors.insert(inEdge.source());
508 }
509 if (phiIncoming != predecessors)
510 return false;
511 }
512
513 return true;
514}
515
516static bool
518{
519 if (bb.no_successor())
520 return false;
521
522 if (!has_valid_phis(bb))
523 return false;
524
525 return true;
526}
527
528static bool
530{
531 if (!cfg.entry()->no_predecessor())
532 return false;
533
534 if (cfg.entry()->NumOutEdges() != 1)
535 return false;
536
537 return true;
538}
539
540static bool
542{
543 return cfg.exit()->no_successor();
544}
545
546bool
548{
549 if (!has_valid_entry(cfg))
550 return false;
551
552 if (!has_valid_exit(cfg))
553 return false;
554
555 // check all basic blocks
556 for (const auto & bb : cfg)
557 {
558 if (!is_valid_basic_block(bb))
559 return false;
560 }
561
562 return true;
563}
564
565bool
567{
568 JLM_ASSERT(is_valid(cfg));
569
570 for (const auto & node : cfg)
571 {
572 if (node.no_predecessor())
573 return false;
574 }
575
576 return true;
577}
578
579bool
581{
582 JLM_ASSERT(is_closed(cfg));
583
584 for (const auto & node : cfg)
585 {
586 if (!node.single_successor() || !node.single_predecessor())
587 return false;
588 }
589
590 return true;
591}
592
593static inline bool
595 const ControlFlowGraph & cfg,
596 const std::function<
597 bool(llvm::ControlFlowGraphNode *, std::unordered_set<llvm::ControlFlowGraphNode *> &)> & f)
598{
599 JLM_ASSERT(is_closed(cfg));
600 auto c = copy_structural(cfg);
601
602 std::unordered_set<ControlFlowGraphNode *> to_visit({ c->entry(), c->exit() });
603 for (auto & node : *c)
604 to_visit.insert(&node);
605
606 auto it = to_visit.begin();
607 while (it != to_visit.end())
608 {
609 bool reduced = f(*it, to_visit);
610 it = reduced ? to_visit.begin() : std::next(it);
611 }
612
613 return to_visit.size() == 1;
614}
615
616bool
618{
619 return reduce(cfg, reduce_structured);
620}
621
622bool
627
628bool
630{
631 return reduce(cfg, reduce_reducible);
632}
633
634void
636{
637 auto it = cfg.begin();
638 while (it != cfg.end())
639 {
640 BasicBlock * bb = &*it;
641
642 // Check if bb only has one successor, and that the successor only has one predecessor
643 if (!is_linear_reduction(bb))
644 {
645 it++;
646 continue;
647 }
648
649 auto successor = dynamic_cast<BasicBlock *>(it->OutEdge(0)->sink());
650 if (!successor || successor->HasSsaPhiOperation())
651 {
652 it++;
653 continue;
654 }
655
656 // successor becomes the single basic block
657 successor->append_first(bb->tacs());
658 bb->divert_inedges(successor);
659 it = cfg.remove_node(it);
660 }
661}
662
663void
665{
666 JLM_ASSERT(is_valid(cfg));
667
668 auto it = cfg.begin();
669 while (it != cfg.end())
670 {
671 auto bb = &*it;
672
673 /*
674 Ignore basic blocks with instructions
675 */
676 if (bb->ntacs() != 0)
677 {
678 it++;
679 continue;
680 }
681
682 JLM_ASSERT(bb->NumOutEdges() == 1);
683 auto outedge = bb->OutEdge(0);
684 /*
685 Ignore endless loops
686 */
687 if (outedge->sink() == bb)
688 {
689 it++;
690 continue;
691 }
692
693 bb->divert_inedges(outedge->sink());
694 it = cfg.remove_node(it);
695 }
696
697 JLM_ASSERT(is_valid(cfg));
698}
699
700/*
701 * @brief Find all nodes dominated by the entry node.
702 */
703static std::unordered_set<const ControlFlowGraphNode *>
705{
706 std::unordered_set<const ControlFlowGraphNode *> visited;
707 std::unordered_set<ControlFlowGraphNode *> to_visit({ cfg.entry() });
708 while (!to_visit.empty())
709 {
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())
715 {
716 if (visited.find(outedge.sink()) == visited.end()
717 && to_visit.find(outedge.sink()) == to_visit.end())
718 to_visit.insert(outedge.sink());
719 }
720 }
721
722 return visited;
723}
724
725/*
726 * @brief Find all nodes that are NOT dominated by the entry node.
727 */
728static std::unordered_set<ControlFlowGraphNode *>
730{
731 auto livenodes = compute_livenodes(cfg);
732
733 std::unordered_set<ControlFlowGraphNode *> deadnodes;
734 for (auto & node : cfg)
735 {
736 if (livenodes.find(&node) == livenodes.end())
737 deadnodes.insert(&node);
738 }
739
740 JLM_ASSERT(deadnodes.find(cfg.entry()) == deadnodes.end());
741 JLM_ASSERT(deadnodes.find(cfg.exit()) == deadnodes.end());
742 return deadnodes;
743}
744
745/*
746 * @brief Returns all basic blocks that are live and a sink
747 * of a dead node.
748 */
749static std::unordered_set<BasicBlock *>
750compute_live_sinks(const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
751{
752 std::unordered_set<BasicBlock *> sinks;
753 for (auto & node : deadnodes)
754 {
755 for (size_t n = 0; n < node->NumOutEdges(); n++)
756 {
757 auto sink = dynamic_cast<BasicBlock *>(node->OutEdge(n)->sink());
758 if (sink && deadnodes.find(sink) == deadnodes.end())
759 sinks.insert(sink);
760 }
761 }
762
763 return sinks;
764}
765
766static void
768 llvm::ThreeAddressCode & phitac,
769 const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
770{
771 const auto phi = util::assertedCast<const SsaPhiOperation>(&phitac.operation());
772
773 std::vector<ControlFlowGraphNode *> incomingNodes;
774 std::vector<const Variable *> operands;
775 for (size_t n = 0; n < phitac.noperands(); n++)
776 {
777 if (deadnodes.find(phi->GetIncomingNode(n)) == deadnodes.end())
778 {
779 operands.push_back(phitac.operand(n));
780 incomingNodes.push_back(phi->GetIncomingNode(n));
781 }
782 }
783
784 phitac.replace(SsaPhiOperation(std::move(incomingNodes), phi->Type()), operands);
785}
786
787static void
789 const std::unordered_set<BasicBlock *> & sinks,
790 const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
791{
792 for (auto & sink : sinks)
793 {
794 for (auto & tac : *sink)
795 {
796 if (!is<SsaPhiOperation>(tac))
797 break;
798
799 update_phi_operands(*tac, deadnodes);
800 }
801 }
802}
803
804static void
805remove_deadnodes(const std::unordered_set<ControlFlowGraphNode *> & deadnodes)
806{
807 for (auto & node : deadnodes)
808 {
809 node->remove_inedges();
810 JLM_ASSERT(is<BasicBlock>(node));
811 node->cfg().remove_node(static_cast<BasicBlock *>(node));
812 }
813}
814
815void
817{
818 JLM_ASSERT(is_valid(cfg));
819
820 auto deadnodes = compute_deadnodes(cfg);
821 auto sinks = compute_live_sinks(deadnodes);
822 update_phi_operands(sinks, deadnodes);
823 remove_deadnodes(deadnodes);
824
825 JLM_ASSERT(is_closed(cfg));
826}
827
828}
ThreeAddressCodeList::const_iterator end() const noexcept
const ThreeAddressCodeList & tacs() const noexcept
static BasicBlock * create(ControlFlowGraph &cfg)
ThreeAddressCode * first() const noexcept
ThreeAddressCodeList::const_iterator begin() const noexcept
llvm::ThreeAddressCode * append_first(std::unique_ptr< llvm::ThreeAddressCode > tac)
ControlFlowGraphNode * sink() const noexcept
Definition cfg-node.hpp:57
inedge_iterator_range InEdges() const
Definition cfg-node.hpp:163
ControlFlowGraph & cfg() const noexcept
Definition cfg-node.hpp:106
bool no_predecessor() const noexcept
Definition cfg-node.cpp:69
ControlFlowGraphEdge * OutEdge(size_t n) const
Definition cfg-node.hpp:115
outedge_iterator_range OutEdges() const
Definition cfg-node.hpp:122
bool no_successor() const noexcept
Definition cfg-node.cpp:91
size_t NumOutEdges() const noexcept
Definition cfg-node.cpp:46
void divert_inedges(llvm::ControlFlowGraphNode *new_successor)
Definition cfg-node.hpp:171
const_iterator begin() const
Definition cfg.hpp:182
ExitNode * exit() const noexcept
Definition cfg.hpp:212
static ControlFlowGraph::iterator remove_node(ControlFlowGraph::iterator &it)
Definition cfg.cpp:36
EntryNode * entry() const noexcept
Definition cfg.hpp:206
InterProceduralGraphModule & module() const noexcept
Definition cfg.hpp:247
const_iterator end() const
Definition cfg.hpp:194
static std::unique_ptr< StronglyConnectedComponentStructure > Create(const StronglyConnectedComponent &scc)
Strongly Connected Component.
std::unordered_set< ControlFlowGraphNode * > nodes_
bool contains(ControlFlowGraphNode *node) const
util::PtrIterator< ControlFlowGraphNode, std::unordered_set< ControlFlowGraphNode * >::const_iterator > constiterator
const rvsdg::SimpleOperation & operation() const noexcept
Definition tac.hpp:84
void replace(const rvsdg::SimpleOperation &operation, const std::vector< const Variable * > &operands)
Definition tac.cpp:108
const Variable * operand(size_t index) const noexcept
Definition tac.hpp:96
size_t noperands() const noexcept
Definition tac.hpp:90
bool insert(ItemType item)
Definition HashSet.hpp:210
std::size_t Size() const noexcept
Definition HashSet.hpp:187
#define JLM_ASSERT(x)
Definition common.hpp:16
Global memory state passed between functions.
static void reduce_loop(jlm::llvm::ControlFlowGraphNode *node, std::unordered_set< jlm::llvm::ControlFlowGraphNode * > &to_visit)
std::vector< StronglyConnectedComponent > find_sccs(const ControlFlowGraph &cfg)
static jlm::llvm::ControlFlowGraphNode * find_join(const jlm::llvm::ControlFlowGraphNode *split) noexcept
static bool is_loop(const jlm::llvm::ControlFlowGraphNode *node) noexcept
bool is_structured(const ControlFlowGraph &cfg)
static std::unordered_set< ControlFlowGraphNode * > compute_deadnodes(ControlFlowGraph &cfg)
static ControlFlowGraphNode * reduce_branch(ControlFlowGraphNode *split, ControlFlowGraphNode **entry, AggregationMap &map)
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 std::unique_ptr< ControlFlowGraph > copy_structural(const ControlFlowGraph &in)
static void remove_deadnodes(const std::unordered_set< ControlFlowGraphNode * > &deadnodes)
bool is_reducible(const ControlFlowGraph &cfg)
static std::unordered_set< const ControlFlowGraphNode * > compute_livenodes(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 ControlFlowGraphNode * reduce_linear(ControlFlowGraphNode *source, ControlFlowGraphNode **entry, ControlFlowGraphNode **exit, AggregationMap &map)
static bool reduce(const ControlFlowGraph &cfg, const std::function< bool(llvm::ControlFlowGraphNode *, std::unordered_set< llvm::ControlFlowGraphNode * > &)> &f)
static bool is_proper_branch(const jlm::llvm::ControlFlowGraphNode *split) noexcept
static bool has_valid_entry(const ControlFlowGraph &cfg)
bool is_valid(const 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 std::unordered_set< BasicBlock * > compute_live_sinks(const std::unordered_set< ControlFlowGraphNode * > &deadnodes)
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)
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)