Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dominators_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
42#include <iostream>
43#include <string>
44#include <Dominators.H>
45#include <tpl_graph.H>
46
47using namespace std;
48using namespace Aleph;
49
50namespace
51{
53
61 template <typename Container>
62 void print_frontier(CFG::Node * node, const Container & frontier)
63 {
64 (void) node;
65 cout << "{";
66 bool first = true;
67 for (auto fi = frontier.get_it(); fi.has_curr(); fi.next_ne())
68 {
69 if (not first)
70 cout << ", ";
71 cout << fi.get_curr()->get_info();
72 first = false;
73 }
74 cout << "}";
75 }
76} // namespace
77
78
90int main()
91{
92 // ========================================================================
93 // 1. Build a control-flow graph
94 // ========================================================================
95 //
96 // entry
97 // |
98 // cond
99 // |- then
100 // `- else
101 // join
102 // |
103 // loop_header <----+
104 // | | |
105 // loop_body | |
106 // | | |
107 // +------+-------+
108 // |
109 // exit
110
111 CFG cfg;
112
113 auto entry = cfg.insert_node("entry");
114 auto cond = cfg.insert_node("cond");
115 auto then_block = cfg.insert_node("then");
116 auto else_block = cfg.insert_node("else");
117 auto join = cfg.insert_node("join");
118 auto loop_header = cfg.insert_node("loop_hdr");
119 auto loop_body = cfg.insert_node("loop_body");
120 auto exit_block = cfg.insert_node("exit");
121
122 cfg.insert_arc(entry, cond);
123 cfg.insert_arc(cond, then_block);
124 cfg.insert_arc(cond, else_block);
125 cfg.insert_arc(then_block, join);
126 cfg.insert_arc(else_block, join);
127 cfg.insert_arc(join, loop_header);
128 cfg.insert_arc(loop_header, loop_body);
129 cfg.insert_arc(loop_header, exit_block);
130 cfg.insert_arc(loop_body, loop_header); // back-edge
131
132 cout << "=== Control-Flow Graph ===" << endl;
133 cout << "Nodes: " << cfg.get_num_nodes() << endl;
134 cout << "Arcs: " << cfg.get_num_arcs() << endl;
135 cout << endl;
136 cout << "Edges:" << endl;
137 for (auto it = cfg.get_arc_it(); it.has_curr(); it.next_ne())
138 {
139 auto arc = it.get_curr();
140 cout << " " << cfg.get_src_node(arc)->get_info()
141 << " -> " << cfg.get_tgt_node(arc)->get_info() << endl;
142 }
143 cout << endl;
144
145 // ========================================================================
146 // 2. Compute immediate dominators
147 // ========================================================================
148
150 auto idoms = dom.compute_idom(cfg, entry);
151
152 cout << "=== Immediate Dominators ===" << endl;
153 for (auto it = idoms.get_it(); it.has_curr(); it.next_ne())
154 {
155 auto [node, idom] = it.get_curr();
156 cout << " idom(" << node->get_info() << ") = "
157 << (idom ? idom->get_info() : "(root)") << endl;
158 }
159 cout << endl;
160
161 // ========================================================================
162 // 3. Build and display dominator tree
163 // ========================================================================
164
166 dom.build_tree(cfg, entry, dom_tree);
167
168 cout << "=== Dominator Tree ===" << endl;
169 cout << "Nodes: " << dom_tree.get_num_nodes() << endl;
170 cout << "Arcs: " << dom_tree.get_num_arcs() << endl;
171 cout << endl;
172 cout << "Tree edges (parent -> child):" << endl;
173 for (auto it = dom_tree.get_arc_it(); it.has_curr(); it.next_ne())
174 {
175 auto arc = it.get_curr();
176 cout << " " << dom_tree.get_src_node(arc)->get_info()
177 << " -> " << dom_tree.get_tgt_node(arc)->get_info() << endl;
178 }
179 cout << endl;
180
181 // ========================================================================
182 // 4. Compute dominance frontiers (for SSA phi-function placement)
183 // ========================================================================
184
185 auto df = dom.dominance_frontiers(cfg, entry);
186
187 cout << "=== Dominance Frontiers ===" << endl;
188 for (auto it = df.get_it(); it.has_curr(); it.next_ne())
189 {
190 auto & [node, frontier] = it.get_curr();
191 cout << " DF(" << node->get_info() << ") = ";
193 cout << endl;
194 }
195 cout << endl;
196
197 // ========================================================================
198 // 5. Identify phi-function placement
199 // ========================================================================
200
201 cout << "=== SSA Phi-Function Placement ===" << endl;
202 cout << "Blocks where phi-functions would be needed:" << endl;
203
204 // In SSA, phi-functions are placed at dominance frontier nodes.
205 // A variable defined in block B needs a phi at each node in DF(B).
206 for (auto it = df.get_it(); it.has_curr(); it.next_ne())
207 {
208 auto & [node, frontier] = it.get_curr();
209 if (not frontier.is_empty())
210 {
211 cout << " Definitions in '" << node->get_info()
212 << "' need phi at: ";
214 cout << endl;
215 }
216 }
217 cout << endl;
218
219 // ========================================================================
220 // 6. Dominance queries
221 // ========================================================================
222
223 cout << "=== Dominance Queries ===" << endl;
224 cout << " entry dominates exit? "
225 << (dom.dominates(cfg, entry, entry, exit_block) ? "yes" : "no") << endl;
226 cout << " cond dominates join? "
227 << (dom.dominates(cfg, entry, cond, join) ? "yes" : "no") << endl;
228 cout << " then dominates join? "
229 << (dom.dominates(cfg, entry, then_block, join) ? "yes" : "no") << endl;
230 cout << " loop_hdr dominates loop_body? "
231 << (dom.dominates(cfg, entry, loop_header, loop_body) ? "yes" : "no") << endl;
232 cout << endl;
233
234 // ========================================================================
235 // 7. Compute post-dominators (from exit node)
236 // ========================================================================
237
240
241 cout << "=== Immediate Post-Dominators (exit = " << exit_block->get_info()
242 << ") ===" << endl;
243 for (auto pit = ipdoms.get_it(); pit.has_curr(); pit.next_ne())
244 {
245 auto [node, ipdom] = pit.get_curr();
246 cout << " ipdom(" << node->get_info() << ") = "
247 << (ipdom ? ipdom->get_info() : "(exit)") << endl;
248 }
249 cout << endl;
250
251 // ========================================================================
252 // 8. Build and display post-dominator tree
253 // ========================================================================
254
256 pdom.build_tree(cfg, exit_block, pdom_tree);
257
258 cout << "=== Post-Dominator Tree ===" << endl;
259 cout << "Nodes: " << pdom_tree.get_num_nodes() << endl;
260 cout << "Arcs: " << pdom_tree.get_num_arcs() << endl;
261 cout << endl;
262 cout << "Tree edges (parent -> child):" << endl;
263 for (auto pit = pdom_tree.get_arc_it(); pit.has_curr(); pit.next_ne())
264 {
265 auto arc = pit.get_curr();
266 cout << " " << pdom_tree.get_src_node(arc)->get_info()
267 << " -> " << pdom_tree.get_tgt_node(arc)->get_info() << endl;
268 }
269 cout << endl;
270
271 // ========================================================================
272 // 9. Compute post-dominance frontiers (for CDG construction)
273 // ========================================================================
274
275 auto pdf = pdom.post_dominance_frontiers(cfg, exit_block);
276
277 cout << "=== Post-Dominance Frontiers ===" << endl;
278 for (auto pit = pdf.get_it(); pit.has_curr(); pit.next_ne())
279 {
280 auto & [node, frontier] = pit.get_curr();
281 cout << " PDF(" << node->get_info() << ") = ";
283 cout << endl;
284 }
285 cout << endl;
286
287 // ========================================================================
288 // 10. Post-dominance queries
289 // ========================================================================
290
291 cout << "=== Post-Dominance Queries ===" << endl;
292 cout << " exit post-dominates entry? "
293 << (pdom.post_dominates(cfg, exit_block, exit_block, entry) ? "yes" : "no")
294 << endl;
295 cout << " loop_hdr post-dominates cond? "
296 << (pdom.post_dominates(cfg, exit_block, loop_header, cond) ? "yes" : "no")
297 << endl;
298 cout << " then post-dominates entry? "
299 << (pdom.post_dominates(cfg, exit_block, then_block, entry) ? "yes" : "no")
300 << endl;
301
302 return 0;
303}
Dominator and post-dominator tree computation via the Lengauer-Tarjan algorithm.
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3854
Computes dominator tree and dominance frontiers of a digraph using the Lengauer-Tarjan algorithm.
Definition Dominators.H:148
DynMapTree< Node *, DynSetTree< Node * > > dominance_frontiers(GT &g, Node *root)
Compute dominance frontiers for all reachable nodes.
Definition Dominators.H:541
void build_tree(GT &g, Node *root, GT &tree)
Build the dominator tree as a separate graph.
Definition Dominators.H:441
bool dominates(GT &g, Node *root, Node *d, Node *v)
Test whether node d dominates node v.
Definition Dominators.H:498
DynList< std::pair< Node *, Node * > > compute_idom(GT &g, Node *root)
Compute immediate dominators.
Definition Dominators.H:416
Computes post-dominator tree and post-dominance frontiers of a digraph using the Lengauer-Tarjan algo...
Definition Dominators.H:729
DynList< std::pair< Node *, Node * > > compute_ipdom(const GT &g, Node *exit_node)
Compute immediate post-dominators.
Definition Dominators.H:838
ArcInfo & get_info() noexcept
Return a modifiable reference to the arc data.
Definition graph-dry.H:595
int main()
Demonstrates construction of a control-flow graph and performs dominance analyses.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
static long & df(typename GT::Node *p)
Internal helper: DFS discovery time stored in NODE_COUNTER(p).
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Generic graph and digraph implementations.