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