Skip to content

Commit a8a7aa8

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 e3a0a8c commit a8a7aa8

File tree

4 files changed

+82
-26
lines changed

4 files changed

+82
-26
lines changed
Lines changed: 16 additions & 0 deletions
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+
}
Lines changed: 9 additions & 0 deletions
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

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bool dep_graph_domaint::merge(
3737
}
3838

3939
changed |= util_set_union(control_deps, src.control_deps);
40+
changed |= util_set_union(control_dep_candidates, src.control_dep_candidates);
4041

4142
return changed;
4243
}
@@ -48,42 +49,54 @@ void dep_graph_domaint::control_dependencies(
4849
{
4950
// Better Slicing of Programs with Jumps and Switches
5051
// 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.
52+
// "Node N is control dependent on node M iff N postdominates, in
53+
// the CFG, one but not all of M's CFG successors."
5354
//
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);
55+
// The "successor" above refers to an immediate successor of M.
56+
//
57+
// When computing the control dependencies of a node N (i.e., "to"
58+
// being N), candidates for M are all control statements (gotos or
59+
// assumes) from which there is a path in the CFG to N.
60+
61+
// Add new candidates
62+
63+
if(from->is_goto() || from->is_assume())
64+
control_dep_candidates.insert(from);
65+
else if(from->is_end_function())
66+
{
67+
control_dep_candidates.clear();
68+
return;
69+
}
70+
71+
if(control_dep_candidates.empty())
72+
return;
73+
74+
// Get postdominators
5975

6076
const irep_idt id=from->function;
6177
const cfg_post_dominatorst &pd=dep_graph.cfg_post_dominators().at(id);
6278

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;
79+
// Check all candidates
7180

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

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

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

8496
const cfg_post_dominatorst::cfgt::nodet &m=
8597
pd.cfg[e->second];
8698

99+
// successors of M
87100
for(const auto &edge : m.out)
88101
{
89102
const cfg_post_dominatorst::cfgt::nodet &m_s=
@@ -95,11 +108,14 @@ void dep_graph_domaint::control_dependencies(
95108
post_dom_all=false;
96109
}
97110

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

@@ -190,7 +206,10 @@ void dep_graph_domaint::transform(
190206
assert(s!=nullptr);
191207

192208
util_set_union(s->control_deps, control_deps);
209+
util_set_union(s->control_dep_candidates, control_dep_candidates);
210+
193211
control_deps.clear();
212+
control_dep_candidates.clear();
194213
}
195214
}
196215
else

src/analyses/dependence_graph.h

Lines changed: 13 additions & 1 deletion
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)