Skip to content

Commit 1f94286

Browse files
authored
Merge pull request #7016 from tautschnig/cleanup/adder-api
Cleanup the API of bv_utilst::adder
2 parents b4a19b2 + 62eeef1 commit 1f94286

File tree

2 files changed

+52
-67
lines changed

2 files changed

+52
-67
lines changed

src/solvers/flattening/bv_utils.cpp

Lines changed: 43 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -290,20 +290,21 @@ literalt bv_utilst::carry(literalt a, literalt b, literalt c)
290290
}
291291
}
292292

293-
void bv_utilst::adder(
294-
bvt &sum,
295-
const bvt &op,
296-
literalt carry_in,
297-
literalt &carry_out)
293+
std::pair<bvt, literalt>
294+
bv_utilst::adder(const bvt &op0, const bvt &op1, literalt carry_in)
298295
{
299-
PRECONDITION(sum.size() == op.size());
296+
PRECONDITION(op0.size() == op1.size());
300297

301-
carry_out=carry_in;
298+
std::pair<bvt, literalt> result{bvt{}, carry_in};
299+
result.first.reserve(op0.size());
300+
literalt &carry_out = result.second;
302301

303-
for(std::size_t i=0; i<sum.size(); i++)
302+
for(std::size_t i = 0; i < op0.size(); i++)
304303
{
305-
sum[i] = full_adder(sum[i], op[i], carry_out, carry_out);
304+
result.first.push_back(full_adder(op0[i], op1[i], carry_out, carry_out));
306305
}
306+
307+
return result;
307308
}
308309

309310
literalt bv_utilst::carry_out(
@@ -327,37 +328,28 @@ bvt bv_utilst::add_sub_no_overflow(
327328
bool subtract,
328329
representationt rep)
329330
{
330-
bvt sum=op0;
331-
adder_no_overflow(sum, op1, subtract, rep);
332-
return sum;
331+
return adder_no_overflow(op0, op1, subtract, rep);
333332
}
334333

335334
bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, bool subtract)
336335
{
337336
PRECONDITION(op0.size() == op1.size());
338337

339338
literalt carry_in=const_literal(subtract);
340-
literalt carry_out;
341339

342-
bvt result=op0;
343340
bvt tmp_op1=subtract?inverted(op1):op1;
344341

345-
adder(result, tmp_op1, carry_in, carry_out);
346-
347-
return result;
342+
// we ignore the carry-out
343+
return adder(op0, tmp_op1, carry_in).first;
348344
}
349345

350346
bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, literalt subtract)
351347
{
352348
const bvt op1_sign_applied=
353349
select(subtract, inverted(op1), op1);
354350

355-
bvt result=op0;
356-
literalt carry_out;
357-
358-
adder(result, op1_sign_applied, subtract, carry_out);
359-
360-
return result;
351+
// we ignore the carry-out
352+
return adder(op0, op1_sign_applied, subtract).first;
361353
}
362354

363355
bvt bv_utilst::saturating_add_sub(
@@ -371,23 +363,22 @@ bvt bv_utilst::saturating_add_sub(
371363
rep == representationt::SIGNED || rep == representationt::UNSIGNED);
372364

373365
literalt carry_in = const_literal(subtract);
374-
literalt carry_out;
375366

376-
bvt add_sub_result = op0;
377367
bvt tmp_op1 = subtract ? inverted(op1) : op1;
378368

379-
adder(add_sub_result, tmp_op1, carry_in, carry_out);
369+
auto add_sub_result = adder(op0, tmp_op1, carry_in);
370+
literalt carry_out = add_sub_result.second;
380371

381372
bvt result;
382-
result.reserve(add_sub_result.size());
373+
result.reserve(add_sub_result.first.size());
383374
if(rep == representationt::UNSIGNED)
384375
{
385376
// An unsigned overflow has occurred when carry_out is not equal to
386377
// subtract: addition with a carry-out means an overflow beyond the maximum
387378
// representable value, subtraction without a carry-out means an underflow
388379
// below zero. For saturating arithmetic the former implies that all bits
389380
// should be set to 1, in the latter case all bits should be set to zero.
390-
for(const auto &literal : add_sub_result)
381+
for(const auto &literal : add_sub_result.first)
391382
{
392383
result.push_back(
393384
subtract ? prop.land(literal, carry_out)
@@ -403,27 +394,27 @@ bvt bv_utilst::saturating_add_sub(
403394
literalt overflow_to_max_int = prop.land(bvt{
404395
!sign_bit(op0),
405396
subtract ? sign_bit(op1) : !sign_bit(op1),
406-
sign_bit(add_sub_result)});
397+
sign_bit(add_sub_result.first)});
407398
// A signed underflow below the minimum representable value occurs when
408399
// adding two negative numbers and arriving at a positive result, or
409400
// subtracting a positive from a negative number (and, again, obtaining a
410401
// positive wrap-around result).
411402
literalt overflow_to_min_int = prop.land(bvt{
412403
sign_bit(op0),
413404
subtract ? !sign_bit(op1) : sign_bit(op1),
414-
!sign_bit(add_sub_result)});
405+
!sign_bit(add_sub_result.first)});
415406

416407
// set all bits except for the sign bit
417-
PRECONDITION(!add_sub_result.empty());
418-
for(std::size_t i = 0; i < add_sub_result.size() - 1; ++i)
408+
PRECONDITION(!add_sub_result.first.empty());
409+
for(std::size_t i = 0; i < add_sub_result.first.size() - 1; ++i)
419410
{
420-
const auto &literal = add_sub_result[i];
411+
const auto &literal = add_sub_result.first[i];
421412
result.push_back(prop.land(
422413
prop.lor(overflow_to_max_int, literal), !overflow_to_min_int));
423414
}
424415
// finally add the sign bit
425416
result.push_back(prop.land(
426-
prop.lor(overflow_to_min_int, add_sub_result.back()),
417+
prop.lor(overflow_to_min_int, sign_bit(add_sub_result.first)),
427418
!overflow_to_max_int));
428419
}
429420

@@ -479,48 +470,44 @@ literalt bv_utilst::overflow_sub(
479470
UNREACHABLE;
480471
}
481472

482-
void bv_utilst::adder_no_overflow(
483-
bvt &sum,
484-
const bvt &op,
473+
bvt bv_utilst::adder_no_overflow(
474+
const bvt &op0,
475+
const bvt &op1,
485476
bool subtract,
486477
representationt rep)
487478
{
488-
const bvt tmp_op=subtract?inverted(op):op;
479+
const bvt tmp_op = subtract ? inverted(op1) : op1;
489480

490481
if(rep==representationt::SIGNED)
491482
{
492483
// an overflow occurs if the signs of the two operands are the same
493484
// and the sign of the sum is the opposite
494485

495-
literalt old_sign=sum[sum.size()-1];
496-
literalt sign_the_same=
497-
prop.lequal(sum[sum.size()-1], tmp_op[tmp_op.size()-1]);
486+
literalt old_sign = sign_bit(op0);
487+
literalt sign_the_same = prop.lequal(sign_bit(op0), sign_bit(tmp_op));
498488

499-
literalt carry;
500-
adder(sum, tmp_op, const_literal(subtract), carry);
489+
// we ignore the carry-out
490+
bvt sum = adder(op0, tmp_op, const_literal(subtract)).first;
501491

502-
// result of addition in sum
503492
prop.l_set_to_false(
504-
prop.land(sign_the_same, prop.lxor(sum[sum.size()-1], old_sign)));
493+
prop.land(sign_the_same, prop.lxor(sign_bit(sum), old_sign)));
494+
495+
return sum;
505496
}
506497
else
507498
{
508499
INVARIANT(
509500
rep == representationt::UNSIGNED,
510501
"representation has either value signed or unsigned");
511-
literalt carry_out;
512-
adder(sum, tmp_op, const_literal(subtract), carry_out);
513-
prop.l_set_to(carry_out, subtract);
502+
auto result = adder(op0, tmp_op, const_literal(subtract));
503+
prop.l_set_to(result.second, subtract);
504+
return std::move(result.first);
514505
}
515506
}
516507

517-
void bv_utilst::adder_no_overflow(bvt &sum, const bvt &op)
508+
bvt bv_utilst::adder_no_overflow(const bvt &op0, const bvt &op1)
518509
{
519-
literalt carry_out=const_literal(false);
520-
521-
adder(sum, op, carry_out, carry_out);
522-
523-
prop.l_set_to_false(carry_out); // enforce no overflow
510+
return adder_no_overflow(op0, op1, false, representationt::UNSIGNED);
524511
}
525512

526513
bvt bv_utilst::shift(const bvt &op, const shiftt s, const bvt &dist)
@@ -790,7 +777,7 @@ bvt bv_utilst::unsigned_multiplier_no_overflow(
790777
for(std::size_t idx=sum; idx<product.size(); idx++)
791778
tmpop.push_back(prop.land(op1[idx-sum], op0[sum]));
792779

793-
adder_no_overflow(product, tmpop);
780+
product = adder_no_overflow(product, tmpop);
794781

795782
for(std::size_t idx=op1.size()-sum; idx<op1.size(); idx++)
796783
prop.l_set_to_false(prop.land(op1[idx], op0[sum]));
@@ -1006,9 +993,7 @@ void bv_utilst::unsigned_divider(
1006993

1007994
// res*op1 + rem = op0
1008995

1009-
bvt sum=product;
1010-
1011-
adder_no_overflow(sum, rem);
996+
bvt sum = adder_no_overflow(product, rem);
1012997

1013998
literalt is_equal=equal(sum, op0);
1014999

src/solvers/flattening/bv_utils.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#define CPROVER_SOLVERS_FLATTENING_BV_UTILS_H
1212

1313
#include <util/mp_arith.h>
14+
#include <util/nodiscard.h>
1415

1516
#include <solvers/prop/prop.h>
1617

@@ -221,19 +222,18 @@ class bv_utilst
221222
protected:
222223
propt &prop;
223224

224-
void adder(
225-
bvt &sum,
226-
const bvt &op,
227-
literalt carry_in,
228-
literalt &carry_out);
225+
/// Return the sum and carry-out when adding \p op0 and \p op1 under initial
226+
/// carry \p carry_in.
227+
NODISCARD std::pair<bvt, literalt>
228+
adder(const bvt &op0, const bvt &op1, literalt carry_in);
229229

230-
void adder_no_overflow(
231-
bvt &sum,
232-
const bvt &op,
230+
NODISCARD bvt adder_no_overflow(
231+
const bvt &op0,
232+
const bvt &op1,
233233
bool subtract,
234234
representationt rep);
235235

236-
void adder_no_overflow(bvt &sum, const bvt &op);
236+
NODISCARD bvt adder_no_overflow(const bvt &op0, const bvt &op1);
237237

238238
bvt unsigned_multiplier_no_overflow(
239239
const bvt &op0, const bvt &op1);

0 commit comments

Comments
 (0)