Skip to content

Commit a408423

Browse files
committed
Simplified state merging in the dependence graph
1 parent 0315816 commit a408423

File tree

2 files changed

+65
-37
lines changed

2 files changed

+65
-37
lines changed

src/analyses/dependence_graph.cpp

+8-37
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Date: August 2013
1616

1717
#include <cassert>
1818

19+
#include <util/container_utils.h>
1920
#include <util/json.h>
2021
#include <util/json_expr.h>
2122

@@ -26,36 +27,16 @@ bool dep_graph_domaint::merge(
2627
goto_programt::const_targett from,
2728
goto_programt::const_targett to)
2829
{
29-
bool changed=has_values.is_false();
30-
has_values=tvt::unknown();
30+
bool changed = false;
3131

32-
depst::iterator it=control_deps.begin();
33-
for(const auto &c_dep : src.control_deps)
32+
if(is_bottom())
3433
{
35-
while(it!=control_deps.end() && *it<c_dep)
36-
++it;
37-
if(it==control_deps.end() || c_dep<*it)
38-
{
39-
control_deps.insert(it, c_dep);
40-
changed=true;
41-
}
42-
else if(it!=control_deps.end())
43-
++it;
34+
has_values = tvt::unknown();
35+
data_deps = src.data_deps;
36+
changed = true;
4437
}
4538

46-
it=data_deps.begin();
47-
for(const auto &d_dep : src.data_deps)
48-
{
49-
while(it!=data_deps.end() && *it<d_dep)
50-
++it;
51-
if(it==data_deps.end() || d_dep<*it)
52-
{
53-
data_deps.insert(it, d_dep);
54-
changed=true;
55-
}
56-
else if(it!=data_deps.end())
57-
++it;
58-
}
39+
changed |= util_inplace_set_union(control_deps, src.control_deps);
5940

6041
return changed;
6142
}
@@ -208,17 +189,7 @@ void dep_graph_domaint::transform(
208189
dynamic_cast<dep_graph_domaint*>(&(dep_graph->get_state(next)));
209190
assert(s!=nullptr);
210191

211-
depst::iterator it=s->control_deps.begin();
212-
for(const auto &c_dep : control_deps)
213-
{
214-
while(it!=s->control_deps.end() && *it<c_dep)
215-
++it;
216-
if(it==s->control_deps.end() || c_dep<*it)
217-
s->control_deps.insert(it, c_dep);
218-
else if(it!=s->control_deps.end())
219-
++it;
220-
}
221-
192+
util_inplace_set_union(s->control_deps, control_deps);
222193
control_deps.clear();
223194
}
224195
}

src/util/container_utils.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*******************************************************************\
2+
3+
Module: Container utilities
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_UTIL_CONTAINER_UTILS_H
10+
#define CPROVER_UTIL_CONTAINER_UTILS_H
11+
12+
#include <set>
13+
14+
/// Compute union of two sets
15+
///
16+
/// This function has complexity O(max(n1, n2)), with n1, n2 being the sizes of
17+
/// the sets of which the union is formed. This is in contrast to
18+
/// `target.insert(source.begin(), source.end())` which has complexity
19+
/// O(n2 * log(n1 + n2)).
20+
///
21+
/// \tparam T value type of the sets
22+
/// \tparam Compare comparison predicate of the sets
23+
/// \tparam Alloc allocator of the sets
24+
/// \param target first input set, will contain the result of the union
25+
/// \param source second input set
26+
/// \return true iff `target` was changed
27+
template <class T, class Compare, class Alloc>
28+
bool util_inplace_set_union(
29+
std::set<T, Compare, Alloc> &target,
30+
const std::set<T, Compare, Alloc> &source)
31+
{
32+
bool changed = false;
33+
typename std::set<T, Compare, Alloc>::iterator it = target.begin();
34+
35+
for(const auto &s : source)
36+
{
37+
while(it != target.end() && *it < s)
38+
{
39+
++it;
40+
}
41+
42+
if(it == target.end() || s < *it)
43+
{
44+
// Insertion hint should point at element that will follow the new element
45+
target.insert(it, s);
46+
changed = true;
47+
}
48+
else if(it != target.end())
49+
{
50+
++it;
51+
}
52+
}
53+
54+
return changed;
55+
}
56+
57+
#endif // CPROVER_UTIL_CONTAINER_UTILS_H

0 commit comments

Comments
 (0)