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