Jlm
Loading...
Searching...
No Matches
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
13namespace jlm::llvm
14{
15
16DominatorTreeNode *
17DominatorTreeNode::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
29static std::unique_ptr<DominatorTreeNode>
31 std::unordered_map<ControlFlowGraphNode *, ControlFlowGraphNode *> & doms,
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
69static 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*/
90std::unique_ptr<DominatorTreeNode>
92{
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}
std::vector< rvsdg::Node * > nodes
ControlFlowGraph & cfg() const noexcept
Definition cfg-node.hpp:106
ExitNode * exit() const noexcept
Definition cfg.hpp:212
EntryNode * entry() const noexcept
Definition cfg.hpp:206
size_t nnodes() const noexcept
Definition cfg.hpp:241
size_t depth() const noexcept
Definition domtree.hpp:82
DominatorTreeNode * child(size_t index) const noexcept
Definition domtree.hpp:63
std::vector< std::unique_ptr< DominatorTreeNode > > children_
Definition domtree.hpp:97
DominatorTreeNode * add_child(std::unique_ptr< DominatorTreeNode > child)
Definition domtree.cpp:17
static std::unique_ptr< DominatorTreeNode > create(ControlFlowGraphNode *node)
Definition domtree.hpp:88
#define JLM_ASSERT(x)
Definition common.hpp:16
Global memory state passed between functions.
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
static std::unique_ptr< DominatorTreeNode > build_domtree(std::unordered_map< ControlFlowGraphNode *, ControlFlowGraphNode * > &doms, ControlFlowGraphNode *root)
Definition domtree.cpp:30
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:314