Skip to content

Commit

Permalink
Contracts/DFCC: split conjunctions in loop invariants
Browse files Browse the repository at this point in the history
Emitting one assertion (and assumption) per conjunct simplifies
debugging when proving a loop invariant fails. It also appears to
improve performance when using Bitwuzla, taking one example from more
than 30 minutes down to 8 seconds. On the same example, performance
using Z3 was not substantially different.
  • Loading branch information
tautschnig committed Sep 17, 2024
1 parent f68cf8c commit eb5466d
Showing 1 changed file with 36 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,24 @@ dfcc_instrument_loopt::add_step_instructions(
const irep_idt &language_mode =
dfcc_utilst::get_function_symbol(symbol_table, function_id).mode;
{
// Assume the loop invariant after havocing the state.
code_assumet assumption{invariant};
assumption.add_source_location() = loop_head_location;
converter.goto_convert(assumption, step_instrs, language_mode);
// Assume the loop invariant after havocing the state; produce one
// assumption per conjunct to ease analysis of counterexamples, and possibly

Check warning on line 429 in src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp#L429

Added line #L429 was not covered by tests
// also improve solver performance (observed with Bitwuzla)
if(invariant.id() == ID_and)
{
for(const auto &op : invariant.operands())
{
code_assumet assumption{op};
assumption.add_source_location() = loop_head_location;
converter.goto_convert(assumption, step_instrs, language_mode);
}
}
else

Check warning on line 440 in src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp#L440

Added line #L440 was not covered by tests
{
code_assumet assumption{invariant};
assumption.add_source_location() = loop_head_location;
converter.goto_convert(assumption, step_instrs, language_mode);
}
}

{
Expand Down Expand Up @@ -506,10 +520,24 @@ void dfcc_instrument_loopt::add_body_instructions(
"Check invariant after step for loop " +
id2string(check_location.get_function()) + "." +
std::to_string(cbmc_loop_id));
// Assume the loop invariant after havocing the state.
code_assertt assertion{invariant};
assertion.add_source_location() = check_location;
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
// Assert the loop invariant after havocing the state; produce one assertion
// per conjunct to ease analysis of counterexamples, and possibly also

Check warning on line 524 in src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp#L524

Added line #L524 was not covered by tests
// improve solver performance (observed with Bitwuzla)
if(invariant.id() == ID_and)
{
for(const auto &op : invariant.operands())
{
code_assertt assertion{op};
assertion.add_source_location() = check_location;
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
}
}
else

Check warning on line 535 in src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument_loop.cpp#L535

Added line #L535 was not covered by tests
{
code_assertt assertion{invariant};
assertion.add_source_location() = check_location;
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
}
}

{
Expand Down

0 comments on commit eb5466d

Please sign in to comment.