@@ -18,7 +18,9 @@ Author: Daniel Kroening, kroening@kroening.com
1818#include " expr_util.h"
1919#include " fixedbv.h"
2020#include " ieee_float.h"
21+ #include " invariant.h"
2122#include " namespace.h"
23+ #include " pointer_offset_size.h"
2224#include " rational.h"
2325#include " rational_tools.h"
2426#include " std_expr.h"
@@ -1101,48 +1103,76 @@ bool simplify_exprt::simplify_power(exprt &expr)
11011103}
11021104
11031105// / Simplifies extracting of bits from a constant.
1104- bool simplify_exprt::simplify_extractbits (exprt &expr)
1106+ bool simplify_exprt::simplify_extractbits (extractbits_exprt &expr)
11051107{
1106- assert (expr.operands ().size ()==3 );
1107-
1108- const typet &op0_type=expr.op0 ().type ();
1108+ const typet &op0_type = expr.src ().type ();
11091109
11101110 if (!is_bitvector_type (op0_type) &&
11111111 !is_bitvector_type (expr.type ()))
11121112 return true ;
11131113
1114- if (expr.op0 ().is_constant ())
1115- {
1116- std::size_t width=to_bitvector_type (op0_type).get_width ();
1117- mp_integer start, end;
1114+ mp_integer start, end;
11181115
1119- if (to_integer (expr.op1 (), start))
1120- return true ;
1116+ if (to_integer (expr.upper (), start))
1117+ return true ;
11211118
1122- if (to_integer (expr.op2 (), end))
1123- return true ;
1119+ if (to_integer (expr.lower (), end))
1120+ return true ;
11241121
1125- if (start<0 || start>=width ||
1126- end<0 || end>=width)
1127- return true ;
1122+ const mp_integer width = pointer_offset_bits (op0_type, ns);
1123+
1124+ if (start < 0 || start >= width || end < 0 || end >= width)
1125+ return true ;
11281126
1129- assert (start>=end); // is this always the case??
1127+ DATA_INVARIANT (
1128+ start >= end,
1129+ " extractbits must have upper() >= lower()" );
11301130
1131- const irep_idt &value=expr.op0 ().get (ID_value);
1131+ if (expr.src ().is_constant ())
1132+ {
1133+ const irep_idt &value = to_constant_expr (expr.src ()).get_value ();
11321134
11331135 if (value.size ()!=width)
11341136 return true ;
11351137
11361138 std::string svalue=id2string (value);
11371139
1138- std::string extracted_value=
1139- svalue.substr (width-integer2size_t (start)-1 ,
1140- integer2size_t (start-end+1 ));
1140+ std::string extracted_value =
1141+ svalue.substr (
1142+ integer2size_t (width - start - 1 ),
1143+ integer2size_t (start - end + 1 ));
11411144
1142- expr = constant_exprt (extracted_value, expr.type ());
1145+ constant_exprt result (extracted_value, expr.type ());
1146+ expr.swap (result);
11431147
11441148 return false ;
11451149 }
1150+ else if (expr.src ().id () == ID_concatenation)
1151+ {
1152+ // the most-significant bit comes first in an concatenation_exprt, hence we
1153+ // count down
1154+ mp_integer offset = width;
1155+
1156+ forall_operands (it, expr.src ())
1157+ {
1158+ mp_integer op_width = pointer_offset_bits (it->type (), ns);
1159+
1160+ if (op_width <= 0 )
1161+ return true ;
1162+
1163+ if (start + 1 == offset && end + op_width == offset)
1164+ {
1165+ exprt tmp = *it;
1166+ if (tmp.type () != expr.type ())
1167+ return true ;
1168+
1169+ expr.swap (tmp);
1170+ return false ;
1171+ }
1172+
1173+ offset -= op_width;
1174+ }
1175+ }
11461176
11471177 return true ;
11481178}
0 commit comments