@@ -887,6 +887,33 @@ simplify_exprt::simplify_concatenation(const concatenation_exprt &expr)
887887 new_expr.operands ().erase (new_expr.operands ().begin () + i + 1 );
888888 no_change = false ;
889889 }
890+ else if (
891+ skip_typecast (opi).id () == ID_extractbits &&
892+ skip_typecast (opn).id () == ID_extractbits)
893+ {
894+ const extractbits_exprt &eb_i = to_extractbits_expr (skip_typecast (opi));
895+ const extractbits_exprt &eb_n = to_extractbits_expr (skip_typecast (opn));
896+
897+ if (
898+ eb_i.src () == eb_n.src () && eb_i.lower ().is_constant () &&
899+ eb_n.upper ().is_constant () &&
900+ numeric_cast_v<mp_integer>(to_constant_expr (eb_i.lower ())) ==
901+ numeric_cast_v<mp_integer>(to_constant_expr (eb_n.upper ())) + 1 )
902+ {
903+ extractbits_exprt eb_merged = eb_i;
904+ eb_merged.lower () = eb_n.lower ();
905+ to_bitvector_type (eb_merged.type ())
906+ .set_width (
907+ to_bitvector_type (eb_i.type ()).get_width () +
908+ to_bitvector_type (eb_n.type ()).get_width ());
909+ opi = eb_merged;
910+ // erase opn
911+ new_expr.operands ().erase (new_expr.operands ().begin () + i + 1 );
912+ no_change = false ;
913+ }
914+ else
915+ ++i;
916+ }
890917 else
891918 i++;
892919 }
@@ -1125,18 +1152,38 @@ simplify_exprt::simplify_extractbits(const extractbits_exprt &expr)
11251152 if (!op_width.has_value () || *op_width <= 0 )
11261153 return unchanged (expr);
11271154
1128- if (*start + 1 == offset && *end + *op_width == offset )
1155+ if (*start < offset && offset <= *end + *op_width)
11291156 {
1130- exprt tmp = *it;
1131- if (tmp.type () != expr.type ())
1132- return unchanged (expr);
1133-
1134- return std::move (tmp);
1157+ extractbits_exprt result = expr;
1158+ result.src () = *it;
1159+ result.lower () =
1160+ from_integer (*end - (offset - *op_width), expr.lower ().type ());
1161+ result.upper () =
1162+ from_integer (*start - (offset - *op_width), expr.upper ().type ());
1163+ return changed (simplify_extractbits (result));
11351164 }
11361165
11371166 offset -= *op_width;
11381167 }
11391168 }
1169+ else if (auto eb_src = expr_try_dynamic_cast<extractbits_exprt>(expr.src ()))
1170+ {
1171+ if (eb_src->upper ().is_constant () && eb_src->lower ().is_constant ())
1172+ {
1173+ extractbits_exprt result = *eb_src;
1174+ result.type () = expr.type ();
1175+ const mp_integer src_lower =
1176+ numeric_cast_v<mp_integer>(to_constant_expr (eb_src->lower ()));
1177+ result.lower () = from_integer (src_lower + *end, eb_src->lower ().type ());
1178+ result.upper () = from_integer (src_lower + *start, eb_src->lower ().type ());
1179+ return changed (simplify_extractbits (result));
1180+ }
1181+ }
1182+ else if (*end == 0 && *start + 1 == *width)
1183+ {
1184+ typecast_exprt tc{expr.src (), expr.type ()};
1185+ return changed (simplify_typecast (tc));
1186+ }
11401187
11411188 return unchanged (expr);
11421189}
0 commit comments