Skip to content

Commit 1bd4401

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 9238a38 commit 1bd4401

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

src/util/simplify_expr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,6 +2735,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
27352735
result=simplify_if_preorder(to_if_expr(expr));
27362736
else if(expr.id() == ID_typecast)
27372737
result = simplify_typecast_preorder(to_typecast_expr(expr));
2738+
else if(expr.id() == ID_not)
2739+
result = simplify_not_preorder(to_not_expr(expr));
27382740
else
27392741
{
27402742
if(expr.has_operands())

src/util/simplify_expr_boolean.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,85 @@ simplify_exprt::resultt<> simplify_exprt::simplify_not(const not_exprt &expr)
377377

378378
return unchanged(expr);
379379
}
380+
381+
bool simplify_exprt::simplify_not_preorder(not_exprt &expr)
382+
{
383+
exprt &op = expr.op();
384+
385+
if(!expr.is_boolean() || !op.is_boolean())
386+
{
387+
return true;
388+
}
389+
390+
if(op.id() == ID_not) // (not not a) == a
391+
{
392+
if(as_const(op).operands().size() == 1)
393+
{
394+
exprt tmp = simplify_rec(to_not_expr(op).op()).expr;
395+
expr.swap(tmp);
396+
return false;
397+
}
398+
}
399+
else if(op.is_false())
400+
{
401+
true_exprt tmp;
402+
expr.swap(tmp);
403+
return false;
404+
}
405+
else if(op.is_true())
406+
{
407+
false_exprt tmp;
408+
expr.swap(tmp);
409+
return false;
410+
}
411+
else if(op.id() == ID_and || op.id() == ID_or)
412+
{
413+
Forall_operands(it, op)
414+
{
415+
*it = boolean_negate(*it);
416+
}
417+
418+
op.id(op.id() == ID_and ? ID_or : ID_and);
419+
420+
exprt tmp = simplify_rec(op);
421+
expr.swap(tmp);
422+
423+
return false;
424+
}
425+
else if(op.id() == ID_notequal) // !(a!=b) <-> a==b
426+
{
427+
op.id(ID_equal);
428+
exprt tmp = simplify_rec(op).expr;
429+
expr.swap(tmp);
430+
return false;
431+
}
432+
else if(op.id() == ID_exists) // !(exists: a) <-> forall: not a
433+
{
434+
auto const &op_as_exists = to_exists_expr(op);
435+
exprt rewritten_op =
436+
simplify_rec(
437+
forall_exprt{op_as_exists.symbol(), not_exprt{op_as_exists.where()}})
438+
.expr;
439+
expr.swap(rewritten_op);
440+
return false;
441+
}
442+
else if(op.id() == ID_forall) // !(forall: a) <-> exists: not a
443+
{
444+
auto const &op_as_forall = to_forall_expr(op);
445+
exprt rewritten_op =
446+
simplify_rec(
447+
exists_exprt{op_as_forall.symbol(), not_exprt{op_as_forall.where()}})
448+
.expr;
449+
expr.swap(rewritten_op);
450+
return false;
451+
}
452+
453+
auto op_result = simplify_rec(op);
454+
if(op_result.has_changed())
455+
{
456+
op = op_result.expr;
457+
return false;
458+
}
459+
else
460+
return true;
461+
}

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+
bool simplify_not_preorder(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)