-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make lower_popcount a method of popcount_exprt
Expression lowering may be useful well outside the solvers/ context. Making it a method of the class being lowered also serves as a way of describing the semantics of the expression. This is mainly a refactoring, no changes in behaviour are intended.
- Loading branch information
1 parent
383aff4
commit a14192f
Showing
8 changed files
with
55 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected] | |
#include "bitvector_expr.h" | ||
|
||
#include "arith_tools.h" | ||
#include "bitvector_types.h" | ||
#include "mathematical_types.h" | ||
|
||
shift_exprt::shift_exprt( | ||
|
@@ -40,3 +41,49 @@ extractbits_exprt::extractbits_exprt( | |
from_integer(_upper, integer_typet()), | ||
from_integer(_lower, integer_typet())); | ||
} | ||
|
||
exprt popcount_exprt::lower() const | ||
{ | ||
// Hacker's Delight, variant pop0: | ||
// x = (x & 0x55555555) + ((x >> 1) & 0x55555555); | ||
// x = (x & 0x33333333) + ((x >> 2) & 0x33333333); | ||
// x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); | ||
// x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); | ||
// etc. | ||
// return x; | ||
// http://www.hackersdelight.org/permissions.htm | ||
|
||
// make sure the operand width is a power of two | ||
exprt x = op(); | ||
const auto x_width = to_bitvector_type(x.type()).get_width(); | ||
CHECK_RETURN(x_width >= 1); | ||
const std::size_t bits = address_bits(x_width); | ||
const std::size_t new_width = numeric_cast_v<std::size_t>(power(2, bits)); | ||
|
||
const bool need_typecast = | ||
new_width > x_width || x.type().id() != ID_unsignedbv; | ||
|
||
if(need_typecast) | ||
x = typecast_exprt(x, unsignedbv_typet(new_width)); | ||
|
||
// repeatedly compute x = (x & bitmask) + ((x >> shift) & bitmask) | ||
for(std::size_t shift = 1; shift < new_width; shift <<= 1) | ||
{ | ||
// x >> shift | ||
lshr_exprt shifted_x( | ||
x, from_integer(shift, unsignedbv_typet(address_bits(shift) + 1))); | ||
// bitmask is a string of alternating shift-many bits starting from lsb set | ||
// to 1 | ||
std::string bitstring; | ||
bitstring.reserve(new_width); | ||
for(std::size_t i = 0; i < new_width / (2 * shift); ++i) | ||
bitstring += std::string(shift, '0') + std::string(shift, '1'); | ||
const mp_integer value = binary2integer(bitstring, false); | ||
const constant_exprt bitmask(integer2bvrep(value, new_width), x.type()); | ||
// build the expression | ||
x = plus_exprt(bitand_exprt(x, bitmask), bitand_exprt(shifted_x, bitmask)); | ||
} | ||
|
||
// the result is restricted to the result type | ||
return typecast_exprt::conditional_cast(x, type()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters