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 // 'all zeros' in bitand yields zero
772 if(new_expr.id() == ID_bitand)
773 {
774 const constant_exprt zero = new_expr.type().id() == ID_bv
775 ? to_bv_type(new_expr.type()).all_zeros_expr()
776 : from_integer(0, new_expr.type());
777 for(const auto &op : new_expr.operands())
778 {
779 if(op == zero)
780 return zero;
781 }
782 }
783
784 // 'all ones' in bitor yields all-ones
785 if(new_expr.id() == ID_bitor)
786 {
788 new_expr.type().id() == ID_bv
789 ? to_bv_type(new_expr.type()).all_ones_expr()
790 : from_integer(power(2, width) - 1, new_expr.type());
791 for(const auto &op : new_expr.operands())
792 {
793 if(op == all_ones)
794 return all_ones;
795 }
796 }
797
798 // now erase 'all zeros' out of bitor, bitxor
799
800 if(new_expr.id() == ID_bitor || new_expr.id() == ID_bitxor)
801 {
802 for(exprt::operandst::iterator it = new_expr.operands().begin();
803 it != new_expr.operands().end();) // no it++
804 {
805 if(*it == 0 && new_expr.operands().size() > 1)
806 {
807 it = new_expr.operands().erase(it);
808 no_change = false;
809 }
810 else if(
811 it->is_constant() && it->type().id() == ID_bv &&
812 *it == to_bv_type(it->type()).all_zeros_expr() &&
813 new_expr.operands().size() > 1)
814 {
815 it = new_expr.operands().erase(it);
816 no_change = false;
817 }
818 else
819 it++;
820 }
821 }
822
823 // now erase 'all ones' out of bitand
824
825 if(new_expr.id() == ID_bitand)
826 {
827 const auto all_ones = power(2, width) - 1;
828 for(exprt::operandst::iterator it = new_expr.operands().begin();
829 it != new_expr.operands().end();) // no it++
830 {
831 if(
832 it->is_constant() &&
833 bvrep2integer(to_constant_expr(*it).get_value(), width, false) ==
834 all_ones &&
835 new_expr.operands().size() > 1)
836 {
837 it = new_expr.operands().erase(it);
838 no_change = false;
839 }
840 else
841 it++;
842 }
843 }
844
845 // two operands that are syntactically the same
846
847 if(new_expr.operands().size() == 2 && new_expr.op0() == new_expr.op1())
848 {
849 if(new_expr.id() == ID_bitand || new_expr.id() == ID_bitor)
850 {
851 return new_expr.op0();
852 }
853 else if(new_expr.id() == ID_bitxor)
854 {
855 return constant_exprt(integer2bvrep(0, width), new_expr.type());
856 }
857 }
858
859 if(new_expr.operands().size() == 1)
860 return new_expr.op0();
861
862 if(no_change)
863 return unchanged(expr);
864 else
865 return std::move(new_expr);
866}
867
870{
871 const typet &src_type = expr.src().type();
872
874 return unchanged(expr);
875
876 const std::size_t src_bit_width = to_bitvector_type(src_type).get_width();
877
879 if(
880 !index_converted_to_int.has_value() || *index_converted_to_int < 0 ||
882 {
883 return unchanged(expr);
884 }
885
886 if(!expr.src().is_constant())
887 return unchanged(expr);
888
889 const bool bit = get_bvrep_bit(
890 to_constant_expr(expr.src()).get_value(),
893
894 return make_boolean_expr(bit);
895}
896
899{
900 bool no_change = true;
901
903
905 {
906 // first, turn bool into bvec[1]
908 {
909 exprt &op=*it;
910 if(op == true || op == false)
911 {
912 const bool value = op == true;
913 op = from_integer(value, unsignedbv_typet(1));
914 no_change = false;
915 }
916 }
917
918 // search for neighboring constants to merge
919 size_t i=0;
920
921 while(i < new_expr.operands().size() - 1)
922 {
923 exprt &opi = new_expr.operands()[i];
924 exprt &opn = new_expr.operands()[i + 1];
925
926 if(
927 opi.is_constant() && opn.is_constant() &&
930 {
931 // merge!
932 const auto &value_i = to_constant_expr(opi).get_value();
933 const auto &value_n = to_constant_expr(opn).get_value();
934 const auto width_i = to_bitvector_type(opi.type()).get_width();
935 const auto width_n = to_bitvector_type(opn.type()).get_width();
936 const auto new_width = width_i + width_n;
937
938 const auto new_value = make_bvrep(
939 new_width, [&value_i, &value_n, width_i, width_n](std::size_t x) {
940 return x < width_n ? get_bvrep_bit(value_n, width_n, x)
942 });
943
944 to_constant_expr(opi).set_value(new_value);
945 to_bitvector_type(opi.type()).set_width(new_width);
946 // erase opn
947 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
948 no_change = false;
949 }
950 else if(
953 {
956
957 if(
958 eb_i.src() == eb_n.src() && eb_i.index().is_constant() &&
959 eb_n.index().is_constant() &&
962 to_bitvector_type(eb_n.type()).get_width())
963 {
965 eb_merged.index() = eb_n.index();
967 .set_width(
968 to_bitvector_type(eb_i.type()).get_width() +
969 to_bitvector_type(eb_n.type()).get_width());
970 if(expr.type().id() != eb_merged.type().id())
971 {
973 bt.set_width(to_bitvector_type(eb_merged.type()).get_width());
975 }
976 else
977 opi = eb_merged;
978 // erase opn
979 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
980 no_change = false;
981 }
982 else
983 ++i;
984 }
985 else
986 i++;
987 }
988 }
989 else if(new_expr.type().id() == ID_verilog_unsignedbv)
990 {
991 // search for neighboring constants to merge
992 size_t i=0;
993
994 while(i < new_expr.operands().size() - 1)
995 {
996 exprt &opi = new_expr.operands()[i];
997 exprt &opn = new_expr.operands()[i + 1];
998
999 if(
1000 opi.is_constant() && opn.is_constant() &&
1003 {
1004 // merge!
1005 const std::string new_value=
1006 opi.get_string(ID_value)+opn.get_string(ID_value);
1007 opi.set(ID_value, new_value);
1008 to_bitvector_type(opi.type()).set_width(new_value.size());
1009 opi.type().id(ID_verilog_unsignedbv);
1010 // erase opn
1011 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
1012 no_change = false;
1013 }
1014 else
1015 i++;
1016 }
1017 }
1018
1019 // { x } = x
1020 if(new_expr.operands().size() == 1)
1021 {
1022 if(new_expr.op0().type() == new_expr.type())
1023 return new_expr.op0();
1024 else
1025 {
1026 return changed(
1028 }
1029 }
1030
1031 if(no_change)
1032 return unchanged(expr);
1033 else
1034 return std::move(new_expr);
1035}
1036
1039{
1041 return unchanged(expr);
1042
1043 if(!can_cast_type<bitvector_typet>(expr.op().type()))
1044 return unchanged(expr);
1045
1046 return changed(simplify_node(expr.lower()));
1047}
1048
1051{
1053 return unchanged(expr);
1054
1055 const auto distance = numeric_cast<mp_integer>(expr.distance());
1056
1057 if(!distance.has_value())
1058 return unchanged(expr);
1059
1060 if(*distance == 0)
1061 return expr.op();
1062
1063 auto value = numeric_cast<mp_integer>(expr.op());
1064
1065 if(
1066 !value.has_value() && expr.op().type().id() == ID_bv &&
1067 expr.op().is_constant())
1068 {
1069 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1070 value =
1071 bvrep2integer(to_constant_expr(expr.op()).get_value(), width, false);
1072 }
1073
1074 if(!value.has_value())
1075 return unchanged(expr);
1076
1077 if(
1078 expr.op().type().id() == ID_unsignedbv ||
1079 expr.op().type().id() == ID_signedbv || expr.op().type().id() == ID_bv)
1080 {
1081 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1082
1083 if(expr.id()==ID_lshr)
1084 {
1085 // this is to guard against large values of distance
1086 if(*distance >= width)
1087 {
1088 return from_integer(0, expr.type());
1089 }
1090 else if(*distance >= 0)
1091 {
1092 if(*value < 0)
1093 *value += power(2, width);
1094 *value /= power(2, *distance);
1095 return from_integer(*value, expr.type());
1096 }
1097 }
1098 else if(expr.id()==ID_ashr)
1099 {
1100 if(*distance >= 0)
1101 {
1102 // this is to simulate an arithmetic right shift
1103 mp_integer new_value = *value >> *distance;
1104 return from_integer(new_value, expr.type());
1105 }
1106 }
1107 else if(expr.id()==ID_shl)
1108 {
1109 // this is to guard against large values of distance
1110 if(*distance >= width)
1111 {
1112 return from_integer(0, expr.type());
1113 }
1114 else if(*distance >= 0)
1115 {
1116 *value *= power(2, *distance);
1117 return from_integer(*value, expr.type());
1118 }
1119 }
1120 }
1121 else if(
1122 expr.op().type().id() == ID_integer || expr.op().type().id() == ID_natural)
1123 {
1124 if(expr.id()==ID_lshr)
1125 {
1126 if(*distance >= 0)
1127 {
1128 *value /= power(2, *distance);
1129 return from_integer(*value, expr.type());
1130 }
1131 }
1132 else if(expr.id()==ID_ashr)
1133 {
1134 // this is to simulate an arithmetic right shift
1135 if(*distance >= 0)
1136 {
1137 mp_integer new_value = *value / power(2, *distance);
1138 if(*value < 0 && new_value == 0)
1139 new_value=-1;
1140
1141 return from_integer(new_value, expr.type());
1142 }
1143 }
1144 else if(expr.id()==ID_shl)
1145 {
1146 if(*distance >= 0)
1147 {
1148 *value *= power(2, *distance);
1149 return from_integer(*value, expr.type());
1150 }
1151 }
1152 }
1153
1154 return unchanged(expr);
1155}
1156
1159{
1160 if(!is_number(expr.type()))
1161 return unchanged(expr);
1162
1163 const auto base = numeric_cast<mp_integer>(expr.base());
1164 const auto exponent = numeric_cast<mp_integer>(expr.exponent());
1165
1166 if(!exponent.has_value())
1167 return unchanged(expr);
1168
1169 if(exponent.value() == 0)
1170 return from_integer(1, expr.type());
1171
1172 if(exponent.value() == 1)
1173 return expr.base();
1174
1175 if(!base.has_value())
1176 return unchanged(expr);
1177
1178 mp_integer result = power(*base, *exponent);
1179
1180 return from_integer(result, expr.type());
1181}
1182
1186{
1187 const typet &op0_type = expr.src().type();
1188
1189 if(
1192 {
1193 return unchanged(expr);
1194 }
1195
1196 const auto end = numeric_cast<mp_integer>(expr.index());
1197
1198 if(!end.has_value())
1199 return unchanged(expr);
1200
1201 const auto width = pointer_offset_bits(op0_type, ns);
1202
1203 if(!width.has_value())
1204 return unchanged(expr);
1205
1206 const auto result_width = pointer_offset_bits(expr.type(), ns);
1207
1208 if(!result_width.has_value())
1209 return unchanged(expr);
1210
1211 const auto start = std::optional(*end + *result_width - 1);
1212
1213 if(*start < 0 || *start >= (*width) || *end < 0 || *end >= (*width))
1214 return unchanged(expr);
1215
1216 DATA_INVARIANT(*start >= *end, "extractbits must have start >= end");
1217
1218 if(expr.src().is_constant())
1219 {
1220 const auto svalue = expr2bits(expr.src(), true, ns);
1221
1222 if(!svalue.has_value() || svalue->size() != *width)
1223 return unchanged(expr);
1224
1225 std::string extracted_value = svalue->substr(
1227 numeric_cast_v<std::size_t>(*start - *end + 1));
1228
1229 auto result = bits2expr(extracted_value, expr.type(), true, ns);
1230 if(!result.has_value())
1231 return unchanged(expr);
1232
1233 return std::move(*result);
1234 }
1235 else if(expr.src().id() == ID_concatenation)
1236 {
1237 // the most-significant bit comes first in an concatenation_exprt, hence we
1238 // count down
1239 mp_integer offset = *width;
1240
1241 for(const auto &op : expr.src().operands())
1242 {
1243 auto op_width = pointer_offset_bits(op.type(), ns);
1244
1245 if(!op_width.has_value() || *op_width <= 0)
1246 return unchanged(expr);
1247
1248 if(*start < offset && offset <= *end + *op_width)
1249 {
1250 extractbits_exprt result = expr;
1251 result.src() = op;
1252 result.index() =
1253 from_integer(*end - (offset - *op_width), expr.index().type());
1254 return changed(simplify_extractbits(result));
1255 }
1256
1257 offset -= *op_width;
1258 }
1259 }
1261 {
1262 if(eb_src->index().is_constant())
1263 {
1264 extractbits_exprt result = *eb_src;
1265 result.type() = expr.type();
1266 const mp_integer src_index =
1268 result.index() = from_integer(src_index + *end, eb_src->index().type());
1269 return changed(simplify_extractbits(result));
1270 }
1271 }
1272 else if(*end == 0 && *start + 1 == *width)
1273 {
1274 typecast_exprt tc{expr.src(), expr.type()};
1275 return changed(simplify_typecast(tc));
1276 }
1277
1278 return unchanged(expr);
1279}
1280
1283{
1284 // simply remove, this is always 'nop'
1285 return expr.op();
1286}
1287
1290{
1291 if(!is_number(expr.type()))
1292 return unchanged(expr);
1293
1294 const exprt &operand = expr.op();
1295
1296 if(expr.type()!=operand.type())
1297 return unchanged(expr);
1298
1299 if(operand.id()==ID_unary_minus)
1300 {
1301 // cancel out "-(-x)" to "x"
1302 if(!is_number(to_unary_minus_expr(operand).op().type()))
1303 return unchanged(expr);
1304
1305 return to_unary_minus_expr(operand).op();
1306 }
1307 else if(operand.is_constant())
1308 {
1309 const irep_idt &type_id=expr.type().id();
1310 const auto &constant_expr = to_constant_expr(operand);
1311
1312 if(type_id==ID_integer ||
1315 {
1317
1318 if(!int_value.has_value())
1319 return unchanged(expr);
1320
1321 return from_integer(-*int_value, expr.type());
1322 }
1323 else if(type_id==ID_rational)
1324 {
1325 rationalt r;
1327 return unchanged(expr);
1328
1329 return from_rational(-r);
1330 }
1331 else if(type_id==ID_fixedbv)
1332 {
1334 f.negate();
1335 return f.to_expr();
1336 }
1337 else if(type_id==ID_floatbv)
1338 {
1340 f.negate();
1341 return f.to_expr();
1342 }
1343 }
1344
1345 return unchanged(expr);
1346}
1347
1350{
1351 const exprt &op = expr.op();
1352
1353 const auto &type = expr.type();
1354
1355 if(
1356 type.id() == ID_bv || type.id() == ID_unsignedbv ||
1357 type.id() == ID_signedbv)
1358 {
1359 const auto width = to_bitvector_type(type).get_width();
1360
1361 if(op.type() == type)
1362 {
1363 if(op.is_constant())
1364 {
1365 const auto &value = to_constant_expr(op).get_value();
1366 const auto new_value =
1367 make_bvrep(width, [&value, &width](std::size_t i) {
1368 return !get_bvrep_bit(value, width, i);
1369 });
1370 return constant_exprt(new_value, op.type());
1371 }
1372 }
1373 }
1374
1375 return unchanged(expr);
1376}
1377
1381{
1382 if(!expr.is_boolean())
1383 return unchanged(expr);
1384
1385 exprt tmp0=expr.op0();
1386 exprt tmp1=expr.op1();
1387
1388 // types must match
1389 if(tmp0.type() != tmp1.type())
1390 return unchanged(expr);
1391
1392 // if rhs is ID_if (and lhs is not), swap operands for == and !=
1393 if((expr.id()==ID_equal || expr.id()==ID_notequal) &&
1394 tmp0.id()!=ID_if &&
1395 tmp1.id()==ID_if)
1396 {
1397 auto new_expr = expr;
1398 new_expr.op0().swap(new_expr.op1());
1399 return changed(simplify_inequality(new_expr)); // recursive call
1400 }
1401
1402 if(tmp0.id()==ID_if && tmp0.operands().size()==3)
1403 {
1404 if_exprt if_expr=lift_if(expr, 0);
1405 if_expr.true_case() =
1407 if_expr.false_case() =
1409 return changed(simplify_if(if_expr));
1410 }
1411
1412 // see if we are comparing pointers that are address_of
1413 if(
1414 skip_typecast(tmp0).id() == ID_address_of &&
1415 skip_typecast(tmp1).id() == ID_address_of &&
1416 (expr.id() == ID_equal || expr.id() == ID_notequal))
1417 {
1418 return simplify_inequality_address_of(expr);
1419 }
1420
1421 if(tmp0.id()==ID_pointer_object &&
1422 tmp1.id()==ID_pointer_object &&
1423 (expr.id()==ID_equal || expr.id()==ID_notequal))
1424 {
1426 }
1427
1428 if(tmp0.type().id()==ID_c_enum_tag)
1429 tmp0.type()=ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1430
1431 if(tmp1.type().id()==ID_c_enum_tag)
1432 tmp1.type()=ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1433
1434 const bool tmp0_const = tmp0.is_constant();
1435 const bool tmp1_const = tmp1.is_constant();
1436
1437 // are _both_ constant?
1438 if(tmp0_const && tmp1_const)
1439 {
1441 }
1442 else if(tmp0_const)
1443 {
1444 // we want the constant on the RHS
1445
1447
1448 if(expr.id()==ID_ge)
1449 new_expr.id(ID_le);
1450 else if(expr.id()==ID_le)
1451 new_expr.id(ID_ge);
1452 else if(expr.id()==ID_gt)
1453 new_expr.id(ID_lt);
1454 else if(expr.id()==ID_lt)
1455 new_expr.id(ID_gt);
1456
1457 new_expr.op0().swap(new_expr.op1());
1458
1459 // RHS is constant, LHS is not
1461 }
1462 else if(tmp1_const)
1463 {
1464 // RHS is constant, LHS is not
1466 }
1467 else
1468 {
1469 // both are not constant
1471 }
1472}
1473
1477 const binary_relation_exprt &expr)
1478{
1479 exprt tmp0 = expr.op0();
1480 exprt tmp1 = expr.op1();
1481
1482 if(tmp0.type().id() == ID_c_enum_tag)
1483 tmp0.type() = ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1484
1485 if(tmp1.type().id() == ID_c_enum_tag)
1486 tmp1.type() = ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1487
1488 const auto &tmp0_const = to_constant_expr(tmp0);
1489 const auto &tmp1_const = to_constant_expr(tmp1);
1490
1491 if(expr.id() == ID_equal || expr.id() == ID_notequal)
1492 {
1493 // two constants compare equal when there values (as strings) are the same
1494 // or both of them are pointers and both represent NULL in some way
1495 bool equal = (tmp0_const.get_value() == tmp1_const.get_value());
1496 if(
1497 !equal && tmp0_const.type().id() == ID_pointer &&
1498 tmp1_const.type().id() == ID_pointer)
1499 {
1500 if(
1501 !config.ansi_c.NULL_is_zero && (tmp0_const.get_value() == ID_NULL ||
1502 tmp1_const.get_value() == ID_NULL))
1503 {
1504 // if NULL is not zero on this platform, we really don't know what it
1505 // is and therefore cannot simplify
1506 return unchanged(expr);
1507 }
1508 equal = tmp0_const == 0 && tmp1_const == 0;
1509 }
1510 return make_boolean_expr(expr.id() == ID_equal ? equal : !equal);
1511 }
1512
1513 if(tmp0.type().id() == ID_fixedbv)
1514 {
1516 fixedbvt f1(tmp1_const);
1517
1518 if(expr.id() == ID_ge)
1519 return make_boolean_expr(f0 >= f1);
1520 else if(expr.id() == ID_le)
1521 return make_boolean_expr(f0 <= f1);
1522 else if(expr.id() == ID_gt)
1523 return make_boolean_expr(f0 > f1);
1524 else if(expr.id() == ID_lt)
1525 return make_boolean_expr(f0 < f1);
1526 else
1528 }
1529 else if(tmp0.type().id() == ID_floatbv)
1530 {
1533
1534 if(expr.id() == ID_ge)
1535 return make_boolean_expr(f0 >= f1);
1536 else if(expr.id() == ID_le)
1537 return make_boolean_expr(f0 <= f1);
1538 else if(expr.id() == ID_gt)
1539 return make_boolean_expr(f0 > f1);
1540 else if(expr.id() == ID_lt)
1541 return make_boolean_expr(f0 < f1);
1542 else
1544 }
1545 else if(tmp0.type().id() == ID_rational)
1546 {
1547 rationalt r0, r1;
1548
1549 if(to_rational(tmp0, r0))
1550 return unchanged(expr);
1551
1552 if(to_rational(tmp1, r1))
1553 return unchanged(expr);
1554
1555 if(expr.id() == ID_ge)
1556 return make_boolean_expr(r0 >= r1);
1557 else if(expr.id() == ID_le)
1558 return make_boolean_expr(r0 <= r1);
1559 else if(expr.id() == ID_gt)
1560 return make_boolean_expr(r0 > r1);
1561 else if(expr.id() == ID_lt)
1562 return make_boolean_expr(r0 < r1);
1563 else
1565 }
1566 else
1567 {
1569
1570 if(!v0.has_value())
1571 return unchanged(expr);
1572
1574
1575 if(!v1.has_value())
1576 return unchanged(expr);
1577
1578 if(expr.id() == ID_ge)
1579 return make_boolean_expr(*v0 >= *v1);
1580 else if(expr.id() == ID_le)
1581 return make_boolean_expr(*v0 <= *v1);
1582 else if(expr.id() == ID_gt)
1583 return make_boolean_expr(*v0 > *v1);
1584 else if(expr.id() == ID_lt)
1585 return make_boolean_expr(*v0 < *v1);
1586 else
1588 }
1589}
1590
1591static bool eliminate_common_addends(exprt &op0, exprt &op1)
1592{
1593 // we can't eliminate zeros
1594 if(
1595 op0 == 0 || op1 == 0 ||
1596 (op0.is_constant() && to_constant_expr(op0).is_null_pointer()) ||
1597 (op1.is_constant() && to_constant_expr(op1).is_null_pointer()))
1598 {
1599 return true;
1600 }
1601
1602 if(op0.id()==ID_plus)
1603 {
1604 bool no_change = true;
1605
1606 Forall_operands(it, op0)
1607 if(!eliminate_common_addends(*it, op1))
1608 no_change = false;
1609
1610 return no_change;
1611 }
1612 else if(op1.id()==ID_plus)
1613 {
1614 bool no_change = true;
1615
1616 Forall_operands(it, op1)
1617 if(!eliminate_common_addends(op0, *it))
1618 no_change = false;
1619
1620 return no_change;
1621 }
1622 else if(op0==op1)
1623 {
1624 if(op0 != 0 && op0.type().id() != ID_complex)
1625 {
1626 // elimination!
1627 op0=from_integer(0, op0.type());
1628 op1=from_integer(0, op1.type());
1629 return false;
1630 }
1631 }
1632
1633 return true;
1634}
1635
1637 const binary_relation_exprt &expr)
1638{
1639 // pretty much all of the simplifications below are unsound
1640 // for IEEE float because of NaN!
1641
1642 if(expr.op0().type().id() == ID_floatbv)
1643 return unchanged(expr);
1644
1645 if(expr.op0().type().id() == ID_pointer)
1646 {
1649
1650 if(ptr_op0 == ptr_op1)
1651 {
1654
1656 std::move(offset_op0), expr.id(), std::move(offset_op1)}));
1657 }
1658 // simplifications below require same-object, which we don't check for
1659 else if(expr.id() != ID_equal && expr.id() != ID_notequal)
1660 {
1661 return unchanged(expr);
1662 }
1663 else if(
1664 expr.id() == ID_equal && ptr_op0.id() == ID_address_of &&
1665 ptr_op1.id() == ID_address_of)
1666 {
1667 // comparing pointers: if both are address-of-plus-some-constant such that
1668 // the resulting pointer remains within object bounds then they can never
1669 // be equal
1670 auto in_bounds = [this](const exprt &object_ptr, const exprt &expr_op) {
1671 auto object_size =
1672 size_of_expr(to_address_of_expr(object_ptr).object().type(), ns);
1673
1674 if(object_size.has_value())
1675 {
1679 std::move(offset), ID_lt, std::move(*object_size)})
1680 .expr;
1681 if(in_object_bounds.is_constant())
1682 return tvt{in_object_bounds == true};
1683 }
1684
1685 return tvt::unknown();
1686 };
1687
1688 if(
1689 in_bounds(ptr_op0, expr.op0()).is_true() &&
1690 in_bounds(ptr_op1, expr.op1()).is_true())
1691 {
1692 return false_exprt{};
1693 }
1694 }
1695 }
1696
1697 // eliminate strict inequalities
1698 if(expr.id()==ID_notequal)
1699 {
1700 auto new_rel_expr = expr;
1704 }
1705 else if(expr.id()==ID_gt)
1706 {
1707 auto new_rel_expr = expr;
1708 new_rel_expr.id(ID_ge);
1709 // swap operands
1710 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1713 }
1714 else if(expr.id()==ID_lt)
1715 {
1716 auto new_rel_expr = expr;
1717 new_rel_expr.id(ID_ge);
1720 }
1721 else if(expr.id()==ID_le)
1722 {
1723 auto new_rel_expr = expr;
1724 new_rel_expr.id(ID_ge);
1725 // swap operands
1726 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1728 }
1729
1730 // now we only have >=, =
1731
1732 INVARIANT(
1733 expr.id() == ID_ge || expr.id() == ID_equal,
1734 "we previously converted all other cases to >= or ==");
1735
1736 // syntactically equal?
1737
1738 if(expr.op0() == expr.op1())
1739 return true_exprt();
1740
1741 // See if we can eliminate common addends on both sides.
1742 // On bit-vectors, this is only sound on '='.
1743 if(expr.id()==ID_equal)
1744 {
1745 auto new_expr = to_equal_expr(expr);
1746 if(!eliminate_common_addends(new_expr.lhs(), new_expr.rhs()))
1747 {
1748 // remove zeros
1749 new_expr.lhs() = simplify_node(new_expr.lhs());
1750 new_expr.rhs() = simplify_node(new_expr.rhs());
1751 return changed(simplify_inequality(new_expr)); // recursive call
1752 }
1753 }
1754
1755 return unchanged(expr);
1756}
1757
1761 const binary_relation_exprt &expr)
1762{
1763 // the constant is always on the RHS
1764 PRECONDITION(expr.op1().is_constant());
1765
1766 if(expr.op0().id()==ID_if && expr.op0().operands().size()==3)
1767 {
1768 if_exprt if_expr=lift_if(expr, 0);
1769 if_expr.true_case() =
1771 if_expr.false_case() =
1773 return changed(simplify_if(if_expr));
1774 }
1775
1776 // do we deal with pointers?
1777 if(expr.op1().type().id()==ID_pointer)
1778 {
1779 if(expr.id()==ID_notequal)
1780 {
1781 auto new_rel_expr = expr;
1785 }
1786
1787 // very special case for pointers
1788 if(expr.id() != ID_equal)
1789 return unchanged(expr);
1790
1792
1793 if(op1_constant.is_null_pointer())
1794 {
1795 // the address of an object is never NULL
1796
1797 if(expr.op0().id() == ID_address_of)
1798 {
1799 const auto &object = to_address_of_expr(expr.op0()).object();
1800
1801 if(
1802 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1803 object.id() == ID_member || object.id() == ID_index ||
1804 object.id() == ID_string_constant)
1805 {
1806 return false_exprt();
1807 }
1808 }
1809 else if(
1810 expr.op0().id() == ID_typecast &&
1811 expr.op0().type().id() == ID_pointer &&
1812 to_typecast_expr(expr.op0()).op().id() == ID_address_of)
1813 {
1814 const auto &object =
1815 to_address_of_expr(to_typecast_expr(expr.op0()).op()).object();
1816
1817 if(
1818 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1819 object.id() == ID_member || object.id() == ID_index ||
1820 object.id() == ID_string_constant)
1821 {
1822 return false_exprt();
1823 }
1824 }
1825 else if(
1826 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_pointer)
1827 {
1828 exprt op = to_typecast_expr(expr.op0()).op();
1829 if(
1830 op.type().id() != ID_pointer &&
1831 (!config.ansi_c.NULL_is_zero || !is_number(op.type()) ||
1832 op.type().id() == ID_complex))
1833 {
1834 return unchanged(expr);
1835 }
1836
1837 // (type)ptr == NULL -> ptr == NULL
1838 // note that 'ptr' may be an integer
1839 auto new_expr = expr;
1840 new_expr.op0().swap(op);
1841 if(new_expr.op0().type().id() != ID_pointer)
1842 new_expr.op1() = from_integer(0, new_expr.op0().type());
1843 else
1844 new_expr.op1().type() = new_expr.op0().type();
1845 return changed(simplify_inequality(new_expr)); // do again!
1846 }
1847 else if(expr.op0().id() == ID_plus)
1848 {
1849 exprt offset =
1851 if(!offset.is_constant())
1852 return unchanged(expr);
1853
1854 exprt ptr = simplify_object(expr.op0()).expr;
1855 // NULL + N == NULL is N == 0
1856 if(ptr.is_constant() && to_constant_expr(ptr).is_null_pointer())
1857 return make_boolean_expr(offset == 0);
1858 // &x + N == NULL is false when the offset is in bounds
1860 {
1861 const auto object_size =
1862 pointer_offset_size(address_of->object().type(), ns);
1863 if(
1864 object_size.has_value() &&
1866 {
1867 return false_exprt();
1868 }
1869 }
1870 }
1871 }
1872
1873 // all we are doing with pointers
1874 return unchanged(expr);
1875 }
1876
1877 // is it a separation predicate?
1878
1879 if(expr.op0().id()==ID_plus)
1880 {
1881 // see if there is a constant in the sum
1882
1883 if(expr.id()==ID_equal || expr.id()==ID_notequal)
1884 {
1885 mp_integer constant=0;
1886 bool op_changed = false;
1887 auto new_expr = expr;
1888
1889 Forall_operands(it, new_expr.op0())
1890 {
1891 if(it->is_constant())
1892 {
1893 mp_integer i;
1894 if(!to_integer(to_constant_expr(*it), i))
1895 {
1896 constant+=i;
1897 *it=from_integer(0, it->type());
1898 op_changed = true;
1899 }
1900 }
1901 }
1902
1903 if(op_changed)
1904 {
1905 // adjust the constant on the RHS
1906 mp_integer i =
1908 i-=constant;
1909 new_expr.op1() = from_integer(i, new_expr.op1().type());
1910
1913 }
1914 }
1915 }
1916
1917 #if 1
1918 // (double)value REL const ---> value rel const
1919 // if 'const' can be represented exactly.
1920
1921 if(
1922 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_floatbv &&
1923 to_typecast_expr(expr.op0()).op().type().id() == ID_floatbv)
1924 {
1929 to_floatbv_type(to_typecast_expr(expr.op0()).op().type())));
1931 const_val_converted_back.change_spec(
1934 {
1935 auto result = expr;
1936 result.op0() = to_typecast_expr(expr.op0()).op();
1937 result.op1()=const_val_converted.to_expr();
1938 return std::move(result);
1939 }
1940 }
1941 #endif
1942
1943 // is the constant zero?
1944
1945 if(expr.op1() == 0)
1946 {
1947 if(expr.id()==ID_ge &&
1948 expr.op0().type().id()==ID_unsignedbv)
1949 {
1950 // zero is always smaller or equal something unsigned
1951 return true_exprt();
1952 }
1953
1954 auto new_expr = expr;
1955 exprt &operand = new_expr.op0();
1956
1957 if(expr.id()==ID_equal)
1958 {
1959 // rules below do not hold for >=
1960 if(operand.id()==ID_unary_minus)
1961 {
1963 return std::move(new_expr);
1964 }
1965 else if(operand.id()==ID_plus)
1966 {
1968
1969 // simplify a+-b=0 to a=b
1970 if(operand_plus_expr.operands().size() == 2)
1971 {
1972 // if we have -b+a=0, make that a+(-b)=0
1973 if(operand_plus_expr.op0().id() == ID_unary_minus)
1974 operand_plus_expr.op0().swap(operand_plus_expr.op1());
1975
1976 if(operand_plus_expr.op1().id() == ID_unary_minus)
1977 {
1978 return binary_exprt(
1979 operand_plus_expr.op0(),
1980 expr.id(),
1982 expr.type());
1983 }
1984 }
1985 }
1986 }
1987
1988 if(config.ansi_c.NULL_is_zero)
1989 {
1990 const exprt &maybe_tc_op = skip_typecast(expr.op0());
1991 if(maybe_tc_op.type().id() == ID_pointer)
1992 {
1993 // make sure none of the type casts lose information
1995 bool bitwidth_unchanged = true;
1996 const exprt *ep = &(expr.op0());
1997 while(bitwidth_unchanged && ep->id() == ID_typecast)
1998 {
1999 if(auto t = type_try_dynamic_cast<bitvector_typet>(ep->type()))
2000 {
2001 bitwidth_unchanged = t->get_width() == p_type.get_width();
2002 }
2003 else
2004 bitwidth_unchanged = false;
2005
2006 ep = &to_typecast_expr(*ep).op();
2007 }
2008
2010 {
2011 if(expr.id() == ID_equal || expr.id() == ID_ge || expr.id() == ID_le)
2012 {
2013 return changed(simplify_rec(
2015 }
2016 else
2017 {
2018 return changed(simplify_rec(
2020 }
2021 }
2022 }
2023 }
2024 }
2025
2026 // are we comparing with a typecast from bool?
2027 if(
2028 expr.op0().id() == ID_typecast &&
2029 to_typecast_expr(expr.op0()).op().is_boolean())
2030 {
2031 const auto &lhs_typecast_op = to_typecast_expr(expr.op0()).op();
2032
2033 // we re-write (TYPE)boolean == 0 -> !boolean
2034 if(expr.op1() == 0 && expr.id() == ID_equal)
2035 {
2037 }
2038
2039 // we re-write (TYPE)boolean != 0 -> boolean
2040 if(expr.op1() == 0 && expr.id() == ID_notequal)
2041 {
2042 return lhs_typecast_op;
2043 }
2044 }
2045
2046 #define NORMALISE_CONSTANT_TESTS
2047 #ifdef NORMALISE_CONSTANT_TESTS
2048 // Normalise to >= and = to improve caching and term sharing
2049 if(expr.op0().type().id()==ID_unsignedbv ||
2050 expr.op0().type().id()==ID_signedbv)
2051 {
2052 mp_integer max(to_integer_bitvector_type(expr.op0().type()).largest());
2053
2054 if(expr.id()==ID_notequal)
2055 {
2056 auto new_rel_expr = expr;
2060 }
2061 else if(expr.id()==ID_gt)
2062 {
2064
2065 if(i==max)
2066 {
2067 return false_exprt();
2068 }
2069
2070 auto new_expr = expr;
2071 new_expr.id(ID_ge);
2072 ++i;
2073 new_expr.op1() = from_integer(i, new_expr.op1().type());
2075 }
2076 else if(expr.id()==ID_lt)
2077 {
2078 auto new_rel_expr = expr;
2079 new_rel_expr.id(ID_ge);
2082 }
2083 else if(expr.id()==ID_le)
2084 {
2086
2087 if(i==max)
2088 {
2089 return true_exprt();
2090 }
2091
2092 auto new_rel_expr = expr;
2093 new_rel_expr.id(ID_ge);
2094 ++i;
2095 new_rel_expr.op1() = from_integer(i, new_rel_expr.op1().type());
2098 }
2099 }
2100#endif
2101 return unchanged(expr);
2102}
2103
2106{
2108 expr.op(),
2110 ns);
2111
2112 if(!const_bits_opt.has_value())
2113 return unchanged(expr);
2114
2115 std::reverse(const_bits_opt->begin(), const_bits_opt->end());
2116
2117 auto result = bits2expr(
2119 expr.type(),
2121 ns);
2122 if(!result.has_value())
2123 return unchanged(expr);
2124
2125 return std::move(*result);
2126}
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:566
A base class for binary expressions.
Definition std_expr.h:639
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:774
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:2997
Division.
Definition std_expr.h:1142
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:1329
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:3125
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:2416
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
Binary minus.
Definition std_expr.h:1055
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1206
Binary multiplication Associativity is not specified.
Definition std_expr.h:1094
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:898
exprt & op1()
Definition std_expr.h:932
exprt & op0()
Definition std_expr.h:926
Boolean negation.
Definition std_expr.h:2378
Disequality.
Definition std_expr.h:1383
The null pointer constant.
The plus expression Associativity is not specified.
Definition std_expr.h:996
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:3116
Definition threeval.h:20
static tvt unknown()
Definition threeval.h:33
Semantic type conversion.
Definition std_expr.h:1985
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:1993
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:384
The unary minus expression.
Definition std_expr.h:467
The unary plus expression.
Definition std_expr.h:509
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:818
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2014
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition std_expr.h:1035
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition std_expr.h:1075
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3068
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
Definition std_expr.h:492
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1365
#define size_type
Definition unistd.c:186