Skip to content

Commit 7a4c06e

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 1ab5de1 commit 7a4c06e

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
@@ -981,21 +981,6 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
981981
}
982982
}
983983

984-
#if 0
985-
// (T)(a?b:c) --> a?(T)b:(T)c
986-
if(expr.op().id()==ID_if &&
987-
expr.op().operands().size()==3)
988-
{
989-
typecast_exprt tmp_op1(expr.op().op1(), expr_type);
990-
typecast_exprt tmp_op2(expr.op().op2(), expr_type);
991-
simplify_typecast(tmp_op1);
992-
simplify_typecast(tmp_op2);
993-
auto new_expr=if_exprt(expr.op().op0(), tmp_op1, tmp_op2, expr_type);
994-
simplify_if(new_expr);
995-
return std::move(new_expr);
996-
}
997-
#endif
998-
999984
const irep_idt &expr_type_id=expr_type.id();
1000985
const exprt &operand = expr.op();
1001986
const irep_idt &op_type_id=op_type.id();
@@ -1323,6 +1308,35 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
13231308
return unchanged(expr);
13241309
}
13251310

1311+
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1312+
{
1313+
const typet &expr_type = as_const(expr).type();
1314+
const typet &op_type = as_const(expr).op().type();
1315+
1316+
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
1317+
// the type cast itself may be costly
1318+
if(
1319+
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1320+
op_type.id() != ID_floatbv)
1321+
{
1322+
if_exprt if_expr = lift_if(expr, 0);
1323+
simplify_if_preorder(if_expr);
1324+
expr.swap(if_expr);
1325+
return false;
1326+
}
1327+
else
1328+
{
1329+
auto r_it = simplify_rec(expr.op()); // recursive call
1330+
if(r_it.has_changed())
1331+
{
1332+
expr.op() = r_it.expr;
1333+
return false;
1334+
}
1335+
else
1336+
return true;
1337+
}
1338+
}
1339+
13261340
simplify_exprt::resultt<>
13271341
simplify_exprt::simplify_dereference(const dereference_exprt &expr)
13281342
{
@@ -2226,6 +2240,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
22262240
}
22272241
else if(expr.id()==ID_if)
22282242
result=simplify_if_preorder(to_if_expr(expr));
2243+
else if(expr.id() == ID_typecast)
2244+
result = simplify_typecast_preorder(to_typecast_expr(expr));
22292245
else
22302246
{
22312247
if(expr.has_operands())

src/util/simplify_expr_class.h

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