diff --git a/src/util/simplify_expr.cpp b/src/util/simplify_expr.cpp index ca80f2eae77..ac66c5c40e5 100644 --- a/src/util/simplify_expr.cpp +++ b/src/util/simplify_expr.cpp @@ -820,9 +820,8 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr) // rewrite (T)(bool) to bool?1:0 auto one = from_integer(1, expr_type); auto zero = from_integer(0, expr_type); - exprt new_expr = if_exprt(expr.op(), std::move(one), std::move(zero)); - simplify_if_preorder(to_if_expr(new_expr)); - return new_expr; + return changed(simplify_if_preorder( + if_exprt{expr.op(), std::move(one), std::move(zero)})); } // circular casts through types shorter than `int` @@ -1340,33 +1339,33 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr) return unchanged(expr); } -bool simplify_exprt::simplify_typecast_preorder(typecast_exprt &expr) +simplify_exprt::resultt<> +simplify_exprt::simplify_typecast_preorder(const typecast_exprt &expr) { - const typet &expr_type = as_const(expr).type(); - const typet &op_type = as_const(expr).op().type(); + const typet &expr_type = expr.type(); + const typet &op_type = expr.op().type(); // (T)(a?b:c) --> a?(T)b:(T)c; don't do this for floating-point type casts as // the type cast itself may be costly if( - as_const(expr).op().id() == ID_if && expr_type.id() != ID_floatbv && + expr.op().id() == ID_if && expr_type.id() != ID_floatbv && op_type.id() != ID_floatbv) { if_exprt if_expr = lift_if(expr, 0); - simplify_if_preorder(if_expr); - expr.swap(if_expr); - return false; + return changed(simplify_if_preorder(if_expr)); } else { auto r_it = simplify_rec(expr.op()); // recursive call if(r_it.has_changed()) { - expr.op() = r_it.expr; - return false; + auto tmp = expr; + tmp.op() = r_it.expr; + return tmp; } - else - return true; } + + return unchanged(expr); } simplify_exprt::resultt<> @@ -1377,23 +1376,6 @@ simplify_exprt::simplify_dereference(const dereference_exprt &expr) if(pointer.type().id()!=ID_pointer) return unchanged(expr); - if(pointer.id()==ID_if && pointer.operands().size()==3) - { - const if_exprt &if_expr=to_if_expr(pointer); - - auto tmp_op1 = expr; - tmp_op1.op() = if_expr.true_case(); - exprt tmp_op1_result = simplify_dereference(tmp_op1); - - auto tmp_op2 = expr; - tmp_op2.op() = if_expr.false_case(); - exprt tmp_op2_result = simplify_dereference(tmp_op2); - - if_exprt tmp{if_expr.cond(), tmp_op1_result, tmp_op2_result}; - - return changed(simplify_if(tmp)); - } - if(pointer.id()==ID_address_of) { exprt tmp=to_address_of_expr(pointer).object(); @@ -1427,6 +1409,30 @@ simplify_exprt::simplify_dereference(const dereference_exprt &expr) return unchanged(expr); } +simplify_exprt::resultt<> +simplify_exprt::simplify_dereference_preorder(const dereference_exprt &expr) +{ + const exprt &pointer = expr.pointer(); + + if(pointer.id() == ID_if) + { + if_exprt if_expr = lift_if(expr, 0); + return changed(simplify_if_preorder(if_expr)); + } + else + { + auto r_it = simplify_rec(pointer); // recursive call + if(r_it.has_changed()) + { + auto tmp = expr; + tmp.pointer() = r_it.expr; + return tmp; + } + } + + return unchanged(expr); +} + simplify_exprt::resultt<> simplify_exprt::simplify_lambda(const lambda_exprt &expr) { @@ -1643,17 +1649,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_object(const exprt &expr) simplify_exprt::resultt<> simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr) { - // lift up any ID_if on the object - if(expr.op().id()==ID_if) - { - if_exprt if_expr=lift_if(expr, 0); - if_expr.true_case() = - simplify_byte_extract(to_byte_extract_expr(if_expr.true_case())); - if_expr.false_case() = - simplify_byte_extract(to_byte_extract_expr(if_expr.false_case())); - return changed(simplify_if(if_expr)); - } - const auto el_size = pointer_offset_bits(expr.type(), ns); if(el_size.has_value() && *el_size < 0) return unchanged(expr); @@ -2011,6 +2006,41 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr) return unchanged(expr); } +simplify_exprt::resultt<> +simplify_exprt::simplify_byte_extract_preorder(const byte_extract_exprt &expr) +{ + // lift up any ID_if on the object + if(expr.op().id() == ID_if) + { + if_exprt if_expr = lift_if(expr, 0); + return changed(simplify_if_preorder(if_expr)); + } + else + { + optionalt new_operands; + + for(std::size_t i = 0; i < expr.operands().size(); ++i) + { + auto r_it = simplify_rec(expr.operands()[i]); // recursive call + if(r_it.has_changed()) + { + if(!new_operands.has_value()) + new_operands = expr.operands(); + (*new_operands)[i] = std::move(r_it.expr); + } + } + + if(new_operands.has_value()) + { + exprt result = expr; + std::swap(result.operands(), *new_operands); + return result; + } + } + + return unchanged(expr); +} + simplify_exprt::resultt<> simplify_exprt::simplify_byte_update(const byte_update_exprt &expr) { @@ -2721,9 +2751,10 @@ simplify_exprt::simplify_overflow_result(const overflow_result_exprt &expr) } } -bool simplify_exprt::simplify_node_preorder(exprt &expr) +simplify_exprt::resultt<> +simplify_exprt::simplify_node_preorder(const exprt &expr) { - bool result=true; + auto result = unchanged(expr); // The ifs below could one day be replaced by a switch() @@ -2732,40 +2763,75 @@ bool simplify_exprt::simplify_node_preorder(exprt &expr) // the argument of this expression needs special treatment } else if(expr.id()==ID_if) - result=simplify_if_preorder(to_if_expr(expr)); + { + result = simplify_if_preorder(to_if_expr(expr)); + } else if(expr.id() == ID_typecast) + { result = simplify_typecast_preorder(to_typecast_expr(expr)); - else + } + else if( + expr.id() == ID_byte_extract_little_endian || + expr.id() == ID_byte_extract_big_endian) + { + result = simplify_byte_extract_preorder(to_byte_extract_expr(expr)); + } + else if(expr.id() == ID_dereference) + { + result = simplify_dereference_preorder(to_dereference_expr(expr)); + } + else if(expr.id() == ID_index) { - if(expr.has_operands()) + result = simplify_index_preorder(to_index_expr(expr)); + } + else if(expr.id() == ID_member) + { + result = simplify_member_preorder(to_member_expr(expr)); + } + else if( + expr.id() == ID_is_dynamic_object || expr.id() == ID_is_invalid_pointer || + expr.id() == ID_object_size || expr.id() == ID_pointer_object || + expr.id() == ID_pointer_offset) + { + result = simplify_unary_pointer_predicate_preorder(to_unary_expr(expr)); + } + else if(expr.has_operands()) + { + optionalt new_operands; + + for(std::size_t i = 0; i < expr.operands().size(); ++i) { - Forall_operands(it, expr) + auto r_it = simplify_rec(expr.operands()[i]); // recursive call + if(r_it.has_changed()) { - auto r_it = simplify_rec(*it); // recursive call - if(r_it.has_changed()) - { - *it = r_it.expr; - result=false; - } + if(!new_operands.has_value()) + new_operands = expr.operands(); + (*new_operands)[i] = std::move(r_it.expr); } } + + if(new_operands.has_value()) + { + std::swap(result.expr.operands(), *new_operands); + result.expr_changed = resultt<>::CHANGED; + } } - if(as_const(expr).type().id() == ID_array) + if(as_const(result.expr).type().id() == ID_array) { - const array_typet &array_type = to_array_type(as_const(expr).type()); + const array_typet &array_type = to_array_type(as_const(result.expr).type()); resultt<> simp_size = simplify_rec(array_type.size()); if(simp_size.has_changed()) { - to_array_type(expr.type()).size() = simp_size.expr; - result = false; + to_array_type(result.expr.type()).size() = simp_size.expr; + result.expr_changed = resultt<>::CHANGED; } } return result; } -simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node) +simplify_exprt::resultt<> simplify_exprt::simplify_node(const exprt &node) { if(!node.has_operands()) return unchanged(node); // no change @@ -3062,53 +3128,54 @@ simplify_exprt::resultt<> simplify_exprt::simplify_rec(const exprt &expr) #endif // We work on a copy to prevent unnecessary destruction of sharing. - exprt tmp=expr; - bool no_change = simplify_node_preorder(tmp); + auto simplify_node_preorder_result = simplify_node_preorder(expr); - auto simplify_node_result = simplify_node(tmp); + auto simplify_node_result = simplify_node(simplify_node_preorder_result.expr); - if(simplify_node_result.has_changed()) + if( + !simplify_node_result.has_changed() && + simplify_node_preorder_result.has_changed()) { - no_change = false; - tmp = simplify_node_result.expr; + simplify_node_result.expr_changed = + simplify_node_preorder_result.expr_changed; } #ifdef USE_LOCAL_REPLACE_MAP - #if 1 - replace_mapt::const_iterator it=local_replace_map.find(tmp); + exprt tmp = simplify_node_result.expr; +# if 1 + replace_mapt::const_iterator it = + local_replace_map.find(simplify_node_result.expr); if(it!=local_replace_map.end()) + simplify_node_result = changed(it->second); +# else + if( + !local_replace_map.empty() && + !replace_expr(local_replace_map, simplify_node_result.expr)) { - tmp=it->second; - no_change = false; - } - #else - if(!local_replace_map.empty() && - !replace_expr(local_replace_map, tmp)) - { - simplify_rec(tmp); - no_change = false; + simplify_node_result = changed(simplify_rec(simplify_node_result.expr)); } - #endif +# endif #endif - if(no_change) // no change + if(!simplify_node_result.has_changed()) { return unchanged(expr); } - else // change, new expression is 'tmp' + else { POSTCONDITION_WITH_DIAGNOSTICS( - (as_const(tmp).type().id() == ID_array && expr.type().id() == ID_array) || - as_const(tmp).type() == expr.type(), - tmp.pretty(), + (as_const(simplify_node_result.expr).type().id() == ID_array && + expr.type().id() == ID_array) || + as_const(simplify_node_result.expr).type() == expr.type(), + simplify_node_result.expr.pretty(), expr.pretty()); #ifdef USE_CACHE // save in cache - cache_result.first->second = tmp; + cache_result.first->second = simplify_node_result.expr; #endif - return std::move(tmp); + return simplify_node_result; } } diff --git a/src/util/simplify_expr_array.cpp b/src/util/simplify_expr_array.cpp index 6729db7f38f..2d71032069f 100644 --- a/src/util/simplify_expr_array.cpp +++ b/src/util/simplify_expr_array.cpp @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "arith_tools.h" #include "byte_operators.h" +#include "expr_util.h" #include "pointer_offset_size.h" #include "replace_expr.h" #include "std_expr.h" @@ -196,22 +197,44 @@ simplify_exprt::simplify_index(const index_exprt &expr) return changed(simplify_byte_extract(result_expr)); } } - else if(array.id()==ID_if) - { - const if_exprt &if_expr=to_if_expr(array); - exprt cond=if_expr.cond(); - - index_exprt idx_false=to_index_expr(expr); - idx_false.array()=if_expr.false_case(); - - new_expr.array() = if_expr.true_case(); - - exprt result = if_exprt(cond, new_expr, idx_false, expr.type()); - return changed(simplify_rec(result)); - } if(no_change) return unchanged(expr); else return std::move(new_expr); } + +simplify_exprt::resultt<> +simplify_exprt::simplify_index_preorder(const index_exprt &expr) +{ + // lift up any ID_if on the array + if(expr.array().id() == ID_if) + { + if_exprt if_expr = lift_if(expr, 0); + return changed(simplify_if_preorder(if_expr)); + } + else + { + optionalt new_operands; + + for(std::size_t i = 0; i < expr.operands().size(); ++i) + { + auto r_it = simplify_rec(expr.operands()[i]); // recursive call + if(r_it.has_changed()) + { + if(!new_operands.has_value()) + new_operands = expr.operands(); + (*new_operands)[i] = std::move(r_it.expr); + } + } + + if(new_operands.has_value()) + { + exprt result = expr; + std::swap(result.operands(), *new_operands); + return result; + } + } + + return unchanged(expr); +} diff --git a/src/util/simplify_expr_class.h b/src/util/simplify_expr_class.h index 5e834c35421..4b08396c190 100644 --- a/src/util/simplify_expr_class.h +++ b/src/util/simplify_expr_class.h @@ -149,7 +149,7 @@ class simplify_exprt // These below all return 'true' if the simplification wasn't applicable. // If false is returned, the expression has changed. NODISCARD resultt<> simplify_typecast(const typecast_exprt &); - bool simplify_typecast_preorder(typecast_exprt &); + NODISCARD resultt<> simplify_typecast_preorder(const typecast_exprt &); NODISCARD resultt<> simplify_extractbit(const extractbit_exprt &); NODISCARD resultt<> simplify_extractbits(const extractbits_exprt &); NODISCARD resultt<> simplify_concatenation(const concatenation_exprt &); @@ -163,7 +163,7 @@ class simplify_exprt NODISCARD resultt<> simplify_shifts(const shift_exprt &); NODISCARD resultt<> simplify_power(const binary_exprt &); NODISCARD resultt<> simplify_bitwise(const multi_ary_exprt &); - bool simplify_if_preorder(if_exprt &expr); + NODISCARD resultt<> simplify_if_preorder(const if_exprt &expr); NODISCARD resultt<> simplify_if(const if_exprt &); NODISCARD resultt<> simplify_bitnot(const bitnot_exprt &); NODISCARD resultt<> simplify_not(const not_exprt &); @@ -175,10 +175,16 @@ class simplify_exprt NODISCARD resultt<> simplify_with(const with_exprt &); NODISCARD resultt<> simplify_update(const update_exprt &); NODISCARD resultt<> simplify_index(const index_exprt &); + NODISCARD resultt<> simplify_index_preorder(const index_exprt &); NODISCARD resultt<> simplify_member(const member_exprt &); + NODISCARD resultt<> simplify_member_preorder(const member_exprt &); NODISCARD resultt<> simplify_byte_update(const byte_update_exprt &); NODISCARD resultt<> simplify_byte_extract(const byte_extract_exprt &); + NODISCARD resultt<> + simplify_byte_extract_preorder(const byte_extract_exprt &); NODISCARD resultt<> simplify_pointer_object(const pointer_object_exprt &); + NODISCARD resultt<> + simplify_unary_pointer_predicate_preorder(const unary_exprt &); NODISCARD resultt<> simplify_object_size(const object_size_exprt &); NODISCARD resultt<> simplify_is_dynamic_object(const unary_exprt &); NODISCARD resultt<> simplify_is_invalid_pointer(const unary_exprt &); @@ -186,6 +192,7 @@ class simplify_exprt NODISCARD resultt<> simplify_unary_minus(const unary_minus_exprt &); NODISCARD resultt<> simplify_unary_plus(const unary_plus_exprt &); NODISCARD resultt<> simplify_dereference(const dereference_exprt &); + NODISCARD resultt<> simplify_dereference_preorder(const dereference_exprt &); NODISCARD resultt<> simplify_address_of(const address_of_exprt &); NODISCARD resultt<> simplify_pointer_offset(const pointer_offset_exprt &); NODISCARD resultt<> simplify_bswap(const bswap_exprt &); @@ -259,8 +266,8 @@ class simplify_exprt simplify_inequality_pointer_object(const binary_relation_exprt &); // main recursion - NODISCARD resultt<> simplify_node(exprt); - bool simplify_node_preorder(exprt &expr); + NODISCARD resultt<> simplify_node(const exprt &); + NODISCARD resultt<> simplify_node_preorder(const exprt &); NODISCARD resultt<> simplify_rec(const exprt &); virtual bool simplify(exprt &expr); diff --git a/src/util/simplify_expr_if.cpp b/src/util/simplify_expr_if.cpp index d56dd9a4192..c951603af48 100644 --- a/src/util/simplify_expr_if.cpp +++ b/src/util/simplify_expr_if.cpp @@ -211,47 +211,66 @@ bool simplify_exprt::simplify_if_cond(exprt &expr) return no_change; } -bool simplify_exprt::simplify_if_preorder(if_exprt &expr) +static simplify_exprt::resultt<> build_if_expr( + const if_exprt &expr, + simplify_exprt::resultt<> cond, + simplify_exprt::resultt<> truevalue, + simplify_exprt::resultt<> falsevalue) { - exprt &cond = expr.cond(); - exprt &truevalue = expr.true_case(); - exprt &falsevalue = expr.false_case(); + if( + !cond.has_changed() && !truevalue.has_changed() && + !falsevalue.has_changed()) + { + return simplify_exprt::resultt<>( + simplify_exprt::resultt<>::UNCHANGED, expr); + } + else + { + if_exprt result = expr; + if(cond.has_changed()) + result.cond() = std::move(cond.expr); + if(truevalue.has_changed()) + result.true_case() = std::move(truevalue.expr); + if(falsevalue.has_changed()) + result.false_case() = std::move(falsevalue.expr); + return result; + } +} - bool no_change = true; +simplify_exprt::resultt<> +simplify_exprt::simplify_if_preorder(const if_exprt &expr) +{ + const exprt &cond = expr.cond(); + const exprt &truevalue = expr.true_case(); + const exprt &falsevalue = expr.false_case(); // we first want to look at the condition auto r_cond = simplify_rec(cond); - if(r_cond.has_changed()) - { - cond = r_cond.expr; - no_change = false; - } // 1 ? a : b -> a and 0 ? a : b -> b - if(cond.is_constant()) + if(r_cond.expr.is_constant()) { - exprt tmp = cond.is_true() ? truevalue : falsevalue; - tmp = simplify_rec(tmp); - expr.swap(tmp); - return false; + return changed( + simplify_rec(r_cond.expr.is_true() ? truevalue : falsevalue)); } if(do_simplify_if) { - if(cond.id() == ID_not) + bool swap_branches = false; + + if(r_cond.expr.id() == ID_not) { - cond = to_not_expr(cond).op(); - truevalue.swap(falsevalue); - no_change = false; + r_cond = changed(to_not_expr(r_cond.expr).op()); + swap_branches = true; } #ifdef USE_LOCAL_REPLACE_MAP replace_mapt map_before(local_replace_map); // a ? b : c --> a ? b[a/true] : c - if(cond.id() == ID_and) + if(r_cond.expr.id() == ID_and) { - for(const auto &op : as_const(cond).operands()) + for(const auto &op : r_cond.expr.operands()) { if(op.id() == ID_not) local_replace_map.insert(std::make_pair(op.op0(), false_exprt())); @@ -260,21 +279,16 @@ bool simplify_exprt::simplify_if_preorder(if_exprt &expr) } } else - local_replace_map.insert(std::make_pair(cond, true_exprt())); + local_replace_map.insert(std::make_pair(r_cond.expr, true_exprt())); - auto r_truevalue = simplify_rec(truevalue); - if(r_truevalue.has_changed()) - { - truevalue = r_truevalue.expr; - no_change = false; - } + auto r_truevalue = simplify_rec(swap_branches ? falsevalue : truevalue); local_replace_map = map_before; // a ? b : c --> a ? b : c[a/false] - if(cond.id() == ID_or) + if(r_cond.expr.id() == ID_or) { - for(const auto &op : as_const(cond).operands()) + for(const auto &op : r_cond.expr.operands()) { if(op.id() == ID_not) local_replace_map.insert(std::make_pair(op.op0(), true_exprt())); @@ -283,48 +297,40 @@ bool simplify_exprt::simplify_if_preorder(if_exprt &expr) } } else - local_replace_map.insert(std::make_pair(cond, false_exprt())); + local_replace_map.insert(std::make_pair(r_cond.expr, false_exprt())); - auto r_falsevalue = simplify_rec(falsevalue); - if(r_falsevalue.has_changed()) - { - falsevalue = r_falsevalue.expr; - no_change = false; - } + auto r_falsevalue = simplify_rec(swap_branches ? truevalue : falsevalue); local_replace_map.swap(map_before); + + if(swap_branches) + { + // tell build_if_expr to replace truevalue and falsevalue + r_truevalue.expr_changed = CHANGED; + r_falsevalue.expr_changed = CHANGED; + } + return build_if_expr(expr, r_cond, r_truevalue, r_falsevalue); #else - auto r_truevalue = simplify_rec(truevalue); - if(r_truevalue.has_changed()) + if(!swap_branches) { - truevalue = r_truevalue.expr; - no_change = false; + return build_if_expr( + expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue)); } - auto r_falsevalue = simplify_rec(falsevalue); - if(r_falsevalue.has_changed()) + else { - falsevalue = r_falsevalue.expr; - no_change = false; + return build_if_expr( + expr, + r_cond, + changed(simplify_rec(falsevalue)), + changed(simplify_rec(truevalue))); } #endif } else { - auto r_truevalue = simplify_rec(truevalue); - if(r_truevalue.has_changed()) - { - truevalue = r_truevalue.expr; - no_change = false; - } - auto r_falsevalue = simplify_rec(falsevalue); - if(r_falsevalue.has_changed()) - { - falsevalue = r_falsevalue.expr; - no_change = false; - } + return build_if_expr( + expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue)); } - - return no_change; } simplify_exprt::resultt<> simplify_exprt::simplify_if(const if_exprt &expr) diff --git a/src/util/simplify_expr_pointer.cpp b/src/util/simplify_expr_pointer.cpp index 1334d4e645f..b2255cd2e95 100644 --- a/src/util/simplify_expr_pointer.cpp +++ b/src/util/simplify_expr_pointer.cpp @@ -53,6 +53,32 @@ static bool is_dereference_integer_object( return false; } +simplify_exprt::resultt<> +simplify_exprt::simplify_unary_pointer_predicate_preorder( + const unary_exprt &expr) +{ + const exprt &pointer = expr.op(); + PRECONDITION(pointer.type().id() == ID_pointer); + + if(pointer.id() == ID_if) + { + if_exprt if_expr = lift_if(expr, 0); + return changed(simplify_if_preorder(if_expr)); + } + else + { + auto r_it = simplify_rec(pointer); // recursive call + if(r_it.has_changed()) + { + auto tmp = expr; + tmp.op() = r_it.expr; + return tmp; + } + } + + return unchanged(expr); +} + simplify_exprt::resultt<> simplify_exprt::simplify_address_of_arg(const exprt &expr) { @@ -249,16 +275,6 @@ simplify_exprt::simplify_pointer_offset(const pointer_offset_exprt &expr) { const exprt &ptr = expr.pointer(); - if(ptr.id()==ID_if && ptr.operands().size()==3) - { - if_exprt if_expr=lift_if(expr, 0); - if_expr.true_case() = - simplify_pointer_offset(to_pointer_offset_expr(if_expr.true_case())); - if_expr.false_case() = - simplify_pointer_offset(to_pointer_offset_expr(if_expr.false_case())); - return changed(simplify_if(if_expr)); - } - if(ptr.type().id()!=ID_pointer) return unchanged(expr); @@ -559,16 +575,6 @@ simplify_exprt::simplify_is_dynamic_object(const unary_exprt &expr) auto new_expr = expr; exprt &op = new_expr.op(); - if(op.id()==ID_if && op.operands().size()==3) - { - if_exprt if_expr=lift_if(expr, 0); - if_expr.true_case() = - simplify_is_dynamic_object(to_unary_expr(if_expr.true_case())); - if_expr.false_case() = - simplify_is_dynamic_object(to_unary_expr(if_expr.false_case())); - return changed(simplify_if(if_expr)); - } - bool no_change = true; auto op_result = simplify_object(op); diff --git a/src/util/simplify_expr_struct.cpp b/src/util/simplify_expr_struct.cpp index 72d98954414..2e66c929a85 100644 --- a/src/util/simplify_expr_struct.cpp +++ b/src/util/simplify_expr_struct.cpp @@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "byte_operators.h" #include "c_types.h" #include "config.h" +#include "expr_util.h" #include "invariant.h" #include "namespace.h" #include "pointer_offset_size.h" @@ -240,20 +241,6 @@ simplify_exprt::simplify_member(const member_exprt &expr) } } } - else if(op.id()==ID_if) - { - const if_exprt &if_expr=to_if_expr(op); - exprt cond=if_expr.cond(); - - member_exprt member_false=to_member_expr(expr); - member_false.compound()=if_expr.false_case(); - - member_exprt member_true = to_member_expr(expr); - member_true.compound() = if_expr.true_case(); - - auto tmp = if_exprt(cond, member_true, member_false, expr.type()); - return changed(simplify_rec(tmp)); - } else if(op.id() == ID_let) { // Push a member operator inside a let binding, to avoid the let bisecting @@ -271,3 +258,27 @@ simplify_exprt::simplify_member(const member_exprt &expr) return unchanged(expr); } + +simplify_exprt::resultt<> +simplify_exprt::simplify_member_preorder(const member_exprt &expr) +{ + const exprt &compound = expr.compound(); + + if(compound.id() == ID_if) + { + if_exprt if_expr = lift_if(expr, 0); + return changed(simplify_if_preorder(if_expr)); + } + else + { + auto r_it = simplify_rec(compound); // recursive call + if(r_it.has_changed()) + { + auto tmp = expr; + tmp.compound() = r_it.expr; + return tmp; + } + } + + return unchanged(expr); +}