@@ -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
13721371simplify_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+
14301436simplify_exprt::resultt<>
14311437simplify_exprt::simplify_lambda (const lambda_exprt &expr)
14321438{
@@ -1643,17 +1649,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_object(const exprt &expr)
16431649simplify_exprt::resultt<>
16441650simplify_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+
20142044simplify_exprt::resultt<>
20152045simplify_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