Jlm
domtree.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
7 #include <jlm/llvm/ir/cfg.hpp>
9 
10 #include <functional>
11 #include <unordered_map>
12 
13 namespace jlm::llvm
14 {
15 
16 DominatorTreeNode *
17 DominatorTreeNode::add_child(std::unique_ptr<DominatorTreeNode> child)
18 {
19  children_.push_back(std::move(child));
20  auto c = children_.back().get();
21  c->depth_ = depth() + 1;
22  c->parent_ = this;
23 
24  return c;
25 }
26 
27 /* dominator computations */
28 
29 static std::unique_ptr<DominatorTreeNode>
31  std::unordered_map<ControlFlowGraphNode *, ControlFlowGraphNode *> & doms,
32  ControlFlowGraphNode * root)
33 {
34  std::function<DominatorTreeNode *(
36  std::unordered_map<ControlFlowGraphNode *, DominatorTreeNode *> &)>
37  build = [&](ControlFlowGraphNode * node,
38  std::unordered_map<ControlFlowGraphNode *, DominatorTreeNode *> & map)
39  {
40  if (map.find(node) != map.end())
41  return map[node];
42 
43  auto parent = build(doms[node], map);
44  auto child = parent->add_child(DominatorTreeNode::create(node));
45  map[node] = child;
46  return child;
47  };
48 
49  auto & cfg = root->cfg();
50 
51  /* find leaves of tree */
52  /* FIXME */
53  std::unordered_set<ControlFlowGraphNode *> nodes({ cfg.entry(), cfg.exit() });
54  for (auto & node : cfg)
55  nodes.insert(&node);
56  for (auto & node : cfg)
57  nodes.erase(doms[&node]);
58 
59  /* build tree bottom-up */
60  std::unordered_map<ControlFlowGraphNode *, DominatorTreeNode *> map;
61  auto domroot = DominatorTreeNode::create(root);
62  map[root] = domroot.get();
63  for (auto node : nodes)
64  build(node, map);
65 
66  return domroot;
67 }
68 
69 static ControlFlowGraphNode *
73  const std::unordered_map<ControlFlowGraphNode *, size_t> & indices,
74  const std::unordered_map<ControlFlowGraphNode *, ControlFlowGraphNode *> & doms)
75 {
76  while (indices.at(b1) != indices.at(b2))
77  {
78  while (indices.at(b1) < indices.at(b2))
79  b1 = doms.at(b1);
80  while (indices.at(b2) < indices.at(b1))
81  b2 = doms.at(b2);
82  }
83 
84  return b1;
85 }
86 
87 /*
88  Keith D. Cooper et. al. - A Simple, Fast Dominance Algorithm
89 */
90 std::unique_ptr<DominatorTreeNode>
92 {
93  JLM_ASSERT(is_closed(cfg));
94 
95  std::unordered_map<ControlFlowGraphNode *, ControlFlowGraphNode *> doms(
96  { { cfg.entry(), cfg.entry() }, { cfg.exit(), nullptr } });
97  for (auto & node : cfg)
98  doms[&node] = nullptr;
99 
100  size_t index = cfg.nnodes() + 2;
101  auto rporder = reverse_postorder(cfg);
102  std::unordered_map<ControlFlowGraphNode *, size_t> indices;
103  for (auto & node : rporder)
104  indices[node] = index--;
105  JLM_ASSERT(index == 0);
106 
107  bool changed = true;
108  while (changed)
109  {
110  changed = false;
111  for (auto & node : rporder)
112  {
113  if (node == cfg.entry())
114  continue;
115 
116  /* find first processed predecessor */
117  ControlFlowGraphNode * newidom = nullptr;
118  for (auto & inedge : node->InEdges())
119  {
120  auto p = inedge.source();
121  if (doms[p] != nullptr)
122  {
123  newidom = p;
124  break;
125  }
126  }
127  JLM_ASSERT(newidom != nullptr);
128 
129  auto pred = newidom;
130  for (auto & inedge : node->InEdges())
131  {
132  auto p = inedge.source();
133  if (p == pred)
134  continue;
135 
136  if (doms[p] != nullptr)
137  newidom = intersect(p, newidom, indices, doms);
138  }
139 
140  if (doms[node] != newidom)
141  {
142  doms[node] = newidom;
143  changed = true;
144  }
145  }
146  }
147 
148  doms[cfg.entry()] = nullptr;
149  return build_domtree(doms, cfg.entry());
150 }
151 
152 }
ControlFlowGraph & cfg() const noexcept
Definition: cfg-node.hpp:106
EntryNode * entry() const noexcept
Definition: cfg.hpp:205
ExitNode * exit() const noexcept
Definition: cfg.hpp:211
size_t nnodes() const noexcept
Definition: cfg.hpp:240
static std::unique_ptr< DominatorTreeNode > create(ControlFlowGraphNode *node)
Definition: domtree.hpp:88
size_t depth() const noexcept
Definition: domtree.hpp:82
std::vector< std::unique_ptr< DominatorTreeNode > > children_
Definition: domtree.hpp:97
DominatorTreeNode * add_child(std::unique_ptr< DominatorTreeNode > child)
Definition: domtree.cpp:17
DominatorTreeNode * child(size_t index) const noexcept
Definition: domtree.hpp:63
#define JLM_ASSERT(x)
Definition: common.hpp:16
Global memory state passed between functions.
static std::unique_ptr< DominatorTreeNode > build_domtree(std::unordered_map< ControlFlowGraphNode *, ControlFlowGraphNode * > &doms, ControlFlowGraphNode *root)
Definition: domtree.cpp:30
static ControlFlowGraphNode * intersect(ControlFlowGraphNode *b1, ControlFlowGraphNode *b2, const std::unordered_map< ControlFlowGraphNode *, size_t > &indices, const std::unordered_map< ControlFlowGraphNode *, ControlFlowGraphNode * > &doms)
Definition: domtree.cpp:70
std::unique_ptr< DominatorTreeNode > domtree(ControlFlowGraph &cfg)
Definition: domtree.cpp:91
bool is_closed(const ControlFlowGraph &cfg)
std::vector< ControlFlowGraphNode * > reverse_postorder(const ControlFlowGraph &cfg)
Definition: cfg.cpp:225