Skip to content

Commit 512f1ce

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 f0a4e75 commit 512f1ce

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

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

1312+
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1313+
{
1314+
const typet &expr_type = as_const(expr).type();
1315+
const typet &op_type = as_const(expr).op().type();
1316+
1317+
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
1318+
// the type cast itself may be costly
1319+
if(
1320+
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1321+
op_type.id() != ID_floatbv)
1322+
{
1323+
if_exprt if_expr = lift_if(expr, 0);
1324+
simplify_if_preorder(if_expr);
1325+
expr.swap(if_expr);
1326+
return false;
1327+
}
1328+
else
1329+
{
1330+
auto r_it = simplify_rec(expr.op()); // recursive call
1331+
if(r_it.has_changed())
1332+
{
1333+
expr.op() = r_it.expr;
1334+
return false;
1335+
}
1336+
else
1337+
return true;
1338+
}
1339+
}
1340+
13271341
simplify_exprt::resultt<>
13281342
simplify_exprt::simplify_dereference(const dereference_exprt &expr)
13291343
{
@@ -2292,6 +2306,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
22922306
}
22932307
else if(expr.id()==ID_if)
22942308
result=simplify_if_preorder(to_if_expr(expr));
2309+
else if(expr.id() == ID_typecast)
2310+
result = simplify_typecast_preorder(to_typecast_expr(expr));
22952311
else
22962312
{
22972313
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)