Skip to content

Commit d98c756

Browse files
committed
Simplify (T)(a?b:c) to a?(T)b:(T)c
The idea of such a rule existed ever since 7285dda, but was possibly too costly when doing it post-order for one would have to re-process multiple sub-expressions. A pre-order rule avoids such repeat processing.
1 parent abba3d7 commit d98c756

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

src/util/simplify_expr.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -956,21 +956,6 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
956956
}
957957
}
958958

959-
#if 0
960-
// (T)(a?b:c) --> a?(T)b:(T)c
961-
if(expr.op().id()==ID_if &&
962-
expr.op().operands().size()==3)
963-
{
964-
typecast_exprt tmp_op1(expr.op().op1(), expr_type);
965-
typecast_exprt tmp_op2(expr.op().op2(), expr_type);
966-
simplify_typecast(tmp_op1);
967-
simplify_typecast(tmp_op2);
968-
auto new_expr=if_exprt(expr.op().op0(), tmp_op1, tmp_op2, expr_type);
969-
simplify_if(new_expr);
970-
return std::move(new_expr);
971-
}
972-
#endif
973-
974959
const irep_idt &expr_type_id=expr_type.id();
975960
const exprt &operand = expr.op();
976961
const irep_idt &op_type_id=op_type.id();
@@ -1298,6 +1283,35 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
12981283
return unchanged(expr);
12991284
}
13001285

1286+
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1287+
{
1288+
const typet &expr_type = as_const(expr).type();
1289+
const typet &op_type = as_const(expr).op().type();
1290+
1291+
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
1292+
// the type cast itself may be costly
1293+
if(
1294+
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1295+
op_type.id() != ID_floatbv)
1296+
{
1297+
if_exprt if_expr = lift_if(expr, 0);
1298+
simplify_if_preorder(if_expr);
1299+
expr.swap(if_expr);
1300+
return false;
1301+
}
1302+
else
1303+
{
1304+
auto r_it = simplify_rec(expr.op()); // recursive call
1305+
if(r_it.has_changed())
1306+
{
1307+
expr.op() = r_it.expr;
1308+
return false;
1309+
}
1310+
else
1311+
return true;
1312+
}
1313+
}
1314+
13011315
simplify_exprt::resultt<>
13021316
simplify_exprt::simplify_dereference(const dereference_exprt &expr)
13031317
{
@@ -2194,6 +2208,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
21942208
}
21952209
else if(expr.id()==ID_if)
21962210
result=simplify_if_preorder(to_if_expr(expr));
2211+
else if(expr.id() == ID_typecast)
2212+
result = simplify_typecast_preorder(to_typecast_expr(expr));
21972213
else
21982214
{
21992215
if(expr.has_operands())

src/util/simplify_expr_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class simplify_exprt
140140
// These below all return 'true' if the simplification wasn't applicable.
141141
// If false is returned, the expression has changed.
142142
NODISCARD resultt<> simplify_typecast(const typecast_exprt &);
143+
bool simplify_typecast_preorder(typecast_exprt &);
143144
NODISCARD resultt<> simplify_extractbit(const extractbit_exprt &);
144145
NODISCARD resultt<> simplify_extractbits(const extractbits_exprt &);
145146
NODISCARD resultt<> simplify_concatenation(const concatenation_exprt &);

unit/util/simplify_expr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,21 @@ TEST_CASE("Simplifying cast expressions", "[core][util]")
500500
const auto simplified_expr = simplify_expr(expr, ns);
501501
REQUIRE(simplified_expr == expr);
502502
}
503+
504+
SECTION("Simplifying (unsigned)(B ? 4 : 5) > 3")
505+
{
506+
signedbv_typet sbv{4};
507+
unsignedbv_typet ubv{4};
508+
509+
symbol_exprt b{"B", bool_typet{}};
510+
if_exprt if_b{b, from_integer(4, sbv), from_integer(5, sbv)};
511+
512+
binary_relation_exprt comparison_gt{
513+
typecast_exprt{if_b, ubv}, ID_gt, from_integer(3, ubv)};
514+
exprt simp = simplify_expr(comparison_gt, ns);
515+
516+
REQUIRE(simp == true_exprt{});
517+
}
503518
}
504519

505520
TEST_CASE("Simplify bitor", "[core][util]")

0 commit comments

Comments
 (0)