-
Notifications
You must be signed in to change notification settings - Fork 273
Allow simplification of singleton interval. #7761
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
Allow simplification of singleton interval. #7761
Conversation
a00ea8e
to
eeff129
Compare
While the simplification is nice to have we must not rely on it in our back-ends. So we also need a back-end fix here plus a test that uses —no-simplify. |
54e46cd
to
7714d51
Compare
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## develop #7761 +/- ##
===========================================
+ Coverage 78.06% 78.57% +0.51%
===========================================
Files 1693 1693
Lines 193308 193346 +38
===========================================
+ Hits 150899 151928 +1029
+ Misses 42409 41418 -991
☔ View full report in Codecov by Sentry. |
7714d51
to
c9cb4c1
Compare
@tautschnig Hi Michael, agree that this is a workaround for the issue, but also believe that the simplification has value itself. I believe that this should go in on the basis that it sidesteps an important bug #7690, and I have also noted that we may need to do a deeper dive to fix the underlying issue at the root level, but it's also worth noting that this issue was only observed on the old SMT backend (the new SMT backend and the SAT backend both worked before). Given that the issue is not observable on the new SMT backend however, and that it's scheduled to (eventually?) take over, it might not be worth to have deeper dive unless the issue comes up again. |
c9cb4c1
to
d8b98b6
Compare
102f758
to
1cc4a4b
Compare
|
||
void *smap_get(smap_t *smap, void *ptr) { | ||
size_t id = __CPROVER_POINTER_OBJECT(ptr); | ||
void *sptr = smap->ptrs[id]; |
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.
I think this test will pass on the VS2019 job if you change this line to char *sptr = smap->ptrs[id];
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.
Yeah that seems to work.
8b29c93
to
614eaef
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.
causing some misbehaviour
What precisely does "misbehaviour" mean here?
If it returns incorrect results then I agree with @tautschnig that we need to fix our code so that we get correct results even with --no-simplify.
If it results just in a performance issue of the SMT backend then I'm fine with this PR as is.
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.
Few simplification can be done
src/util/simplify_expr_boolean.cpp
Outdated
}; | ||
|
||
// We need to match both operands, at the particular sequence we expect. | ||
structure_matched |= match_first_operand(new_operands[0]); |
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 variable structure_matched
is set roughly 50 lines above and never used, so I suggest defining it here and assigning to match_first_operand(new_operands[0])
.
bool structure_matched = match_first_operand(new_operands[0]);
Or even better
bool structure_matched = match_first_operand(new_operands[0]) && match_second_operand(new_operands[1])
.
This will also be faster as the &&
will short-circuit if the former condition is false.
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.
Done.
src/util/simplify_expr_boolean.cpp
Outdated
for(const auto &op : new_operands) | ||
{ | ||
if( | ||
const auto ge_expr = | ||
expr_try_dynamic_cast<greater_than_or_equal_exprt>(op)) |
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 loop and check are redundant.
We already know that new_operands.size() == 2
( line 148) and that they are both greater_than_or_equal_exprt
(lines 170 and 191), so I suggest to check only structure_matched && bounds.lower == bounds.higher
and return new_expr{ge_expr->lhs(), ge_expr->rhs()}
.
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.
Yeah, you're right, I've changed to just handle take the info from new_operands[0]
without any further processing.
// If we are here, we came across a (simplified?) expression that was | ||
// not anticipated - normally this would be a bug, but if you made | ||
// changes to the simplifier (as an example), you would need to add an | ||
// else-if branch that handles that type above. |
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.
Isn't this shouting INVARIANT
loud?
No, then the comment should be changed to specify that if we are here we may have a non-simplified expression
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.
Clarified the comment.
@@ -8,7 +8,7 @@ int main(int argc, char **argv) | |||
|
|||
__CPROVER_assert( | |||
__CPROVER_exists { int z; (0 < z && z < 2) && | |||
__CPROVER_forall { int o; (10 < o && o < 20) ==> o > z && z == * i }}, |
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 commit message looks split between title and body...
Misbehaviour in this context is an assertion failing when it wouldn't fail for the SAT or the new SMT backend. I played around with the code and there does remain an issue with the old SMT2 backend and this particular assertion if the interval is not the singleton interval (as in, the interval is wider than 1 element), so there will probably need to be a fix for that issue, but outside of that, this PR allows for improving performance, at least in the context of the SAT backend, with the following numbers coming out of the runs on the
|
Is this a general bug in the old SMT backend that non-constant dynamic object sizes lead to incorrect results? |
The old SMT2 backend does just skip defining the cbmc/src/solvers/smt2/smt2_conv.cpp Lines 301 to 314 in ce831a0
It does this because the size term is solely implemented as a bit vector constant. The new back end just converts the size expression into an SMT term. As such, it works for more complex expressions - cbmc/src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp Lines 590 to 591 in ce831a0
For the example given in #7690 the new SMT back end produces the same verification results as the SAT backend. As in the issue is not reproducible. So this difference between the new and old SMT backends could be the source of the bug. |
If I understand correctly this means that the old SMT backend is simply broken (and probably has always been) and the simplification hides the bug in some specific cases. |
Before this change, an expression like `value >= 255 && value <= 255` would fail to be simplified to `value == 255` by the expression simplifier. While the simplification itself is useful, the *lack* of it was causing some misbehaviour in one of our backends (the old SMT one under `src/solvers/smt2`) because the lack of simplification resulted in less constraints being propagated to the solver, missing some assertions around the expression that was using `value` as the size of an array.
…on of singleton interval
ea48112
to
de8b169
Compare
@NlightNFotis I ran more tests with this fix and did not observe negative effects, approving |
Cheers @remi-delmas-3000 , thanks for having a look. |
Before this change, an expression like
value >= 255 && value <= 255
would fail to be simplified tovalue == 255
by the expression simplifier.While the simplification itself is useful, the lack of it was causing some misbehaviour in one of our backends (the old SMT one undersrc/solvers/smt2
) because the lack of simplification resulted in less constraints being propagated to the solver, missing some assertions around the expression that was usingvalue
as the size of an array.This was originally presented as a fix for #7690 , but #7768 is a more robust fix for that, so I'm changing the presentation of this as improvement to the expression simplifier instead of a workaround for an issue with the old SMT backend.