Skip to content

Commit f6de15d

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 9220c3a commit f6de15d

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
@@ -2806,6 +2806,10 @@ simplify_exprt::simplify_node_preorder(const exprt &expr)
28062806
{
28072807
result = simplify_unary_pointer_predicate_preorder(to_unary_expr(expr));
28082808
}
2809+
else if(expr.id() == ID_not)
2810+
{
2811+
result = simplify_not_preorder(to_not_expr(expr));
2812+
}
28092813
else if(expr.has_operands())
28102814
{
28112815
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
@@ -377,3 +377,66 @@ simplify_exprt::resultt<> simplify_exprt::simplify_not(const not_exprt &expr)
377377

378378
return unchanged(expr);
379379
}
380+
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+
}

src/util/simplify_expr_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class simplify_exprt
167167
[[nodiscard]] resultt<> simplify_if(const if_exprt &);
168168
[[nodiscard]] resultt<> simplify_bitnot(const bitnot_exprt &);
169169
[[nodiscard]] resultt<> simplify_not(const not_exprt &);
170+
[[nodiscard]] resultt<> simplify_not_preorder(const not_exprt &expr);
170171
[[nodiscard]] resultt<> simplify_boolean(const exprt &);
171172
[[nodiscard]] resultt<> simplify_inequality(const binary_relation_exprt &);
172173
[[nodiscard]] resultt<>

0 commit comments

Comments
 (0)