Skip to content

Commit f7f693e

Browse files
committed
Don't use let-bound temporaries for simple pointers
For example, we're willing to directly quote `p`, `(type *)p`, `p[some_constant]` and other simple expressions directly when comparing a pointer against its possible aliases-- the case we really must prevent is a large if-expression like `q == &o1 ? o1 : q == &o2 ? o2 : ...` that can result from a nested dereference -- in this case we must use a let-bound temporary to avoid producing a very large expression that can founder subsequent algorithms such as simplification, renaming and irep-merging.
1 parent 61cf267 commit f7f693e

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Author: Daniel Kroening, [email protected]
2222
#include <util/c_types.h>
2323
#include <util/config.h>
2424
#include <util/cprover_prefix.h>
25+
#include <util/expr_iterator.h>
2526
#include <util/format_type.h>
2627
#include <util/fresh_symbol.h>
2728
#include <util/options.h>
@@ -30,6 +31,30 @@ Author: Daniel Kroening, [email protected]
3031
#include <util/simplify_expr.h>
3132
#include <util/ssa_expr.h>
3233

34+
/// Returns true if \p expr is complicated enough that a local definition (using
35+
/// a let expression) is preferable to repeating it, potentially many times.
36+
/// Of course this is just a heuristic -- currently we allow any expression that
37+
/// only involves one symbol, such as "x", "(type*)x", "x[0]" (but not "x[y]").
38+
/// Particularly we want to make sure to insist on a local definition of \p expr
39+
/// is a large if-expression, such as `p == &o1 ? o1 : p == &o2 ? o2 : ...`, as
40+
/// can result from dereferencing a subexpression.
41+
static bool should_use_local_definition_for(const exprt &expr)
42+
{
43+
bool seen_symbol = false;
44+
for(auto it = expr.depth_begin(), itend = expr.depth_end(); it != itend; ++it)
45+
{
46+
if(it->id() == ID_symbol)
47+
{
48+
if(seen_symbol)
49+
return true;
50+
else
51+
seen_symbol = true;
52+
}
53+
}
54+
55+
return false;
56+
}
57+
3358
exprt value_set_dereferencet::dereference(const exprt &pointer)
3459
{
3560
if(pointer.type().id()!=ID_pointer)
@@ -78,7 +103,7 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
78103

79104
exprt compare_against_pointer = pointer;
80105

81-
if(pointer.id() != ID_symbol && retained_values.size() >= 2)
106+
if(retained_values.size() >= 2 && should_use_local_definition_for(pointer))
82107
{
83108
symbolt fresh_binder = get_fresh_aux_symbol(
84109
pointer.type(),

0 commit comments

Comments
 (0)