@@ -26,20 +26,68 @@ template <class P, class T, bool post_dom>
26
26
class cfg_dominators_templatet
27
27
{
28
28
public:
29
- typedef std::set<T > target_sett;
29
+ typedef std::set<std:: size_t > target_sett;
30
30
31
31
struct nodet
32
32
{
33
33
target_sett dominators;
34
34
};
35
35
36
- typedef procedure_local_cfg_baset< nodet, P, T> cfgt;
36
+ typedef cfg_basic_blockst<procedure_local_cfg_baset, nodet, P, T> cfgt;
37
37
cfgt cfg;
38
38
39
39
void operator ()(P &program);
40
40
41
41
T entry_node;
42
42
43
+ // / Returns true if basic block \p lhs [post]dominates \p rhs
44
+ bool basic_block_dominates (std::size_t lhs, std::size_t rhs) const
45
+ {
46
+ return cfg[rhs].dominators .count (lhs);
47
+ }
48
+
49
+ // / Returns true if program point \p lhs [post]dominates \p rhs
50
+ bool dominates_same_block (T lhs, T rhs, std::size_t block) const ;
51
+
52
+ bool dominates (T lhs, T rhs) const
53
+ {
54
+ const auto lhs_block = cfg.entry_map .at (lhs);
55
+ const auto rhs_block = cfg.entry_map .at (rhs);
56
+
57
+ if (lhs == rhs)
58
+ return true ;
59
+
60
+ if (lhs_block != rhs_block)
61
+ return basic_block_dominates (lhs_block, rhs_block);
62
+ else
63
+ return dominates_same_block (lhs, rhs, lhs_block);
64
+ }
65
+
66
+ const target_sett &basic_block_dominators (std::size_t block) const
67
+ {
68
+ return cfg[block].dominators ;
69
+ }
70
+
71
+ const typename cfgt::nodet &get_node (const T &program_point) const
72
+ {
73
+ return cfg[cfg.entry_map .at (program_point)];
74
+ }
75
+
76
+ typename cfgt::nodet &get_node (const T &program_point)
77
+ {
78
+ return cfg[cfg.entry_map .at (program_point)];
79
+ }
80
+
81
+ bool basic_block_reachable (std::size_t block) const
82
+ {
83
+ return !cfg[block].dominators .empty ();
84
+ }
85
+
86
+ bool instruction_reachable (T instruction) const
87
+ {
88
+ return basic_block_reachable (cfg.entry_map .at (instruction));
89
+ }
90
+
43
91
void output (std::ostream &) const ;
44
92
45
93
protected:
@@ -76,32 +124,33 @@ void cfg_dominators_templatet<P, T, post_dom>::initialise(P &program)
76
124
template <class P , class T , bool post_dom>
77
125
void cfg_dominators_templatet<P, T, post_dom>::fixedpoint(P &program)
78
126
{
79
- std::list<T > worklist;
127
+ std::list<typename cfgt::node_indext > worklist;
80
128
81
129
if (cfg.nodes_empty (program))
82
130
return ;
83
131
84
132
if (post_dom)
85
- entry_node=cfg. get_last_node (program);
133
+ entry_node = cfgt:: get_last_node (program);
86
134
else
87
- entry_node=cfg.get_first_node (program);
88
- typename cfgt::nodet &n=cfg[cfg.entry_map [entry_node]];
89
- n.dominators .insert (entry_node);
135
+ entry_node = cfgt::get_first_node (program);
136
+ const auto entry_node_index = cfg.entry_map [entry_node];
137
+ typename cfgt::nodet &n = cfg[entry_node_index];
138
+ n.dominators .insert (entry_node_index);
90
139
91
140
for (typename cfgt::edgest::const_iterator
92
141
s_it=(post_dom?n.in :n.out ).begin ();
93
142
s_it!=(post_dom?n.in :n.out ).end ();
94
143
++s_it)
95
- worklist.push_back (cfg[ s_it->first ]. PC );
144
+ worklist.push_back (s_it->first );
96
145
97
146
while (!worklist.empty ())
98
147
{
99
148
// get node from worklist
100
- T current= worklist.front ();
149
+ const auto current = worklist.front ();
101
150
worklist.pop_front ();
102
151
103
152
bool changed=false ;
104
- typename cfgt::nodet &node= cfg[cfg. entry_map [ current] ];
153
+ typename cfgt::nodet &node = cfg[current];
105
154
if (node.dominators .empty ())
106
155
{
107
156
for (const auto &edge : (post_dom ? node.out : node.in ))
@@ -158,12 +207,33 @@ void cfg_dominators_templatet<P, T, post_dom>::fixedpoint(P &program)
158
207
{
159
208
for (const auto &edge : (post_dom ? node.in : node.out ))
160
209
{
161
- worklist.push_back (cfg[ edge.first ]. PC );
210
+ worklist.push_back (edge.first );
162
211
}
163
212
}
164
213
}
165
214
}
166
215
216
+ template <class P , class T , bool post_dom>
217
+ bool cfg_dominators_templatet<P, T, post_dom>::dominates_same_block(
218
+ T lhs,
219
+ T rhs,
220
+ std::size_t block) const
221
+ {
222
+ // Special case when the program points belong to the same block: lhs
223
+ // dominates rhs iff it is <= rhs in program order (or the reverse if we're
224
+ // a postdominator analysis)
225
+
226
+ for (const auto &instruction : cfg[block].block )
227
+ {
228
+ if (instruction == lhs)
229
+ return !post_dom;
230
+ else if (instruction == rhs)
231
+ return post_dom;
232
+ }
233
+
234
+ UNREACHABLE; // Entry map is inconsistent with block members?
235
+ }
236
+
167
237
// / Pretty-print a single node in the dominator tree. Supply a specialisation if
168
238
// / operator<< is not sufficient.
169
239
// / \par parameters: `node` to print and stream `out` to pretty-print it to
@@ -184,22 +254,20 @@ inline void dominators_pretty_print_node(
184
254
template <class P , class T , bool post_dom>
185
255
void cfg_dominators_templatet<P, T, post_dom>::output(std::ostream &out) const
186
256
{
187
- for (const auto &node : cfg.entry_map )
257
+ for (typename cfgt::node_indext i = 0 ; i < cfg.size (); ++i )
188
258
{
189
- auto n=node.first ;
190
-
191
- dominators_pretty_print_node (n, out);
259
+ out << " Block " << dominators_pretty_print_node (cfg[i].block .at (0 ), out);
192
260
if (post_dom)
193
261
out << " post-dominated by " ;
194
262
else
195
263
out << " dominated by " ;
196
264
bool first=true ;
197
- for (const auto &d : cfg[node. second ].dominators )
265
+ for (const auto &d : cfg[i ].dominators )
198
266
{
199
267
if (!first)
200
268
out << " , " ;
201
269
first=false ;
202
- dominators_pretty_print_node (d , out);
270
+ dominators_pretty_print_node (cfg[d]. block . at ( 0 ) , out);
203
271
}
204
272
out << " \n " ;
205
273
}
0 commit comments