Skip to content

Commit 5806d02

Browse files
committed
value_set_abstract_objectt non destruct compact
If the size of the set is large, if there are any intervals in the set, try merging values into them.
1 parent 933e15c commit 5806d02

File tree

4 files changed

+242
-0
lines changed

4 files changed

+242
-0
lines changed

src/analyses/variable-sensitivity/abstract_object_set.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class abstract_object_sett
4444
insert(value);
4545
}
4646

47+
void push_back(const abstract_object_pointert &v)
48+
{
49+
// alias for insert so we can use back_inserter
50+
values.insert(v);
51+
}
52+
4753
abstract_object_pointert first() const
4854
{
4955
return *begin();

src/analyses/variable-sensitivity/value_set_abstract_object.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ maybe_extract_single_value(const abstract_object_pointert &maybe_singleton);
113113

114114
static bool are_any_top(const abstract_object_sett &set);
115115

116+
static abstract_object_sett compact_values(const abstract_object_sett &values);
117+
116118
value_set_abstract_objectt::value_set_abstract_objectt(const typet &type)
117119
: abstract_value_objectt(type)
118120
{
@@ -148,6 +150,8 @@ abstract_object_pointert value_set_abstract_objectt::make_value_set(
148150

149151
auto values = unwrap_and_extract_values(initial_values);
150152

153+
values = compact_values(values);
154+
151155
const auto &type = values.first()->type();
152156
auto value_set =
153157
std::make_shared<value_set_abstract_objectt>(type, false, false);
@@ -342,3 +346,65 @@ static bool are_any_top(const abstract_object_sett &set)
342346
return value->is_top();
343347
}) != set.end();
344348
}
349+
350+
/////////////////
351+
static abstract_object_sett
352+
non_destructive_compact(const abstract_object_sett &values);
353+
static bool value_is_not_contained_in(
354+
const abstract_object_pointert &object,
355+
const std::vector<constant_interval_exprt> &intervals);
356+
357+
static abstract_object_sett compact_values(const abstract_object_sett &values)
358+
{
359+
if(values.size() <= value_set_abstract_objectt::max_value_set_size)
360+
return values;
361+
362+
return non_destructive_compact(values);
363+
}
364+
365+
static abstract_object_sett
366+
non_destructive_compact(const abstract_object_sett &values)
367+
{
368+
auto intervals = std::vector<constant_interval_exprt>{};
369+
for(auto const &object : values)
370+
{
371+
auto value =
372+
std::dynamic_pointer_cast<const abstract_value_objectt>(object);
373+
auto as_expr = value->to_interval();
374+
if(!as_expr.is_single_value_interval())
375+
intervals.push_back(as_expr);
376+
}
377+
378+
if(intervals.empty())
379+
return values;
380+
381+
auto compacted = abstract_object_sett{};
382+
// for each value, including the intervals
383+
// keep it if it is not in any of the intervals
384+
std::copy_if(
385+
values.begin(),
386+
values.end(),
387+
std::back_inserter(compacted),
388+
[&intervals](const abstract_object_pointert &object) {
389+
return value_is_not_contained_in(object, intervals);
390+
});
391+
392+
return compacted;
393+
}
394+
395+
static bool value_is_not_contained_in(
396+
const abstract_object_pointert &object,
397+
const std::vector<constant_interval_exprt> &intervals)
398+
{
399+
auto value = std::dynamic_pointer_cast<const abstract_value_objectt>(object);
400+
auto as_expr = value->to_interval();
401+
402+
return std::none_of(
403+
intervals.begin(),
404+
intervals.end(),
405+
[&as_expr](const constant_interval_exprt &interval) {
406+
if(interval == as_expr)
407+
return false;
408+
return interval.contains(as_expr);
409+
});
410+
}

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ SRC += analyses/ai/ai.cpp \
2828
analyses/variable-sensitivity/last_written_location.cpp \
2929
analyses/variable-sensitivity/value_expression_evaluation/assume.cpp \
3030
analyses/variable-sensitivity/value_expression_evaluation/expression_evaluation.cpp \
31+
analyses/variable-sensitivity/value_set_abstract_object/compacting.cpp \
3132
analyses/variable-sensitivity/value_set_abstract_object/meet.cpp \
3233
analyses/variable-sensitivity/value_set_abstract_object/merge.cpp \
3334
analyses/variable-sensitivity/variable_sensitivity_test_helpers.cpp \
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for value_set_abstract_valuet compacting
4+
5+
Compacting occurs when the value_set get 'large', and takes two forms
6+
non-destructive (eg, can we merge constants into an existing interval
7+
with no loss of precision) and desctructive (creating intervals from
8+
the constants, or merging existing intervals).
9+
10+
Author: Jez Higgins, [email protected]
11+
12+
\*******************************************************************/
13+
14+
#include "../variable_sensitivity_test_helpers.h"
15+
16+
#include <analyses/variable-sensitivity/variable_sensitivity_object_factory.h>
17+
18+
#include <testing-utils/use_catch.h>
19+
20+
#include <util/arith_tools.h>
21+
#include <util/bitvector_types.h>
22+
#include <util/mathematical_types.h>
23+
24+
SCENARIO(
25+
"compacting value sets",
26+
"[core][analysis][variable-sensitivity][value_set_abstract_object][compact]")
27+
{
28+
const typet type = signedbv_typet(32);
29+
const exprt val1 = from_integer(1, type);
30+
const exprt val2 = from_integer(2, type);
31+
const exprt val3 = from_integer(3, type);
32+
const exprt val4 = from_integer(4, type);
33+
const exprt val5 = from_integer(5, type);
34+
const exprt val6 = from_integer(6, type);
35+
const exprt val7 = from_integer(7, type);
36+
const exprt val8 = from_integer(8, type);
37+
const exprt val9 = from_integer(9, type);
38+
const exprt val10 = from_integer(10, type);
39+
const exprt val11 = from_integer(11, type);
40+
const exprt val12 = from_integer(12, type);
41+
const exprt interval_5_10 = constant_interval_exprt(val5, val10);
42+
const exprt interval_1_10 = constant_interval_exprt(val1, val10);
43+
44+
auto config = vsd_configt::constant_domain();
45+
config.context_tracking.data_dependency_context = false;
46+
config.context_tracking.last_write_context = false;
47+
auto object_factory =
48+
variable_sensitivity_object_factoryt::configured_with(config);
49+
auto environment = abstract_environmentt{object_factory};
50+
environment.make_top();
51+
auto symbol_table = symbol_tablet{};
52+
auto ns = namespacet{symbol_table};
53+
54+
GIVEN("compact values into existing interval")
55+
{
56+
WHEN("compacting { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, [5, 10]")
57+
{
58+
auto value_set = make_value_set(
59+
{val1,
60+
val2,
61+
val3,
62+
val4,
63+
val5,
64+
val6,
65+
val7,
66+
val8,
67+
val9,
68+
val10,
69+
interval_5_10},
70+
environment,
71+
ns);
72+
THEN("{ 1, 2, 3, 4, [5, 10] }")
73+
{
74+
EXPECT(value_set, {val1, val2, val3, val4, interval_5_10});
75+
}
76+
}
77+
WHEN("compacting { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, [1, 10]")
78+
{
79+
auto value_set = make_value_set(
80+
{val1,
81+
val2,
82+
val3,
83+
val4,
84+
val5,
85+
val6,
86+
val7,
87+
val8,
88+
val9,
89+
val10,
90+
interval_1_10},
91+
environment,
92+
ns);
93+
THEN("{ [1, 10] }")
94+
{
95+
EXPECT(value_set, {interval_1_10});
96+
}
97+
}
98+
WHEN("compacting { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, [5, 10]")
99+
{
100+
auto value_set = make_value_set(
101+
{val1,
102+
val2,
103+
val3,
104+
val4,
105+
val5,
106+
val6,
107+
val7,
108+
val8,
109+
val9,
110+
val10,
111+
val11,
112+
val12,
113+
interval_5_10},
114+
environment,
115+
ns);
116+
THEN("{ 1, 2, 3, 4, 11, 12, [5, 10] }")
117+
{
118+
EXPECT(
119+
value_set, {val1, val2, val3, val4, val11, val12, interval_5_10});
120+
}
121+
}
122+
WHEN("compacting { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, [1, 10], [5, 10]")
123+
{
124+
auto value_set = make_value_set(
125+
{val1,
126+
val2,
127+
val3,
128+
val4,
129+
val5,
130+
val6,
131+
val7,
132+
val8,
133+
val9,
134+
val10,
135+
interval_1_10,
136+
interval_5_10},
137+
environment,
138+
ns);
139+
THEN("{ [1, 10] }")
140+
{
141+
EXPECT(value_set, {interval_1_10});
142+
}
143+
}
144+
WHEN("compacting { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, [5, 10], [1, 10]")
145+
{
146+
auto value_set = make_value_set(
147+
{val1,
148+
val2,
149+
val3,
150+
val4,
151+
val5,
152+
val6,
153+
val7,
154+
val8,
155+
val9,
156+
val10,
157+
val11,
158+
val12,
159+
interval_5_10,
160+
interval_1_10},
161+
environment,
162+
ns);
163+
THEN("{ 11, 12, [1, 10] }")
164+
{
165+
EXPECT(value_set, {val11, val12, interval_1_10});
166+
}
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)