Jlm
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 
13 namespace jlm::llvm
14 {
15 
18 {
19  return constiterator(nodes_.begin());
20 }
21 
24 {
25  return constiterator(nodes_.end());
26 }
27 
28 bool
30 {
31  return NumEntryNodes() == 1 && NumRepetitionEdges() == 1 && NumExitEdges() == 1
32  && (*RepetitionEdges().begin())->source() == (*ExitEdges().begin())->source();
33 }
34 
35 std::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 
78 static void
80  ControlFlowGraphNode * node,
81  ControlFlowGraphNode * exit,
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 
126 std::vector<StronglyConnectedComponent>
128 {
129  JLM_ASSERT(is_closed(cfg));
130 
131  return find_sccs(cfg.entry(), cfg.exit());
132 }
133 
134 std::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 
146 static 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 
175 static inline bool
177 {
178  return node->NumInEdges() == 2 && node->NumOutEdges() == 2 && node->has_selfloop_edge();
179 }
180 
181 static 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 
193 static inline jlm::llvm::ControlFlowGraphNode *
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 
213 static 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 
238 static 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 
261 static 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 
273 static 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 
289 static 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 
315 static 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 
335 static 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 
361 static 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 
380 static 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 
395 static 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 
408 static 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 
434 static 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 
460 static 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 
480 static 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 
516 static 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 
528 static 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 
540 static bool
542 {
543  return cfg.exit()->no_successor();
544 }
545 
546 bool
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 
565 bool
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 
579 bool
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 
593 static 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 
616 bool
618 {
619  return reduce(cfg, reduce_structured);
620 }
621 
622 bool
624 {
625  return reduce(cfg, reduce_proper_structured);
626 }
627 
628 bool
630 {
631  return reduce(cfg, reduce_reducible);
632 }
633 
634 void
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 
663 void
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  */
703 static 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  */
728 static 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  */
749 static std::unordered_set<BasicBlock *>
750 compute_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 
766 static 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 
787 static 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 
804 static void
805 remove_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 
815 void
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
Definition: basic-block.hpp:62
const ThreeAddressCodeList & tacs() const noexcept
Definition: basic-block.hpp:38
llvm::ThreeAddressCode * append_first(std::unique_ptr< llvm::ThreeAddressCode > tac)
ThreeAddressCode * first() const noexcept
Definition: basic-block.hpp:80
static BasicBlock * create(ControlFlowGraph &cfg)
Definition: basic-block.cpp:37
ThreeAddressCodeList::const_iterator begin() const noexcept
Definition: basic-block.hpp:50
ControlFlowGraphNode * sink() const noexcept
Definition: cfg-node.hpp:57
inedge_iterator_range InEdges() const
Definition: cfg-node.hpp:163
ControlFlowGraphEdge * OutEdge(size_t n) const
Definition: cfg-node.hpp:115
bool no_predecessor() const noexcept
Definition: cfg-node.cpp:69
ControlFlowGraph & cfg() const noexcept
Definition: cfg-node.hpp:106
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:181
EntryNode * entry() const noexcept
Definition: cfg.hpp:205
static ControlFlowGraph::iterator remove_node(ControlFlowGraph::iterator &it)
Definition: cfg.cpp:34
ExitNode * exit() const noexcept
Definition: cfg.hpp:211
const_iterator end() const
Definition: cfg.hpp:193
InterProceduralGraphModule & module() const noexcept
Definition: cfg.hpp:246
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
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
const rvsdg::SimpleOperation & operation() const noexcept
Definition: tac.hpp:84
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.
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)
Definition: node.hpp:1049