Skip to content

Commit b836b4f

Browse files
authored
Merge pull request #6118 from tautschnig/simplify-resultt
Use simplify_exprtt::resultt in pre-order simplification steps
2 parents 9238a38 + 5d29491 commit b836b4f

6 files changed

+314
-194
lines changed

src/util/simplify_expr.cpp

Lines changed: 151 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,8 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
820820
// rewrite (T)(bool) to bool?1:0
821821
auto one = from_integer(1, expr_type);
822822
auto zero = from_integer(0, expr_type);
823-
exprt new_expr = if_exprt(expr.op(), std::move(one), std::move(zero));
824-
simplify_if_preorder(to_if_expr(new_expr));
825-
return new_expr;
823+
return changed(simplify_if_preorder(
824+
if_exprt{expr.op(), std::move(one), std::move(zero)}));
826825
}
827826

828827
// circular casts through types shorter than `int`
@@ -1340,33 +1339,33 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
13401339
return unchanged(expr);
13411340
}
13421341

1343-
bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr)
1342+
simplify_exprt::resultt<>
1343+
simplify_exprt::simplify_typecast_preorder(const typecast_exprt &expr)
13441344
{
1345-
const typet &expr_type = as_const(expr).type();
1346-
const typet &op_type = as_const(expr).op().type();
1345+
const typet &expr_type = expr.type();
1346+
const typet &op_type = expr.op().type();
13471347

13481348
// (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as
13491349
// the type cast itself may be costly
13501350
if(
1351-
as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv &&
1351+
expr.op().id() == ID_if && expr_type.id() != ID_floatbv &&
13521352
op_type.id() != ID_floatbv)
13531353
{
13541354
if_exprt if_expr = lift_if(expr, 0);
1355-
simplify_if_preorder(if_expr);
1356-
expr.swap(if_expr);
1357-
return false;
1355+
return changed(simplify_if_preorder(if_expr));
13581356
}
13591357
else
13601358
{
13611359
auto r_it = simplify_rec(expr.op()); // recursive call
13621360
if(r_it.has_changed())
13631361
{
1364-
expr.op() = r_it.expr;
1365-
return false;
1362+
auto tmp = expr;
1363+
tmp.op() = r_it.expr;
1364+
return tmp;
13661365
}
1367-
else
1368-
return true;
13691366
}
1367+
1368+
return unchanged(expr);
13701369
}
13711370

13721371
simplify_exprt::resultt<>
@@ -1377,23 +1376,6 @@ simplify_exprt::simplify_dereference(const dereference_exprt &expr)
13771376
if(pointer.type().id()!=ID_pointer)
13781377
return unchanged(expr);
13791378

1380-
if(pointer.id()==ID_if && pointer.operands().size()==3)
1381-
{
1382-
const if_exprt &if_expr=to_if_expr(pointer);
1383-
1384-
auto tmp_op1 = expr;
1385-
tmp_op1.op() = if_expr.true_case();
1386-
exprt tmp_op1_result = simplify_dereference(tmp_op1);
1387-
1388-
auto tmp_op2 = expr;
1389-
tmp_op2.op() = if_expr.false_case();
1390-
exprt tmp_op2_result = simplify_dereference(tmp_op2);
1391-
1392-
if_exprt tmp{if_expr.cond(), tmp_op1_result, tmp_op2_result};
1393-
1394-
return changed(simplify_if(tmp));
1395-
}
1396-
13971379
if(pointer.id()==ID_address_of)
13981380
{
13991381
exprt tmp=to_address_of_expr(pointer).object();
@@ -1427,6 +1409,30 @@ simplify_exprt::simplify_dereference(const dereference_exprt &expr)
14271409
return unchanged(expr);
14281410
}
14291411

1412+
simplify_exprt::resultt<>
1413+
simplify_exprt::simplify_dereference_preorder(const dereference_exprt &expr)
1414+
{
1415+
const exprt &pointer = expr.pointer();
1416+
1417+
if(pointer.id() == ID_if)
1418+
{
1419+
if_exprt if_expr = lift_if(expr, 0);
1420+
return changed(simplify_if_preorder(if_expr));
1421+
}
1422+
else
1423+
{
1424+
auto r_it = simplify_rec(pointer); // recursive call
1425+
if(r_it.has_changed())
1426+
{
1427+
auto tmp = expr;
1428+
tmp.pointer() = r_it.expr;
1429+
return tmp;
1430+
}
1431+
}
1432+
1433+
return unchanged(expr);
1434+
}
1435+
14301436
simplify_exprt::resultt<>
14311437
simplify_exprt::simplify_lambda(const lambda_exprt &expr)
14321438
{
@@ -1643,17 +1649,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_object(const exprt &expr)
16431649
simplify_exprt::resultt<>
16441650
simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
16451651
{
1646-
// lift up any ID_if on the object
1647-
if(expr.op().id()==ID_if)
1648-
{
1649-
if_exprt if_expr=lift_if(expr, 0);
1650-
if_expr.true_case() =
1651-
simplify_byte_extract(to_byte_extract_expr(if_expr.true_case()));
1652-
if_expr.false_case() =
1653-
simplify_byte_extract(to_byte_extract_expr(if_expr.false_case()));
1654-
return changed(simplify_if(if_expr));
1655-
}
1656-
16571652
const auto el_size = pointer_offset_bits(expr.type(), ns);
16581653
if(el_size.has_value() && *el_size < 0)
16591654
return unchanged(expr);
@@ -2011,6 +2006,41 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
20112006
return unchanged(expr);
20122007
}
20132008

2009+
simplify_exprt::resultt<>
2010+
simplify_exprt::simplify_byte_extract_preorder(const byte_extract_exprt &expr)
2011+
{
2012+
// lift up any ID_if on the object
2013+
if(expr.op().id() == ID_if)
2014+
{
2015+
if_exprt if_expr = lift_if(expr, 0);
2016+
return changed(simplify_if_preorder(if_expr));
2017+
}
2018+
else
2019+
{
2020+
optionalt<exprt::operandst> new_operands;
2021+
2022+
for(std::size_t i = 0; i < expr.operands().size(); ++i)
2023+
{
2024+
auto r_it = simplify_rec(expr.operands()[i]); // recursive call
2025+
if(r_it.has_changed())
2026+
{
2027+
if(!new_operands.has_value())
2028+
new_operands = expr.operands();
2029+
(*new_operands)[i] = std::move(r_it.expr);
2030+
}
2031+
}
2032+
2033+
if(new_operands.has_value())
2034+
{
2035+
exprt result = expr;
2036+
std::swap(result.operands(), *new_operands);
2037+
return result;
2038+
}
2039+
}
2040+
2041+
return unchanged(expr);
2042+
}
2043+
20142044
simplify_exprt::resultt<>
20152045
simplify_exprt::simplify_byte_update(const byte_update_exprt &expr)
20162046
{
@@ -2721,9 +2751,10 @@ simplify_exprt::simplify_overflow_result(const overflow_result_exprt &expr)
27212751
}
27222752
}
27232753

2724-
bool simplify_exprt::simplify_node_preorder(exprt &expr)
2754+
simplify_exprt::resultt<>
2755+
simplify_exprt::simplify_node_preorder(const exprt &expr)
27252756
{
2726-
bool result=true;
2757+
auto result = unchanged(expr);
27272758

27282759
// The ifs below could one day be replaced by a switch()
27292760

@@ -2732,40 +2763,75 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr)
27322763
// the argument of this expression needs special treatment
27332764
}
27342765
else if(expr.id()==ID_if)
2735-
result=simplify_if_preorder(to_if_expr(expr));
2766+
{
2767+
result = simplify_if_preorder(to_if_expr(expr));
2768+
}
27362769
else if(expr.id() == ID_typecast)
2770+
{
27372771
result = simplify_typecast_preorder(to_typecast_expr(expr));
2738-
else
2772+
}
2773+
else if(
2774+
expr.id() == ID_byte_extract_little_endian ||
2775+
expr.id() == ID_byte_extract_big_endian)
2776+
{
2777+
result = simplify_byte_extract_preorder(to_byte_extract_expr(expr));
2778+
}
2779+
else if(expr.id() == ID_dereference)
2780+
{
2781+
result = simplify_dereference_preorder(to_dereference_expr(expr));
2782+
}
2783+
else if(expr.id() == ID_index)
27392784
{
2740-
if(expr.has_operands())
2785+
result = simplify_index_preorder(to_index_expr(expr));
2786+
}
2787+
else if(expr.id() == ID_member)
2788+
{
2789+
result = simplify_member_preorder(to_member_expr(expr));
2790+
}
2791+
else if(
2792+
expr.id() == ID_is_dynamic_object || expr.id() == ID_is_invalid_pointer ||
2793+
expr.id() == ID_object_size || expr.id() == ID_pointer_object ||
2794+
expr.id() == ID_pointer_offset)
2795+
{
2796+
result = simplify_unary_pointer_predicate_preorder(to_unary_expr(expr));
2797+
}
2798+
else if(expr.has_operands())
2799+
{
2800+
optionalt<exprt::operandst> new_operands;
2801+
2802+
for(std::size_t i = 0; i < expr.operands().size(); ++i)
27412803
{
2742-
Forall_operands(it, expr)
2804+
auto r_it = simplify_rec(expr.operands()[i]); // recursive call
2805+
if(r_it.has_changed())
27432806
{
2744-
auto r_it = simplify_rec(*it); // recursive call
2745-
if(r_it.has_changed())
2746-
{
2747-
*it = r_it.expr;
2748-
result=false;
2749-
}
2807+
if(!new_operands.has_value())
2808+
new_operands = expr.operands();
2809+
(*new_operands)[i] = std::move(r_it.expr);
27502810
}
27512811
}
2812+
2813+
if(new_operands.has_value())
2814+
{
2815+
std::swap(result.expr.operands(), *new_operands);
2816+
result.expr_changed = resultt<>::CHANGED;
2817+
}
27522818
}
27532819

2754-
if(as_const(expr).type().id() == ID_array)
2820+
if(as_const(result.expr).type().id() == ID_array)
27552821
{
2756-
const array_typet &array_type = to_array_type(as_const(expr).type());
2822+
const array_typet &array_type = to_array_type(as_const(result.expr).type());
27572823
resultt<> simp_size = simplify_rec(array_type.size());
27582824
if(simp_size.has_changed())
27592825
{
2760-
to_array_type(expr.type()).size() = simp_size.expr;
2761-
result = false;
2826+
to_array_type(result.expr.type()).size() = simp_size.expr;
2827+
result.expr_changed = resultt<>::CHANGED;
27622828
}
27632829
}
27642830

27652831
return result;
27662832
}
27672833

2768-
simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
2834+
simplify_exprt::resultt<> simplify_exprt::simplify_node(const exprt &node)
27692835
{
27702836
if(!node.has_operands())
27712837
return unchanged(node); // no change
@@ -3062,53 +3128,54 @@ simplify_exprt::resultt<> simplify_exprt::simplify_rec(const exprt &expr)
30623128
#endif
30633129

30643130
// We work on a copy to prevent unnecessary destruction of sharing.
3065-
exprt tmp=expr;
3066-
bool no_change = simplify_node_preorder(tmp);
3131+
auto simplify_node_preorder_result = simplify_node_preorder(expr);
30673132

3068-
auto simplify_node_result = simplify_node(tmp);
3133+
auto simplify_node_result = simplify_node(simplify_node_preorder_result.expr);
30693134

3070-
if(simplify_node_result.has_changed())
3135+
if(
3136+
!simplify_node_result.has_changed() &&
3137+
simplify_node_preorder_result.has_changed())
30713138
{
3072-
no_change = false;
3073-
tmp = simplify_node_result.expr;
3139+
simplify_node_result.expr_changed =
3140+
simplify_node_preorder_result.expr_changed;
30743141
}
30753142

30763143
#ifdef USE_LOCAL_REPLACE_MAP
3077-
#if 1
3078-
replace_mapt::const_iterator it=local_replace_map.find(tmp);
3144+
exprt tmp = simplify_node_result.expr;
3145+
# if 1
3146+
replace_mapt::const_iterator it =
3147+
local_replace_map.find(simplify_node_result.expr);
30793148
if(it!=local_replace_map.end())
3149+
simplify_node_result = changed(it->second);
3150+
# else
3151+
if(
3152+
!local_replace_map.empty() &&
3153+
!replace_expr(local_replace_map, simplify_node_result.expr))
30803154
{
3081-
tmp=it->second;
3082-
no_change = false;
3083-
}
3084-
#else
3085-
if(!local_replace_map.empty() &&
3086-
!replace_expr(local_replace_map, tmp))
3087-
{
3088-
simplify_rec(tmp);
3089-
no_change = false;
3155+
simplify_node_result = changed(simplify_rec(simplify_node_result.expr));
30903156
}
3091-
#endif
3157+
# endif
30923158
#endif
30933159

3094-
if(no_change) // no change
3160+
if(!simplify_node_result.has_changed())
30953161
{
30963162
return unchanged(expr);
30973163
}
3098-
else // change, new expression is 'tmp'
3164+
else
30993165
{
31003166
POSTCONDITION_WITH_DIAGNOSTICS(
3101-
(as_const(tmp).type().id() == ID_array && expr.type().id() == ID_array) ||
3102-
as_const(tmp).type() == expr.type(),
3103-
tmp.pretty(),
3167+
(as_const(simplify_node_result.expr).type().id() == ID_array &&
3168+
expr.type().id() == ID_array) ||
3169+
as_const(simplify_node_result.expr).type() == expr.type(),
3170+
simplify_node_result.expr.pretty(),
31043171
expr.pretty());
31053172

31063173
#ifdef USE_CACHE
31073174
// save in cache
3108-
cache_result.first->second = tmp;
3175+
cache_result.first->second = simplify_node_result.expr;
31093176
#endif
31103177

3111-
return std::move(tmp);
3178+
return simplify_node_result;
31123179
}
31133180
}
31143181

0 commit comments

Comments
 (0)