Skip to content

Commit fac7964

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 0a09814 commit fac7964

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

src/util/simplify_expr.cpp

+31-15
Original file line numberDiff line numberDiff line change
@@ -1007,21 +1007,6 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
10071007
}
10081008
}
10091009

1010-
#if 0
1011-
// (T)(a?b:c) --> a?(T)b:(T)c
1012-
if(expr.op().id()==ID_if &&
1013-
expr.op().operands().size()==3)
1014-
{
1015-
typecast_exprt tmp_op1(expr.op().op1(), expr_type);
1016-
typecast_exprt tmp_op2(expr.op().op2(), expr_type);
1017-
simplify_typecast(tmp_op1);
1018-
simplify_typecast(tmp_op2);
1019-
auto new_expr=if_exprt(expr.op().op0(), tmp_op1, tmp_op2, expr_type);
1020-
simplify_if(new_expr);
1021-
return std::move(new_expr);
1022-
}
1023-
#endif
1024-
10251010
const irep_idt &expr_type_id=expr_type.id();
10261011
const exprt &operand = expr.op();
10271012
const irep_idt &op_type_id=op_type.id();
@@ -1349,6 +1334,35 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
13491334
return unchanged(expr);
13501335
}
13511336

1337+
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1338+
{
1339+
const typet &expr_type = as_const(expr).type();
1340+
const typet &op_type = as_const(expr).op().type();
1341+
1342+
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
1343+
// the type cast itself may be costly
1344+
if(
1345+
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1346+
op_type.id() != ID_floatbv)
1347+
{
1348+
if_exprt if_expr = lift_if(expr, 0);
1349+
simplify_if_preorder(if_expr);
1350+
expr.swap(if_expr);
1351+
return false;
1352+
}
1353+
else
1354+
{
1355+
auto r_it = simplify_rec(expr.op()); // recursive call
1356+
if(r_it.has_changed())
1357+
{
1358+
expr.op() = r_it.expr;
1359+
return false;
1360+
}
1361+
else
1362+
return true;
1363+
}
1364+
}
1365+
13521366
simplify_exprt::resultt<>
13531367
simplify_exprt::simplify_dereference(const dereference_exprt &expr)
13541368
{
@@ -2616,6 +2630,8 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
26162630
}
26172631
else if(expr.id()==ID_if)
26182632
result=simplify_if_preorder(to_if_expr(expr));
2633+
else if(expr.id() == ID_typecast)
2634+
result = simplify_typecast_preorder(to_typecast_expr(expr));
26192635
else
26202636
{
26212637
if(expr.has_operands())

src/util/simplify_expr_class.h

+1
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class simplify_exprt
147147
// These below all return 'true' if the simplification wasn't applicable.
148148
// If false is returned, the expression has changed.
149149
NODISCARD resultt<> simplify_typecast(const typecast_exprt &);
150+
bool simplify_typecast_preorder(typecast_exprt &);
150151
NODISCARD resultt<> simplify_extractbit(const extractbit_exprt &);
151152
NODISCARD resultt<> simplify_extractbits(const extractbits_exprt &);
152153
NODISCARD resultt<> simplify_concatenation(const concatenation_exprt &);

unit/util/simplify_expr.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,21 @@ TEST_CASE("Simplifying cast expressions", "[core][util]")
524524
const auto simplified_expr = simplify_expr(expr, ns);
525525
REQUIRE(simplified_expr == expr);
526526
}
527+
528+
SECTION("Simplifying (unsigned)(B ? 4 : 5) > 3")
529+
{
530+
signedbv_typet sbv{4};
531+
unsignedbv_typet ubv{4};
532+
533+
symbol_exprt b{"B", bool_typet{}};
534+
if_exprt if_b{b, from_integer(4, sbv), from_integer(5, sbv)};
535+
536+
binary_relation_exprt comparison_gt{
537+
typecast_exprt{if_b, ubv}, ID_gt, from_integer(3, ubv)};
538+
exprt simp = simplify_expr(comparison_gt, ns);
539+
540+
REQUIRE(simp == true_exprt{});
541+
}
527542
}
528543

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

0 commit comments

Comments
 (0)