Skip to content

Commit 584b38b

Browse files
committed
Perform simplification of not_exprt as preorder step
Each of the possible simplifications has an impact on its operands, which in turn mostly needs to be simplified. Instead of doing this again (as the operand has already been simplified), do most of the work as a preorder step so that only the modified operand is subject to simplification.
1 parent 2e6200a commit 584b38b

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

src/util/simplify_expr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,10 @@ simplify_exprt::simplify_node_preorder(const exprt &expr)
29362936
{
29372937
result = simplify_unary_pointer_predicate_preorder(to_unary_expr(expr));
29382938
}
2939+
else if(expr.id() == ID_not)
2940+
{
2941+
result = simplify_not_preorder(to_not_expr(expr));
2942+
}
29392943
else if(expr.has_operands())
29402944
{
29412945
std::optional<exprt::operandst> new_operands;

src/util/simplify_expr_boolean.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,69 @@ simplify_exprt::resultt<> simplify_exprt::simplify_not(const not_exprt &expr)
378378
return unchanged(expr);
379379
}
380380

381+
simplify_exprt::resultt<>
382+
simplify_exprt::simplify_not_preorder(const not_exprt &expr)
383+
{
384+
const exprt &op = expr.op();
385+
386+
if(!expr.is_boolean() || !op.is_boolean())
387+
{
388+
return unchanged(expr);
389+
}
390+
391+
if(op.id() == ID_not) // (not not a) == a
392+
{
393+
return changed(simplify_rec(to_not_expr(op).op()));
394+
}
395+
else if(op.is_false())
396+
{
397+
return true_exprt{};
398+
}
399+
else if(op.is_true())
400+
{
401+
return false_exprt{};
402+
}
403+
else if(op.id() == ID_and || op.id() == ID_or)
404+
{
405+
exprt tmp = op;
406+
407+
Forall_operands(it, tmp)
408+
{
409+
*it = boolean_negate(*it);
410+
}
411+
412+
tmp.id(tmp.id() == ID_and ? ID_or : ID_and);
413+
414+
return changed(simplify_rec(tmp));
415+
}
416+
else if(op.id() == ID_notequal) // !(a!=b) <-> a==b
417+
{
418+
exprt tmp = op;
419+
tmp.id(ID_equal);
420+
return changed(simplify_rec(tmp));
421+
}
422+
else if(op.id() == ID_exists) // !(exists: a) <-> forall: not a
423+
{
424+
auto const &op_as_exists = to_exists_expr(op);
425+
return changed(simplify_rec(
426+
forall_exprt{op_as_exists.symbol(), not_exprt{op_as_exists.where()}}));
427+
}
428+
else if(op.id() == ID_forall) // !(forall: a) <-> exists: not a
429+
{
430+
auto const &op_as_forall = to_forall_expr(op);
431+
return changed(simplify_rec(
432+
exists_exprt{op_as_forall.symbol(), not_exprt{op_as_forall.where()}}));
433+
}
434+
435+
auto op_result = simplify_rec(op);
436+
if(!op_result.has_changed())
437+
return unchanged(expr);
438+
439+
not_exprt tmp = expr;
440+
tmp.op() = std::move(op_result.expr);
441+
return std::move(tmp);
442+
}
443+
381444
simplify_exprt::resultt<>
382445
simplify_exprt::simplify_quantifier_expr(const quantifier_exprt &expr)
383446
{

src/util/simplify_expr_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class simplify_exprt
174174
[[nodiscard]] resultt<> simplify_if(const if_exprt &);
175175
[[nodiscard]] resultt<> simplify_bitnot(const bitnot_exprt &);
176176
[[nodiscard]] resultt<> simplify_not(const not_exprt &);
177+
[[nodiscard]] resultt<> simplify_not_preorder(const not_exprt &expr);
177178
[[nodiscard]] resultt<> simplify_boolean(const exprt &);
178179
[[nodiscard]] virtual resultt<>
179180
simplify_inequality(const binary_relation_exprt &);

0 commit comments

Comments
 (0)