Skip to content

Commit 357dfbf

Browse files
smowtonowen-mc-diffblue
authored andcommitted
GOTO-symex: propagate notequal conditions for boolean types
Conditional branches on "x != false", as well as "x" and "!x", can and should lead to constant propagation just as "x == true" does now. This is particularly beneficial for the "clinit_already_run" variables that are maintained to determine if a static initialiser should be run or not -- the current "if(already_run != true) clinit(); already_run = true;" condition now leaves symex certain that it has been run at the bottom of the function regardless of the already_run flag's initial value, whereas before it could remain uncertain and so explore the static initialiser more than is necessary.
1 parent fc0a0cd commit 357dfbf

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

src/goto-symex/goto_state.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,71 @@ void goto_statet::apply_condition(
4646
{
4747
if(condition.id() == ID_and)
4848
{
49+
// A == B && C == D && E == F ...
50+
// -->
51+
// Apply each condition individually
4952
for(const auto &op : condition.operands())
5053
apply_condition(op, previous_state, ns);
5154
}
55+
else if(
56+
condition.id() == ID_notequal &&
57+
to_notequal_expr(condition).lhs().type() == bool_typet())
58+
{
59+
// A != (true|false)
60+
// -->
61+
// A == (false|true)
62+
exprt lhs = to_notequal_expr(condition).lhs();
63+
exprt rhs = to_notequal_expr(condition).rhs();
64+
if(is_ssa_expr(rhs))
65+
std::swap(lhs, rhs);
66+
67+
if(rhs.is_true())
68+
apply_condition(equal_exprt(lhs, false_exprt()), previous_state, ns);
69+
else if(rhs.is_false())
70+
apply_condition(equal_exprt(lhs, true_exprt()), previous_state, ns);
71+
}
72+
else if(
73+
condition.id() == ID_not && to_not_expr(condition).op().id() == ID_notequal)
74+
{
75+
// !(A != B)
76+
// -->
77+
// A == B
78+
const auto &notequal_expr = to_notequal_expr(to_not_expr(condition).op());
79+
apply_condition(
80+
equal_exprt(notequal_expr.lhs(), notequal_expr.rhs()),
81+
previous_state,
82+
ns);
83+
}
84+
else if(
85+
condition.id() == ID_not && to_not_expr(condition).op().id() == ID_equal)
86+
{
87+
// !(A == B)
88+
// -->
89+
// A != B
90+
const auto &equal_expr = to_equal_expr(to_not_expr(condition).op());
91+
apply_condition(
92+
notequal_exprt(equal_expr.lhs(), equal_expr.rhs()), previous_state, ns);
93+
}
94+
else if(condition.id() == ID_not)
95+
{
96+
// !A
97+
// -->
98+
// A == false
99+
apply_condition(
100+
equal_exprt(to_not_expr(condition).op(), false_exprt()),
101+
previous_state,
102+
ns);
103+
}
104+
else if(condition.id() == ID_symbol && condition.type() == bool_typet())
105+
{
106+
// A
107+
// -->
108+
// A == true
109+
apply_condition(equal_exprt(condition, true_exprt()), previous_state, ns);
110+
}
52111
else if(condition.id() == ID_equal)
53112
{
113+
// Base case: try to apply a single equality constraint
54114
exprt lhs = to_equal_expr(condition).lhs();
55115
exprt rhs = to_equal_expr(condition).rhs();
56116
if(is_ssa_expr(rhs))

src/goto-symex/symex_goto.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,12 @@ void goto_symext::apply_goto_condition(
5555

5656
jump_taken_state.apply_condition(new_guard, current_state, ns);
5757

58-
// Try to find a negative condition that implies an equality constraint on
59-
// the branch-not-taken path.
6058
// Could use not_exprt + simplify, but let's avoid paying that cost on quite
6159
// a hot path:
62-
if(new_guard.id() == ID_not)
63-
jump_not_taken_state.apply_condition(
64-
to_not_expr(new_guard).op(), current_state, ns);
65-
else if(new_guard.id() == ID_notequal)
66-
{
67-
auto &not_equal_expr = to_notequal_expr(new_guard);
68-
jump_not_taken_state.apply_condition(
69-
equal_exprt(not_equal_expr.lhs(), not_equal_expr.rhs()),
70-
current_state,
71-
ns);
72-
}
60+
exprt negated_new_guard = new_guard.id() == ID_not
61+
? to_not_expr(new_guard).op()
62+
: not_exprt(new_guard);
63+
jump_not_taken_state.apply_condition(negated_new_guard, current_state, ns);
7364
}
7465

7566
/// Try to evaluate a simple pointer comparison.

0 commit comments

Comments
 (0)