Skip to content

Commit cf40d22

Browse files
authored
Merge pull request #1997 from tautschnig/no-sort-operands
Do not sort operands as part of simplification [blocks: #3486]
2 parents f2fafac + 375f208 commit cf40d22

File tree

17 files changed

+92
-38
lines changed

17 files changed

+92
-38
lines changed
Binary file not shown.

jbmc/regression/jbmc-strings/ConstantEvaluationTrim/Main.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ public void trimRight() {
2424
}
2525

2626
public void noprop(String str) {
27-
str = str.trim();
28-
assert str.equals("abc");
27+
if(str != null) {
28+
str = str.trim();
29+
assert str.equals("abc");
30+
}
2931
}
3032

3133
public void empty() {

jbmc/regression/jbmc-strings/ConstantEvaluationTrim/noprop.desc

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ CORE
22
Main
33
--function Main.noprop --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar`
44
^Generated [1-9]\d* VCC\(s\), [1-9]\d* remaining after simplification$
5+
line 29 assertion at file Main.java line 29 .*: FAILURE$
6+
^\*\* 1 of \d+ failed
57
^EXIT=10$
68
^SIGNAL=0$
79
^VERIFICATION FAILED$

jbmc/regression/jbmc/throwing-function-return-value/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
Test
33
--function Test.main --show-vcc
44
java::Test\.main:\(Z\)V::14::t1!0@1#\d+ = address_of\(symex_dynamic::dynamic_object\d+\)
5-
java::Test\.main:\(Z\)V::9::x!0@1#\d+ = 5 \+ java::Test\.main:\(Z\)V::9::x!0@1#\d+
5+
java::Test\.main:\(Z\)V::9::x!0@1#\d+ = java::Test\.main:\(Z\)V::9::x!0@1#\d+ \+ 5
66
java::Test\.g:\(\)I#return_value!0#[0-9]+ = 5
77
^EXIT=0$
88
^SIGNAL=0$

regression/cbmc-library/float-nan-check/test.desc

+14-13
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ main.c
66
\[main.NaN.3\] line \d+ NaN on / in \(float\)n / myinf: FAILURE
77
\[main.NaN.4\] line \d+ NaN on \* in myinf \* myzero: FAILURE
88
\[main.NaN.5\] line \d+ NaN on \+ in -myinf \+ myinf: FAILURE
9-
\[main.NaN.6\] line \d+ NaN on - in myinf - myinf: FAILURE
10-
\[main.NaN.7\] line \d+ NaN on - in -myinf - -myinf: FAILURE
11-
\[main.NaN.8\] line \d+ NaN on \+ in byte_extract_little_endian\(c, (0|0l|0ll), float\) \+ byte_extract_little_endian\(c, (0|0l|0ll), float\): SUCCESS
12-
\[main.NaN.9\] line \d+ NaN on / in byte_extract_little_endian\(c, (0|0l|0ll), float\) / myzero: SUCCESS
13-
\[main.NaN.10\] line \d+ NaN on \* in mynan \* mynan: SUCCESS
14-
\[main.NaN.11\] line \d+ NaN on \+ in mynan \+ mynan: SUCCESS
15-
\[main.NaN.12\] line \d+ NaN on - in mynan - mynan: SUCCESS
16-
\[main.NaN.13\] line \d+ NaN on / in mynan / mynan: SUCCESS
17-
\[main.NaN.14\] line \d+ NaN on \+ in mynan \+ \(float\)n: SUCCESS
18-
\[main.NaN.15\] line \d+ NaN on - in mynan - \(float\)n: SUCCESS
19-
\[main.NaN.16\] line \d+ NaN on \* in mynan \* \(float\)n: SUCCESS
20-
\[main.NaN.17\] line \d+ NaN on / in mynan / \(float\)n: SUCCESS
9+
\[main.NaN.6\] line \d+ NaN on \+ in myinf \+ -myinf: FAILURE
10+
\[main.NaN.7\] line \d+ NaN on - in myinf - myinf: FAILURE
11+
\[main.NaN.8\] line \d+ NaN on - in -myinf - -myinf: FAILURE
12+
\[main.NaN.9\] line \d+ NaN on \+ in byte_extract_little_endian\(c, (0|0l|0ll), float\) \+ byte_extract_little_endian\(c, (0|0l|0ll), float\): SUCCESS
13+
\[main.NaN.10\] line \d+ NaN on / in byte_extract_little_endian\(c, (0|0l|0ll), float\) / myzero: SUCCESS
14+
\[main.NaN.11\] line \d+ NaN on \* in mynan \* mynan: SUCCESS
15+
\[main.NaN.12\] line \d+ NaN on \+ in mynan \+ mynan: SUCCESS
16+
\[main.NaN.13\] line \d+ NaN on - in mynan - mynan: SUCCESS
17+
\[main.NaN.14\] line \d+ NaN on / in mynan / mynan: SUCCESS
18+
\[main.NaN.15\] line \d+ NaN on \+ in mynan \+ \(float\)n: SUCCESS
19+
\[main.NaN.16\] line \d+ NaN on - in mynan - \(float\)n: SUCCESS
20+
\[main.NaN.17\] line \d+ NaN on \* in mynan \* \(float\)n: SUCCESS
21+
\[main.NaN.18\] line \d+ NaN on / in mynan / \(float\)n: SUCCESS
2122
^EXIT=10$
2223
^SIGNAL=0$
2324
^VERIFICATION FAILED$
2425
--
25-
\[main.NaN.18\]
26+
\[main.NaN.19\]
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <assert.h>
2+
#include <math.h>
3+
4+
int main()
5+
{
6+
float a;
7+
float b;
8+
// We could do "if (isnormal(a) && isnormal(b))", but __CPROVER_isnanf(a+b)
9+
// will permit solving this entirely via the simplifier, if, and only if, the
10+
// equality is successfully simplified (despite the different order of
11+
// operands).
12+
assert(__CPROVER_isnanf(a + b) || a + b == b + a);
13+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
4+
(Starting CEGAR Loop|VCC\(s\), 0 remaining after simplification$)
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
11+
This requires simplification of commutative, but not associative operations.

regression/cbmc/array-cell-sensitivity2/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
test.c
33
--show-vcc
4-
main::1::array!0@1#2 = with\(main::1::array!0@1#1, cast\(-1 \+ main::argc!0@1#1, signedbv\[64\]\), 1\)
4+
main::1::array!0@1#2 = with\(main::1::array!0@1#1, cast\(main::argc!0@1#1 \+ -1, signedbv\[64\]\), 1\)
55
main::1::array!0@1#3 = with\(main::1::array!0@1#2, 1, main::argc!0@1#1\)
66
^EXIT=0$
77
^SIGNAL=0$

regression/cbmc/field-sensitivity1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
test.c
33
--show-vcc
44
main::1::a!0@1#2\.\.x = main::argc!0@1#1
5-
main::1::a!0@1#2\.\.y = 1 \+ main::argc!0@1#1
5+
main::1::a!0@1#2\.\.y = main::argc!0@1#1 \+ 1
66
^EXIT=0$
77
^SIGNAL=0$
88
--

regression/cbmc/field-sensitivity11/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
test.c
33
--show-vcc
44
main::1::a1!0@1#2\.\.x = main::argc!0@1#1
5-
main::1::a1!0@1#2\.\.y = 1 \+ main::argc!0@1#1
5+
main::1::a1!0@1#2\.\.y = main::argc!0@1#1 \+ 1
66
main::1::a2!0@1#2\.\.x = main::1::a1!0@1#2\.\.x
77
main::1::a2!0@1#2\.\.y = main::1::a1!0@1#2\.\.y
88
^EXIT=0$

regression/cbmc/field-sensitivity12/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
test.c
33
--show-vcc
44
main::1::a1!0@1#2\.\.x = main::argc!0@1#1
5-
main::1::a1!0@1#2\.\.y = 1 \+ main::argc!0@1#1
5+
main::1::a1!0@1#2\.\.y = main::argc!0@1#1 \+ 1
66
main::1::a1!0@1#3\.\.x = main::1::a1!0@1#2\.\.x
77
main::1::a1!0@1#3\.\.y = main::1::a1!0@1#2\.\.y
88
main::1::a2!0@1#2\.\.x =

regression/cbmc/field-sensitivity13/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
test.c
33
--show-vcc
44
main::1::b1!0@1#2\.\.a\.\.x = main::argc!0@1#1
5-
main::1::b1!0@1#2\.\.a\.\.y = 1 \+ main::argc!0@1#1
5+
main::1::b1!0@1#2\.\.a\.\.y = main::argc!0@1#1 \+ 1
66
main::1::b1!0@1#3\.\.a\.\.x = main::1::b1!0@1#2\.\.a\.\.x
77
main::1::b1!0@1#3\.\.a\.\.y = main::1::b1!0@1#2\.\.a\.\.y
88
main::1::b2!0@1#2\.\.a\.\.x =

regression/goto-analyzer/constant_propagation_07/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--constants --simplify out.gb
44
^EXIT=0$
55
^SIGNAL=0$
6-
^Simplified: assert: 1, assume: 0, goto: 3, assigns: 13, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 14, function calls: 2$
6+
^Simplified: assert: 1, assume: 0, goto: 3, assigns: 9, function calls: 0$
7+
^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 18, function calls: 2$
88
--
99
^warning: ignoring

src/util/simplify_expr.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,7 @@ simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
20902090
#endif
20912091

20922092
exprt expr = node;
2093-
bool no_change_sort_and_join = sort_and_join(expr);
2093+
bool no_change_join_operands = join_operands(expr);
20942094

20952095
resultt<> r = unchanged(expr);
20962096

@@ -2291,7 +2291,7 @@ simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
22912291
r = simplify_complex(to_unary_expr(expr));
22922292
}
22932293

2294-
if(!no_change_sort_and_join)
2294+
if(!no_change_join_operands)
22952295
r = changed(r);
22962296

22972297
#ifdef DEBUGX

src/util/simplify_expr_floatbv.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include "invariant.h"
1717
#include "namespace.h"
1818
#include "simplify_expr.h"
19+
#include "simplify_utils.h"
1920
#include "std_expr.h"
2021

2122
simplify_exprt::resultt<>
@@ -361,7 +362,15 @@ simplify_exprt::simplify_ieee_float_relation(const binary_relation_exprt &expr)
361362
UNREACHABLE;
362363
}
363364

364-
if(expr.lhs() == expr.rhs())
365+
// addition and multiplication are commutative, but not associative
366+
exprt lhs_sorted = expr.lhs();
367+
if(lhs_sorted.id() == ID_floatbv_plus || lhs_sorted.id() == ID_floatbv_mult)
368+
sort_operands(lhs_sorted.operands());
369+
exprt rhs_sorted = expr.rhs();
370+
if(rhs_sorted.id() == ID_floatbv_plus || rhs_sorted.id() == ID_floatbv_mult)
371+
sort_operands(rhs_sorted.operands());
372+
373+
if(lhs_sorted == rhs_sorted)
365374
{
366375
// x!=x is the same as saying isnan(op)
367376
exprt isnan = isnan_exprt(expr.lhs());

src/util/simplify_utils.cpp

+26-12
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct saj_tablet
105105
{ irep_idt(), { irep_idt() }}
106106
};
107107

108-
static bool sort_and_join(
108+
static bool is_associative_and_commutative_for_type(
109109
const struct saj_tablet &saj_entry,
110110
const irep_idt &type_id)
111111
{
@@ -116,42 +116,44 @@ static bool sort_and_join(
116116
return false;
117117
}
118118

119-
static const struct saj_tablet &sort_and_join(
120-
const irep_idt &id,
121-
const irep_idt &type_id)
119+
static const struct saj_tablet &
120+
get_sort_and_join_table_entry(const irep_idt &id, const irep_idt &type_id)
122121
{
123122
unsigned i=0;
124123

125124
for( ; !saj_table[i].id.empty(); i++)
126-
if(id==saj_table[i].id &&
127-
sort_and_join(saj_table[i], type_id))
125+
{
126+
if(
127+
id == saj_table[i].id &&
128+
is_associative_and_commutative_for_type(saj_table[i], type_id))
128129
return saj_table[i];
130+
}
129131

130132
return saj_table[i];
131133
}
132134

133-
bool sort_and_join(exprt &expr)
135+
static bool sort_and_join(exprt &expr, bool do_sort)
134136
{
135137
bool no_change = true;
136138

137139
if(!expr.has_operands())
138140
return true;
139141

140142
const struct saj_tablet &saj_entry =
141-
sort_and_join(expr.id(), as_const(expr).type().id());
143+
get_sort_and_join_table_entry(expr.id(), as_const(expr).type().id());
142144
if(saj_entry.id.empty())
143145
return true;
144146

145147
// check operand types
146148

147149
forall_operands(it, expr)
148-
if(!sort_and_join(saj_entry, it->type().id()))
150+
if(!is_associative_and_commutative_for_type(saj_entry, it->type().id()))
149151
return true;
150152

151153
// join expressions
152154

153155
exprt::operandst new_ops;
154-
new_ops.reserve(expr.operands().size());
156+
new_ops.reserve(as_const(expr).operands().size());
155157

156158
forall_operands(it, expr)
157159
{
@@ -169,13 +171,25 @@ bool sort_and_join(exprt &expr)
169171
}
170172

171173
// sort it
174+
if(do_sort)
175+
no_change = sort_operands(new_ops) && no_change;
172176

173-
no_change = sort_operands(new_ops) && no_change;
174-
expr.operands().swap(new_ops);
177+
if(!no_change)
178+
expr.operands().swap(new_ops);
175179

176180
return no_change;
177181
}
178182

183+
bool sort_and_join(exprt &expr)
184+
{
185+
return sort_and_join(expr, true);
186+
}
187+
188+
bool join_operands(exprt &expr)
189+
{
190+
return sort_and_join(expr, false);
191+
}
192+
179193
optionalt<exprt> bits2expr(
180194
const std::string &bits,
181195
const typet &type,

src/util/simplify_utils.h

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class namespacet;
2020

2121
bool sort_operands(exprt::operandst &operands);
2222

23+
bool join_operands(exprt &expr);
24+
2325
bool sort_and_join(exprt &expr);
2426

2527
// bit-level conversions

0 commit comments

Comments
 (0)