CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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->is_zero() &&
196 it->type().id()!=ID_floatbv)
197 {
198 return from_integer(0, expr.type());
199 }
200
201 // true if the given operand has to be erased
202 bool do_erase = false;
203
204 // if this is a constant of the same time as the result
205 if(it->is_constant() && it->type()==expr.type())
206 {
207 // preserve the sizeof type annotation
208 if(!c_sizeof_type.has_value())
209 {
210 const typet &sizeof_type =
211 static_cast<const typet &>(it->find(ID_C_c_sizeof_type));
212 if(sizeof_type.is_not_nil())
214 }
215
217 {
218 // update the constant factor
219 if(!mul_expr(to_constant_expr(*constant), to_constant_expr(*it)))
220 do_erase=true;
221 }
222 else
223 {
224 // set it as the constant factor if this is the first
225 constant=it;
226 constant_found = true;
227 }
228 }
229
230 // erase the factor if necessary
231 if(do_erase)
232 {
233 it = new_operands.erase(it);
234 no_change = false;
235 }
236 else
237 it++; // move to the next operand
238 }
239
240 if(c_sizeof_type.has_value())
241 {
242 INVARIANT(
244 "c_sizeof_type is only set to a non-nil value "
245 "if a constant has been found");
246 constant->set(ID_C_c_sizeof_type, *c_sizeof_type);
247 }
248
249 if(new_operands.size() == 1)
250 {
251 return new_operands.front();
252 }
253 else
254 {
255 // if the constant is a one and there are other factors
256 if(constant_found && constant->is_one())
257 {
258 // just delete it
259 new_operands.erase(constant);
260 no_change = false;
261
262 if(new_operands.size() == 1)
263 return new_operands.front();
264 }
265 }
266
267 if(no_change)
268 return unchanged(expr);
269 else
270 {
271 exprt tmp = expr;
272 tmp.operands() = std::move(new_operands);
273 return std::move(tmp);
274 }
275}
276
278{
279 if(!is_number(expr.type()))
280 return unchanged(expr);
281
282 const typet &expr_type=expr.type();
283
284 if(expr_type!=expr.op0().type() ||
285 expr_type!=expr.op1().type())
286 {
287 return unchanged(expr);
288 }
289
290 if(expr_type.id()==ID_signedbv ||
291 expr_type.id()==ID_unsignedbv ||
292 expr_type.id()==ID_natural ||
293 expr_type.id()==ID_integer)
294 {
295 const auto int_value0 = numeric_cast<mp_integer>(expr.op0());
296 const auto int_value1 = numeric_cast<mp_integer>(expr.op1());
297
298 // division by zero?
299 if(int_value1.has_value() && *int_value1 == 0)
300 return unchanged(expr);
301
302 // x/1?
303 if(int_value1.has_value() && *int_value1 == 1)
304 {
305 return expr.op0();
306 }
307
308 // 0/x?
309 if(int_value0.has_value() && *int_value0 == 0)
310 {
311 return expr.op0();
312 }
313
314 if(int_value0.has_value() && int_value1.has_value())
315 {
316 mp_integer result = *int_value0 / *int_value1;
317 return from_integer(result, expr_type);
318 }
319 }
320 else if(expr_type.id()==ID_rational)
321 {
323 bool ok0, ok1;
324
325 ok0=!to_rational(expr.op0(), rat_value0);
326 ok1=!to_rational(expr.op1(), rat_value1);
327
328 if(ok1 && rat_value1.is_zero())
329 return unchanged(expr);
330
331 if((ok1 && rat_value1.is_one()) ||
332 (ok0 && rat_value0.is_zero()))
333 {
334 return expr.op0();
335 }
336
337 if(ok0 && ok1)
338 {
340 exprt tmp=from_rational(result);
341
342 if(tmp.is_not_nil())
343 return std::move(tmp);
344 }
345 }
346 else if(expr_type.id()==ID_fixedbv)
347 {
348 // division by one?
349 if(expr.op1().is_constant() &&
350 expr.op1().is_one())
351 {
352 return expr.op0();
353 }
354
355 if(expr.op0().is_constant() &&
356 expr.op1().is_constant())
357 {
359 fixedbvt f1(to_constant_expr(expr.op1()));
360 if(!f1.is_zero())
361 {
362 f0/=f1;
363 return f0.to_expr();
364 }
365 }
366 }
367
368 return unchanged(expr);
369}
370
372{
373 if(!is_number(expr.type()))
374 return unchanged(expr);
375
376 if(expr.type().id()==ID_signedbv ||
377 expr.type().id()==ID_unsignedbv ||
378 expr.type().id()==ID_natural ||
379 expr.type().id()==ID_integer)
380 {
381 if(expr.type()==expr.op0().type() &&
382 expr.type()==expr.op1().type())
383 {
384 const auto int_value0 = numeric_cast<mp_integer>(expr.op0());
385 const auto int_value1 = numeric_cast<mp_integer>(expr.op1());
386
387 if(int_value1.has_value() && *int_value1 == 0)
388 return unchanged(expr); // division by zero
389
390 if(
391 (int_value1.has_value() && *int_value1 == 1) ||
392 (int_value0.has_value() && *int_value0 == 0))
393 {
394 return from_integer(0, expr.type());
395 }
396
397 if(int_value0.has_value() && int_value1.has_value())
398 {
399 mp_integer result = *int_value0 % *int_value1;
400 return from_integer(result, expr.type());
401 }
402 }
403 }
404
405 return unchanged(expr);
406}
407
409{
410 if(!is_number(expr.type()) && expr.type().id() != ID_pointer)
411 return unchanged(expr);
412
413 bool no_change = true;
414
416
417 // floating-point addition is _NOT_ associative; thus,
418 // there is special case for float
419
420 if(expr.type().id() == ID_floatbv)
421 {
422 // we only merge neighboring constants!
424 {
425 const exprt::operandst::iterator next = std::next(it);
426
427 if(next != new_operands.end())
428 {
429 if(it->type()==next->type() &&
430 it->is_constant() &&
431 next->is_constant())
432 {
434 new_operands.erase(next);
435 no_change = false;
436 }
437 }
438 }
439 }
440 else
441 {
442 // ((T*)p+a)+b -> (T*)p+(a+b)
443 if(
444 expr.type().id() == ID_pointer && expr.operands().size() == 2 &&
445 expr.op0().id() == ID_plus && expr.op0().type().id() == ID_pointer &&
446 expr.op0().operands().size() == 2)
447 {
448 plus_exprt result = to_plus_expr(expr.op0());
449 if(as_const(result).op0().type().id() != ID_pointer)
450 result.op0().swap(result.op1());
451 const exprt &op1 = as_const(result).op1();
452
453 if(op1.id() == ID_plus)
454 {
456 new_op1.add_to_operands(
457 typecast_exprt::conditional_cast(expr.op1(), new_op1.op0().type()));
458 result.op1() = simplify_plus(new_op1);
459 }
460 else
461 {
463 op1, typecast_exprt::conditional_cast(expr.op1(), op1.type())};
464 result.op1() = simplify_plus(new_op1);
465 }
466
467 return changed(simplify_plus(result));
468 }
469
470 // count the constants
471 size_t count=0;
472 for(const auto &op : expr.operands())
473 {
474 if(is_number(op.type()) && op.is_constant())
475 count++;
476 }
477
478 // merge constants?
479 if(count>=2)
480 {
481 exprt::operandst::iterator const_sum;
482 bool const_sum_set=false;
483
484 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
485 {
486 if(is_number(it->type()) && it->is_constant())
487 {
488 if(!const_sum_set)
489 {
490 const_sum=it;
491 const_sum_set=true;
492 }
493 else
494 {
496 to_constant_expr(*it)))
497 {
498 *it=from_integer(0, it->type());
499 no_change = false;
500 }
501 }
502 }
503 }
504 }
505
506 // search for a and -a
507 // first gather all the a's with -a
508 typedef std::unordered_map<exprt, exprt::operandst::iterator, irep_hash>
509 expr_mapt;
510 expr_mapt expr_map;
511
512 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
513 if(it->id() == ID_unary_minus)
514 {
515 expr_map.insert(std::make_pair(to_unary_minus_expr(*it).op(), it));
516 }
517
518 // now search for a
519 for(auto it = new_operands.begin(); it != new_operands.end(); it++)
520 {
521 if(expr_map.empty())
522 break;
523 else if(it->id()==ID_unary_minus)
524 continue;
525
526 expr_mapt::iterator itm=expr_map.find(*it);
527
528 if(itm!=expr_map.end())
529 {
530 *(itm->second)=from_integer(0, expr.type());
531 *it=from_integer(0, expr.type());
532 expr_map.erase(itm);
533 no_change = false;
534 }
535 }
536
537 // delete zeros
538 // (can't do for floats, as the result of 0.0 + (-0.0)
539 // need not be -0.0 in std rounding)
540 for(exprt::operandst::iterator it = new_operands.begin();
541 it != new_operands.end();
542 /* no it++ */)
543 {
544 if(is_number(it->type()) && it->is_zero())
545 {
546 it = new_operands.erase(it);
547 no_change = false;
548 }
549 else
550 it++;
551 }
552 }
553
554 if(new_operands.empty())
555 {
556 return from_integer(0, expr.type());
557 }
558 else if(new_operands.size() == 1)
559 {
560 return new_operands.front();
561 }
562
563 if(no_change)
564 return unchanged(expr);
565 else
566 {
567 auto tmp = expr;
568 tmp.operands() = std::move(new_operands);
569 return std::move(tmp);
570 }
571}
572
575{
576 auto const &minus_expr = to_minus_expr(expr);
577 if(!is_number(minus_expr.type()) && minus_expr.type().id() != ID_pointer)
578 return unchanged(expr);
579
580 const exprt::operandst &operands = minus_expr.operands();
581
582 if(
583 is_number(minus_expr.type()) && is_number(operands[0].type()) &&
584 is_number(operands[1].type()))
585 {
586 // rewrite "a-b" to "a+(-b)"
587 unary_minus_exprt rhs_negated(operands[1]);
590 }
591 else if(
592 minus_expr.type().id() == ID_pointer &&
593 operands[0].type().id() == ID_pointer && is_number(operands[1].type()))
594 {
595 // pointer arithmetic: rewrite "p-i" to "p+(-i)"
597
601 }
602 else if(
603 is_number(minus_expr.type()) && operands[0].type().id() == ID_pointer &&
604 operands[1].type().id() == ID_pointer)
605 {
606 exprt ptr_op0 = simplify_object(operands[0]).expr;
607 exprt ptr_op1 = simplify_object(operands[1]).expr;
608
610 if(ptr_op0 == ptr_op1 && address_of)
611 {
613 pointer_offset_exprt{operands[0], minus_expr.type()});
615 pointer_offset_exprt{operands[1], minus_expr.type()});
616
617 const auto object_size =
618 pointer_offset_size(address_of->object().type(), ns);
619 auto element_size =
620 size_of_expr(to_pointer_type(operands[0].type()).base_type(), ns);
621
622 if(
623 offset_op0.is_constant() && offset_op1.is_constant() &&
624 object_size.has_value() && element_size.has_value() &&
625 element_size->is_constant() && !element_size->is_zero() &&
627 *object_size &&
630 {
634 }
635 }
636
639 if(
642 {
644 pointer_offset_exprt{operands[0], minus_expr.type()});
646 pointer_offset_exprt{operands[1], minus_expr.type()});
647
648 auto element_size =
649 size_of_expr(to_pointer_type(operands[0].type()).base_type(), ns);
650
651 if(
652 element_size.has_value() && element_size->is_constant() &&
653 !element_size->is_zero())
654 {
658 }
659 }
660 }
661
662 return unchanged(expr);
663}
664
667{
669 return unchanged(expr);
670
671 // check if these are really boolean
672 if(!expr.is_boolean())
673 {
674 bool all_bool=true;
675
676 for(const auto &op : expr.operands())
677 {
678 if(op.id() == ID_typecast && to_typecast_expr(op).op().is_boolean())
679 {
680 }
681 else if(op.is_zero() || op.is_one())
682 {
683 }
684 else
685 all_bool=false;
686 }
687
688 if(all_bool)
689 {
690 // re-write to boolean+typecast
691 exprt new_expr=expr;
692
693 if(expr.id()==ID_bitand)
694 new_expr.id(ID_and);
695 else if(expr.id()==ID_bitor)
696 new_expr.id(ID_or);
697 else if(expr.id()==ID_bitxor)
698 new_expr.id(ID_xor);
699 else if(expr.id() == ID_bitxnor)
700 new_expr.id(ID_equal);
701 else
703
705 {
706 if(it->id()==ID_typecast)
707 *it = to_typecast_expr(*it).op();
708 else if(it->is_zero())
709 *it=false_exprt();
710 else if(it->is_one())
711 *it=true_exprt();
712 }
713
714 new_expr.type() = bool_typet{};
716
718 }
719 }
720
721 bool no_change = true;
722 auto new_expr = expr;
723
724 // try to merge constants
725
726 const std::size_t width = to_bitvector_type(expr.type()).get_width();
727
728 while(new_expr.operands().size() >= 2)
729 {
730 if(!new_expr.op0().is_constant())
731 break;
732
733 if(!new_expr.op1().is_constant())
734 break;
735
736 if(new_expr.op0().type() != new_expr.type())
737 break;
738
739 if(new_expr.op1().type() != new_expr.type())
740 break;
741
742 const auto &a_val = to_constant_expr(new_expr.op0()).get_value();
743 const auto &b_val = to_constant_expr(new_expr.op1()).get_value();
744
745 std::function<bool(bool, bool)> f;
746
747 if(new_expr.id() == ID_bitand)
748 f = [](bool a, bool b) { return a && b; };
749 else if(new_expr.id() == ID_bitor)
750 f = [](bool a, bool b) { return a || b; };
751 else if(new_expr.id() == ID_bitxor)
752 f = [](bool a, bool b) { return a != b; };
753 else if(new_expr.id() == ID_bitxnor)
754 f = [](bool a, bool b) { return a == b; };
755 else
757
758 const irep_idt new_value =
759 make_bvrep(width, [&a_val, &b_val, &width, &f](std::size_t i) {
760 return f(
761 get_bvrep_bit(a_val, width, i), get_bvrep_bit(b_val, width, i));
762 });
763
764 constant_exprt new_op(new_value, expr.type());
765
766 // erase first operand
767 new_expr.operands().erase(new_expr.operands().begin());
768 new_expr.op0().swap(new_op);
769
770 no_change = false;
771 }
772
773 // now erase 'all zeros' out of bitor, bitxor
774
775 if(new_expr.id() == ID_bitor || new_expr.id() == ID_bitxor)
776 {
777 for(exprt::operandst::iterator it = new_expr.operands().begin();
778 it != new_expr.operands().end();) // no it++
779 {
780 if(it->is_zero() && new_expr.operands().size() > 1)
781 {
782 it = new_expr.operands().erase(it);
783 no_change = false;
784 }
785 else if(
786 it->is_constant() && it->type().id() == ID_bv &&
787 to_constant_expr(*it).value_is_zero_string() &&
788 new_expr.operands().size() > 1)
789 {
790 it = new_expr.operands().erase(it);
791 no_change = false;
792 }
793 else
794 it++;
795 }
796 }
797
798 // now erase 'all ones' out of bitand
799
800 if(new_expr.id() == ID_bitand)
801 {
802 const auto all_ones = power(2, width) - 1;
803 for(exprt::operandst::iterator it = new_expr.operands().begin();
804 it != new_expr.operands().end();) // no it++
805 {
806 if(
807 it->is_constant() &&
808 bvrep2integer(to_constant_expr(*it).get_value(), width, false) ==
809 all_ones &&
810 new_expr.operands().size() > 1)
811 {
812 it = new_expr.operands().erase(it);
813 no_change = false;
814 }
815 else
816 it++;
817 }
818 }
819
820 // two operands that are syntactically the same
821
822 if(new_expr.operands().size() == 2 && new_expr.op0() == new_expr.op1())
823 {
824 if(new_expr.id() == ID_bitand || new_expr.id() == ID_bitor)
825 {
826 return new_expr.op0();
827 }
828 else if(new_expr.id() == ID_bitxor)
829 {
830 return constant_exprt(integer2bvrep(0, width), new_expr.type());
831 }
832 }
833
834 if(new_expr.operands().size() == 1)
835 return new_expr.op0();
836
837 if(no_change)
838 return unchanged(expr);
839 else
840 return std::move(new_expr);
841}
842
845{
846 const typet &src_type = expr.src().type();
847
849 return unchanged(expr);
850
851 const std::size_t src_bit_width = to_bitvector_type(src_type).get_width();
852
854 if(
855 !index_converted_to_int.has_value() || *index_converted_to_int < 0 ||
857 {
858 return unchanged(expr);
859 }
860
861 if(!expr.src().is_constant())
862 return unchanged(expr);
863
864 const bool bit = get_bvrep_bit(
865 to_constant_expr(expr.src()).get_value(),
868
869 return make_boolean_expr(bit);
870}
871
874{
875 bool no_change = true;
876
878
880 {
881 // first, turn bool into bvec[1]
883 {
884 exprt &op=*it;
885 if(op.is_true() || op.is_false())
886 {
887 const bool value = op.is_true();
888 op = from_integer(value, unsignedbv_typet(1));
889 no_change = false;
890 }
891 }
892
893 // search for neighboring constants to merge
894 size_t i=0;
895
896 while(i < new_expr.operands().size() - 1)
897 {
898 exprt &opi = new_expr.operands()[i];
899 exprt &opn = new_expr.operands()[i + 1];
900
901 if(
902 opi.is_constant() && opn.is_constant() &&
905 {
906 // merge!
907 const auto &value_i = to_constant_expr(opi).get_value();
908 const auto &value_n = to_constant_expr(opn).get_value();
909 const auto width_i = to_bitvector_type(opi.type()).get_width();
910 const auto width_n = to_bitvector_type(opn.type()).get_width();
911 const auto new_width = width_i + width_n;
912
913 const auto new_value = make_bvrep(
914 new_width, [&value_i, &value_n, width_i, width_n](std::size_t x) {
915 return x < width_n ? get_bvrep_bit(value_n, width_n, x)
917 });
918
919 to_constant_expr(opi).set_value(new_value);
920 to_bitvector_type(opi.type()).set_width(new_width);
921 // erase opn
922 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
923 no_change = false;
924 }
925 else if(
928 {
931
932 if(
933 eb_i.src() == eb_n.src() && eb_i.index().is_constant() &&
934 eb_n.index().is_constant() &&
937 to_bitvector_type(eb_n.type()).get_width())
938 {
940 eb_merged.index() = eb_n.index();
942 .set_width(
943 to_bitvector_type(eb_i.type()).get_width() +
944 to_bitvector_type(eb_n.type()).get_width());
945 if(expr.type().id() != eb_merged.type().id())
946 {
948 bt.set_width(to_bitvector_type(eb_merged.type()).get_width());
950 }
951 else
952 opi = eb_merged;
953 // erase opn
954 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
955 no_change = false;
956 }
957 else
958 ++i;
959 }
960 else
961 i++;
962 }
963 }
964 else if(new_expr.type().id() == ID_verilog_unsignedbv)
965 {
966 // search for neighboring constants to merge
967 size_t i=0;
968
969 while(i < new_expr.operands().size() - 1)
970 {
971 exprt &opi = new_expr.operands()[i];
972 exprt &opn = new_expr.operands()[i + 1];
973
974 if(
975 opi.is_constant() && opn.is_constant() &&
978 {
979 // merge!
980 const std::string new_value=
981 opi.get_string(ID_value)+opn.get_string(ID_value);
982 opi.set(ID_value, new_value);
983 to_bitvector_type(opi.type()).set_width(new_value.size());
984 opi.type().id(ID_verilog_unsignedbv);
985 // erase opn
986 new_expr.operands().erase(new_expr.operands().begin() + i + 1);
987 no_change = false;
988 }
989 else
990 i++;
991 }
992 }
993
994 // { x } = x
995 if(
996 new_expr.operands().size() == 1 && new_expr.op0().type() == new_expr.type())
997 {
998 return new_expr.op0();
999 }
1000
1001 if(no_change)
1002 return unchanged(expr);
1003 else
1004 return std::move(new_expr);
1005}
1006
1009{
1011 return unchanged(expr);
1012
1013 if(!can_cast_type<bitvector_typet>(expr.op().type()))
1014 return unchanged(expr);
1015
1016 return changed(simplify_node(expr.lower()));
1017}
1018
1021{
1023 return unchanged(expr);
1024
1025 const auto distance = numeric_cast<mp_integer>(expr.distance());
1026
1027 if(!distance.has_value())
1028 return unchanged(expr);
1029
1030 if(*distance == 0)
1031 return expr.op();
1032
1033 auto value = numeric_cast<mp_integer>(expr.op());
1034
1035 if(
1036 !value.has_value() && expr.op().type().id() == ID_bv &&
1037 expr.op().is_constant())
1038 {
1039 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1040 value =
1041 bvrep2integer(to_constant_expr(expr.op()).get_value(), width, false);
1042 }
1043
1044 if(!value.has_value())
1045 return unchanged(expr);
1046
1047 if(
1048 expr.op().type().id() == ID_unsignedbv ||
1049 expr.op().type().id() == ID_signedbv || expr.op().type().id() == ID_bv)
1050 {
1051 const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
1052
1053 if(expr.id()==ID_lshr)
1054 {
1055 // this is to guard against large values of distance
1056 if(*distance >= width)
1057 {
1058 return from_integer(0, expr.type());
1059 }
1060 else if(*distance >= 0)
1061 {
1062 if(*value < 0)
1063 *value += power(2, width);
1064 *value /= power(2, *distance);
1065 return from_integer(*value, expr.type());
1066 }
1067 }
1068 else if(expr.id()==ID_ashr)
1069 {
1070 if(*distance >= 0)
1071 {
1072 // this is to simulate an arithmetic right shift
1073 mp_integer new_value = *value >> *distance;
1074 return from_integer(new_value, expr.type());
1075 }
1076 }
1077 else if(expr.id()==ID_shl)
1078 {
1079 // this is to guard against large values of distance
1080 if(*distance >= width)
1081 {
1082 return from_integer(0, expr.type());
1083 }
1084 else if(*distance >= 0)
1085 {
1086 *value *= power(2, *distance);
1087 return from_integer(*value, expr.type());
1088 }
1089 }
1090 }
1091 else if(
1092 expr.op().type().id() == ID_integer || expr.op().type().id() == ID_natural)
1093 {
1094 if(expr.id()==ID_lshr)
1095 {
1096 if(*distance >= 0)
1097 {
1098 *value /= power(2, *distance);
1099 return from_integer(*value, expr.type());
1100 }
1101 }
1102 else if(expr.id()==ID_ashr)
1103 {
1104 // this is to simulate an arithmetic right shift
1105 if(*distance >= 0)
1106 {
1107 mp_integer new_value = *value / power(2, *distance);
1108 if(*value < 0 && new_value == 0)
1109 new_value=-1;
1110
1111 return from_integer(new_value, expr.type());
1112 }
1113 }
1114 else if(expr.id()==ID_shl)
1115 {
1116 if(*distance >= 0)
1117 {
1118 *value *= power(2, *distance);
1119 return from_integer(*value, expr.type());
1120 }
1121 }
1122 }
1123
1124 return unchanged(expr);
1125}
1126
1129{
1130 if(!is_number(expr.type()))
1131 return unchanged(expr);
1132
1133 const auto base = numeric_cast<mp_integer>(expr.base());
1134 const auto exponent = numeric_cast<mp_integer>(expr.exponent());
1135
1136 if(!exponent.has_value())
1137 return unchanged(expr);
1138
1139 if(exponent.value() == 0)
1140 return from_integer(1, expr.type());
1141
1142 if(exponent.value() == 1)
1143 return expr.base();
1144
1145 if(!base.has_value())
1146 return unchanged(expr);
1147
1148 mp_integer result = power(*base, *exponent);
1149
1150 return from_integer(result, expr.type());
1151}
1152
1156{
1157 const typet &op0_type = expr.src().type();
1158
1159 if(
1162 {
1163 return unchanged(expr);
1164 }
1165
1166 const auto end = numeric_cast<mp_integer>(expr.index());
1167
1168 if(!end.has_value())
1169 return unchanged(expr);
1170
1171 const auto width = pointer_offset_bits(op0_type, ns);
1172
1173 if(!width.has_value())
1174 return unchanged(expr);
1175
1176 const auto result_width = pointer_offset_bits(expr.type(), ns);
1177
1178 if(!result_width.has_value())
1179 return unchanged(expr);
1180
1181 const auto start = std::optional(*end + *result_width - 1);
1182
1183 if(*start < 0 || *start >= (*width) || *end < 0 || *end >= (*width))
1184 return unchanged(expr);
1185
1186 DATA_INVARIANT(*start >= *end, "extractbits must have start >= end");
1187
1188 if(expr.src().is_constant())
1189 {
1190 const auto svalue = expr2bits(expr.src(), true, ns);
1191
1192 if(!svalue.has_value() || svalue->size() != *width)
1193 return unchanged(expr);
1194
1195 std::string extracted_value = svalue->substr(
1197 numeric_cast_v<std::size_t>(*start - *end + 1));
1198
1199 auto result = bits2expr(extracted_value, expr.type(), true, ns);
1200 if(!result.has_value())
1201 return unchanged(expr);
1202
1203 return std::move(*result);
1204 }
1205 else if(expr.src().id() == ID_concatenation)
1206 {
1207 // the most-significant bit comes first in an concatenation_exprt, hence we
1208 // count down
1209 mp_integer offset = *width;
1210
1211 for(const auto &op : expr.src().operands())
1212 {
1213 auto op_width = pointer_offset_bits(op.type(), ns);
1214
1215 if(!op_width.has_value() || *op_width <= 0)
1216 return unchanged(expr);
1217
1218 if(*start < offset && offset <= *end + *op_width)
1219 {
1220 extractbits_exprt result = expr;
1221 result.src() = op;
1222 result.index() =
1223 from_integer(*end - (offset - *op_width), expr.index().type());
1224 return changed(simplify_extractbits(result));
1225 }
1226
1227 offset -= *op_width;
1228 }
1229 }
1231 {
1232 if(eb_src->index().is_constant())
1233 {
1234 extractbits_exprt result = *eb_src;
1235 result.type() = expr.type();
1236 const mp_integer src_index =
1238 result.index() = from_integer(src_index + *end, eb_src->index().type());
1239 return changed(simplify_extractbits(result));
1240 }
1241 }
1242 else if(*end == 0 && *start + 1 == *width)
1243 {
1244 typecast_exprt tc{expr.src(), expr.type()};
1245 return changed(simplify_typecast(tc));
1246 }
1247
1248 return unchanged(expr);
1249}
1250
1253{
1254 // simply remove, this is always 'nop'
1255 return expr.op();
1256}
1257
1260{
1261 if(!is_number(expr.type()))
1262 return unchanged(expr);
1263
1264 const exprt &operand = expr.op();
1265
1266 if(expr.type()!=operand.type())
1267 return unchanged(expr);
1268
1269 if(operand.id()==ID_unary_minus)
1270 {
1271 // cancel out "-(-x)" to "x"
1272 if(!is_number(to_unary_minus_expr(operand).op().type()))
1273 return unchanged(expr);
1274
1275 return to_unary_minus_expr(operand).op();
1276 }
1277 else if(operand.is_constant())
1278 {
1279 const irep_idt &type_id=expr.type().id();
1280 const auto &constant_expr = to_constant_expr(operand);
1281
1282 if(type_id==ID_integer ||
1285 {
1287
1288 if(!int_value.has_value())
1289 return unchanged(expr);
1290
1291 return from_integer(-*int_value, expr.type());
1292 }
1293 else if(type_id==ID_rational)
1294 {
1295 rationalt r;
1297 return unchanged(expr);
1298
1299 return from_rational(-r);
1300 }
1301 else if(type_id==ID_fixedbv)
1302 {
1304 f.negate();
1305 return f.to_expr();
1306 }
1307 else if(type_id==ID_floatbv)
1308 {
1310 f.negate();
1311 return f.to_expr();
1312 }
1313 }
1314
1315 return unchanged(expr);
1316}
1317
1320{
1321 const exprt &op = expr.op();
1322
1323 const auto &type = expr.type();
1324
1325 if(
1326 type.id() == ID_bv || type.id() == ID_unsignedbv ||
1327 type.id() == ID_signedbv)
1328 {
1329 const auto width = to_bitvector_type(type).get_width();
1330
1331 if(op.type() == type)
1332 {
1333 if(op.is_constant())
1334 {
1335 const auto &value = to_constant_expr(op).get_value();
1336 const auto new_value =
1337 make_bvrep(width, [&value, &width](std::size_t i) {
1338 return !get_bvrep_bit(value, width, i);
1339 });
1340 return constant_exprt(new_value, op.type());
1341 }
1342 }
1343 }
1344
1345 return unchanged(expr);
1346}
1347
1351{
1352 if(!expr.is_boolean())
1353 return unchanged(expr);
1354
1355 exprt tmp0=expr.op0();
1356 exprt tmp1=expr.op1();
1357
1358 // types must match
1359 if(tmp0.type() != tmp1.type())
1360 return unchanged(expr);
1361
1362 // if rhs is ID_if (and lhs is not), swap operands for == and !=
1363 if((expr.id()==ID_equal || expr.id()==ID_notequal) &&
1364 tmp0.id()!=ID_if &&
1365 tmp1.id()==ID_if)
1366 {
1367 auto new_expr = expr;
1368 new_expr.op0().swap(new_expr.op1());
1369 return changed(simplify_inequality(new_expr)); // recursive call
1370 }
1371
1372 if(tmp0.id()==ID_if && tmp0.operands().size()==3)
1373 {
1374 if_exprt if_expr=lift_if(expr, 0);
1375 if_expr.true_case() =
1377 if_expr.false_case() =
1379 return changed(simplify_if(if_expr));
1380 }
1381
1382 // see if we are comparing pointers that are address_of
1383 if(
1384 skip_typecast(tmp0).id() == ID_address_of &&
1385 skip_typecast(tmp1).id() == ID_address_of &&
1386 (expr.id() == ID_equal || expr.id() == ID_notequal))
1387 {
1388 return simplify_inequality_address_of(expr);
1389 }
1390
1391 if(tmp0.id()==ID_pointer_object &&
1392 tmp1.id()==ID_pointer_object &&
1393 (expr.id()==ID_equal || expr.id()==ID_notequal))
1394 {
1396 }
1397
1398 if(tmp0.type().id()==ID_c_enum_tag)
1399 tmp0.type()=ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1400
1401 if(tmp1.type().id()==ID_c_enum_tag)
1402 tmp1.type()=ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1403
1404 const bool tmp0_const = tmp0.is_constant();
1405 const bool tmp1_const = tmp1.is_constant();
1406
1407 // are _both_ constant?
1408 if(tmp0_const && tmp1_const)
1409 {
1411 }
1412 else if(tmp0_const)
1413 {
1414 // we want the constant on the RHS
1415
1417
1418 if(expr.id()==ID_ge)
1419 new_expr.id(ID_le);
1420 else if(expr.id()==ID_le)
1421 new_expr.id(ID_ge);
1422 else if(expr.id()==ID_gt)
1423 new_expr.id(ID_lt);
1424 else if(expr.id()==ID_lt)
1425 new_expr.id(ID_gt);
1426
1427 new_expr.op0().swap(new_expr.op1());
1428
1429 // RHS is constant, LHS is not
1431 }
1432 else if(tmp1_const)
1433 {
1434 // RHS is constant, LHS is not
1436 }
1437 else
1438 {
1439 // both are not constant
1441 }
1442}
1443
1447 const binary_relation_exprt &expr)
1448{
1449 exprt tmp0 = expr.op0();
1450 exprt tmp1 = expr.op1();
1451
1452 if(tmp0.type().id() == ID_c_enum_tag)
1453 tmp0.type() = ns.follow_tag(to_c_enum_tag_type(tmp0.type()));
1454
1455 if(tmp1.type().id() == ID_c_enum_tag)
1456 tmp1.type() = ns.follow_tag(to_c_enum_tag_type(tmp1.type()));
1457
1458 const auto &tmp0_const = to_constant_expr(tmp0);
1459 const auto &tmp1_const = to_constant_expr(tmp1);
1460
1461 if(expr.id() == ID_equal || expr.id() == ID_notequal)
1462 {
1463 // two constants compare equal when there values (as strings) are the same
1464 // or both of them are pointers and both represent NULL in some way
1465 bool equal = (tmp0_const.get_value() == tmp1_const.get_value());
1466 if(
1467 !equal && tmp0_const.type().id() == ID_pointer &&
1468 tmp1_const.type().id() == ID_pointer)
1469 {
1470 if(
1471 !config.ansi_c.NULL_is_zero && (tmp0_const.get_value() == ID_NULL ||
1472 tmp1_const.get_value() == ID_NULL))
1473 {
1474 // if NULL is not zero on this platform, we really don't know what it
1475 // is and therefore cannot simplify
1476 return unchanged(expr);
1477 }
1478 equal = tmp0_const.is_zero() && tmp1_const.is_zero();
1479 }
1480 return make_boolean_expr(expr.id() == ID_equal ? equal : !equal);
1481 }
1482
1483 if(tmp0.type().id() == ID_fixedbv)
1484 {
1486 fixedbvt f1(tmp1_const);
1487
1488 if(expr.id() == ID_ge)
1489 return make_boolean_expr(f0 >= f1);
1490 else if(expr.id() == ID_le)
1491 return make_boolean_expr(f0 <= f1);
1492 else if(expr.id() == ID_gt)
1493 return make_boolean_expr(f0 > f1);
1494 else if(expr.id() == ID_lt)
1495 return make_boolean_expr(f0 < f1);
1496 else
1498 }
1499 else if(tmp0.type().id() == ID_floatbv)
1500 {
1503
1504 if(expr.id() == ID_ge)
1505 return make_boolean_expr(f0 >= f1);
1506 else if(expr.id() == ID_le)
1507 return make_boolean_expr(f0 <= f1);
1508 else if(expr.id() == ID_gt)
1509 return make_boolean_expr(f0 > f1);
1510 else if(expr.id() == ID_lt)
1511 return make_boolean_expr(f0 < f1);
1512 else
1514 }
1515 else if(tmp0.type().id() == ID_rational)
1516 {
1517 rationalt r0, r1;
1518
1519 if(to_rational(tmp0, r0))
1520 return unchanged(expr);
1521
1522 if(to_rational(tmp1, r1))
1523 return unchanged(expr);
1524
1525 if(expr.id() == ID_ge)
1526 return make_boolean_expr(r0 >= r1);
1527 else if(expr.id() == ID_le)
1528 return make_boolean_expr(r0 <= r1);
1529 else if(expr.id() == ID_gt)
1530 return make_boolean_expr(r0 > r1);
1531 else if(expr.id() == ID_lt)
1532 return make_boolean_expr(r0 < r1);
1533 else
1535 }
1536 else
1537 {
1539
1540 if(!v0.has_value())
1541 return unchanged(expr);
1542
1544
1545 if(!v1.has_value())
1546 return unchanged(expr);
1547
1548 if(expr.id() == ID_ge)
1549 return make_boolean_expr(*v0 >= *v1);
1550 else if(expr.id() == ID_le)
1551 return make_boolean_expr(*v0 <= *v1);
1552 else if(expr.id() == ID_gt)
1553 return make_boolean_expr(*v0 > *v1);
1554 else if(expr.id() == ID_lt)
1555 return make_boolean_expr(*v0 < *v1);
1556 else
1558 }
1559}
1560
1561static bool eliminate_common_addends(exprt &op0, exprt &op1)
1562{
1563 // we can't eliminate zeros
1564 if(
1565 op0.is_zero() || op1.is_zero() ||
1566 (op0.is_constant() && to_constant_expr(op0).is_null_pointer()) ||
1568 {
1569 return true;
1570 }
1571
1572 if(op0.id()==ID_plus)
1573 {
1574 bool no_change = true;
1575
1576 Forall_operands(it, op0)
1577 if(!eliminate_common_addends(*it, op1))
1578 no_change = false;
1579
1580 return no_change;
1581 }
1582 else if(op1.id()==ID_plus)
1583 {
1584 bool no_change = true;
1585
1586 Forall_operands(it, op1)
1587 if(!eliminate_common_addends(op0, *it))
1588 no_change = false;
1589
1590 return no_change;
1591 }
1592 else if(op0==op1)
1593 {
1594 if(!op0.is_zero() &&
1595 op0.type().id()!=ID_complex)
1596 {
1597 // elimination!
1598 op0=from_integer(0, op0.type());
1599 op1=from_integer(0, op1.type());
1600 return false;
1601 }
1602 }
1603
1604 return true;
1605}
1606
1608 const binary_relation_exprt &expr)
1609{
1610 // pretty much all of the simplifications below are unsound
1611 // for IEEE float because of NaN!
1612
1613 if(expr.op0().type().id() == ID_floatbv)
1614 return unchanged(expr);
1615
1616 if(expr.op0().type().id() == ID_pointer)
1617 {
1620
1621 if(ptr_op0 == ptr_op1)
1622 {
1625
1627 std::move(offset_op0), expr.id(), std::move(offset_op1)}));
1628 }
1629 // simplifications below require same-object, which we don't check for
1630 else if(expr.id() != ID_equal && expr.id() != ID_notequal)
1631 {
1632 return unchanged(expr);
1633 }
1634 else if(
1635 expr.id() == ID_equal && ptr_op0.id() == ID_address_of &&
1636 ptr_op1.id() == ID_address_of)
1637 {
1638 // comparing pointers: if both are address-of-plus-some-constant such that
1639 // the resulting pointer remains within object bounds then they can never
1640 // be equal
1641 auto in_bounds = [this](const exprt &object_ptr, const exprt &expr_op) {
1642 auto object_size =
1643 size_of_expr(to_address_of_expr(object_ptr).object().type(), ns);
1644
1645 if(object_size.has_value())
1646 {
1650 std::move(offset), ID_lt, std::move(*object_size)})
1651 .expr;
1652 if(in_object_bounds.is_constant())
1653 return tvt{in_object_bounds.is_true()};
1654 }
1655
1656 return tvt::unknown();
1657 };
1658
1659 if(
1660 in_bounds(ptr_op0, expr.op0()).is_true() &&
1661 in_bounds(ptr_op1, expr.op1()).is_true())
1662 {
1663 return false_exprt{};
1664 }
1665 }
1666 }
1667
1668 // eliminate strict inequalities
1669 if(expr.id()==ID_notequal)
1670 {
1671 auto new_rel_expr = expr;
1675 }
1676 else if(expr.id()==ID_gt)
1677 {
1678 auto new_rel_expr = expr;
1679 new_rel_expr.id(ID_ge);
1680 // swap operands
1681 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1684 }
1685 else if(expr.id()==ID_lt)
1686 {
1687 auto new_rel_expr = expr;
1688 new_rel_expr.id(ID_ge);
1691 }
1692 else if(expr.id()==ID_le)
1693 {
1694 auto new_rel_expr = expr;
1695 new_rel_expr.id(ID_ge);
1696 // swap operands
1697 new_rel_expr.lhs().swap(new_rel_expr.rhs());
1699 }
1700
1701 // now we only have >=, =
1702
1703 INVARIANT(
1704 expr.id() == ID_ge || expr.id() == ID_equal,
1705 "we previously converted all other cases to >= or ==");
1706
1707 // syntactically equal?
1708
1709 if(expr.op0() == expr.op1())
1710 return true_exprt();
1711
1712 // See if we can eliminate common addends on both sides.
1713 // On bit-vectors, this is only sound on '='.
1714 if(expr.id()==ID_equal)
1715 {
1716 auto new_expr = to_equal_expr(expr);
1717 if(!eliminate_common_addends(new_expr.lhs(), new_expr.rhs()))
1718 {
1719 // remove zeros
1720 new_expr.lhs() = simplify_node(new_expr.lhs());
1721 new_expr.rhs() = simplify_node(new_expr.rhs());
1722 return changed(simplify_inequality(new_expr)); // recursive call
1723 }
1724 }
1725
1726 return unchanged(expr);
1727}
1728
1732 const binary_relation_exprt &expr)
1733{
1734 // the constant is always on the RHS
1735 PRECONDITION(expr.op1().is_constant());
1736
1737 if(expr.op0().id()==ID_if && expr.op0().operands().size()==3)
1738 {
1739 if_exprt if_expr=lift_if(expr, 0);
1740 if_expr.true_case() =
1742 if_expr.false_case() =
1744 return changed(simplify_if(if_expr));
1745 }
1746
1747 // do we deal with pointers?
1748 if(expr.op1().type().id()==ID_pointer)
1749 {
1750 if(expr.id()==ID_notequal)
1751 {
1752 auto new_rel_expr = expr;
1756 }
1757
1758 // very special case for pointers
1759 if(expr.id() != ID_equal)
1760 return unchanged(expr);
1761
1763
1764 if(op1_constant.is_null_pointer())
1765 {
1766 // the address of an object is never NULL
1767
1768 if(expr.op0().id() == ID_address_of)
1769 {
1770 const auto &object = to_address_of_expr(expr.op0()).object();
1771
1772 if(
1773 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1774 object.id() == ID_member || object.id() == ID_index ||
1775 object.id() == ID_string_constant)
1776 {
1777 return false_exprt();
1778 }
1779 }
1780 else if(
1781 expr.op0().id() == ID_typecast &&
1782 expr.op0().type().id() == ID_pointer &&
1783 to_typecast_expr(expr.op0()).op().id() == ID_address_of)
1784 {
1785 const auto &object =
1786 to_address_of_expr(to_typecast_expr(expr.op0()).op()).object();
1787
1788 if(
1789 object.id() == ID_symbol || object.id() == ID_dynamic_object ||
1790 object.id() == ID_member || object.id() == ID_index ||
1791 object.id() == ID_string_constant)
1792 {
1793 return false_exprt();
1794 }
1795 }
1796 else if(
1797 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_pointer)
1798 {
1799 exprt op = to_typecast_expr(expr.op0()).op();
1800 if(
1801 op.type().id() != ID_pointer &&
1802 (!config.ansi_c.NULL_is_zero || !is_number(op.type()) ||
1803 op.type().id() == ID_complex))
1804 {
1805 return unchanged(expr);
1806 }
1807
1808 // (type)ptr == NULL -> ptr == NULL
1809 // note that 'ptr' may be an integer
1810 auto new_expr = expr;
1811 new_expr.op0().swap(op);
1812 if(new_expr.op0().type().id() != ID_pointer)
1813 new_expr.op1() = from_integer(0, new_expr.op0().type());
1814 else
1815 new_expr.op1().type() = new_expr.op0().type();
1816 return changed(simplify_inequality(new_expr)); // do again!
1817 }
1818 else if(expr.op0().id() == ID_plus)
1819 {
1820 exprt offset =
1822 if(!offset.is_constant())
1823 return unchanged(expr);
1824
1825 exprt ptr = simplify_object(expr.op0()).expr;
1826 // NULL + N == NULL is N == 0
1827 if(ptr.is_constant() && to_constant_expr(ptr).is_null_pointer())
1828 return make_boolean_expr(offset.is_zero());
1829 // &x + N == NULL is false when the offset is in bounds
1831 {
1832 const auto object_size =
1833 pointer_offset_size(address_of->object().type(), ns);
1834 if(
1835 object_size.has_value() &&
1837 {
1838 return false_exprt();
1839 }
1840 }
1841 }
1842 }
1843
1844 // all we are doing with pointers
1845 return unchanged(expr);
1846 }
1847
1848 // is it a separation predicate?
1849
1850 if(expr.op0().id()==ID_plus)
1851 {
1852 // see if there is a constant in the sum
1853
1854 if(expr.id()==ID_equal || expr.id()==ID_notequal)
1855 {
1856 mp_integer constant=0;
1857 bool op_changed = false;
1858 auto new_expr = expr;
1859
1860 Forall_operands(it, new_expr.op0())
1861 {
1862 if(it->is_constant())
1863 {
1864 mp_integer i;
1865 if(!to_integer(to_constant_expr(*it), i))
1866 {
1867 constant+=i;
1868 *it=from_integer(0, it->type());
1869 op_changed = true;
1870 }
1871 }
1872 }
1873
1874 if(op_changed)
1875 {
1876 // adjust the constant on the RHS
1877 mp_integer i =
1879 i-=constant;
1880 new_expr.op1() = from_integer(i, new_expr.op1().type());
1881
1884 }
1885 }
1886 }
1887
1888 #if 1
1889 // (double)value REL const ---> value rel const
1890 // if 'const' can be represented exactly.
1891
1892 if(
1893 expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_floatbv &&
1894 to_typecast_expr(expr.op0()).op().type().id() == ID_floatbv)
1895 {
1900 to_floatbv_type(to_typecast_expr(expr.op0()).op().type())));
1902 const_val_converted_back.change_spec(
1905 {
1906 auto result = expr;
1907 result.op0() = to_typecast_expr(expr.op0()).op();
1908 result.op1()=const_val_converted.to_expr();
1909 return std::move(result);
1910 }
1911 }
1912 #endif
1913
1914 // is the constant zero?
1915
1916 if(expr.op1().is_zero())
1917 {
1918 if(expr.id()==ID_ge &&
1919 expr.op0().type().id()==ID_unsignedbv)
1920 {
1921 // zero is always smaller or equal something unsigned
1922 return true_exprt();
1923 }
1924
1925 auto new_expr = expr;
1926 exprt &operand = new_expr.op0();
1927
1928 if(expr.id()==ID_equal)
1929 {
1930 // rules below do not hold for >=
1931 if(operand.id()==ID_unary_minus)
1932 {
1934 return std::move(new_expr);
1935 }
1936 else if(operand.id()==ID_plus)
1937 {
1939
1940 // simplify a+-b=0 to a=b
1941 if(operand_plus_expr.operands().size() == 2)
1942 {
1943 // if we have -b+a=0, make that a+(-b)=0
1944 if(operand_plus_expr.op0().id() == ID_unary_minus)
1945 operand_plus_expr.op0().swap(operand_plus_expr.op1());
1946
1947 if(operand_plus_expr.op1().id() == ID_unary_minus)
1948 {
1949 return binary_exprt(
1950 operand_plus_expr.op0(),
1951 expr.id(),
1953 expr.type());
1954 }
1955 }
1956 }
1957 }
1958
1959 if(config.ansi_c.NULL_is_zero)
1960 {
1961 const exprt &maybe_tc_op = skip_typecast(expr.op0());
1962 if(maybe_tc_op.type().id() == ID_pointer)
1963 {
1964 // make sure none of the type casts lose information
1966 bool bitwidth_unchanged = true;
1967 const exprt *ep = &(expr.op0());
1968 while(bitwidth_unchanged && ep->id() == ID_typecast)
1969 {
1970 if(auto t = type_try_dynamic_cast<bitvector_typet>(ep->type()))
1971 {
1972 bitwidth_unchanged = t->get_width() == p_type.get_width();
1973 }
1974 else
1975 bitwidth_unchanged = false;
1976
1977 ep = &to_typecast_expr(*ep).op();
1978 }
1979
1981 {
1982 if(expr.id() == ID_equal || expr.id() == ID_ge || expr.id() == ID_le)
1983 {
1984 return changed(simplify_rec(
1986 }
1987 else
1988 {
1989 return changed(simplify_rec(
1991 }
1992 }
1993 }
1994 }
1995 }
1996
1997 // are we comparing with a typecast from bool?
1998 if(
1999 expr.op0().id() == ID_typecast &&
2000 to_typecast_expr(expr.op0()).op().is_boolean())
2001 {
2002 const auto &lhs_typecast_op = to_typecast_expr(expr.op0()).op();
2003
2004 // we re-write (TYPE)boolean == 0 -> !boolean
2005 if(expr.op1().is_zero() && expr.id()==ID_equal)
2006 {
2008 }
2009
2010 // we re-write (TYPE)boolean != 0 -> boolean
2011 if(expr.op1().is_zero() && expr.id()==ID_notequal)
2012 {
2013 return lhs_typecast_op;
2014 }
2015 }
2016
2017 #define NORMALISE_CONSTANT_TESTS
2018 #ifdef NORMALISE_CONSTANT_TESTS
2019 // Normalise to >= and = to improve caching and term sharing
2020 if(expr.op0().type().id()==ID_unsignedbv ||
2021 expr.op0().type().id()==ID_signedbv)
2022 {
2023 mp_integer max(to_integer_bitvector_type(expr.op0().type()).largest());
2024
2025 if(expr.id()==ID_notequal)
2026 {
2027 auto new_rel_expr = expr;
2031 }
2032 else if(expr.id()==ID_gt)
2033 {
2035
2036 if(i==max)
2037 {
2038 return false_exprt();
2039 }
2040
2041 auto new_expr = expr;
2042 new_expr.id(ID_ge);
2043 ++i;
2044 new_expr.op1() = from_integer(i, new_expr.op1().type());
2046 }
2047 else if(expr.id()==ID_lt)
2048 {
2049 auto new_rel_expr = expr;
2050 new_rel_expr.id(ID_ge);
2053 }
2054 else if(expr.id()==ID_le)
2055 {
2057
2058 if(i==max)
2059 {
2060 return true_exprt();
2061 }
2062
2063 auto new_rel_expr = expr;
2064 new_rel_expr.id(ID_ge);
2065 ++i;
2066 new_rel_expr.op1() = from_integer(i, new_rel_expr.op1().type());
2069 }
2070 }
2071#endif
2072 return unchanged(expr);
2073}
2074
2077{
2079 expr.op(),
2081 ns);
2082
2083 if(!const_bits_opt.has_value())
2084 return unchanged(expr);
2085
2086 std::reverse(const_bits_opt->begin(), const_bits_opt->end());
2087
2088 auto result = bits2expr(
2090 expr.type(),
2092 ns);
2093 if(!result.has_value())
2094 return unchanged(expr);
2095
2096 return std::move(*result);
2097}
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 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:133
exprt & op1()
Definition expr.h:136
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:3117
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:56
std::vector< exprt > operandst
Definition expr.h:58
bool is_one() const
Return whether the expression is a constant representing 1.
Definition expr.cpp:96
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:224
bool is_false() const
Return whether the expression is a constant representing false.
Definition expr.cpp:34
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition expr.cpp:47
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
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:3199
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:2497
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:2454
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 &)
resultt simplify_inequality(const binary_relation_exprt &)
simplifies inequalities !=, <=, <, >=, >, and also ==
resultt simplify_not(const not_exprt &)
resultt simplify_bswap(const bswap_exprt &)
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 &)
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:3190
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:27
#define Forall_expr(it, expr)
Definition expr.h:36
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
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
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:3172
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