@@ -37,11 +37,9 @@ template <class P, class T, bool post_dom>
37
37
class cfg_dominators_templatet
38
38
{
39
39
public:
40
- typedef std::set<T> target_sett;
41
-
42
40
struct nodet
43
41
{
44
- target_sett dominators ;
42
+ optionalt<std:: size_t > dominator ;
45
43
};
46
44
47
45
typedef procedure_local_cfg_baset<nodet, P, T> cfgt;
@@ -76,7 +74,45 @@ class cfg_dominators_templatet
76
74
// / Note by definition all program points dominate themselves.
77
75
bool dominates (T lhs, const nodet &rhs_node) const
78
76
{
79
- return rhs_node.dominators .count (lhs);
77
+ if (!rhs_node.dominator )
78
+ return false ;
79
+
80
+ auto target_index = cfg.get_node_index (lhs);
81
+ auto current_index = rhs_node.dominator ;
82
+ while (current_index.has_value ())
83
+ {
84
+ if (*current_index == target_index)
85
+ return true ;
86
+
87
+ // As the root dominates itself, we will cancel if we get here and we're
88
+ // not compared.
89
+ if (*current_index == 0 )
90
+ return false ;
91
+
92
+ current_index = cfg[*current_index].dominator ;
93
+ }
94
+
95
+ return false ;
96
+ }
97
+
98
+ // / Returns a set of T that are the dominators of start_node.
99
+ std::set<T> dominated_by (T start_node) const
100
+ {
101
+ auto current_index = cfg.get_node_index (start_node);
102
+ std::set<T> results;
103
+ while (current_index.has_value ())
104
+ {
105
+ // As the root dominates itself, we will cancel if we get here and we're
106
+ // not compared.
107
+ if (*current_index == 0 )
108
+ return false ;
109
+
110
+ auto ¤t_node = cfg[*current_index];
111
+ results.emplace (current_node.PC );
112
+ current_index = current_node.dominator ;
113
+ }
114
+
115
+ return results;
80
116
}
81
117
82
118
// / Returns true if program point \p lhs dominates \p rhs.
@@ -94,7 +130,7 @@ class cfg_dominators_templatet
94
130
// Dominator analysis walks from the entry point, so a side-effect is to
95
131
// identify unreachable program points (those which don't dominate even
96
132
// themselves).
97
- return ! program_point_node.dominators . empty ();
133
+ return program_point_node.dominator . has_value ();
98
134
}
99
135
100
136
// / Returns true if the program point for \p program_point_node is reachable
@@ -156,7 +192,7 @@ void cfg_dominators_templatet<P, T, post_dom>::fixedpoint(P &program)
156
192
else
157
193
entry_node = cfgt::get_first_node (program);
158
194
typename cfgt::nodet &n = cfg.get_node (entry_node);
159
- n.dominators . insert (entry_node);
195
+ n.dominator = cfg. get_node_index (entry_node);
160
196
161
197
for (typename cfgt::edgest::const_iterator
162
198
s_it=(post_dom?n.in :n.out ).begin ();
@@ -172,58 +208,40 @@ void cfg_dominators_templatet<P, T, post_dom>::fixedpoint(P &program)
172
208
173
209
bool changed=false ;
174
210
typename cfgt::nodet &node = cfg.get_node (current);
175
- if (node.dominators .empty ())
176
- {
177
- for (const auto &edge : (post_dom ? node.out : node.in ))
178
- if (!cfg[edge.first ].dominators .empty ())
179
- {
180
- node.dominators =cfg[edge.first ].dominators ;
181
- node.dominators .insert (current);
182
- changed=true ;
183
- }
184
- }
211
+
212
+ auto potential_dominator = node.dominator ;
185
213
186
214
// compute intersection of predecessors
187
215
for (const auto &edge : (post_dom ? node.out : node.in ))
188
216
{
189
- const target_sett &other= cfg[edge.first ]. dominators ;
190
- if (other.empty () )
217
+ const typename cfgt::nodet &other = cfg[edge.first ];
218
+ if (! other.dominator )
191
219
continue ;
192
220
193
- typename target_sett::const_iterator n_it=node. dominators . begin ();
194
- typename target_sett::const_iterator o_it= other.begin () ;
221
+ if (!potential_dominator)
222
+ potential_dominator = other.dominator ;
195
223
196
- // in-place intersection. not safe to use set_intersect
197
- while (n_it!=node. dominators . end () && o_it!=other. end () )
224
+ auto edge_index = *other. dominator ;
225
+ while (potential_dominator != edge_index )
198
226
{
199
- if (*n_it==current)
200
- ++n_it;
201
- else if (*n_it<*o_it)
202
- {
203
- changed=true ;
204
- node.dominators .erase (n_it++);
205
- }
206
- else if (*o_it<*n_it)
207
- ++o_it;
208
- else
227
+ while (potential_dominator > edge_index)
209
228
{
210
- ++n_it;
211
- ++o_it;
229
+ potential_dominator = cfg[*potential_dominator].dominator ;
212
230
}
213
- }
214
231
215
- while (n_it!=node.dominators .end ())
216
- {
217
- if (*n_it==current)
218
- ++n_it;
219
- else
232
+ while (edge_index < potential_dominator)
220
233
{
221
- changed=true ;
222
- node.dominators .erase (n_it++);
234
+ edge_index = *cfg[edge_index].dominator ;
223
235
}
224
236
}
225
237
}
226
238
239
+ if (!node.dominator || *potential_dominator != *node.dominator )
240
+ {
241
+ node.dominator = potential_dominator;
242
+ changed = true ;
243
+ }
244
+
227
245
if (changed) // fixed point for node reached?
228
246
{
229
247
for (const auto &edge : (post_dom ? node.in : node.out ))
0 commit comments