Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dded843

Browse files
committedDec 5, 2021
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 d0c403a commit dded843

File tree

3 files changed

+114
-103
lines changed

3 files changed

+114
-103
lines changed
 

‎src/util/simplify_expr.cpp

+48-41
Original file line numberDiff line numberDiff line change
@@ -794,9 +794,8 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
794794
// rewrite (T)(bool) to bool?1:0
795795
auto one = from_integer(1, expr_type);
796796
auto zero = from_integer(0, expr_type);
797-
exprt new_expr = if_exprt(expr.op(), std::move(one), std::move(zero));
798-
simplify_if_preorder(to_if_expr(new_expr));
799-
return new_expr;
797+
return changed(simplify_if_preorder(
798+
if_exprt{expr.op(), std::move(one), std::move(zero)}));
800799
}
801800

802801
// circular casts through types shorter than `int`
@@ -2280,38 +2279,46 @@ simplify_exprt::simplify_overflow_unary(const unary_overflow_exprt &expr)
22802279
return false_exprt{};
22812280
}
22822281

2283-
bool simplify_exprt::simplify_node_preorder(exprt &expr)
2282+
simplify_exprt::resultt<>
2283+
simplify_exprt::simplify_node_preorder(const exprt &expr)
22842284
{
2285-
bool result=true;
2286-
22872285
// The ifs below could one day be replaced by a switch()
22882286

22892287
if(expr.id()==ID_address_of)
22902288
{
22912289
// the argument of this expression needs special treatment
22922290
}
22932291
else if(expr.id()==ID_if)
2294-
result=simplify_if_preorder(to_if_expr(expr));
2295-
else
22962292
{
2297-
if(expr.has_operands())
2293+
return simplify_if_preorder(to_if_expr(expr));
2294+
}
2295+
else if(expr.has_operands())
2296+
{
2297+
optionalt<exprt::operandst> new_operands;
2298+
2299+
for(std::size_t i = 0; i < expr.operands().size(); ++i)
22982300
{
2299-
Forall_operands(it, expr)
2301+
auto r_it = simplify_rec(expr.operands()[i]); // recursive call
2302+
if(r_it.has_changed())
23002303
{
2301-
auto r_it = simplify_rec(*it); // recursive call
2302-
if(r_it.has_changed())
2303-
{
2304-
*it = r_it.expr;
2305-
result=false;
2306-
}
2304+
if(!new_operands.has_value())
2305+
new_operands = expr.operands();
2306+
(*new_operands)[i] = std::move(r_it.expr);
23072307
}
23082308
}
2309+
2310+
if(new_operands.has_value())
2311+
{
2312+
exprt result = expr;
2313+
std::swap(result.operands(), *new_operands);
2314+
return result;
2315+
}
23092316
}
23102317

2311-
return result;
2318+
return unchanged(expr);
23122319
}
23132320

2314-
simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
2321+
simplify_exprt::resultt<> simplify_exprt::simplify_node(const exprt &node)
23152322
{
23162323
if(!node.has_operands())
23172324
return unchanged(node); // no change
@@ -2583,49 +2590,49 @@ simplify_exprt::resultt<> simplify_exprt::simplify_rec(const exprt &expr)
25832590
#endif
25842591

25852592
// We work on a copy to prevent unnecessary destruction of sharing.
2586-
exprt tmp=expr;
2587-
bool no_change = simplify_node_preorder(tmp);
2593+
auto simplify_node_preorder_result = simplify_node_preorder(expr);
25882594

2589-
auto simplify_node_result = simplify_node(tmp);
2595+
auto simplify_node_result = simplify_node(simplify_node_preorder_result.expr);
25902596

2591-
if(simplify_node_result.has_changed())
2597+
if(
2598+
!simplify_node_result.has_changed() &&
2599+
simplify_node_preorder_result.has_changed())
25922600
{
2593-
no_change = false;
2594-
tmp = simplify_node_result.expr;
2601+
simplify_node_result.expr_changed =
2602+
simplify_node_preorder_result.expr_changed;
25952603
}
25962604

25972605
#ifdef USE_LOCAL_REPLACE_MAP
2598-
#if 1
2599-
replace_mapt::const_iterator it=local_replace_map.find(tmp);
2606+
exprt tmp = simplify_node_result.expr;
2607+
# if 1
2608+
replace_mapt::const_iterator it =
2609+
local_replace_map.find(simplify_node_result.expr);
26002610
if(it!=local_replace_map.end())
2611+
simplify_node_result = changed(it->second);
2612+
# else
2613+
if(
2614+
!local_replace_map.empty() &&
2615+
!replace_expr(local_replace_map, simplify_node_result.expr))
26012616
{
2602-
tmp=it->second;
2603-
no_change = false;
2604-
}
2605-
#else
2606-
if(!local_replace_map.empty() &&
2607-
!replace_expr(local_replace_map, tmp))
2608-
{
2609-
simplify_rec(tmp);
2610-
no_change = false;
2617+
simplify_node_result = changed(simplify_rec(simplify_node_result.expr));
26112618
}
2612-
#endif
2619+
# endif
26132620
#endif
26142621

2615-
if(no_change) // no change
2622+
if(!simplify_node_result.has_changed())
26162623
{
26172624
return unchanged(expr);
26182625
}
2619-
else // change, new expression is 'tmp'
2626+
else
26202627
{
2621-
POSTCONDITION(as_const(tmp).type() == expr.type());
2628+
POSTCONDITION(as_const(simplify_node_result.expr).type() == expr.type());
26222629

26232630
#ifdef USE_CACHE
26242631
// save in cache
2625-
cache_result.first->second = tmp;
2632+
cache_result.first->second = simplify_node_result.expr;
26262633
#endif
26272634

2628-
return std::move(tmp);
2635+
return simplify_node_result;
26292636
}
26302637
}
26312638

‎src/util/simplify_expr_class.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class simplify_exprt
154154
NODISCARD resultt<> simplify_shifts(const shift_exprt &);
155155
NODISCARD resultt<> simplify_power(const binary_exprt &);
156156
NODISCARD resultt<> simplify_bitwise(const multi_ary_exprt &);
157-
bool simplify_if_preorder(if_exprt &expr);
157+
NODISCARD resultt<> simplify_if_preorder(const if_exprt &expr);
158158
NODISCARD resultt<> simplify_if(const if_exprt &);
159159
NODISCARD resultt<> simplify_bitnot(const bitnot_exprt &);
160160
NODISCARD resultt<> simplify_not(const not_exprt &);
@@ -231,8 +231,8 @@ class simplify_exprt
231231
simplify_inequality_pointer_object(const binary_relation_exprt &);
232232

233233
// main recursion
234-
NODISCARD resultt<> simplify_node(exprt);
235-
bool simplify_node_preorder(exprt &expr);
234+
NODISCARD resultt<> simplify_node(const exprt &);
235+
NODISCARD resultt<> simplify_node_preorder(const exprt &);
236236
NODISCARD resultt<> simplify_rec(const exprt &);
237237

238238
virtual bool simplify(exprt &expr);

‎src/util/simplify_expr_if.cpp

+63-59
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,18 @@ 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);
285+
if(swap_branches)
286+
r_truevalue.expr_changed = CHANGED;
271287

272288
local_replace_map = map_before;
273289

274290
// a ? b : c --> a ? b : c[a/false]
275-
if(cond.id() == ID_or)
291+
if(r_cond.expr.id() == ID_or)
276292
{
277-
forall_operands(it, cond)
293+
forall_operands(it, r_cond.expr)
278294
{
279295
if(it->id() == ID_not)
280296
local_replace_map.insert(std::make_pair(it->op0(), true_exprt()));
@@ -283,48 +299,36 @@ bool simplify_exprt::simplify_if_preorder(if_exprt &expr)
283299
}
284300
}
285301
else
286-
local_replace_map.insert(std::make_pair(cond, false_exprt()));
302+
local_replace_map.insert(std::make_pair(r_cond.expr, false_exprt()));
287303

288-
auto r_falsevalue = simplify_rec(falsevalue);
289-
if(r_falsevalue.has_changed())
290-
{
291-
falsevalue = r_falsevalue.expr;
292-
no_change = false;
293-
}
304+
auto falsevalue = simplify_rec(swap_branches ? falsevalue : truevalue);
305+
if(swap_branches)
306+
r_falsevalue.expr_changed = CHANGED;
294307

295308
local_replace_map.swap(map_before);
309+
310+
return build_if_expr(expr, r_cond, r_truevalue, r_falsevalue);
296311
#else
297-
auto r_truevalue = simplify_rec(truevalue);
298-
if(r_truevalue.has_changed())
312+
if(!swap_branches)
299313
{
300-
truevalue = r_truevalue.expr;
301-
no_change = false;
314+
return build_if_expr(
315+
expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue));
302316
}
303-
auto r_falsevalue = simplify_rec(falsevalue);
304-
if(r_falsevalue.has_changed())
317+
else
305318
{
306-
falsevalue = r_falsevalue.expr;
307-
no_change = false;
319+
return build_if_expr(
320+
expr,
321+
r_cond,
322+
changed(simplify_rec(falsevalue)),
323+
changed(simplify_rec(truevalue)));
308324
}
309325
#endif
310326
}
311327
else
312328
{
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-
}
329+
return build_if_expr(
330+
expr, r_cond, simplify_rec(truevalue), simplify_rec(falsevalue));
325331
}
326-
327-
return no_change;
328332
}
329333

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

0 commit comments

Comments
 (0)
Please sign in to comment.