Skip to content

Commit 7092be8

Browse files
committed
Use simplify_exprtt::resultt in pre-order simplification steps
The use of resultt increases type safety as the expression to be simplified is no longer modified in place. All post-order simplification steps already use resultt, but pre-order steps had been left to be done.
1 parent b08632a commit 7092be8

File tree

3 files changed

+116
-103
lines changed

3 files changed

+116
-103
lines changed

src/util/simplify_expr.cpp

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,8 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
815815
// rewrite (T)(bool) to bool?1:0
816816
auto one = from_integer(1, expr_type);
817817
auto zero = from_integer(0, expr_type);
818-
exprt new_expr = if_exprt(expr.op(), std::move(one), std::move(zero));
819-
simplify_if_preorder(to_if_expr(new_expr));
820-
return new_expr;
818+
return changed(simplify_if_preorder(
819+
if_exprt{expr.op(), std::move(one), std::move(zero)}));
821820
}
822821

823822
// circular casts through types shorter than `int`
@@ -2557,38 +2556,46 @@ simplify_exprt::simplify_overflow_result(const overflow_result_exprt &expr)
25572556
}
25582557
}
25592558

2560-
bool simplify_exprt::simplify_node_preorder(exprt &expr)
2559+
simplify_exprt::resultt<>
2560+
simplify_exprt::simplify_node_preorder(const exprt &expr)
25612561
{
2562-
bool result=true;
2563-
25642562
// The ifs below could one day be replaced by a switch()
25652563

25662564
if(expr.id()==ID_address_of)
25672565
{
25682566
// the argument of this expression needs special treatment
25692567
}
25702568
else if(expr.id()==ID_if)
2571-
result=simplify_if_preorder(to_if_expr(expr));
2572-
else
25732569
{
2574-
if(expr.has_operands())
2570+
return simplify_if_preorder(to_if_expr(expr));
2571+
}
2572+
else if(expr.has_operands())
2573+
{
2574+
optionalt<exprt::operandst> new_operands;
2575+
2576+
for(std::size_t i = 0; i < expr.operands().size(); ++i)
25752577
{
2576-
Forall_operands(it, expr)
2578+
auto r_it = simplify_rec(expr.operands()[i]); // recursive call
2579+
if(r_it.has_changed())
25772580
{
2578-
auto r_it = simplify_rec(*it); // recursive call
2579-
if(r_it.has_changed())
2580-
{
2581-
*it = r_it.expr;
2582-
result=false;
2583-
}
2581+
if(!new_operands.has_value())
2582+
new_operands = expr.operands();
2583+
(*new_operands)[i] = std::move(r_it.expr);
25842584
}
25852585
}
2586+
2587+
if(new_operands.has_value())
2588+
{
2589+
exprt result = expr;
2590+
std::swap(result.operands(), *new_operands);
2591+
return result;
2592+
}
25862593
}
25872594

2588-
return result;
2595+
return unchanged(expr);
25892596
}
25902597

2591-
simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
2598+
simplify_exprt::resultt<> simplify_exprt::simplify_node(const exprt &node)
25922599
{
25932600
if(!node.has_operands())
25942601
return unchanged(node); // no change
@@ -2877,49 +2884,49 @@ simplify_exprt::resultt<> simplify_exprt::simplify_rec(const exprt &expr)
28772884
#endif
28782885

28792886
// We work on a copy to prevent unnecessary destruction of sharing.
2880-
exprt tmp=expr;
2881-
bool no_change = simplify_node_preorder(tmp);
2887+
auto simplify_node_preorder_result = simplify_node_preorder(expr);
28822888

2883-
auto simplify_node_result = simplify_node(tmp);
2889+
auto simplify_node_result = simplify_node(simplify_node_preorder_result.expr);
28842890

2885-
if(simplify_node_result.has_changed())
2891+
if(
2892+
!simplify_node_result.has_changed() &&
2893+
simplify_node_preorder_result.has_changed())
28862894
{
2887-
no_change = false;
2888-
tmp = simplify_node_result.expr;
2895+
simplify_node_result.expr_changed =
2896+
simplify_node_preorder_result.expr_changed;
28892897
}
28902898

28912899
#ifdef USE_LOCAL_REPLACE_MAP
2892-
#if 1
2893-
replace_mapt::const_iterator it=local_replace_map.find(tmp);
2900+
exprt tmp = simplify_node_result.expr;
2901+
# if 1
2902+
replace_mapt::const_iterator it =
2903+
local_replace_map.find(simplify_node_result.expr);
28942904
if(it!=local_replace_map.end())
2905+
simplify_node_result = changed(it->second);
2906+
# else
2907+
if(
2908+
!local_replace_map.empty() &&
2909+
!replace_expr(local_replace_map, simplify_node_result.expr))
28952910
{
2896-
tmp=it->second;
2897-
no_change = false;
2898-
}
2899-
#else
2900-
if(!local_replace_map.empty() &&
2901-
!replace_expr(local_replace_map, tmp))
2902-
{
2903-
simplify_rec(tmp);
2904-
no_change = false;
2911+
simplify_node_result = changed(simplify_rec(simplify_node_result.expr));
29052912
}
2906-
#endif
2913+
# endif
29072914
#endif
29082915

2909-
if(no_change) // no change
2916+
if(!simplify_node_result.has_changed())
29102917
{
29112918
return unchanged(expr);
29122919
}
2913-
else // change, new expression is 'tmp'
2920+
else
29142921
{
2915-
POSTCONDITION(as_const(tmp).type() == expr.type());
2922+
POSTCONDITION(as_const(simplify_node_result.expr).type() == expr.type());
29162923

29172924
#ifdef USE_CACHE
29182925
// save in cache
2919-
cache_result.first->second = tmp;
2926+
cache_result.first->second = simplify_node_result.expr;
29202927
#endif
29212928

2922-
return std::move(tmp);
2929+
return simplify_node_result;
29232930
}
29242931
}
29252932

src/util/simplify_expr_class.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class simplify_exprt
160160
NODISCARD resultt<> simplify_shifts(const shift_exprt &);
161161
NODISCARD resultt<> simplify_power(const binary_exprt &);
162162
NODISCARD resultt<> simplify_bitwise(const multi_ary_exprt &);
163-
bool simplify_if_preorder(if_exprt &expr);
163+
NODISCARD resultt<> simplify_if_preorder(const if_exprt &expr);
164164
NODISCARD resultt<> simplify_if(const if_exprt &);
165165
NODISCARD resultt<> simplify_bitnot(const bitnot_exprt &);
166166
NODISCARD resultt<> simplify_not(const not_exprt &);
@@ -249,8 +249,8 @@ class simplify_exprt
249249
simplify_inequality_pointer_object(const binary_relation_exprt &);
250250

251251
// main recursion
252-
NODISCARD resultt<> simplify_node(exprt);
253-
bool simplify_node_preorder(exprt &expr);
252+
NODISCARD resultt<> simplify_node(const exprt &);
253+
NODISCARD resultt<> simplify_node_preorder(const exprt &);
254254
NODISCARD resultt<> simplify_rec(const exprt &);
255255

256256
virtual bool simplify(exprt &expr);

src/util/simplify_expr_if.cpp

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -211,47 +211,66 @@ bool simplify_exprt::simplify_if_cond(exprt &expr)
211211
return no_change;
212212
}
213213

214-
bool simplify_exprt::simplify_if_preorder(if_exprt &expr)
214+
static simplify_exprt::resultt<> build_if_expr(
215+
const if_exprt &expr,
216+
simplify_exprt::resultt<> cond,
217+
simplify_exprt::resultt<> truevalue,
218+
simplify_exprt::resultt<> falsevalue)
215219
{
216-
exprt &cond = expr.cond();
217-
exprt &truevalue = expr.true_case();
218-
exprt &falsevalue = expr.false_case();
220+
if(
221+
!cond.has_changed() && !truevalue.has_changed() &&
222+
!falsevalue.has_changed())
223+
{
224+
return simplify_exprt::resultt<>(
225+
simplify_exprt::resultt<>::UNCHANGED, expr);
226+
}
227+
else
228+
{
229+
if_exprt result = expr;
230+
if(cond.has_changed())
231+
result.cond() = std::move(cond.expr);
232+
if(truevalue.has_changed())
233+
result.true_case() = std::move(truevalue.expr);
234+
if(falsevalue.has_changed())
235+
result.false_case() = std::move(falsevalue.expr);
236+
return result;
237+
}
238+
}
219239

220-
bool no_change = true;
240+
simplify_exprt::resultt<>
241+
simplify_exprt::simplify_if_preorder(const if_exprt &expr)
242+
{
243+
const exprt &cond = expr.cond();
244+
const exprt &truevalue = expr.true_case();
245+
const exprt &falsevalue = expr.false_case();
221246

222247
// we first want to look at the condition
223248
auto r_cond = simplify_rec(cond);
224-
if(r_cond.has_changed())
225-
{
226-
cond = r_cond.expr;
227-
no_change = false;
228-
}
229249

230250
// 1 ? a : b -> a and 0 ? a : b -> b
231-
if(cond.is_constant())
251+
if(r_cond.expr.is_constant())
232252
{
233-
exprt tmp = cond.is_true() ? truevalue : falsevalue;
234-
tmp = simplify_rec(tmp);
235-
expr.swap(tmp);
236-
return false;
253+
return changed(
254+
simplify_rec(r_cond.expr.is_true() ? truevalue : falsevalue));
237255
}
238256

239257
if(do_simplify_if)
240258
{
241-
if(cond.id() == ID_not)
259+
bool swap_branches = false;
260+
261+
if(r_cond.expr.id() == ID_not)
242262
{
243-
cond = to_not_expr(cond).op();
244-
truevalue.swap(falsevalue);
245-
no_change = false;
263+
r_cond = changed(to_not_expr(r_cond.expr).op());
264+
swap_branches = true;
246265
}
247266

248267
#ifdef USE_LOCAL_REPLACE_MAP
249268
replace_mapt map_before(local_replace_map);
250269

251270
// a ? b : c --> a ? b[a/true] : c
252-
if(cond.id() == ID_and)
271+
if(r_cond.expr.id() == ID_and)
253272
{
254-
forall_operands(it, cond)
273+
forall_operands(it, r_cond.expr)
255274
{
256275
if(it->id() == ID_not)
257276
local_replace_map.insert(std::make_pair(it->op0(), false_exprt()));
@@ -260,21 +279,16 @@ bool simplify_exprt::simplify_if_preorder(if_exprt &expr)
260279
}
261280
}
262281
else
263-
local_replace_map.insert(std::make_pair(cond, true_exprt()));
282+
local_replace_map.insert(std::make_pair(r_cond.expr, true_exprt()));
264283

265-
auto r_truevalue = simplify_rec(truevalue);
266-
if(r_truevalue.has_changed())
267-
{
268-
truevalue = r_truevalue.expr;
269-
no_change = false;
270-
}
284+
auto r_truevalue = simplify_rec(swap_branches ? falsevalue : truevalue);
271285

272286
local_replace_map = map_before;
273287

274288
// a ? b : c --> a ? b : c[a/false]
275-
if(cond.id() == ID_or)
289+
if(r_cond.expr.id() == ID_or)
276290
{
277-
forall_operands(it, cond)
291+
forall_operands(it, r_cond.expr)
278292
{
279293
if(it->id() == ID_not)
280294
local_replace_map.insert(std::make_pair(it->op0(), true_exprt()));
@@ -283,48 +297,40 @@ bool simplify_exprt::simplify_if_preorder(if_exprt &expr)
283297
}
284298
}
285299
else
286-
local_replace_map.insert(std::make_pair(cond, false_exprt()));
300+
local_replace_map.insert(std::make_pair(r_cond.expr, false_exprt()));
287301

288-
auto r_falsevalue = simplify_rec(falsevalue);
289-
if(r_falsevalue.has_changed())
290-
{
291-
falsevalue = r_falsevalue.expr;
292-
no_change = false;
293-
}
302+
auto r_falsevalue = simplify_rec(swap_branches ? truevalue : falsevalue);
294303

295304
local_replace_map.swap(map_before);
305+
306+
if(swap_branches)
307+
{
308+
// tell build_if_expr to replace truevalue and falsevalue
309+
r_truevalue.expr_changed = CHANGED;
310+
r_falsevalue.expr_changed = CHANGED;
311+
}
312+
return build_if_expr(expr, r_cond, r_truevalue, r_falsevalue);
296313
#else
297-
auto r_truevalue = simplify_rec(truevalue);
298-
if(r_truevalue.has_changed())
314+
if(!swap_branches)
299315
{
300-
truevalue = r_truevalue.expr;
301-
no_change = false;
316+
return build_if_expr(
317+
expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue));
302318
}
303-
auto r_falsevalue = simplify_rec(falsevalue);
304-
if(r_falsevalue.has_changed())
319+
else
305320
{
306-
falsevalue = r_falsevalue.expr;
307-
no_change = false;
321+
return build_if_expr(
322+
expr,
323+
r_cond,
324+
changed(simplify_rec(falsevalue)),
325+
changed(simplify_rec(truevalue)));
308326
}
309327
#endif
310328
}
311329
else
312330
{
313-
auto r_truevalue = simplify_rec(truevalue);
314-
if(r_truevalue.has_changed())
315-
{
316-
truevalue = r_truevalue.expr;
317-
no_change = false;
318-
}
319-
auto r_falsevalue = simplify_rec(falsevalue);
320-
if(r_falsevalue.has_changed())
321-
{
322-
falsevalue = r_falsevalue.expr;
323-
no_change = false;
324-
}
331+
return build_if_expr(
332+
expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue));
325333
}
326-
327-
return no_change;
328334
}
329335

330336
simplify_exprt::resultt<> simplify_exprt::simplify_if(const if_exprt &expr)

0 commit comments

Comments
 (0)