Skip to content

Commit 8599eaf

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 526ea61 commit 8599eaf

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
@@ -932,21 +932,6 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
932932
}
933933
}
934934

935-
#if 0
936-
// (T)(a?b:c) --> a?(T)b:(T)c
937-
if(expr.op().id()==ID_if &&
938-
expr.op().operands().size()==3)
939-
{
940-
typecast_exprt tmp_op1(expr.op().op1(), expr_type);
941-
typecast_exprt tmp_op2(expr.op().op2(), expr_type);
942-
simplify_typecast(tmp_op1);
943-
simplify_typecast(tmp_op2);
944-
auto new_expr=if_exprt(expr.op().op0(), tmp_op1, tmp_op2, expr_type);
945-
simplify_if(new_expr);
946-
return std::move(new_expr);
947-
}
948-
#endif
949-
950935
const irep_idt &expr_type_id=expr_type.id();
951936
const exprt &operand = expr.op();
952937
const irep_idt &op_type_id=op_type.id();
@@ -1274,6 +1259,35 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
12741259
return unchanged(expr);
12751260
}
12761261

1262+
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1263+
{
1264+
const typet &expr_type = as_const(expr).type();
1265+
const typet &op_type = as_const(expr).op().type();
1266+
1267+
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
1268+
// the type cast itself may be costly
1269+
if(
1270+
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1271+
op_type.id() != ID_floatbv)
1272+
{
1273+
if_exprt if_expr = lift_if(expr, 0);
1274+
simplify_if_preorder(if_expr);
1275+
expr.swap(if_expr);
1276+
return false;
1277+
}
1278+
else
1279+
{
1280+
auto r_it = simplify_rec(expr.op()); // recursive call
1281+
if(r_it.has_changed())
1282+
{
1283+
expr.op() = r_it.expr;
1284+
return false;
1285+
}
1286+
else
1287+
return true;
1288+
}
1289+
}
1290+
12771291
simplify_exprt::resultt<>
12781292
simplify_exprt::simplify_dereference(const dereference_exprt &expr)
12791293
{
@@ -2170,6 +2184,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
21702184
}
21712185
else if(expr.id()==ID_if)
21722186
result=simplify_if_preorder(to_if_expr(expr));
2187+
else if(expr.id() == ID_typecast)
2188+
result = simplify_typecast_preorder(to_typecast_expr(expr));
21732189
else
21742190
{
21752191
if(expr.has_operands())

src/util/simplify_expr_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class simplify_exprt
137137
// These below all return 'true' if the simplification wasn't applicable.
138138
// If false is returned, the expression has changed.
139139
NODISCARD resultt<> simplify_typecast(const typecast_exprt &);
140+
bool simplify_typecast_preorder(typecast_exprt &);
140141
NODISCARD resultt<> simplify_extractbit(const extractbit_exprt &);
141142
NODISCARD resultt<> simplify_extractbits(const extractbits_exprt &);
142143
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)