Skip to content

Add separate overflow expr classes #6744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions src/solvers/flattening/boolbv_overflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,33 @@ Author: Daniel Kroening, [email protected]

literalt boolbvt::convert_overflow(const exprt &expr)
{
if(expr.id()==ID_overflow_plus ||
expr.id()==ID_overflow_minus)
const auto plus_or_minus_conversion =
[&](
const binary_overflow_exprt &overflow_expr,
const std::function<literalt(
bv_utilst *, const bvt &, const bvt &, bv_utilst::representationt)>
&bv_util_overflow) {
const bvt &bv0 = convert_bv(overflow_expr.lhs());
const bvt &bv1 = convert_bv(overflow_expr.rhs());

if(bv0.size() != bv1.size())
return SUB::convert_rest(expr);

bv_utilst::representationt rep =
overflow_expr.lhs().type().id() == ID_signedbv
? bv_utilst::representationt::SIGNED
: bv_utilst::representationt::UNSIGNED;

return bv_util_overflow(&bv_utils, bv0, bv1, rep);
};
if(
const auto plus_overflow = expr_try_dynamic_cast<plus_overflow_exprt>(expr))
{
const auto &overflow_expr = to_binary_expr(expr);

const bvt &bv0 = convert_bv(overflow_expr.lhs());
const bvt &bv1 = convert_bv(overflow_expr.rhs());

if(bv0.size()!=bv1.size())
return SUB::convert_rest(expr);

bv_utilst::representationt rep =
overflow_expr.lhs().type().id() == ID_signedbv
? bv_utilst::representationt::SIGNED
: bv_utilst::representationt::UNSIGNED;

return expr.id()==ID_overflow_minus?
bv_utils.overflow_sub(bv0, bv1, rep):
bv_utils.overflow_add(bv0, bv1, rep);
return plus_or_minus_conversion(*plus_overflow, &bv_utilst::overflow_add);
}
if(const auto minus = expr_try_dynamic_cast<minus_overflow_exprt>(expr))
{
return plus_or_minus_conversion(*minus, &bv_utilst::overflow_sub);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the lambda helps readability here. I'd perhaps favour two branches with almost identical code, or else a slightly larger refactor: all the branches in boolbvt::convert_overflow need to convert the operands, perhaps also need to determine signed/unsigned representation. And we might opt to be consistent in whether we support (multiply) or don't support (other cases) operands of different width. (I have no idea why we would support them.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the more ideal refactor would be to remove more of the duplication between all of the branches here. However given that I have approvals on this PR and I have other work which is based on top of this, I am going to merge this as-is and then come back to refactoring boolbvt::convert_overflow as a follow-up PR. That way the larger refactor can be considered in isolation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about mismatched operand widths, I think there is the potential for a simpler/smaller formula for multiplying two operands of mismatched but shorter widths instead of 2 operands of matched but larger widths due to being extended to match. Any potential benefits to this are speculation on my part and it seems like a case which may be rare in source code or even always eliminated by implicit type casts before we reach this stage.

}
else if(
const auto mult_overflow = expr_try_dynamic_cast<mult_overflow_exprt>(expr))
Expand Down