Skip to content

Commit 03ed18f

Browse files
committed
Simplify quantified expressions over constants
Other simplification rules may turn the where-clause of a quantified expression into a (Boolean) constant. We can completely remove such quantified expressions so as not to distract back-ends that may special-case quantified expressions. We saw such expressions when working on mlkem-native.
1 parent 32143dd commit 03ed18f

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

src/util/simplify_expr.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -3128,6 +3128,10 @@ simplify_exprt::resultt<> simplify_exprt::simplify_node(const exprt &node)
31283128
{
31293129
r = simplify_prophecy_pointer_in_range(*prophecy_pointer_in_range);
31303130
}
3131+
else if(expr.id() == ID_exists || expr.id() == ID_forall)
3132+
{
3133+
r = simplify_quantifier_expr(to_quantifier_expr(expr));
3134+
}
31313135

31323136
if(!no_change_join_operands)
31333137
r = changed(r);

src/util/simplify_expr_boolean.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,25 @@ 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_quantifier_expr(const quantifier_exprt &expr)
383+
{
384+
const exprt &where = expr.where();
385+
386+
if(!expr.is_boolean() || !where.is_boolean())
387+
{
388+
return unchanged(expr);
389+
}
390+
391+
if(where.is_false())
392+
{
393+
return false_exprt{};
394+
}
395+
else if(where.is_true())
396+
{
397+
return true_exprt{};
398+
}
399+
400+
return unchanged(expr);
401+
}

src/util/simplify_expr_class.h

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class popcount_exprt;
6868
class power_exprt;
6969
class prophecy_pointer_in_range_exprt;
7070
class prophecy_r_or_w_ok_exprt;
71+
class quantifier_exprt;
7172
class refined_string_exprt;
7273
class shift_exprt;
7374
class sign_exprt;
@@ -254,6 +255,9 @@ class simplify_exprt
254255
[[nodiscard]] resultt<>
255256
simplify_prophecy_pointer_in_range(const prophecy_pointer_in_range_exprt &);
256257

258+
/// Try to simplify exists/forall to a constant expression.
259+
[[nodiscard]] resultt<> simplify_quantifier_expr(const quantifier_exprt &);
260+
257261
// auxiliary
258262
bool simplify_if_implies(
259263
exprt &expr, const exprt &cond, bool truth, bool &new_truth);

unit/util/simplify_expr.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,27 @@ TEST_CASE("Simplify power", "[core][util]")
586586
simplify_expr(power_exprt{a, from_integer(1, integer_typet{})}, ns) == a);
587587
}
588588
}
589+
590+
TEST_CASE("Simplify quantifier", "[core][util]")
591+
{
592+
const symbol_tablet symbol_table;
593+
const namespacet ns{symbol_table};
594+
595+
SECTION("Simplification for exists")
596+
{
597+
symbol_exprt a{"a", integer_typet{}};
598+
599+
REQUIRE(simplify_expr(exists_exprt{a, false_exprt{}}, ns) == false_exprt{});
600+
601+
REQUIRE(simplify_expr(exists_exprt{a, true_exprt{}}, ns) == true_exprt{});
602+
}
603+
604+
SECTION("Simplification for forall")
605+
{
606+
symbol_exprt a{"a", integer_typet{}};
607+
608+
REQUIRE(simplify_expr(forall_exprt{a, false_exprt{}}, ns) == false_exprt{});
609+
610+
REQUIRE(simplify_expr(forall_exprt{a, true_exprt{}}, ns) == true_exprt{});
611+
}
612+
}

0 commit comments

Comments
 (0)