CBMC
Loading...
Searching...
No Matches
simplify_expr_int.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 "bitvector_expr.h"
13#include "c_types.h"
14#include "config.h"
15#include "expr_util.h"
16#include "fixedbv.h"
17#include "ieee_float.h"
18#include "invariant.h"
19#include "mathematical_expr.h"
20#include "mathematical_types.h"
21#include "namespace.h"
22#include "pointer_expr.h"
23#include "pointer_offset_size.h"
24#include "rational.h"
25#include "rational_tools.h"
26#include "simplify_utils.h"
27#include "std_expr.h"
28#include "threeval.h"
29
30#include <algorithm>
31
34{
35 if(expr.type().id() == ID_unsignedbv && expr.op().is_constant())
36 {
37 auto bits_per_byte = expr.get_bits_per_byte();
38 std::size_t width=to_bitvector_type(expr.type()).get_width();
39 const mp_integer value =
41 std::vector<mp_integer> bytes;
42
43 // take apart
44 for(std::size_t bit = 0; bit < width; bit += bits_per_byte)
45 bytes.push_back((value >> bit)%power(2, bits_per_byte));
46
47 // put back together, but backwards
48 mp_integer new_value=0;
49 for(std::size_t bit = 0; bit < width; bit += bits_per_byte)
50 {
52 !bytes.empty(),
53 "bytes is not empty because we just pushed just as many elements on "
54 "top of it as we are popping now");
55 new_value+=bytes.back()<<bit;
56 bytes.pop_back();
57 }
58
59 return from_integer(new_value, expr.type());
60 }
61
62 return unchanged(expr);
63}
64
67static bool sum_expr(
68 constant_exprt &dest,
69 const constant_exprt &expr)
70{
71 if(dest.type()!=expr.type())
72 return true;
73
74 const irep_idt &type_id=dest.type().id();
75
76 if(
79 {
80 mp_integer a, b;
81 if(!to_integer(dest, a) && !to_integer(expr, b))
82 {
83 dest = from_integer(a + b, dest.type());
84 return false;
85 }
86 }
87 else if(type_id==ID_rational)
88 {
89 rationalt a, b;
90 if(!to_rational(dest, a) && !to_rational(expr, b))
91 {
92 dest=from_rational(a+b);
93 return false;
94 }
95 }
96 else if(type_id==ID_fixedbv)
97 {
98 fixedbvt f(dest);
99 f += fixedbvt(expr);
100 dest = f.to_expr();
101 return false;
102 }
103 else if(type_id==ID_floatbv)
104 {
106 ieee_floatt f(dest, rm);
107 f += ieee_floatt(expr, rm);
108 dest=f.to_expr();
109 return false;
110 }
111
112 return true;
113}
114
117static bool mul_expr(
118 constant_exprt &dest,
119 const constant_exprt &expr)
120{
121 if(dest.type()!=expr.type())
122 return true;
123
124 const irep_idt &type_id=dest.type().id();
125
126 if(
129 {
130 mp_integer a, b;
131 if(!to_integer(dest, a) && !to_integer(expr, b))
132 {
133 dest = from_integer(a * b, dest.type());
134 return false;
135 }
136 }
137 else if(type_id==ID_rational)
138 {
139 rationalt a, b;
140 if(!to_rational(dest, a) && !to_rational(expr, b))
141 {
142 dest=from_rational(a*b);
143 return false;
144 }
145 }
146 else if(type_id==ID_fixedbv)
147 {
148 fixedbvt f(to_constant_expr(dest));
149 f*=fixedbvt(to_constant_expr(expr));
150 dest=f.to_expr();
151 return false;
152 }
153 else if(type_id==ID_floatbv)
154 {
157 f *= ieee_floatt(to_constant_expr(expr), rm);
158 dest=f.to_expr();
159 return false;
160 }
161
162 return true;
163}
164
166{
167 // check to see if it is a number type
168 if(!is_number(expr.type()))
169 return unchanged(expr);
170
171 // vector of operands
173
174 // result of the simplification
175 bool no_change = true;
176
177 // position of the constant
178 exprt::operandst::iterator constant;
179
180 // true if we have found a constant
181 bool constant_found = false;
182
183 std::optional<typet> c_sizeof_type;
184
185 // scan all the operands
186 for(exprt::operandst::iterator it = new_operands.begin();
187 it != new_operands.end();)
188 {
189 // if one of the operands is not a number return
190 if(!is_number(it->type()))
191 return unchanged(expr);
192
193 // if one of the operands is zero the result is zero
194 // note: not true on IEEE floating point arithmetic
195 if(*it == 0 && it->type().id() != ID_floatbv)
196 {
197 return from_integer(0, expr.type());
198 }
199
200 // true if the given operand has to be erased
201 bool do_erase = false;
202
203 // if this is a constant of the same time as the result
204 if(it->is_constant() && it->type()==expr.type())
205 {
206 // preserve the sizeof type annotation
207 if(!c_sizeof_type.has_value())
208 {
209 const typet &sizeof_type =
210 static_cast<const typet &>(it->find(ID_C_c_sizeof_type));
211 if(sizeof_type.is_not_nil())
213 }
214
216 {
217 // update the constant factor
218 if(!mul_expr(to_constant_expr(*constant), to_constant_expr(*it)))
219 do_erase=true;
220 }
221 else
222 {
223 // set it as the constant factor if this is the first
224 constant=it;
225 constant_found = true;
226 }
227 }
228
229 // erase the factor if necessary
230 if(do_erase)
231 {
232 it = new_operands.erase(it);
233 no_change = false;
234 }
235 else
236 it++; // move to the next operand
237 }
238
239 if(c_sizeof_type.has_value())
240 {
241 INVARIANT(
243 "c_sizeof_type is only set to a non-nil value "
244 "if a constant has been found");
245 constant->set(ID_C_c_sizeof_type, *c_sizeof_type);
246 }
247
248 if(new_operands.size() == 1)
249 {
250 return new_operands.front();
251 }
252 else
253 {
254 // if the constant is a one and there are other factors
255 if(constant_found && *constant == 1)
256 {
257 // just delete it
258 new_operands.erase(constant);
259 no_change = false;
260
261 if(new_operands.size() == 1)
262 return new_operands.front();
263 }
264 }
265
266 if(no_change)
267 return unchanged(expr);
268 else
269 {
270 exprt tmp = expr;
271 tmp.operands() = std::move(new_operands);
272 return std::move(tmp);
273 }
274}
275
277{
278 if(!is_number(expr.type()))
279 return unchanged(expr);
280
281 const typet &expr_type=expr.type();
282
283 if(expr_type!=expr.op0().type() ||
284 expr_type!=expr.op1().type())
285 {
286 return unchanged(expr);
287 }
288
289 if(expr_type.id()==ID_signedbv ||
290 expr_type.id()==ID_unsignedbv ||
291 expr_type.id()==ID_natural ||
292 expr_type.id()==ID_integer)
293 {
294 const auto int_value0 = numeric_cast<mp_integer>(expr.op0());
295 const auto int_value1 = numeric_cast<mp_integer>(expr.op1());
296
297 // division by zero?
298 if(int_value1.has_value() && *int_value1 == 0)
299 return unchanged(expr);
300
301 // x/1?
302 if(int_value1.has_value() && *int_value1 == 1)
303 {
304 return expr.op0();
305 }
306
307 // 0/x?
308 if(int_value0.has_value() && *int_value0 == 0)
309 {
310 return expr.op0();
311 }
312
313 if(int_value0.has_value() && int_value1.has_value())
314 {
315 mp_integer result = *int_value0 / *int_value1;
316 return from_integer(result, expr_type);
317 }
318 }
319 else if(expr_type.id()==ID_rational)
320 {
322 bool ok0, ok1;
323
324 ok0=!to_rational(expr.op0(), rat_value0);
325 ok1=!to_rational(expr.op1(), rat_value1);
326
327 if(ok1 && rat_value1.is_zero())
328 return unchanged(expr);
329
330 if((ok1 && rat_value1.is_one()) ||
331 (ok0 && rat_value0.is_zero()))
332 {
333 return expr.op0();
334 }
335
336 if(ok0 && ok1)
337 {
339 exprt tmp=from_rational(result);
340
341 if(tmp.is_not_nil())
342 return std::move(tmp);
343 }
344 }
345 else if(expr_type.id()==ID_fixedbv)
346 {
347 // division by one?
348 if(expr.op1().is_constant() && expr.op1() == 1)
349 {
350 return expr.op0();
351 }
352
353 if(expr.op0().is_constant() &&
354 expr.op1().is_constant())
355 {
357 fixedbvt f1(to_constant_expr(expr.op1()));
358 if(!f1.is_zero())
359 {
360 f0/=f1;
361 return f0.to_expr();
362 }
363 }
364 }
365
366 return unchanged(expr);
367}
368
370{
371 if(!is_number(expr.type()))
372 return unchanged(expr);
373
374 if(expr.type().id()==ID_signedbv ||
375 expr.type().id()==ID_unsignedbv ||
376 expr.type().id()==ID_natural ||
377 expr.type().id()==ID_integer)
378 {
379 if(expr.type()==expr.op0().type() &&
380 expr.type()==expr.op1().type())
381 {
382 const auto int_value0 = numeric_cast<mp_integer>(expr.op0());
383 const auto int_value1 = numeric_cast<mp_integer>(expr.op1());
384
385 if(int_value1.has_value() && *int_value1 == 0)
386 return unchanged(expr); // division by zero
387
388 if(
389 (int_value1.has_value() && *int_value1 == 1) ||
390 (int_value0.has_value() && *int_value0 == 0))
391 {
392 return from_integer(0, expr.type());
393 }
394
395 if(int_value0.has_value() && int_value1.has_value())
396 {
397 mp_integer result = *int_value0 % *int_value1;
398 return from_integer(result, expr.type());
399 }
400 }
401 }
402
403 return unchanged(expr);
404}
405
407{
408 if(!is_number(expr.type()) && expr.type().id() != ID_pointer)
409 return unchanged(expr);
410
411 bool no_change = true;
412
414
415 // floating-point addition is _NOT_ associative; thus,
416 // there is special case for float
417
418 if(expr.type().id() == ID_floatbv)
419 {
420 // we only merge neighboring constants!
422 {
423 const exprt::operandst::iterator next = std::next(it);
424
425 if(next != new_operands.end())
426 {
427 if(it->type()==next->type() &&
428 it->is_constant() &&
429 next->is_constant())
430 {
432 new_operands.erase(next);
433 no_change = false;
434 }
435 }
436 }
437 }
438 else
439 {
440 // ((T*)p+a)+b -> (T*)p+(a+b)
441 if(
442 expr.type().id() == ID_pointer && expr.operands().size() == 2 &&
443 expr.op0().id() == ID_plus && expr.op0().type().id() == ID_pointer &&
444 expr.op0().operands().size() == 2)
445 {
446 plus_exprt result = to_plus_expr(expr.op0());
447 if(as_const(result).op0().type().id() != ID_pointer)
448 result.op0().swap(result.op1());
449 const exprt &op1 = as_const(result).op1();
450
451 if(op1.id() == ID_plus)
452 {
454 new_op1.add_to_operands(
455 typecast_exprt::conditional_cast(expr.op1(), new_op1.op0().type()));
456 result.op1() = simplify_plus(new_op1);
457 }
458 else
459 {
461 op1, typecast_exprt::conditional_cast(expr.op1(), op1.type())};
462 result.op1() = simplify_plus(new_op1);
463 }
464
465 return changed(simplify_plus(result));
466 }
467
468 // count the constants
469 size_t count=0;
470 for(const auto &op : expr.operands())
471 {
472 if(is_number(op.type()) && op.is_constant())
473 count++;
474 }
475
476 // merge constants?
477 if(count>=2)
478 {
479 exprt::operandst::iterator const_sum;
480 bool const_sum_set=false;
481
482 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
483 {
484 if(is_number(it->type()) && it->is_constant())
485 {
486 if(!const_sum_set)
487 {
488 const_sum=it;
489 const_sum_set=true;
490 }
491 else
492 {
494 to_constant_expr(*it)))
495 {
496 *it=from_integer(0, it->type());
497 no_change = false;
498 }
499 }
500 }
501 }
502 }
503
504 // search for a and -a
505 // first gather all the a's with -a
506 typedef std::unordered_map<exprt, exprt::operandst::iterator, irep_hash>
507 expr_mapt;
508 expr_mapt expr_map;
509
510 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
511 if(it->id() == ID_unary_minus)
512 {
513 expr_map.insert(std::make_pair(to_unary_minus_expr(*it).op(), it));
514 }
515
516 // now search for a
517 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
518 {
519 if(expr_map.empty())
520 break;
521 else if(it->id()==ID_unary_minus)
522 continue;
523
524 expr_mapt::iterator itm=expr_map.find(*it);
525
526 if(itm!=expr_map.end())
527 {
528 *(itm->second)=from_integer(0, expr.type());
529 *it=from_integer(0, expr.type());
530 expr_map.erase(itm);
531 no_change = false;
532 }
533 }
534
535 // delete zeros
536 // (can't do for floats, as the result of 0.0 + (-0.0)
537 // need not be -0.0 in std rounding)
538 for(exprt::operandst::iterator it = new_operands.begin();
539 it != new_operands.end();
540 /* no it++ */)
541 {
542 if(is_number(it->type()) && *it == 0)
543 {
544 it = new_operands.erase(it);
545 no_change = false;
546 }
547 else
548 it++;
549 }
550 }
551
552 if(new_operands.empty())
553 {
554 return from_integer(0, expr.type());
555 }
556 else if(new_operands.size() == 1)
557 {
558 return new_operands.front();
559 }
560
561 if(no_change)
562 return unchanged(expr);
563 else
564 {
565 auto tmp = expr;
566 tmp.operands() = std::move(new_operands);
567 return std::move(tmp);
568 }
569}
570
573{
574 auto const &minus_expr = to_minus_expr(expr);
575 if(!is_number(minus_expr.type()) && minus_expr.type().id() != ID_pointer)
576 return unchanged(expr);
577
578 const exprt::operandst &operands = minus_expr.operands();
579
580 if(
581 is_number(minus_expr.type()) && is_number(operands[0].type()) &&
582 is_number(operands[1].type()))
583 {
584 // rewrite "a-b" to "a+(-b)"
585 unary_minus_exprt rhs_negated(operands[1]);
588 }
589 else if(
590 minus_expr.type().id() == ID_pointer &&
591 operands[0].type().id() == ID_pointer && is_number(operands[1].type()))
592 {
593 // pointer arithmetic: rewrite "p-i" to "p+(-i)"
595
599 }
600 else if(
601 is_number(minus_expr.type()) && operands[0].type().id() == ID_pointer &&
602 operands[1].type().id() == ID_pointer)
603 {
604 exprt ptr_op0 = simplify_object(operands[0]).expr;
605 exprt ptr_op1 = simplify_object(operands[1]).expr;
606
608 if(ptr_op0 == ptr_op1 && address_of)
609 {
611 pointer_offset_exprt{operands[0], minus_expr.type()});
613 pointer_offset_exprt{operands[1], minus_expr.type()});
614
615 const auto object_size =
616 pointer_offset_size(address_of->object().type(), ns);
617 auto element_size =
618 size_of_expr(to_pointer_type(operands[0].type()).base_type(), ns);
619
620 if(
621 offset_op0.is_constant() && offset_op1.is_constant() &&
622 object_size.has_value() && element_size.has_value() &&
623 element_size->is_constant() && *element_size != 0 &&
625 *object_size &&
628 {
632 }
633 }
634
637 if(
640 {
642 pointer_offset_exprt{operands[0], minus_expr.type()});
644 pointer_offset_exprt{operands[1], minus_expr.type()});
645
646 auto element_size =
647 size_of_expr(to_pointer_type(operands[0].type()).base_type(), ns);
648
649 if(
650 element_size.has_value() && element_size->is_constant() &&
651 *element_size != 0)
652 {
656 }
657 }
658 }
659
660 return unchanged(expr);
661}
662
665{
667 return unchanged(expr);
668
669 // check if these are really boolean
670 if(!expr.is_boolean())
671 {
672 bool all_bool=true;
673
674 for(const auto &op : expr.operands())
675 {
676 if(op.id() == ID_typecast && to_typecast_expr(op).op().is_boolean())
677 {
678 }
679 else if(op == 0 || op == 1)
680 {
681 }
682 else
683 all_bool=false;
684 }
685
686 if(all_bool)
687 {
688 // re-write to boolean+typecast
689 exprt new_expr=expr;
690
691 if(expr.id()==ID_bitand)
692 new_expr.id(ID_and);
693 else if(expr.id()==ID_bitor)
694 new_expr.id(ID_or);
695 else if(expr.id()==ID_bitxor)
696 new_expr.id(ID_xor);
697 else if(expr.id() == ID_bitxnor)
698 new_expr.id(ID_equal);
699 else
701
703 {
704 if(it->id()==ID_typecast)
705 *it = to_typecast_expr(*it).op();
706 else if(*it == 0)
707 *it=false_exprt();
708 else if(*it == 1)
709 *it=true_exprt();
710 }
711
712 new_expr.type() = bool_typet{};
714
716 }
717 }
718
719 bool no_change = true;
720 auto new_expr = expr;
721
722 // try to merge constants
723
724 const std::size_t width = to_bitvector_type(expr.type()).get_width();
725
726 while(new_expr.operands().size() >= 2)
727 {
728 if(!new_expr.op0().is_constant())
729 break;
730
731 if(!new_expr.op1().is_constant())
732 break;
733
734 if(new_expr.op0().type() != new_expr.type())
735 break;
736
737 if(new_expr.op1().type() != new_expr.type())
738 break;
739
740 const auto &a_val = to_constant_expr(new_expr.op0()).get_value();
741 const auto &b_val = to_constant_expr(new_expr.op1()).get_value();
742
743 std::function<bool(bool, bool)> f;
744
745 if(new_expr.id() == ID_bitand)
746 f = [](bool a, bool b) { return a && b; };
747 else if(new_expr.id() == ID_bitor)
748 f = [](bool a, bool b) { return a || b; };
749 else if(new_expr.id() == ID_bitxor)
750 f = [](bool a, bool b) { return a != b; };
751 else if(new_expr.id() == ID_bitxnor)
752 f = [](bool a, bool b) { return a == b; };
753 else
755
756 const irep_idt new_value =
757 make_bvrep(width, [&a_val, &b_val, &width, &f](std::size_t i) {
758 return f(
759 get_bvrep_bit(a_val, width, i), get_bvrep_bit(b_val, width, i));
760 });
761
762 constant_exprt new_op(new_value, expr.type());
763
764 // erase first operand
765 new_expr.operands().erase(new_expr.operands().begin());
766 new_expr.op0().swap(new_op);
767
768 no_change = false;
769 }
770
771 // now erase 'all zeros' out of bitor, bitxor
772
773 if(new_expr.id() == ID_bitor || new_expr.id() == ID_bitxor)
774 {
775 for(exprt::operandst::iterator it = new_expr.operands().begin();
776 it != new_expr.operands().end();) // no it++
777 {
778 if(*it == 0 && new_expr.operands().size() > 1)
779 {
780 it = new_expr.operands().erase(it);
781 no_change = false;
782 }
783 else if(
784 it->is_constant() && it->type().id() == ID_bv &&
785 *it == to_bv_type(it->type()).all_zeros_expr() &&
786 new_expr.operands().size() > 1)
787 {
788 it = new_expr.operands().erase(it);
789 no_change = false;
790 }
791 else
792 it++;
793 }
794 }
795
796 // now erase 'all ones' out of bitand
797
798 if(new_expr.id() == ID_bitand)
799 {
800 const auto all_ones = power(2, width) - 1;
801 for(exprt::operandst::iterator it = new_expr.operands().begin();
802 it != new_expr.operands().end();) // no it++
803 {
804 if(
805 it->is_constant() &&
806 bvrep2integer(to_constant_expr(*it).get_value(), width, false) ==
807 all_ones &&
808 new_expr.operands().size() > 1)
809 {
810 it = new_expr.operands().erase(it);
811 no_change = false;
812 }
813 else
814 it++;
815 }
816 }
817
818 // two operands that are syntactically the same
819
820 if(new_expr.operands().size() == 2 && new_expr.op0() == new_expr.op1())
821 {
822 if(new_expr.id() == ID_bitand || new_expr.id() == ID_bitor)
823 {
824 return new_expr.op0();
825 }
826 else if(new_expr.id() == ID_bitxor)
827 {
828 return constant_exprt(integer2bvrep(0, width), new_expr.type());
829 }
830 }
831
832 if(new_expr.operands().size() == 1)
833 return new_expr.op0();
834
835 if(no_change)
836 return unchanged(expr);
837 else
838 return std::move(new_expr);
839}
840
843{
844 const typet &src_type = expr.src().type();
845
847 return unchanged(expr);
848
849 const std::size_t src_bit_width = to_bitvector_type(src_type).get_width();
850
852 if(
853 !index_converted_to_int.has_value() || *index_converted_to_int < 0 ||
855 {
856 return unchanged(expr);
857 }
858
859 if(!expr.src().is_constant())
860 return unchanged(expr);
861
862 const bool bit = get_bvrep_bit(
863 to_constant_expr(expr.src()).get_value(),
866
867 return make_boolean_expr(bit);
868}
869
872{
873 bool no_change = true;
874
876
878 {
879 // first, turn bool into bvec[1]
881 {
882 exprt &op=*it;
883 if(op == true || op == false)
884 {
885 const bool value = op == true;
886 op = from_integer(value, unsignedbv_typet(1));
887 no_change = false;
888 }
889 }
890
891 // search for neighboring constants to merge
892 size_t i=0;
893
894 while(i < new_expr.operands().size() - 1)
895 {
896 exprt &opi = new_expr.operands()[i];
897 exprt &opn = new_expr.operands()[i + 1];
898
899 if(
900 opi.is_constant() && opn.is_constant() &&
903 {
904 // merge!
905 const auto &value_i = to_constant_expr(opi).get_value();
906 const auto &value_n = to_constant_expr(opn).get_value();
907 const auto width_i = to_bitvector_type(opi.type()).get_width();
908 const auto width_n = to_bitvector_type(opn.type()).get_width();
909 const auto new_width = width_i + width_n;
910
911 const auto new_value = make_bvrep(
912 new_width, [&value_i, &value_n, width_i, width_n](std::size_t x) {
913 return x < width_n ? get_bvrep_bit(value_n, width_n, x)
915 });
916
917 to_constant_expr(opi).set_value(new_value);
918 to_bitvector_type(opi.type()).set_width(new_width);
919 // erase opn
920 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
921 no_change = false;
922 }
923 else if(
926 {
929
930 if(
931 eb_i.src() == eb_n.src() && eb_i.index().is_constant() &&
932 eb_n.index().is_constant() &&
935 to_bitvector_type(eb_n.type()).get_width())
936 {
938 eb_merged.index() = eb_n.index();
940 .set_width(
941 to_bitvector_type(eb_i.type()).get_width() +
942 to_bitvector_type(eb_n.type()).get_width());
943 if(expr.type().id() != eb_merged.type().id())
944 {
946 bt.set_width(to_bitvector_type(eb_merged.type()).get_width());
948 }
949 else
950 opi = eb_merged;
951 // erase opn
952 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
953 no_change = false;
954 }
955 else
956 ++i;
957 }
958 else
959 i++;
960 }
961 }
962 else if(new_expr.type().id() == ID_verilog_unsignedbv)
963 {
964 // search for neighboring constants to merge
965 size_t i=0;
966
967 while(i < new_expr.operands().size() - 1)
968 {
969 exprt &opi = new_expr.operands()[i];
970 exprt &opn = new_expr.operands()[i + 1];
971
972 if(
973 opi.is_constant() && opn.is_constant() &&
976 {
977 // merge!
978 const std::string new_value=
979 opi.get_string(ID_value)+opn.get_string(ID_value);
980 opi.set(ID_value, new_value);
981 to_bitvector_type(opi.type()).set_width(new_value.size());
982 opi.type().id(ID_verilog_unsignedbv);
983 // erase opn
984 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
985 no_change = false;
986 }
987 else
988 i++;
989 }
990 }
991
992 // { x } = x
993 if(new_expr.operands().size() == 1)
994 {
995 if(new_expr.op0().type() == new_expr.type())
996 return new_expr.op0();
997 else
998 {
999 return changed(
1001 }
1002 }
1003
1004 if(no_change)
1005 return unchanged(expr);
1006 else
1007 return std::move(new_expr);
1008}
1009
1012{
1014 return unchanged(expr);
1015
1016 if(!can_cast_type<bitvector_typet>(expr.op().type()))
1017 return unchanged(expr);
1018
1019 return changed(simplify_node(expr.lower()));
1020}
1021
1024{
1026 return unchanged(expr);
1027
1028 const auto distance = numeric_cast<mp_integer>(expr.distance());
1029
1030 if(!distance.has_value())
1031 return unchanged(expr);
1032
1033 if(*distance == 0)
1034 return expr.op();
1035
1036 auto value = numeric_cast<mp_integer>(expr.op());
1037
1038 if(
1039 !value.has_value() && expr.op().type().id() == ID_bv &&
1040 expr.op().is_constant())
1041 {
1042 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1043 value =
1044 bvrep2integer(to_constant_expr(expr.op()).get_value(), width, false);
1045 }
1046
1047 if(!value.has_value())
1048 return unchanged(expr);
1049
1050 if(
1051 expr.op().type().id() == ID_unsignedbv ||
1052 expr.op().type().id() == ID_signedbv || expr.op().type().id() == ID_bv)
1053 {
1054 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1055
1056 if(expr.id()==ID_lshr)
1057 {
1058 // this is to guard against large values of distance
1059 if(*distance >= width)
1060 {
1061 return from_integer(0, expr.type());
1062 }
1063 else if(*distance >= 0)
1064 {
1065 if(*value < 0)
1066 *value += power(2, width);
1067 *value /= power(2, *distance);
1068 return from_integer(*value, expr.type());
1069 }
1070 }
1071 else if(expr.id()==ID_ashr)
1072 {
1073 if(*distance >= 0)
1074 {
1075 // this is to simulate an arithmetic right shift
1076 mp_integer new_value = *value >> *distance;
1077 return from_integer(new_value, expr.type());
1078 }
1079 }
1080 else if(expr.id()==ID_shl)
1081 {
1082 // this is to guard against large values of distance
1083 if(*distance >= width)
1084 {
1085 return from_integer(0, expr.type());
1086 }
1087 else if(*distance >= 0)
1088 {
1089 *value *= power(2, *distance);
1090 return from_integer(*value, expr.type());
1091 }
1092 }
1093 }
1094 else if(
1095 expr.op().type().id() == ID_integer || expr.op().type().id() == ID_natural)
1096 {
1097 if(expr.id()==ID_lshr)
1098 {
1099 if(*distance >= 0)
1100 {
1101 *value /= power(2, *distance);
1102 return from_integer(*value, expr.type());
1103 }
1104 }
1105 else if(expr.id()==ID_ashr)
1106 {
1107 // this is to simulate an arithmetic right shift
1108 if(*distance >= 0)
1109 {
1110 mp_integer new_value = *value / power(2, *distance);
1111 if(*value < 0 && new_value == 0)
1112 new_value=-1;
1113
1114 return from_integer(new_value, expr.type());
1115 }
1116 }
1117 else if(expr.id()==ID_shl)
1118 {
1119 if(*distance >= 0)
1120 {
1121 *value *= power(2, *distance);
1122 return from_integer(*value, expr.type());
1123 }
1124 }
1125 }
1126
1127 return unchanged(expr);
1128}
1129
1132{
1133 if(!is_number(expr.type()))
1134 return unchanged(expr);
1135
1136 const auto base = numeric_cast<mp_integer>(expr.base());
1137 const auto exponent = numeric_cast<mp_integer>(expr.exponent());
1138
1139 if(!exponent.has_value())
1140 return unchanged(expr);
1141
1142 if(exponent.value() == 0)
1143 return from_integer(1, expr.type());
1144
1145 if(exponent.value() == 1)
1146 return expr.base();
1147
1148 if(!base.has_value())
1149 return unchanged(expr);
1150
1151 mp_integer result = power(*base, *exponent);
1152
1153 return from_integer(result, expr.type());
1154}
1155
1159{
1160 const typet &op0_type = expr.src().type();
1161
1162 if(
1165 {
1166 return unchanged(expr);
1167 }
1168
1169 const auto end = numeric_cast<mp_integer>(expr.index());
1170
1171 if(!end.has_value())
1172 return unchanged(expr);
1173
1174 const auto width = pointer_offset_bits(op0_type, ns);
1175
1176 if(!width.has_value())
1177 return unchanged(expr);
1178
1179 const auto result_width = pointer_offset_bits(expr.type(), ns);
1180
1181 if(!result_width.has_value())
1182 return unchanged(expr);
1183
1184 const auto start = std::optional(*end + *result_width - 1);
1185
1186 if(*start < 0 || *start >= (*width) || *end < 0 || *end >= (*width))
1187 return unchanged(expr);
1188
1189 DATA_INVARIANT(*start >= *end, "extractbits must have start >= end");
1190
1191 if(expr.src().is_constant())
1192 {
1193 const auto svalue = expr2bits(expr.src(), true, ns);
1194
1195 if(!svalue.has_value() || svalue->size() != *width)
1196 return unchanged(expr);
1197
1198 std::string extracted_value = svalue->substr(
1200 numeric_cast_v<std::size_t>(*start - *end + 1));
1201
1202 auto result = bits2expr(extracted_value, expr.type(), true, ns);
1203 if(!result.has_value())
1204 return unchanged(expr);
1205
1206 return std::move(*result);
1207 }
1208 else if(expr.src().id() == ID_concatenation)
1209 {
1210 // the most-significant bit comes first in an concatenation_exprt, hence we
1211 // count down
1212 mp_integer offset = *width;
1213
1214 for(const auto &op : expr.src().operands())
1215 {
1216 auto op_width = pointer_offset_bits(op.type(), ns);
1217
1218 if(!op_width.has_value() || *op_width <= 0)
1219 return unchanged(expr);
1220
1221 if(*start < offset && offset <= *end + *op_width)
1222 {
1223 extractbits_exprt result = expr;
1224 result.src() = op;
1225 result.index() =
1226 from_integer(*end - (offset - *op_width), expr.index().type());
1227 return changed(simplify_extractbits(result));
1228 }
1229
1230 offset -= *op_width;
1231 }
1232 }
1234 {
1235 if(eb_src->index().is_constant())
1236 {
1237 extractbits_exprt result = *eb_src;
1238 result.type() = expr.type();
1239 const mp_integer src_index =
1241 result.index() = from_integer(src_index + *end, eb_src->index().type());
1242 return changed(simplify_extractbits(result));
1243 }
1244 }
1245 else if(*end == 0 && *start + 1 == *width)
1246 {
1247 typecast_exprt tc{expr.src(), expr.type()};
1248 return changed(simplify_typecast(tc));
1249 }
1250
1251 return unchanged(expr);
1252}
1253
1256{
1257 // simply remove, this is always 'nop'
1258 return expr.op();
1259}
1260
1263{
1264 if(!is_number(expr.type()))
1265 return unchanged(expr);
1266
1267 const exprt &operand = expr.op();
1268
1269 if(expr.type()!=operand.type())
1270 return unchanged(expr);
1271
1272 if(operand.id()==ID_unary_minus)
1273 {
1274 // cancel out "-(-x)" to "x"
1275 if(!is_number(to_unary_minus_expr(operand).op().type()))
1276 return unchanged(expr);
1277
1278 return to_unary_minus_expr(operand).op();
1279 }
1280 else if(operand.is_constant())
1281 {
1282 const irep_idt &type_id=expr.type().id();
1283 const auto &constant_expr = to_constant_expr(operand);
1284
1285 if(type_id==ID_integer ||
1288 {
1290
1291 if(!int_value.has_value())
1292 return unchanged(expr);
1293
1294 return from_integer(-*int_value, expr.type());
1295 }
1296 else if(type_id==ID_rational)
1297 {
1298 rationalt r;
1300 return unchanged(expr);
1301
1302 return from_rational(-r);
1303 }
1304 else if(type_id==ID_fixedbv)
1305 {
1307 f.negate();
1308 return f.to_expr();
1309 }
1310 else if(type_id==ID_floatbv)
1311 {
1313 f.negate();
1314 return f.to_expr();
1315 }
1316 }
1317
1318 return unchanged(expr);
1319}
1320
1323{
1324 const exprt &op = expr.op();
1325
1326 const auto &type = expr.type();
1327
1328 if(
1329 type.id() == ID_bv || type.id() == ID_unsignedbv ||
1330 type.id() == ID_signedbv)
1331 {
1332 const auto width = to_bitvector_type(type).get_width();
1333
1334 if(op.type() == type)
1335 {
1336 if(op.is_constant())
1337 {
1338 const auto &value = to_constant_expr(op).get_value();
1339 const auto new_value =
1340 make_bvrep(width, [&value, &width](std::size_t i) {
1341 return !get_bvrep_bit(value, width, i);
1342 });
1343 return constant_exprt(new_value, op.type());
1344 }
1345 }
1346 }
1347
1348 return unchanged(expr);
1349}
1350
1354{
1355 if(!expr.is_boolean())
1356 return unchanged(expr);
1357
1358 exprt tmp0=expr.op0();
1359 exprt tmp1=expr.op1();
1360
1361 // types must match
1362 if(tmp0.type() != tmp1.type())
1363 return unchanged(expr);
1364
1365 // if rhs is ID_if (and lhs is not), swap operands for == and !=
1366 if((expr.id()==ID_equal || expr.id()==ID_notequal) &&
1367 tmp0.id()!=ID_if &&
1368 tmp1.id()==ID_if)
1369 {
1370 auto new_expr = expr;
1371 new_expr.op0().swap(new_expr.op1());
1372 return changed(simplify_inequality(new_expr)); // recursive call
1373 }
1374
1375 if(tmp0.id()==ID_if && tmp0.operands().size()==3)
1376 {
1377 if_exprt if_expr=lift_if(expr, 0);
1378 if_expr.true_case() =
1380 if_expr.false_case() =
1382 return changed(simplify_if(if_expr));
1383 }
1384
1385 // see if we are comparing pointers that are address_of
1386 if(
1387 skip_typecast(tmp0).id() == ID_address_of &&
1388 skip_typecast(tmp1).id() == ID_address_of &&
1389 (expr.id() == ID_equal || expr.id() == ID_notequal))
1390 {
1391 return simplify_inequality_address_of(expr);
1392 }
1393
1394 if(tmp0.id()==ID_pointer_object &&
1395 tmp1.id()==ID_pointer_object &&
1396 (expr.id()==ID_equal || expr.id()==ID_notequal))
1397 {
1399 }
1400
1401 if(tmp0.type().id()==ID_c_enum_tag)
1402 tmp0.type()=ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1403
1404 if(tmp1.type().id()==ID_c_enum_tag)
1405 tmp1.type()=ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1406
1407 const bool tmp0_const = tmp0.is_constant();
1408 const bool tmp1_const = tmp1.is_constant();
1409
1410 // are _both_ constant?
1411 if(tmp0_const && tmp1_const)
1412 {
1414 }
1415 else if(tmp0_const)
1416 {
1417 // we want the constant on the RHS
1418
1420
1421 if(expr.id()==ID_ge)
1422 new_expr.id(ID_le);
1423 else if(expr.id()==ID_le)
1424 new_expr.id(ID_ge);
1425 else if(expr.id()==ID_gt)
1426 new_expr.id(ID_lt);
1427 else if(expr.id()==ID_lt)
1428 new_expr.id(ID_gt);
1429
1430 new_expr.op0().swap(new_expr.op1());
1431
1432 // RHS is constant, LHS is not
1434 }
1435 else if(tmp1_const)
1436 {
1437 // RHS is constant, LHS is not
1439 }
1440 else
1441 {
1442 // both are not constant
1444 }
1445}
1446
1450 const binary_relation_exprt &expr)
1451{
1452 exprt tmp0 = expr.op0();
1453 exprt tmp1 = expr.op1();
1454
1455 if(tmp0.type().id() == ID_c_enum_tag)
1456 tmp0.type() = ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1457
1458 if(tmp1.type().id() == ID_c_enum_tag)
1459 tmp1.type() = ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1460
1461 const auto &tmp0_const = to_constant_expr(tmp0);
1462 const auto &tmp1_const = to_constant_expr(tmp1);
1463
1464 if(expr.id() == ID_equal || expr.id() == ID_notequal)
1465 {
1466 // two constants compare equal when there values (as strings) are the same
1467 // or both of them are pointers and both represent NULL in some way
1468 bool equal = (tmp0_const.get_value() == tmp1_const.get_value());
1469 if(
1470 !equal && tmp0_const.type().id() == ID_pointer &&
1471 tmp1_const.type().id() == ID_pointer)
1472 {
1473 if(
1474 !config.ansi_c.NULL_is_zero && (tmp0_const.get_value() == ID_NULL ||
1475 tmp1_const.get_value() == ID_NULL))
1476 {
1477 // if NULL is not zero on this platform, we really don't know what it
1478 // is and therefore cannot simplify
1479 return unchanged(expr);
1480 }
1481 equal = tmp0_const == 0 && tmp1_const == 0;
1482 }
1483 return make_boolean_expr(expr.id() == ID_equal ? equal : !equal);
1484 }
1485
1486 if(tmp0.type().id() == ID_fixedbv)
1487 {
1489 fixedbvt f1(tmp1_const);
1490
1491 if(expr.id() == ID_ge)
1492 return make_boolean_expr(f0 >= f1);
1493 else if(expr.id() == ID_le)
1494 return make_boolean_expr(f0 <= f1);
1495 else if(expr.id() == ID_gt)
1496 return make_boolean_expr(f0 > f1);
1497 else if(expr.id() == ID_lt)
1498 return make_boolean_expr(f0 < f1);
1499 else
1501 }
1502 else if(tmp0.type().id() == ID_floatbv)
1503 {
1506
1507 if(expr.id() == ID_ge)
1508 return make_boolean_expr(f0 >= f1);
1509 else if(expr.id() == ID_le)
1510 return make_boolean_expr(f0 <= f1);
1511 else if(expr.id() == ID_gt)
1512 return make_boolean_expr(f0 > f1);
1513 else if(expr.id() == ID_lt)
1514 return make_boolean_expr(f0 < f1);
1515 else
1517 }
1518 else if(tmp0.type().id() == ID_rational)
1519 {
1520 rationalt r0, r1;
1521
1522 if(to_rational(tmp0, r0))
1523 return unchanged(expr);
1524
1525 if(to_rational(tmp1, r1))
1526 return unchanged(expr);
1527
1528 if(expr.id() == ID_ge)
1529 return make_boolean_expr(r0 >= r1);
1530 else if(expr.id() == ID_le)
1531 return make_boolean_expr(r0 <= r1);
1532 else if(expr.id() == ID_gt)
1533 return make_boolean_expr(r0 > r1);
1534 else if(expr.id() == ID_lt)
1535 return make_boolean_expr(r0 < r1);
1536 else
1538 }
1539 else
1540 {
1542
1543 if(!v0.has_value())
1544 return unchanged(expr);
1545
1547
1548 if(!v1.has_value())
1549 return unchanged(expr);
1550
1551 if(expr.id() == ID_ge)
1552 return make_boolean_expr(*v0 >= *v1);
1553 else if(expr.id() == ID_le)
1554 return make_boolean_expr(*v0 <= *v1);
1555 else if(expr.id() == ID_gt)
1556 return make_boolean_expr(*v0 > *v1);
1557 else if(expr.id() == ID_lt)
1558 return make_boolean_expr(*v0 < *v1);
1559 else
1561 }
1562}
1563
1564static bool eliminate_common_addends(exprt &op0, exprt &op1)
1565{
1566 // we can't eliminate zeros
1567 if(
1568 op0 == 0 || op1 == 0 ||
1569 (op0.is_constant() && to_constant_expr(op0).is_null_pointer()) ||
1570 (op1.is_constant() && to_constant_expr(op1).is_null_pointer()))
1571 {
1572 return true;
1573 }
1574
1575 if(op0.id()==ID_plus)
1576 {
1577 bool no_change = true;
1578
1579 Forall_operands(it, op0)
1580 if(!eliminate_common_addends(*it, op1))
1581 no_change = false;
1582
1583 return no_change;
1584 }
1585 else if(op1.id()==ID_plus)
1586 {
1587 bool no_change = true;
1588
1589 Forall_operands(it, op1)
1590 if(!eliminate_common_addends(op0, *it))
1591 no_change = false;
1592
1593 return no_change;
1594 }
1595 else if(op0==op1)
1596 {
1597 if(op0 != 0 && op0.type().id() != ID_complex)
1598 {
1599 // elimination!
1600 op0=from_integer(0, op0.type());
1601 op1=from_integer(0, op1.type());
1602 return false;
1603 }
1604 }
1605
1606 return true;
1607}
1608
1610 const binary_relation_exprt &expr)
1611{
1612 // pretty much all of the simplifications below are unsound
1613 // for IEEE float because of NaN!
1614
1615 if(expr.op0().type().id() == ID_floatbv)
1616 return unchanged(expr);
1617
1618 if(expr.op0().type().id() == ID_pointer)
1619 {
1622
1623 if(ptr_op0 == ptr_op1)
1624 {
1627
1629 std::move(offset_op0), expr.id(), std::move(offset_op1)}));
1630 }
1631 // simplifications below require same-object, which we don't check for
1632 else if(expr.id() != ID_equal && expr.id() != ID_notequal)
1633 {
1634 return unchanged(expr);
1635 }
1636 else if(
1637 expr.id() == ID_equal && ptr_op0.id() == ID_address_of &&
1638 ptr_op1.id() == ID_address_of)
1639 {
1640 // comparing pointers: if both are address-of-plus-some-constant such that
1641 // the resulting pointer remains within object bounds then they can never
1642 // be equal
1643 auto in_bounds = [this](const exprt &object_ptr, const exprt &expr_op) {
1644 auto object_size =
1645 size_of_expr(to_address_of_expr(object_ptr).object().type(), ns);
1646
1647 if(object_size.has_value())
1648 {
1652 std::move(offset), ID_lt, std::move(*object_size)})
1653 .expr;
1654 if(in_object_bounds.is_constant())
1655 return tvt{in_object_bounds == true};
1656 }
1657
1658 return tvt::unknown();
1659 };
1660
1661 if(
1662 in_bounds(ptr_op0, expr.op0()).is_true() &&
1663 in_bounds(ptr_op1, expr.op1()).is_true())
1664 {
1665 return false_exprt{};
1666 }
1667 }
1668 }
1669
1670 // eliminate strict inequalities
1671 if(expr.id()==ID_notequal)
1672 {
1673 auto new_rel_expr = expr;
1677 }
1678 else if(expr.id()==ID_gt)
1679 {
1680 auto new_rel_expr = expr;
1681 new_rel_expr.id(ID_ge);
1682 // swap operands
1683 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1686 }
1687 else if(expr.id()==ID_lt)
1688 {
1689 auto new_rel_expr = expr;
1690 new_rel_expr.id(ID_ge);
1693 }
1694 else if(expr.id()==ID_le)
1695 {
1696 auto new_rel_expr = expr;
1697 new_rel_expr.id(ID_ge);
1698 // swap operands
1699 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1701 }
1702
1703 // now we only have >=, =
1704
1705 INVARIANT(
1706 expr.id() == ID_ge || expr.id() == ID_equal,
1707 "we previously converted all other cases to >= or ==");
1708
1709 // syntactically equal?
1710
1711 if(expr.op0() == expr.op1())
1712 return true_exprt();
1713
1714 // See if we can eliminate common addends on both sides.
1715 // On bit-vectors, this is only sound on '='.
1716 if(expr.id()==ID_equal)
1717 {
1718 auto new_expr = to_equal_expr(expr);
1719 if(!eliminate_common_addends(new_expr.lhs(), new_expr.rhs()))
1720 {
1721 // remove zeros
1722 new_expr.lhs() = simplify_node(new_expr.lhs());
1723 new_expr.rhs() = simplify_node(new_expr.rhs());
1724 return changed(simplify_inequality(new_expr)); // recursive call
1725 }
1726 }
1727
1728 return unchanged(expr);
1729}
1730
1734 const binary_relation_exprt &expr)
1735{
1736 // the constant is always on the RHS
1737 PRECONDITION(expr.op1().is_constant());
1738
1739 if(expr.op0().id()==ID_if && expr.op0().operands().size()==3)
1740 {
1741 if_exprt if_expr=lift_if(expr, 0);
1742 if_expr.true_case() =
1744 if_expr.false_case() =
1746 return changed(simplify_if(if_expr));
1747 }
1748
1749 // do we deal with pointers?
1750 if(expr.op1().type().id()==ID_pointer)
1751 {
1752 if(expr.id()==ID_notequal)
1753 {
1754 auto new_rel_expr = expr;
1758 }
1759
1760 // very special case for pointers
1761 if(expr.id() != ID_equal)
1762 return unchanged(expr);
1763
1765
1766 if(op1_constant.is_null_pointer())
1767 {
1768 // the address of an object is never NULL
1769
1770 if(expr.op0().id() == ID_address_of)
1771 {
1772 const auto &object = to_address_of_expr(expr.op0()).object();
1773
1774 if(
1775 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1776 object.id() == ID_member || object.id() == ID_index ||
1777 object.id() == ID_string_constant)
1778 {
1779 return false_exprt();
1780 }
1781 }
1782 else if(
1783 expr.op0().id() == ID_typecast &&
1784 expr.op0().type().id() == ID_pointer &&
1785 to_typecast_expr(expr.op0()).op().id() == ID_address_of)
1786 {
1787 const auto &object =
1788 to_address_of_expr(to_typecast_expr(expr.op0()).op()).object();
1789
1790 if(
1791 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1792 object.id() == ID_member || object.id() == ID_index ||
1793 object.id() == ID_string_constant)
1794 {
1795 return false_exprt();
1796 }
1797 }
1798 else if(
1799 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_pointer)
1800 {
1801 exprt op = to_typecast_expr(expr.op0()).op();
1802 if(
1803 op.type().id() != ID_pointer &&
1804 (!config.ansi_c.NULL_is_zero || !is_number(op.type()) ||
1805 op.type().id() == ID_complex))
1806 {
1807 return unchanged(expr);
1808 }
1809
1810 // (type)ptr == NULL -> ptr == NULL
1811 // note that 'ptr' may be an integer
1812 auto new_expr = expr;
1813 new_expr.op0().swap(op);
1814 if(new_expr.op0().type().id() != ID_pointer)
1815 new_expr.op1() = from_integer(0, new_expr.op0().type());
1816 else
1817 new_expr.op1().type() = new_expr.op0().type();
1818 return changed(simplify_inequality(new_expr)); // do again!
1819 }
1820 else if(expr.op0().id() == ID_plus)
1821 {
1822 exprt offset =
1824 if(!offset.is_constant())
1825 return unchanged(expr);
1826
1827 exprt ptr = simplify_object(expr.op0()).expr;
1828 // NULL + N == NULL is N == 0
1829 if(ptr.is_constant() && to_constant_expr(ptr).is_null_pointer())
1830 return make_boolean_expr(offset == 0);
1831 // &x + N == NULL is false when the offset is in bounds
1833 {
1834 const auto object_size =
1835 pointer_offset_size(address_of->object().type(), ns);
1836 if(
1837 object_size.has_value() &&
1839 {
1840 return false_exprt();
1841 }
1842 }
1843 }
1844 }
1845
1846 // all we are doing with pointers
1847 return unchanged(expr);
1848 }
1849
1850 // is it a separation predicate?
1851
1852 if(expr.op0().id()==ID_plus)
1853 {
1854 // see if there is a constant in the sum
1855
1856 if(expr.id()==ID_equal || expr.id()==ID_notequal)
1857 {
1858 mp_integer constant=0;
1859 bool op_changed = false;
1860 auto new_expr = expr;
1861
1862 Forall_operands(it, new_expr.op0())
1863 {
1864 if(it->is_constant())
1865 {
1866 mp_integer i;
1867 if(!to_integer(to_constant_expr(*it), i))
1868 {
1869 constant+=i;
1870 *it=from_integer(0, it->type());
1871 op_changed = true;
1872 }
1873 }
1874 }
1875
1876 if(op_changed)
1877 {
1878 // adjust the constant on the RHS
1879 mp_integer i =
1881 i-=constant;
1882 new_expr.op1() = from_integer(i, new_expr.op1().type());
1883
1886 }
1887 }
1888 }
1889
1890 #if 1
1891 // (double)value REL const ---> value rel const
1892 // if 'const' can be represented exactly.
1893
1894 if(
1895 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_floatbv &&
1896 to_typecast_expr(expr.op0()).op().type().id() == ID_floatbv)
1897 {
1902 to_floatbv_type(to_typecast_expr(expr.op0()).op().type())));
1904 const_val_converted_back.change_spec(
1907 {
1908 auto result = expr;
1909 result.op0() = to_typecast_expr(expr.op0()).op();
1910 result.op1()=const_val_converted.to_expr();
1911 return std::move(result);
1912 }
1913 }
1914 #endif
1915
1916 // is the constant zero?
1917
1918 if(expr.op1() == 0)
1919 {
1920 if(expr.id()==ID_ge &&
1921 expr.op0().type().id()==ID_unsignedbv)
1922 {
1923 // zero is always smaller or equal something unsigned
1924 return true_exprt();
1925 }
1926
1927 auto new_expr = expr;
1928 exprt &operand = new_expr.op0();
1929
1930 if(expr.id()==ID_equal)
1931 {
1932 // rules below do not hold for >=
1933 if(operand.id()==ID_unary_minus)
1934 {
1936 return std::move(new_expr);
1937 }
1938 else if(operand.id()==ID_plus)
1939 {
1941
1942 // simplify a+-b=0 to a=b
1943 if(operand_plus_expr.operands().size() == 2)
1944 {
1945 // if we have -b+a=0, make that a+(-b)=0
1946 if(operand_plus_expr.op0().id() == ID_unary_minus)
1947 operand_plus_expr.op0().swap(operand_plus_expr.op1());
1948
1949 if(operand_plus_expr.op1().id() == ID_unary_minus)
1950 {
1951 return binary_exprt(
1952 operand_plus_expr.op0(),
1953 expr.id(),
1955 expr.type());
1956 }
1957 }
1958 }
1959 }
1960
1961 if(config.ansi_c.NULL_is_zero)
1962 {
1963 const exprt &maybe_tc_op = skip_typecast(expr.op0());
1964 if(maybe_tc_op.type().id() == ID_pointer)
1965 {
1966 // make sure none of the type casts lose information
1968 bool bitwidth_unchanged = true;
1969 const exprt *ep = &(expr.op0());
1970 while(bitwidth_unchanged && ep->id() == ID_typecast)
1971 {
1972 if(auto t = type_try_dynamic_cast<bitvector_typet>(ep->type()))
1973 {
1974 bitwidth_unchanged = t->get_width() == p_type.get_width();
1975 }
1976 else
1977 bitwidth_unchanged = false;
1978
1979 ep = &to_typecast_expr(*ep).op();
1980 }
1981
1983 {
1984 if(expr.id() == ID_equal || expr.id() == ID_ge || expr.id() == ID_le)
1985 {
1986 return changed(simplify_rec(
1988 }
1989 else
1990 {
1991 return changed(simplify_rec(
1993 }
1994 }
1995 }
1996 }
1997 }
1998
1999 // are we comparing with a typecast from bool?
2000 if(
2001 expr.op0().id() == ID_typecast &&
2002 to_typecast_expr(expr.op0()).op().is_boolean())
2003 {
2004 const auto &lhs_typecast_op = to_typecast_expr(expr.op0()).op();
2005
2006 // we re-write (TYPE)boolean == 0 -> !boolean
2007 if(expr.op1() == 0 && expr.id() == ID_equal)
2008 {
2010 }
2011
2012 // we re-write (TYPE)boolean != 0 -> boolean
2013 if(expr.op1() == 0 && expr.id() == ID_notequal)
2014 {
2015 return lhs_typecast_op;
2016 }
2017 }
2018
2019 #define NORMALISE_CONSTANT_TESTS
2020 #ifdef NORMALISE_CONSTANT_TESTS
2021 // Normalise to >= and = to improve caching and term sharing
2022 if(expr.op0().type().id()==ID_unsignedbv ||
2023 expr.op0().type().id()==ID_signedbv)
2024 {
2025 mp_integer max(to_integer_bitvector_type(expr.op0().type()).largest());
2026
2027 if(expr.id()==ID_notequal)
2028 {
2029 auto new_rel_expr = expr;
2033 }
2034 else if(expr.id()==ID_gt)
2035 {
2037
2038 if(i==max)
2039 {
2040 return false_exprt();
2041 }
2042
2043 auto new_expr = expr;
2044 new_expr.id(ID_ge);
2045 ++i;
2046 new_expr.op1() = from_integer(i, new_expr.op1().type());
2048 }
2049 else if(expr.id()==ID_lt)
2050 {
2051 auto new_rel_expr = expr;
2052 new_rel_expr.id(ID_ge);
2055 }
2056 else if(expr.id()==ID_le)
2057 {
2059
2060 if(i==max)
2061 {
2062 return true_exprt();
2063 }
2064
2065 auto new_rel_expr = expr;
2066 new_rel_expr.id(ID_ge);
2067 ++i;
2068 new_rel_expr.op1() = from_integer(i, new_rel_expr.op1().type());
2071 }
2072 }
2073#endif
2074 return unchanged(expr);
2075}
2076
2079{
2081 expr.op(),
2083 ns);
2084
2085 if(!const_bits_opt.has_value())
2086 return unchanged(expr);
2087
2088 std::reverse(const_bits_opt->begin(), const_bits_opt->end());
2089
2090 auto result = bits2expr(
2092 expr.type(),
2094 ns);
2095 if(!result.has_value())
2096 return unchanged(expr);
2097
2098 return std::move(*result);
2099}
std::unordered_map< exprt, exprt, irep_hash > expr_mapt
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
irep_idt make_bvrep(const std::size_t width, const std::function< bool(std::size_t)> f)
construct a bit-vector representation from a functor
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
bool get_bvrep_bit(const irep_idt &src, std::size_t width, std::size_t bit_index)
Get a bit with given index from bit-vector representation.
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition as_const.h:14
API to expression classes for bitvectors.
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const integer_bitvector_typet & to_integer_bitvector_type(const typet &type)
Cast a typet to an integer_bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
A base class for binary expressions.
Definition std_expr.h:638
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:762
Bit-wise negation of bit-vectors.
Reverse the order of bits in a bit-vector.
Base class of fixed-width bit-vector types.
Definition std_types.h:909
The Boolean type.
Definition std_types.h:36
The byte swap expression.
std::size_t get_bits_per_byte() const
Concatenation of bit-vector operands.
struct configt::ansi_ct ansi_c
A constant literal expression.
Definition std_expr.h:3118
Division.
Definition std_expr.h:1157
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Equality.
Definition std_expr.h:1366
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:229
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
The Boolean constant false.
Definition std_expr.h:3246
void negate()
Definition fixedbv.cpp:90
bool is_zero() const
Definition fixedbv.h:71
constant_exprt to_expr() const
Definition fixedbv.cpp:43
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
constant_exprt to_expr() const
An IEEE 754 value plus a rounding mode, enabling operations with rounding on values.
Definition ieee_float.h:338
The trinary if-then-else operator.
Definition std_expr.h:2502
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
Binary minus.
Definition std_expr.h:1061
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1228
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:912
exprt & op1()
Definition std_expr.h:938
exprt & op0()
Definition std_expr.h:932
Boolean negation.
Definition std_expr.h:2459
Disequality.
Definition std_expr.h:1425
The null pointer constant.
The plus expression Associativity is not specified.
Definition std_expr.h:1002
The offset (in bytes) of a pointer relative to the object.
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Exponentiation.
const exprt & base() const
const exprt & exponent() const
A base class for shift and rotate operators.
exprt & distance()
resultt simplify_bitwise(const multi_ary_exprt &)
const namespacet & ns
resultt simplify_inequality_address_of(const binary_relation_exprt &)
resultt simplify_div(const div_exprt &)
resultt simplify_bitreverse(const bitreverse_exprt &)
Try to simplify bit-reversing to a constant expression.
resultt simplify_bitnot(const bitnot_exprt &)
resultt simplify_zero_extend(const zero_extend_exprt &)
static resultt changed(resultt<> result)
resultt simplify_if(const if_exprt &)
resultt simplify_node(const exprt &)
resultt simplify_minus(const minus_exprt &)
resultt simplify_extractbit(const extractbit_exprt &)
resultt simplify_rec(const exprt &)
resultt simplify_shifts(const shift_exprt &)
resultt simplify_typecast(const typecast_exprt &)
resultt simplify_object(const exprt &)
resultt simplify_mult(const mult_exprt &)
resultt simplify_inequality_rhs_is_constant(const binary_relation_exprt &)
virtual resultt simplify_inequality(const binary_relation_exprt &)
simplifies inequalities !=, <=, <, >=, >, and also ==
resultt simplify_not(const not_exprt &)
resultt simplify_bswap(const bswap_exprt &)
virtual resultt simplify_inequality_pointer_object(const binary_relation_exprt &)
static resultt unchanged(exprt expr)
resultt simplify_extractbits(const extractbits_exprt &)
Simplifies extracting of bits from a constant.
resultt simplify_mod(const mod_exprt &)
virtual resultt simplify_pointer_offset(const pointer_offset_exprt &)
resultt simplify_plus(const plus_exprt &)
resultt simplify_inequality_no_constant(const binary_relation_exprt &)
resultt simplify_unary_plus(const unary_plus_exprt &)
resultt simplify_power(const power_exprt &)
resultt simplify_concatenation(const concatenation_exprt &)
resultt simplify_inequality_both_constant(const binary_relation_exprt &)
simplifies inequalities for the case in which both sides of the inequality are constants
resultt simplify_unary_minus(const unary_minus_exprt &)
The Boolean constant true.
Definition std_expr.h:3237
Definition threeval.h:20
static tvt unknown()
Definition threeval.h:33
Semantic type conversion.
Definition std_expr.h:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:391
The unary minus expression.
Definition std_expr.h:484
The unary plus expression.
Definition std_expr.h:531
Fixed-width bit-vector with unsigned binary interpretation.
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
#define Forall_operands(it, expr)
Definition expr.h:28
#define Forall_expr(it, expr)
Definition expr.h:37
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
if_exprt lift_if(const exprt &src, std::size_t operand_number)
lift up an if_exprt one level
Deprecated expression utility functions.
static int8_t r
Definition irep_hash.h:60
API to expression classes for 'mathematical' expressions.
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Mathematical types.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
exprt object_size(const exprt &pointer)
bool to_rational(const exprt &expr, rationalt &rational_value)
constant_exprt from_rational(const rationalt &a)
static bool mul_expr(constant_exprt &dest, const constant_exprt &expr)
produce a product of two expressions of the same type
static bool sum_expr(constant_exprt &dest, const constant_exprt &expr)
produce a sum of two constant expressions of the same type
static bool eliminate_common_addends(exprt &op0, exprt &op1)
std::optional< exprt > bits2expr(const std::string &bits, const typet &type, bool little_endian, const namespacet &ns)
std::optional< std::string > expr2bits(const exprt &expr, bool little_endian, const namespacet &ns)
BigInt mp_integer
Definition smt_terms.h:17
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
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 typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition std_expr.h:1041
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition std_expr.h:1086
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3189
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
Definition std_expr.h:514
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1407
#define size_type
Definition unistd.c:186