Skip to content

Commit 8d6a842

Browse files
hannes-steffenhagen-diffbluemartin
authored and
martin
committed
Allows simplification of expressions containing non-const
Previously, abstract_objectt::expression_transform returned top whenever one of the subexpressions of an operator was non-const, which didn't allow simplification in situations like int x = 0; int y = nondet_int(); int z = x * y; The old behavior would've replaced x * y with 0 * y, with this change it will correctly simplify it to 0 instead.
1 parent 19e51b0 commit 8d6a842

File tree

5 files changed

+63
-6
lines changed

5 files changed

+63
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
int nondet_int(void);
2+
3+
int main(void)
4+
{
5+
int r = nondet_int();
6+
r = r + 1;
7+
if(r == 2) {
8+
return 1;
9+
}
10+
return 0;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--variable
4+
r == 2
5+
^SIGNAL=0$
6+
^EXIT=6$
7+
--
8+
--
9+
10+
Checks for a bug that occurred while changing the simplifier,
11+
where a variable would be replaced by the RHS of its last assignment,
12+
even if the value of that expression had changed since then;
13+
Most egregiously when the RHS contained the symbol on the LHS (thus leading
14+
to a recursive definition).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int nondet_int(void);
2+
3+
int main(void)
4+
{
5+
int K = nondet_int();
6+
int x = 0;
7+
return K * x;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
"--variable"
4+
^SIGNAL=0$
5+
^EXIT=6$
6+
main#return_value = 0;
7+
--
8+
--
9+
Tests that a multiplication
10+
of variable*variable can be simplified
11+
if one of the variables can be evaluated to 0.

src/analyses/variable-sensitivity/abstract_object.cpp

+19-6
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,18 @@ abstract_object_pointert abstract_objectt::expression_transform(
184184
{
185185
exprt constant_replaced_expr=expr;
186186
constant_replaced_expr.operands().clear();
187+
188+
// Two passes over the expression - one for simplification,
189+
// another to check if there are any top subexpressions left
187190
for(const exprt &op : expr.operands())
188191
{
189192
abstract_object_pointert lhs_abstract_object=environment.eval(op, ns);
190193
const exprt &lhs_value=lhs_abstract_object->to_constant();
191-
192194
if(lhs_value.is_nil())
193195
{
194-
// One of the values is not resolvable to a constant
195-
// so we can't really do anything more with
196-
// this expression and should just return top for the result
197-
return environment.abstract_object_factory(expr.type(), ns, true, false);
196+
// do not give up if a sub-expression is not a constant,
197+
// because the whole expression may still be simplified in some cases
198+
constant_replaced_expr.operands().push_back(op);
198199
}
199200
else
200201
{
@@ -204,7 +205,19 @@ abstract_object_pointert abstract_objectt::expression_transform(
204205
}
205206
}
206207

207-
exprt simplified=simplify_expr(constant_replaced_expr, ns);
208+
exprt simplified = simplify_expr(constant_replaced_expr, ns);
209+
210+
for(const exprt &op : simplified.operands())
211+
{
212+
abstract_object_pointert lhs_abstract_object = environment.eval(op, ns);
213+
const exprt &lhs_value = lhs_abstract_object->to_constant();
214+
if(lhs_value.is_nil())
215+
{
216+
return environment.abstract_object_factory(
217+
simplified.type(), ns, true, false);
218+
}
219+
}
220+
208221
return environment.abstract_object_factory(simplified.type(), simplified, ns);
209222
}
210223

0 commit comments

Comments
 (0)