-
Notifications
You must be signed in to change notification settings - Fork 273
Use BDDs for encoding symex guards #3730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use BDDs for encoding symex guards #3730
Conversation
Before reviewing this in any way: I believe I had mentioned #310. Does this PR relate to it in any way? |
Yes, the idea is similar, but this is taking it one step further: instead of keeping guards as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given this is marked "In progress" I'm sure this is the plan, but just to be explicit: please turn this into a series of PRs, there are a lot of seemingly unrelated changes.
src/analyses/goto_check.cpp
Outdated
@@ -1342,8 +1342,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address) | |||
guard.add(op); | |||
} | |||
|
|||
guard.swap(old_guard); | |||
|
|||
guard = std::move(old_guard); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost randomly poking at commits: what's the improvement here? (I actually have a yet-to-be-PR'ed commit lying around making the opposite change, i.e., replacing uses of std::move
by swap
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new implementation of guardt doesn't have a swap
(though exprt has). And since old_guard
is not used afterward, I don't see a reason for using swap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For irept
-based implementations = std::move(...)
is at best as efficient as swap
, and possibly less efficient if USE_MOVE
is not enabled. (But I do concede that we should just get rid of USE_MOVE
as an optional feature as we require C++11 anyway.) So in that setting the change doesn't seem to provide any added value.
With the new implementation of guardt
not being an irept
, the situation of course is different. But that needs to be spelled out in the commit message...
Ok, but do note that in terms of history this is a step backwards: |
src/analyses/goto_rw.cpp
Outdated
|
||
guard.add(not_exprt(if_expr.cond())); | ||
copy.add(not_exprt(if_expr.cond())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be guard.add
There is a lot of great cleanup in this PR that should be merged as soon as possible, but via individual PRs (really one per commit). Then this PR can be reduced to the necessary minimum and also the effect of BDDs (and not that of the cleanup) can be measured. |
0b6eca3
to
a8ba19d
Compare
9ca95cd
to
88ff3a4
Compare
398bd01
to
468c01d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR failed Diffblue compatibility checks (cbmc commit: 468c01d).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103158445
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
This test is deactivated for the build with BDDs because it takes more | ||
than 10 minutes for the test to complete. | ||
This is due to the size of the BDD representing the guards growing more than | ||
they do when reprented as exprt. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: s/reprented/represented/
than 10 minutes for the test to complete. | ||
This is due to the size of the BDD representing the guards growing more than | ||
they do when reprented as exprt. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick 2: No need for blank line
468c01d
to
ddf0491
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR failed Diffblue compatibility checks (cbmc commit: ddf0491).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103176652
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
No functional changes. This was done automatically using clang-format. This is in preparation to moving this two files, so that clang-format doesn't reformat the file at the same time they are moved, and so that the move commit is clean.
We want to add an implementation of guard that uses BDDs, which are part of the solvers module. We cannot add a dependency of the util module on solvers.
The guard used there was actually only used as a conjunction, so it can be replaced by a list of expressions, of which we take the conjunction when needed.
This in preparation to using BDDs to encode guards, every part of the code creating guards need to reference a guard_manager.
A reference to a namespace was stored without being ever used.
Instead the result of from_exprt and the input of as_expr should be BDDs. This makes it possible to reuse the same manager for several exprt conversion and to combine the results obtain from the from_expr conversion with BDD operations.
The type of identifier can vary depending on the BDD implementation used. Using long there was kind of a hack and not correct on architecture where pointers wouldn't fit in a long.
Caching the intermediary results can lead to big performance improvements since the number of calls without cache could be potentially exponential in the size of the BDD.
This is not used yet in CBMC. The aim is to specify at compile time whether we want to use this new implementation or the old one. Using BDDs ensures the guards are always in some "simple" form.
This is to clearly seperate the two implementations. The choice between the two will be made in guard.h
To avoid confusion with the other guard implementation. This forces us to use includes instead of forward declaration for guardt because forward declaration doesn't work well with typedef.
Depending on the BDD_GUARDS flag, we will use the expr implementation or the BDD implementation.
This adds instruction to COMPILING.md so that people interested in performances can find about it, and try it.
Expressions obtained from BDDs are already simple. Trying to simplify them is redundant and can slow down the execution. We add this field so that symex code can take the decision to simplify or not an expression based on this information.
We add the BDD_GUARDS flags in the travis step which is compiling with CUDD to test that the bdd_guard implementation.
One of the JBMC tests will take a long time when BDD are used. We deactivate it for now in the case BDD_GUARDS is defined. This is acceptable since using BDDs for guards is still experimental. Ideally we should find what takes too long in the execution and optimize it, but it may be that we hit a particular class of guards for which the BDDs have to be big.
This avoids having an argument that is both input and output and makes using this function nicer.
No functional change
ddf0491
to
22ed54b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR failed Diffblue compatibility checks (cbmc commit: 22ed54b).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103523152
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
The main commit is "Use BDDs for encoding guards in symex". Commits that are before are in preparation for this one (in particular getting rid of usage of functions the new version will not implement). Commits that follow are clean-up in the code that use the guard (in particular getting rid of simplifications that are now unnecessary).
I still wan't to run this on more benchmarks before it is merged. For what I've seen so far, this is about 10% faster than the current symex, but this is not uniform across benchmarks (it doesn't help for "simple" instances, i.e. which take less than 2s).