Skip to content

Commit 738e682

Browse files
committed
Make dependence graph merge() return true when abstract state changes
The dependency graph has special handling for function entry edges (in transform()) where it merges the current state into the state of the return location before entering the function. This may change the abstract state at the return location. When later the function exit edge is handled, the merge() into the return location may not change the state, thus merge() may not return true, and thus the return location may not be inserted into the worklist of the fixpoint computation when it should. We introduce a flag has_changed that records whether the abstract state has changed on the handling of the function entry edge. On the function return edge later, merge() checks the flag to know whether it needs to return true.
1 parent a8a7aa8 commit 738e682

File tree

2 files changed

+52
-17
lines changed

2 files changed

+52
-17
lines changed

src/analyses/dependence_graph.cpp

+23-7
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,27 @@ bool dep_graph_domaint::merge(
2727
goto_programt::const_targett from,
2828
goto_programt::const_targett to)
2929
{
30-
bool changed = false;
31-
32-
if(is_bottom())
30+
// An abstract state at location `to` may be non-bottom even if
31+
// `merge(..., `to`) has not been called so far. This is due to the special
32+
// handling of function entry edges (see transform()).
33+
bool changed = is_bottom() || has_changed;
34+
35+
// For computing the data dependencies, we would not need a fixpoint
36+
// computation. The data dependencies at a location are computed from the
37+
// result of the reaching definitions analysis at that location
38+
// (in data_dependencies()). Thus, we only need to set the data dependencies
39+
// part of an abstract state at a certain location once.
40+
if(changed && data_deps.empty())
3341
{
34-
has_values = tvt::unknown();
3542
data_deps = src.data_deps;
36-
changed = true;
43+
has_values = tvt::unknown();
3744
}
3845

3946
changed |= util_set_union(control_deps, src.control_deps);
4047
changed |= util_set_union(control_dep_candidates, src.control_dep_candidates);
4148

49+
has_changed = false;
50+
4251
return changed;
4352
}
4453

@@ -205,8 +214,15 @@ void dep_graph_domaint::transform(
205214
dynamic_cast<dep_graph_domaint*>(&(dep_graph->get_state(next)));
206215
assert(s!=nullptr);
207216

208-
util_set_union(s->control_deps, control_deps);
209-
util_set_union(s->control_dep_candidates, control_dep_candidates);
217+
if(s->is_bottom())
218+
{
219+
s->has_values = tvt::unknown();
220+
s->has_changed = true;
221+
}
222+
223+
s->has_changed |= util_set_union(s->control_deps, control_deps);
224+
s->has_changed |=
225+
util_set_union(s->control_dep_candidates, control_dep_candidates);
210226

211227
control_deps.clear();
212228
control_dep_candidates.clear();

src/analyses/dependence_graph.h

+29-10
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@ class dep_graph_domaint:public ai_domain_baset
6868
public:
6969
typedef grapht<dep_nodet>::node_indext node_indext;
7070

71-
dep_graph_domaint():
72-
has_values(false),
73-
node_id(std::numeric_limits<node_indext>::max())
71+
dep_graph_domaint()
72+
: has_values(false),
73+
node_id(std::numeric_limits<node_indext>::max()),
74+
has_changed(false)
7475
{
7576
}
7677

@@ -101,6 +102,7 @@ class dep_graph_domaint:public ai_domain_baset
101102

102103
has_values=tvt(true);
103104
control_deps.clear();
105+
control_dep_candidates.clear();
104106
data_deps.clear();
105107
}
106108

@@ -111,22 +113,36 @@ class dep_graph_domaint:public ai_domain_baset
111113

112114
has_values=tvt(false);
113115
control_deps.clear();
116+
control_dep_candidates.clear();
114117
data_deps.clear();
118+
119+
has_changed = false;
115120
}
116121

117122
void make_entry() final override
118123
{
119-
make_top();
124+
DATA_INVARIANT(
125+
node_id != std::numeric_limits<node_indext>::max(),
126+
"node_id must not be valid");
127+
128+
has_values = tvt::unknown();
129+
control_deps.clear();
130+
control_dep_candidates.clear();
131+
data_deps.clear();
132+
133+
has_changed = false;
120134
}
121135

122136
bool is_top() const final override
123137
{
124138
DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
125139
"node_id must be valid");
126140

127-
DATA_INVARIANT(!has_values.is_true() ||
128-
(control_deps.empty() && data_deps.empty()),
129-
"If the domain is top, it must have no dependencies");
141+
DATA_INVARIANT(
142+
!has_values.is_true() ||
143+
(control_deps.empty() && control_dep_candidates.empty() &&
144+
data_deps.empty()),
145+
"If the domain is top, it must have no dependencies");
130146

131147
return has_values.is_true();
132148
}
@@ -136,9 +152,11 @@ class dep_graph_domaint:public ai_domain_baset
136152
DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
137153
"node_id must be valid");
138154

139-
DATA_INVARIANT(!has_values.is_false() ||
140-
(control_deps.empty() && data_deps.empty()),
141-
"If the domain is bottom, it must have no dependencies");
155+
DATA_INVARIANT(
156+
!has_values.is_false() ||
157+
(control_deps.empty() && control_dep_candidates.empty() &&
158+
data_deps.empty()),
159+
"If the domain is bottom, it must have no dependencies");
142160

143161
return has_values.is_false();
144162
}
@@ -160,6 +178,7 @@ class dep_graph_domaint:public ai_domain_baset
160178
private:
161179
tvt has_values;
162180
node_indext node_id;
181+
bool has_changed;
163182

164183
typedef std::set<goto_programt::const_targett> depst;
165184

0 commit comments

Comments
 (0)