Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use simplify_exprtt::resultt in pre-order simplification steps #6118

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 151 additions & 84 deletions src/util/simplify_expr.cpp
Original file line number Diff line number Diff line change
@@ -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<exprt::operandst> 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<exprt::operandst> 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;
}
}

49 changes: 36 additions & 13 deletions src/util/simplify_expr_array.cpp
Original file line number Diff line number Diff line change
@@ -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<exprt::operandst> 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);
}
15 changes: 11 additions & 4 deletions src/util/simplify_expr_class.h
Original file line number Diff line number Diff line change
@@ -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,17 +175,24 @@ 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 &);
NODISCARD resultt<> simplify_object(const 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);
124 changes: 65 additions & 59 deletions src/util/simplify_expr_if.cpp
Original file line number Diff line number Diff line change
@@ -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);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? The if-expression will be marked as changed anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but build_if_expr would not actually replace the truevalue.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have refactored the code and added a comment.

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)
46 changes: 26 additions & 20 deletions src/util/simplify_expr_pointer.cpp
Original file line number Diff line number Diff line change
@@ -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);
39 changes: 25 additions & 14 deletions src/util/simplify_expr_struct.cpp
Original file line number Diff line number Diff line change
@@ -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);
}