Skip to content

Commit c988532

Browse files
authored
Merge pull request #7343 from tautschnig/feature/simp-extractbits
Extend simplification of extractbits
2 parents d43d0ec + eaea3ae commit c988532

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

src/util/simplify_expr_int.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)