Skip to content

Commit b47bb51

Browse files
committed
Contracts/DFCC: split conjunctions in loop invariants
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.
1 parent 5002f3b commit b47bb51

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

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

+30-6
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,21 @@ dfcc_instrument_loopt::add_step_instructions(
426426
dfcc_utilst::get_function_symbol(symbol_table, function_id).mode;
427427
{
428428
// Assume the loop invariant after havocing the state.
429-
code_assumet assumption{invariant};
430-
assumption.add_source_location() = loop_head_location;
431-
converter.goto_convert(assumption, step_instrs, language_mode);
429+
if(invariant.id() == ID_and)
430+
{
431+
for(const auto &op : invariant.operands())
432+
{
433+
code_assumet assumption{op};
434+
assumption.add_source_location() = loop_head_location;
435+
converter.goto_convert(assumption, step_instrs, language_mode);
436+
}
437+
}
438+
else
439+
{
440+
code_assumet assumption{invariant};
441+
assumption.add_source_location() = loop_head_location;
442+
converter.goto_convert(assumption, step_instrs, language_mode);
443+
}
432444
}
433445

434446
{
@@ -507,9 +519,21 @@ void dfcc_instrument_loopt::add_body_instructions(
507519
id2string(check_location.get_function()) + "." +
508520
std::to_string(cbmc_loop_id));
509521
// Assume the loop invariant after havocing the state.
510-
code_assertt assertion{invariant};
511-
assertion.add_source_location() = check_location;
512-
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
522+
if(invariant.id() == ID_and)
523+
{
524+
for(const auto &op : invariant.operands())
525+
{
526+
code_assertt assertion{op};
527+
assertion.add_source_location() = check_location;
528+
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
529+
}
530+
}
531+
else
532+
{
533+
code_assertt assertion{invariant};
534+
assertion.add_source_location() = check_location;
535+
converter.goto_convert(assertion, pre_loop_latch_instrs, language_mode);
536+
}
513537
}
514538

515539
{

0 commit comments

Comments
 (0)