-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8489 from qinheping/better_loop_locals_detect
[CONTRACTS] Detect loop locals with goto_rw in DFCC
- Loading branch information
Showing
9 changed files
with
175 additions
and
50 deletions.
There are no files selected for viewing
9 changes: 6 additions & 3 deletions
9
regression/contracts-dfcc/dont_skip_cprover_prefixed_vars_fail/main.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 6 additions & 3 deletions
9
regression/contracts-dfcc/dont_skip_cprover_prefixed_vars_pass/main.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ Author: Remi Delmas, [email protected] | |
#include <util/pointer_expr.h> | ||
#include <util/std_code.h> | ||
|
||
#include <analyses/goto_rw.h> | ||
#include <goto-instrument/contracts/utils.h> | ||
#include <goto-instrument/havoc_utils.h> | ||
|
||
|
@@ -46,23 +47,127 @@ depends_on(const exprt &expr, std::unordered_set<irep_idt> identifiers) | |
return false; | ||
} | ||
|
||
/// Collect identifiers that are local to this loop. | ||
/// A identifier is or is equivalent to a loop local if | ||
/// 1. it is declared inside the loop, or | ||
/// 2. there is no write or read of it outside the loop. | ||
/// 3. it is not used in loop contracts. | ||
std::unordered_set<irep_idt> gen_loop_locals_set( | ||
const irep_idt &function_id, | ||
goto_functiont &goto_function, | ||
const dfcc_loop_nesting_graph_nodet &loop_node, | ||
message_handlert &message_handler, | ||
const namespacet &ns) | ||
{ | ||
std::unordered_set<irep_idt> loop_locals; | ||
std::unordered_set<irep_idt> non_loop_locals; | ||
|
||
const auto &loop = loop_node.instructions; | ||
|
||
// All identifiers declared outside the loop. | ||
std::unordered_set<irep_idt> non_loop_decls; | ||
// Ranges of all read/write outside the loop. | ||
rw_range_sett non_loop_rw_range_set(ns, message_handler); | ||
|
||
Forall_goto_program_instructions(i_it, goto_function.body) | ||
{ | ||
// All variables declared in loops are loop locals. | ||
if(i_it->is_decl() && loop.contains(i_it)) | ||
{ | ||
loop_locals.insert(i_it->decl_symbol().get_identifier()); | ||
} | ||
// Record all other declared variables and their ranges. | ||
else if(i_it->is_decl()) | ||
{ | ||
non_loop_decls.insert(i_it->decl_symbol().get_identifier()); | ||
} | ||
// Record all writing/reading outside the loop. | ||
else if( | ||
(i_it->is_assign() || i_it->is_function_call()) && !loop.contains(i_it)) | ||
{ | ||
goto_rw(function_id, i_it, non_loop_rw_range_set); | ||
} | ||
} | ||
|
||
// Check if declared variables are loop locals. | ||
for(const auto &decl_id : non_loop_decls) | ||
{ | ||
bool is_loop_local = true; | ||
// No write to the declared variable. | ||
for(const auto &writing_rw : non_loop_rw_range_set.get_w_set()) | ||
{ | ||
if(decl_id == writing_rw.first) | ||
{ | ||
is_loop_local = false; | ||
break; | ||
} | ||
} | ||
|
||
// No read to the declared variable. | ||
for(const auto &writing_rw : non_loop_rw_range_set.get_r_set()) | ||
{ | ||
if(decl_id == writing_rw.first) | ||
{ | ||
is_loop_local = false; | ||
break; | ||
} | ||
} | ||
|
||
const auto latch_target = loop_node.latch; | ||
|
||
// Loop locals are not used in loop contracts. | ||
for(const auto &id : | ||
find_symbol_identifiers(get_loop_assigns(latch_target))) | ||
{ | ||
if(decl_id == id) | ||
{ | ||
is_loop_local = false; | ||
break; | ||
} | ||
} | ||
|
||
for(const auto &id : | ||
find_symbol_identifiers(get_loop_invariants(latch_target, false))) | ||
{ | ||
if(decl_id == id) | ||
{ | ||
is_loop_local = false; | ||
break; | ||
} | ||
} | ||
|
||
for(const auto &id : | ||
find_symbol_identifiers(get_loop_decreases(latch_target, false))) | ||
{ | ||
if(decl_id == id) | ||
{ | ||
is_loop_local = false; | ||
break; | ||
} | ||
} | ||
|
||
// Collect all loop locals. | ||
if(is_loop_local) | ||
loop_locals.insert(decl_id); | ||
} | ||
|
||
return loop_locals; | ||
} | ||
|
||
assignst dfcc_infer_loop_assigns( | ||
const local_may_aliast &local_may_alias, | ||
const loopt &loop_instructions, | ||
const source_locationt &loop_head_location, | ||
goto_functiont &goto_function, | ||
const dfcc_loop_nesting_graph_nodet &loop, | ||
message_handlert &message_handler, | ||
const namespacet &ns) | ||
{ | ||
// infer | ||
assignst assigns; | ||
infer_loop_assigns(local_may_alias, loop_instructions, assigns); | ||
infer_loop_assigns(local_may_alias, loop.instructions, assigns); | ||
|
||
// compute locals | ||
std::unordered_set<irep_idt> loop_locals; | ||
for(const auto &target : loop_instructions) | ||
{ | ||
if(target->is_decl()) | ||
loop_locals.insert(target->decl_symbol().get_identifier()); | ||
} | ||
std::unordered_set<irep_idt> loop_locals = | ||
gen_loop_locals_set(irep_idt(), goto_function, loop, message_handler, ns); | ||
|
||
// widen or drop targets that depend on loop-locals or are non-constant, | ||
// ie. depend on other locations assigned by the loop. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,16 +14,29 @@ Author: Remi Delmas, [email protected] | |
|
||
#include <analyses/local_may_alias.h> | ||
#include <goto-instrument/loop_utils.h> | ||
|
||
#include "dfcc_loop_nesting_graph.h" | ||
|
||
class source_locationt; | ||
class messaget; | ||
class namespacet; | ||
class message_handlert; | ||
|
||
// \brief Infer assigns clause targets for a loop from its instructions and a | ||
// may alias analysis at the function level. | ||
assignst dfcc_infer_loop_assigns( | ||
const local_may_aliast &local_may_alias, | ||
const loopt &loop_instructions, | ||
const source_locationt &loop_head_location, | ||
goto_functiont &goto_function, | ||
const dfcc_loop_nesting_graph_nodet &loop_instructions, | ||
message_handlert &message_handler, | ||
const namespacet &ns); | ||
|
||
/// Collect identifiers that are local to `loop`. | ||
std::unordered_set<irep_idt> gen_loop_locals_set( | ||
const irep_idt &function_id, | ||
goto_functiont &goto_function, | ||
const dfcc_loop_nesting_graph_nodet &loop, | ||
message_handlert &message_handler, | ||
const namespacet &ns); | ||
|
||
#endif |