CBMC
Loading...
Searching...
No Matches
simplify_expr_if.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
10
11#include "arith_tools.h"
12#include "range.h"
13#include "std_expr.h"
14
16 exprt &expr,
17 const exprt &cond,
18 bool truth,
19 bool &new_truth)
20{
21 if(expr == cond)
22 {
24 return false;
25 }
26
27 if(truth && cond.id() == ID_lt && expr.id() == ID_lt)
28 {
29 const auto &cond_lt = to_binary_relation_expr(cond);
30 const auto &expr_lt = to_binary_relation_expr(expr);
31
32 if(
33 cond_lt.op0() == expr_lt.op0() && cond_lt.op1().is_constant() &&
34 expr_lt.op1().is_constant() &&
35 cond_lt.op1().type() == expr_lt.op1().type())
36 {
38
39 if(
42 {
43 if(i1 >= i2)
44 {
45 new_truth = true;
46 return false;
47 }
48 }
49 }
50
51 if(
52 cond_lt.op1() == expr_lt.op1() && cond_lt.op0().is_constant() &&
53 expr_lt.op0().is_constant() &&
54 cond_lt.op0().type() == expr_lt.op0().type())
55 {
57
58 if(
61 {
62 if(i1 <= i2)
63 {
64 new_truth = true;
65 return false;
66 }
67 }
68 }
69 }
70
71 return true;
72}
73
75 exprt &expr,
76 const exprt &cond,
77 bool truth)
78{
79 if(expr.is_boolean())
80 {
81 bool new_truth;
82
83 if(!simplify_if_implies(expr, cond, truth, new_truth))
84 {
85 if(new_truth)
86 {
87 expr = true_exprt();
88 return false;
89 }
90 else
91 {
92 expr = false_exprt();
93 return false;
94 }
95 }
96 }
97
98 bool no_change = true;
99
100 Forall_operands(it, expr)
102
103 return no_change;
104}
105
107{
108 for(const auto &op : cond.operands())
109 {
110 if(expr == op)
111 {
112 expr = true_exprt();
113 return false;
114 }
115 }
116
117 bool no_change = true;
118
119 Forall_operands(it, expr)
120 no_change = simplify_if_conj(*it, cond) && no_change;
121
122 return no_change;
123}
124
126{
127 for(const auto &op : cond.operands())
128 {
129 if(expr == op)
130 {
131 expr = false_exprt();
132 return false;
133 }
134 }
135
136 bool no_change = true;
137
138 Forall_operands(it, expr)
139 no_change = simplify_if_disj(*it, cond) && no_change;
140
141 return no_change;
142}
143
147 const exprt &cond)
148{
149 bool tno_change = true;
150 bool fno_change = true;
151
152 if(cond.id() == ID_and)
153 {
156 }
157 else if(cond.id() == ID_or)
158 {
161 }
162 else
163 {
166 }
167
168 if(!tno_change)
169 trueexpr = simplify_rec(trueexpr); // recursive call
170 if(!fno_change)
171 falseexpr = simplify_rec(falseexpr); // recursive call
172
173 return tno_change && fno_change;
174}
175
177{
178 bool no_change = true;
179 bool tmp = false;
180
181 while(!tmp)
182 {
183 tmp = true;
184
185 if(expr.id() == ID_and)
186 {
187 if(expr.has_operands())
188 {
189 exprt::operandst &operands = expr.operands();
190 for(exprt::operandst::iterator it1 = operands.begin();
191 it1 != operands.end();
192 it1++)
193 {
194 for(exprt::operandst::iterator it2 = operands.begin();
195 it2 != operands.end();
196 it2++)
197 {
198 if(it1 != it2)
199 tmp = simplify_if_recursive(*it1, *it2, true) && tmp;
200 }
201 }
202 }
203 }
204
205 if(!tmp)
206 expr = simplify_rec(expr); // recursive call
207
209 }
210
211 return no_change;
212}
213
215 const if_exprt &expr,
219{
220 if(
221 !cond.has_changed() && !truevalue.has_changed() &&
222 !falsevalue.has_changed())
223 {
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}
239
242{
243 const exprt &cond = expr.cond();
244 const exprt &truevalue = expr.true_case();
245 const exprt &falsevalue = expr.false_case();
246
247 // we first want to look at the condition
248 auto r_cond = simplify_rec(cond);
249
250 // 1 ? a : b -> a and 0 ? a : b -> b
251 if(r_cond.expr.is_constant())
252 {
253 return changed(simplify_rec(r_cond.expr == true ? truevalue : falsevalue));
254 }
255
257 {
258 bool swap_branches = false;
259
260 if(r_cond.expr.id() == ID_not)
261 {
262 r_cond = changed(to_not_expr(r_cond.expr).op());
263 swap_branches = true;
264 }
265
266#ifdef USE_LOCAL_REPLACE_MAP
268
269 // a ? b : c --> a ? b[a/true] : c
270 if(r_cond.expr.id() == ID_and)
271 {
272 for(const auto &op : r_cond.expr.operands())
273 {
274 if(op.id() == ID_not)
275 local_replace_map.insert(std::make_pair(op.op0(), false_exprt()));
276 else
277 local_replace_map.insert(std::make_pair(op, true_exprt()));
278 }
279 }
280 else
281 local_replace_map.insert(std::make_pair(r_cond.expr, true_exprt()));
282
284
286
287 // a ? b : c --> a ? b : c[a/false]
288 if(r_cond.expr.id() == ID_or)
289 {
290 for(const auto &op : r_cond.expr.operands())
291 {
292 if(op.id() == ID_not)
293 local_replace_map.insert(std::make_pair(op.op0(), true_exprt()));
294 else
295 local_replace_map.insert(std::make_pair(op, false_exprt()));
296 }
297 }
298 else
299 local_replace_map.insert(std::make_pair(r_cond.expr, false_exprt()));
300
302
304
305 if(swap_branches)
306 {
307 // tell build_if_expr to replace truevalue and falsevalue
308 r_truevalue.expr_changed = CHANGED;
309 r_falsevalue.expr_changed = CHANGED;
310 }
312#else
313 if(!swap_branches)
314 {
315 return build_if_expr(
317 }
318 else
319 {
320 return build_if_expr(
321 expr,
322 r_cond,
325 }
326#endif
327 }
328 else
329 {
330 return build_if_expr(
332 }
333}
334
336{
337 const exprt &cond = expr.cond();
338 const exprt &truevalue = expr.true_case();
339 const exprt &falsevalue = expr.false_case();
340
342 {
343#if 0
346#endif
347
348 if(expr.type() == bool_typet())
349 {
350 // a?b:c <-> (a && b) || (!a && c)
351
352 if(truevalue == true && falsevalue == false)
353 {
354 // a?1:0 <-> a
355 return cond;
356 }
357 else if(truevalue == false && falsevalue == true)
358 {
359 // a?0:1 <-> !a
360 return changed(simplify_not(not_exprt(cond)));
361 }
362 else if(falsevalue == false)
363 {
364 // a?b:0 <-> a AND b
366 }
367 else if(falsevalue == true)
368 {
369 // a?b:1 <-> !a OR b
370 return changed(
372 }
373 else if(truevalue == true)
374 {
375 // a?1:b <-> a||(!a && b) <-> a OR b
377 }
378 else if(truevalue == false)
379 {
380 // a?0:b <-> !a && b
383 }
384 }
385 }
386
387 if(truevalue == falsevalue)
388 return truevalue;
389
390 // this pushes the if-then-else into struct and array constructors
391 if(
392 ((truevalue.id() == ID_struct && falsevalue.id() == ID_struct) ||
393 (truevalue.id() == ID_array && falsevalue.id() == ID_array)) &&
394 truevalue.operands().size() == falsevalue.operands().size())
395 {
396 exprt cond_copy = cond;
399
400 auto range_false = make_range(falsevalue_copy.operands());
401 auto range_true = make_range(truevalue_copy.operands());
402 auto new_expr = truevalue;
403 new_expr.operands().clear();
404
405 for(const auto &pair : range_true.zip(range_false))
406 {
407 new_expr.operands().push_back(
408 simplify_if(if_exprt(cond_copy, pair.first, pair.second)));
409 }
410
411 return std::move(new_expr);
412 }
413
414 return unchanged(expr);
415}
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Boolean AND.
Definition std_expr.h:2125
The Boolean type.
Definition std_types.h:36
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:92
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:229
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
The Boolean constant false.
Definition std_expr.h:3246
The trinary if-then-else operator.
Definition std_expr.h:2502
exprt & cond()
Definition std_expr.h:2519
exprt & false_case()
Definition std_expr.h:2539
exprt & true_case()
Definition std_expr.h:2529
const irep_idt & id() const
Definition irep.h:388
Boolean negation.
Definition std_expr.h:2459
Boolean OR.
Definition std_expr.h:2275
bool simplify_if_conj(exprt &expr, const exprt &cond)
bool simplify_if_disj(exprt &expr, const exprt &cond)
static resultt changed(resultt<> result)
resultt simplify_if(const if_exprt &)
bool simplify_if_recursive(exprt &expr, const exprt &cond, bool truth)
resultt simplify_rec(const exprt &)
bool simplify_if_cond(exprt &expr)
resultt simplify_boolean(const exprt &)
bool simplify_if_branch(exprt &trueexpr, exprt &falseexpr, const exprt &cond)
resultt simplify_not(const not_exprt &)
static resultt unchanged(exprt expr)
resultt simplify_if_preorder(const if_exprt &expr)
bool simplify_if_implies(exprt &expr, const exprt &cond, bool truth, bool &new_truth)
The Boolean constant true.
Definition std_expr.h:3237
#define Forall_operands(it, expr)
Definition expr.h:28
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
std::unordered_map< exprt, exprt, irep_hash > replace_mapt
static simplify_exprt::resultt build_if_expr(const if_exprt &expr, simplify_exprt::resultt<> cond, simplify_exprt::resultt<> truevalue, simplify_exprt::resultt<> falsevalue)
API to expression classes.
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition std_expr.h:895
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3189
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2484