Skip to content

Commit 81b6b69

Browse files
committed
Extend simplification of extractbits
Simplify nested extractbits expressions, simplify more cases of extractbits-out-of-concatenation, simplify concatenation of back-to-back extractbits.
1 parent ef4e270 commit 81b6b69

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
@@ -862,6 +862,33 @@ simplify_exprt::simplify_concatenation(const concatenation_exprt &expr)
862862
new_expr.operands().erase(new_expr.operands().begin() + i + 1);
863863
no_change = false;
864864
}
865+
else if(
866+
skip_typecast(opi).id() == ID_extractbits &&
867+
skip_typecast(opn).id() == ID_extractbits)
868+
{
869+
const extractbits_exprt &eb_i = to_extractbits_expr(skip_typecast(opi));
870+
const extractbits_exprt &eb_n = to_extractbits_expr(skip_typecast(opn));
871+
872+
if(
873+
eb_i.src() == eb_n.src() && eb_i.lower().is_constant() &&
874+
eb_n.upper().is_constant() &&
875+
numeric_cast_v<mp_integer>(to_constant_expr(eb_i.lower())) ==
876+
numeric_cast_v<mp_integer>(to_constant_expr(eb_n.upper())) + 1)
877+
{
878+
extractbits_exprt eb_merged = eb_i;
879+
eb_merged.lower() = eb_n.lower();
880+
to_bitvector_type(eb_merged.type())
881+
.set_width(
882+
to_bitvector_type(eb_i.type()).get_width() +
883+
to_bitvector_type(eb_n.type()).get_width());
884+
opi = eb_merged;
885+
// erase opn
886+
new_expr.operands().erase(new_expr.operands().begin() + i + 1);
887+
no_change = false;
888+
}
889+
else
890+
++i;
891+
}
865892
else
866893
i++;
867894
}
@@ -1100,18 +1127,38 @@ simplify_exprt::simplify_extractbits(const extractbits_exprt &expr)
11001127
if(!op_width.has_value() || *op_width <= 0)
11011128
return unchanged(expr);
11021129

1103-
if(*start + 1 == offset && *end + *op_width == offset)
1130+
if(*start < offset && *end >= offset - *op_width)
11041131
{
1105-
exprt tmp = *it;
1106-
if(tmp.type() != expr.type())
1107-
return unchanged(expr);
1108-
1109-
return std::move(tmp);
1132+
extractbits_exprt result = expr;
1133+
result.src() = *it;
1134+
result.lower() =
1135+
from_integer(*end - (offset - *op_width), expr.lower().type());
1136+
result.upper() =
1137+
from_integer(*start - (offset - *op_width), expr.upper().type());
1138+
return changed(simplify_extractbits(result));
11101139
}
11111140

11121141
offset -= *op_width;
11131142
}
11141143
}
1144+
else if(auto eb_src = expr_try_dynamic_cast<extractbits_exprt>(expr.src()))
1145+
{
1146+
if(eb_src->upper().is_constant() && eb_src->lower().is_constant())
1147+
{
1148+
extractbits_exprt result = *eb_src;
1149+
result.type() = expr.type();
1150+
const mp_integer src_lower =
1151+
numeric_cast_v<mp_integer>(to_constant_expr(eb_src->lower()));
1152+
result.lower() = from_integer(src_lower + *end, eb_src->lower().type());
1153+
result.upper() = from_integer(src_lower + *start, eb_src->lower().type());
1154+
return changed(simplify_extractbits(result));
1155+
}
1156+
}
1157+
else if(*end == 0 && *start + 1 == *width)
1158+
{
1159+
typecast_exprt tc{expr.src(), expr.type()};
1160+
return changed(simplify_typecast(tc));
1161+
}
11151162

11161163
return unchanged(expr);
11171164
}

0 commit comments

Comments
 (0)