Skip to content

Commit 0b58dc5

Browse files
Merge pull request diffblue#3730 from romainbrenguier/experiment/bdd-guards4
Use BDDs for encoding symex guards
2 parents 35a0ac3 + 22ed54b commit 0b58dc5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+747
-324
lines changed

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ jobs:
201201
- cmake --build build -- -j4
202202
script: (cd build; bin/unit "[core][irept]")
203203

204-
# cmake build using g++-7, enable CMAKE_USE_CUDD
204+
# cmake build using g++-7, enable CMAKE_USE_CUDD and BDD_GUARDS
205205
- stage: Test different OS/CXX/Flags
206206
os: linux
207207
sudo: false
@@ -223,7 +223,7 @@ jobs:
223223
install:
224224
- ccache -z
225225
- ccache --max-size=1G
226-
- cmake -H. -Bbuild '-DCMAKE_BUILD_TYPE=Release' '-DCMAKE_CXX_COMPILER=/usr/bin/g++-7' '-DCMAKE_USE_CUDD=true'
226+
- cmake -H. -Bbuild '-DCMAKE_BUILD_TYPE=Release' '-DCMAKE_CXX_COMPILER=/usr/bin/g++-7' '-DCMAKE_USE_CUDD=true' -DCMAKE_CXX_FLAGS="-DBDD_GUARDS"
227227
- git submodule update --init --recursive
228228
- cmake --build build -- -j4
229229
script: (cd build; ctest -V -L CORE -j2)

COMPILING.md

+19
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,22 @@ If compiling with cmake:
310310
```
311311
cmake --build build
312312
```
313+
314+
## Use BDDs for guards
315+
316+
There are two implementation for symex guards. The default one uses the
317+
internal representation of expression. The other one uses BDDs and
318+
though experimental, it is expected to have better performance,
319+
in particular when used in conjunction with CUDD.
320+
321+
To use the BDD implementation of guards, add the `BDD_GUARDS`
322+
compilation flag:
323+
* If compiling with make:
324+
```
325+
make -C src CXXFLAGS="-O2 -DBDD_GUARDS"
326+
```
327+
* If compiling with CMake:
328+
```
329+
cmake -H. -Bbuild -DCMAKE_CXX_FLAGS="-DBDD_GUARDS"
330+
```
331+
and then `cmake --build build`

jbmc/regression/jbmc/CMakeLists.txt

+15-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@ add_test_pl_tests(
22
"$<TARGET_FILE:jbmc> --validate-goto-model --validate-ssa-equation"
33
)
44

5-
add_test_pl_profile(
6-
"jbmc-symex-driven-lazy-loading"
7-
"$<TARGET_FILE:jbmc> --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading"
8-
"-C;-X;symex-driven-lazy-loading-expected-failure;-s;symex-driven-loading"
9-
"CORE"
10-
)
5+
if(DEFINED BDD_GUARDS)
6+
add_test_pl_profile(
7+
"jbmc-symex-driven-lazy-loading"
8+
"$<TARGET_FILE:jbmc> --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading"
9+
"-C;-X;symex-driven-lazy-loading-expected-failure;-s;symex-driven-loading"
10+
"CORE"
11+
)
12+
else()
13+
add_test_pl_profile(
14+
"jbmc-symex-driven-lazy-loading"
15+
"$<TARGET_FILE:jbmc> --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading"
16+
"-C;-X;symex-driven-lazy-loading-expected-failure;-X;bdd-expected-timeout;-s;symex-driven-loading"
17+
"CORE"
18+
)
19+
endif()

jbmc/regression/jbmc/Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ include ../../src/config.inc
44

55
test:
66
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation"
7+
ifeq ($(filter %DBDD_GUARDS, $(CXXFLAGS)),)
78
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -s symex-driven-loading
9+
else
10+
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -X bdd-expected-timeout -s symex-driven-loading
11+
endif
812

913
tests.log: ../$(CPROVER_DIR)/regression/test.pl
1014
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation"
15+
ifeq ($(filter %DBDD_GUARDS, $(CXXFLAGS)),)
1116
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -s symex-driven-loading
17+
else
18+
@../$(CPROVER_DIR)/regression/test.pl -e -p -c "../../../src/jbmc/jbmc --validate-goto-model --validate-ssa-equation --symex-driven-lazy-loading" -X symex-driven-lazy-loading-expected-failure -X bdd-expected-timeout -s symex-driven-loading
19+
endif
1220

1321
show:
1422
@for dir in *; do \
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
CORE
1+
CORE bdd-expected-timeout
22
Test.class
33
--function Test.main
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
88
^warning: ignoring
9+
--
10+
This test is deactivated for the build with BDDs because it takes more
11+
than 10 minutes for the test to complete.
12+
This is due to the size of the BDD representing the guards growing more than
13+
they do when represented as exprt.

src/analyses/CMakeLists.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ add_library(analyses ${sources})
33

44
generic_includes(analyses)
55

6-
target_link_libraries(analyses util pointer-analysis)
6+
if(CMAKE_USE_CUDD)
7+
target_include_directories(analyses PUBLIC ${CUDD_INCLUDE}/cudd/)
8+
endif()
9+
10+
target_link_libraries(analyses util pointer-analysis solvers)

src/analyses/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ SRC = ai.cpp \
1212
global_may_alias.cpp \
1313
goto_check.cpp \
1414
goto_rw.cpp \
15+
guard_bdd.cpp \
16+
guard_expr.cpp \
1517
interval_analysis.cpp \
1618
interval_domain.cpp \
1719
invariant_propagation.cpp \

src/analyses/goto_check.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ Author: Daniel Kroening, [email protected]
2020
#include <util/cprover_prefix.h>
2121
#include <util/expr_util.h>
2222
#include <util/find_symbols.h>
23-
#include <util/guard.h>
2423
#include <util/ieee_float.h>
2524
#include <util/invariant.h>
2625
#include <util/make_unique.h>
@@ -36,6 +35,7 @@ Author: Daniel Kroening, [email protected]
3635

3736
#include <goto-programs/remove_skip.h>
3837

38+
#include "guard.h"
3939
#include "local_bitvector_analysis.h"
4040

4141
class goto_checkt
@@ -84,6 +84,7 @@ class goto_checkt
8484
const namespacet &ns;
8585
std::unique_ptr<local_bitvector_analysist> local_bitvector_analysis;
8686
goto_programt::const_targett current_target;
87+
guard_managert guard_manager;
8788

8889
void check_rec(
8990
const exprt &expr,
@@ -1650,7 +1651,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
16501651

16511652
void goto_checkt::check(const exprt &expr)
16521653
{
1653-
guardt guard{true_exprt{}};
1654+
guardt guard{true_exprt{}, guard_manager};
16541655
check_rec(expr, guard, false);
16551656
}
16561657

@@ -1782,7 +1783,7 @@ void goto_checkt::goto_check(
17821783
"pointer dereference",
17831784
i.source_location,
17841785
pointer,
1785-
guardt(true_exprt()));
1786+
guardt(true_exprt(), guard_manager));
17861787
}
17871788
}
17881789

@@ -1820,7 +1821,7 @@ void goto_checkt::goto_check(
18201821
"pointer dereference",
18211822
i.source_location,
18221823
pointer,
1823-
guardt(true_exprt()));
1824+
guardt(true_exprt(), guard_manager));
18241825
}
18251826

18261827
// this has no successor
@@ -1897,7 +1898,7 @@ void goto_checkt::goto_check(
18971898
"memory-leak",
18981899
source_location,
18991900
eq,
1900-
guardt(true_exprt()));
1901+
guardt(true_exprt(), guard_manager));
19011902
}
19021903
}
19031904

src/analyses/goto_rw.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Date: April 2010
1717
#include <map>
1818
#include <memory> // unique_ptr
1919

20-
#include <util/guard.h>
20+
#include "guard.h"
2121

2222
#include <goto-programs/goto_model.h>
2323

@@ -352,8 +352,11 @@ class rw_guarded_range_set_value_sett:public rw_range_set_value_sett
352352
public:
353353
rw_guarded_range_set_value_sett(
354354
const namespacet &_ns,
355-
value_setst &_value_sets):
356-
rw_range_set_value_sett(_ns, _value_sets)
355+
value_setst &_value_sets,
356+
guard_managert &guard_manager)
357+
: rw_range_set_value_sett(_ns, _value_sets),
358+
guard_manager(guard_manager),
359+
guard(true_exprt(), guard_manager)
357360
{
358361
}
359362

@@ -370,7 +373,7 @@ class rw_guarded_range_set_value_sett:public rw_range_set_value_sett
370373
get_modet mode,
371374
const exprt &expr) override
372375
{
373-
guard = guardt(true_exprt());
376+
guard = guardt(true_exprt(), guard_manager);
374377

375378
rw_range_set_value_sett::get_objects_rec(_function, _target, mode, expr);
376379
}
@@ -384,7 +387,8 @@ class rw_guarded_range_set_value_sett:public rw_range_set_value_sett
384387
}
385388

386389
protected:
387-
guardt guard = guardt(true_exprt());
390+
guard_managert &guard_manager;
391+
guardt guard;
388392

389393
using rw_range_sett::get_objects_rec;
390394

src/analyses/guard.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*******************************************************************\
2+
3+
Module: Guard Data Structure
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Guard Data Structure
11+
12+
#ifndef CPROVER_ANALYSES_GUARD_H
13+
#define CPROVER_ANALYSES_GUARD_H
14+
15+
#ifdef BDD_GUARDS
16+
17+
#include "guard_bdd.h"
18+
19+
using guard_managert = bdd_exprt;
20+
using guardt = guard_bddt;
21+
22+
#else
23+
24+
#include "guard_expr.h"
25+
26+
using guard_managert = guard_expr_managert;
27+
using guardt = guard_exprt;
28+
29+
#endif // BDD_GUARDS
30+
31+
#endif // CPROVER_ANALYSES_GUARD_H

src/analyses/guard_bdd.cpp

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*******************************************************************\
2+
3+
Module: Guard Data Structure
4+
5+
Author: Romain Brenguier, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Implementation of guards using BDDs
11+
12+
#include "guard_bdd.h"
13+
14+
#include <algorithm>
15+
#include <ostream>
16+
#include <set>
17+
18+
#include <solvers/bdd/bdd.h>
19+
#include <solvers/prop/bdd_expr.h>
20+
#include <util/expr_util.h>
21+
#include <util/invariant.h>
22+
#include <util/make_unique.h>
23+
#include <util/namespace.h>
24+
#include <util/simplify_utils.h>
25+
#include <util/std_expr.h>
26+
#include <util/symbol_table.h>
27+
28+
guard_bddt::guard_bddt(const exprt &e, bdd_exprt &manager)
29+
: manager(manager), bdd(manager.from_expr(e))
30+
{
31+
}
32+
33+
guard_bddt &guard_bddt::operator=(const guard_bddt &other)
34+
{
35+
PRECONDITION(&manager == &other.manager);
36+
bdd = other.bdd;
37+
return *this;
38+
}
39+
40+
guard_bddt &guard_bddt::operator=(guard_bddt &&other)
41+
{
42+
PRECONDITION(&manager == &other.manager);
43+
std::swap(bdd, other.bdd);
44+
return *this;
45+
}
46+
47+
exprt guard_bddt::guard_expr(exprt expr) const
48+
{
49+
if(is_true())
50+
{
51+
// do nothing
52+
return expr;
53+
}
54+
else
55+
{
56+
if(expr.is_false())
57+
{
58+
return boolean_negate(as_expr());
59+
}
60+
else
61+
{
62+
return implies_exprt{as_expr(), expr};
63+
}
64+
}
65+
}
66+
67+
guard_bddt &guard_bddt::append(const guard_bddt &guard)
68+
{
69+
bdd = bdd.bdd_and(guard.bdd);
70+
return *this;
71+
}
72+
73+
guard_bddt &guard_bddt::add(const exprt &expr)
74+
{
75+
bdd = bdd.bdd_and(manager.from_expr(expr));
76+
return *this;
77+
}
78+
79+
guard_bddt &operator-=(guard_bddt &g1, const guard_bddt &g2)
80+
{
81+
g1.bdd = g1.bdd.constrain(g2.bdd.bdd_or(g1.bdd));
82+
return g1;
83+
}
84+
85+
guard_bddt &operator|=(guard_bddt &g1, const guard_bddt &g2)
86+
{
87+
g1.bdd = g1.bdd.bdd_or(g2.bdd);
88+
return g1;
89+
}
90+
91+
exprt guard_bddt::as_expr() const
92+
{
93+
return manager.as_expr(bdd);
94+
}

0 commit comments

Comments
 (0)