Skip to content

Commit 3aa6dca

Browse files
committed
Control dependency computation fix
Previously in transform() only the control dependencies in the set control_deps (plus gotos and assumes at the from location) were considered candidates for the control dependencies at the to location. With this scheme however one misses control dependencies when there are nested if statements. We introduce a new set control_dep_candidates in addition to control_deps, which contains all control statements encountered so far.
1 parent a408423 commit 3aa6dca

File tree

4 files changed

+83
-26
lines changed

4 files changed

+83
-26
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
int g_in1, g_in2;
2+
int g_out;
3+
4+
void main(void)
5+
{
6+
int t;
7+
if(g_in1)
8+
{
9+
if(g_in2)
10+
t = 0;
11+
else
12+
t = 1;
13+
14+
g_out = 1; // depends on "if(g_in1)
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--show --dependence-graph --text -
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
\/\/ ([0-9]+) file.*\n.*IF.*g_in1.*THEN GOTO(.*\n)*Control dependencies: \1\n\n.*\n.*g_out = 1
8+
--
9+
^warning: ignoring

src/analyses/dependence_graph.cpp

+45-25
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ bool dep_graph_domaint::merge(
3737
}
3838

3939
changed |= util_inplace_set_union(control_deps, src.control_deps);
40+
changed |=
41+
util_inplace_set_union(control_dep_candidates, src.control_dep_candidates);
4042

4143
return changed;
4244
}
@@ -48,42 +50,54 @@ void dep_graph_domaint::control_dependencies(
4850
{
4951
// Better Slicing of Programs with Jumps and Switches
5052
// Kumar and Horwitz, FASE'02:
51-
// Node N is control dependent on node M iff N postdominates one
52-
// but not all of M's CFG successors.
53+
// "Node N is control dependent on node M iff N postdominates, in
54+
// the CFG, one but not all of M's CFG successors."
5355
//
54-
// candidates for M are from and all existing control-depended on
55-
// nodes; from is added if it is a goto or assume instruction
56-
if(from->is_goto() ||
57-
from->is_assume())
58-
control_deps.insert(from);
56+
// The "successor" above refers to an immediate successor of M.
57+
//
58+
// When computing the control dependencies of a node N (i.e., "to"
59+
// being N), candidates for M are all control statements (gotos or
60+
// assumes) from which there is a path in the CFG to N.
61+
62+
// Add new candidates
63+
64+
if(from->is_goto() || from->is_assume())
65+
control_dep_candidates.insert(from);
66+
else if(from->is_end_function())
67+
{
68+
control_dep_candidates.clear();
69+
return;
70+
}
71+
72+
if(control_dep_candidates.empty())
73+
return;
74+
75+
// Get postdominators
5976

6077
const irep_idt id=from->function;
6178
const cfg_post_dominatorst &pd=dep_graph.cfg_post_dominators().at(id);
6279

63-
// check all candidates for M
64-
for(depst::iterator
65-
it=control_deps.begin();
66-
it!=control_deps.end();
67-
) // no ++it
68-
{
69-
depst::iterator next=it;
70-
++next;
80+
// Check all candidates
7181

72-
// check all CFG successors
82+
for(const auto &control_dep_candidate : control_dep_candidates)
83+
{
84+
// check all CFG successors of M
7385
// special case: assumptions also introduce a control dependency
74-
bool post_dom_all=!(*it)->is_assume();
86+
bool post_dom_all = !control_dep_candidate->is_assume();
7587
bool post_dom_one=false;
7688

7789
// we could hard-code assume and goto handling here to improve
7890
// performance
79-
cfg_post_dominatorst::cfgt::entry_mapt::const_iterator e=
80-
pd.cfg.entry_map.find(*it);
91+
cfg_post_dominatorst::cfgt::entry_mapt::const_iterator e =
92+
pd.cfg.entry_map.find(control_dep_candidate);
8193

82-
assert(e!=pd.cfg.entry_map.end());
94+
INVARIANT(
95+
e != pd.cfg.entry_map.end(), "cfg must have an entry for every location");
8396

8497
const cfg_post_dominatorst::cfgt::nodet &m=
8598
pd.cfg[e->second];
8699

100+
// successors of M
87101
for(const auto &edge : m.out)
88102
{
89103
const cfg_post_dominatorst::cfgt::nodet &m_s=
@@ -95,11 +109,14 @@ void dep_graph_domaint::control_dependencies(
95109
post_dom_all=false;
96110
}
97111

98-
if(post_dom_all ||
99-
!post_dom_one)
100-
control_deps.erase(it);
101-
102-
it=next;
112+
if(post_dom_all || !post_dom_one)
113+
{
114+
control_deps.erase(control_dep_candidate);
115+
}
116+
else
117+
{
118+
control_deps.insert(control_dep_candidate);
119+
}
103120
}
104121
}
105122

@@ -190,7 +207,10 @@ void dep_graph_domaint::transform(
190207
assert(s!=nullptr);
191208

192209
util_inplace_set_union(s->control_deps, control_deps);
210+
util_inplace_set_union(s->control_dep_candidates, control_dep_candidates);
211+
193212
control_deps.clear();
213+
control_dep_candidates.clear();
194214
}
195215
}
196216
else

src/analyses/dependence_graph.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,19 @@ class dep_graph_domaint:public ai_domain_baset
162162
node_indext node_id;
163163

164164
typedef std::set<goto_programt::const_targett> depst;
165-
depst control_deps, data_deps;
165+
166+
// Set of locations with control instructions on which the instruction at this
167+
// location has a control dependency on
168+
depst control_deps;
169+
170+
// Set of locations with control instructions from which there is a path in
171+
// the CFG to the current location (with the locations being in the same
172+
// function). The set control_deps is a subset of this set.
173+
depst control_dep_candidates;
174+
175+
// Set of locations with instructions on which the instruction at this
176+
// location has a data dependency on
177+
depst data_deps;
166178

167179
friend const depst &
168180
dependence_graph_test_get_control_deps(const dep_graph_domaint &);

0 commit comments

Comments
 (0)