Commit 12aedf5b authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[base] Skip unneeded masks in CountPopulation

Out of the six masks (for 64 bit value), three can be skipped because
the values are known to be within certain bounds.

R=jkummerow@chromium.org

Bug: v8:9810
Change-Id: I50c3bf2d374b14456aa0cbec076e894f25779151
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1910110Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64916}
parent 7c3ffd8a
......@@ -27,31 +27,36 @@ constexpr inline
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8,
unsigned>::type
CountPopulation(T value) {
STATIC_ASSERT(sizeof(T) <= 8);
#if V8_HAS_BUILTIN_POPCOUNT
return sizeof(T) == 8 ? __builtin_popcountll(static_cast<uint64_t>(value))
: __builtin_popcount(static_cast<uint32_t>(value));
#else
constexpr uint64_t mask[] = {0x5555555555555555, 0x3333333333333333,
0x0f0f0f0f0f0f0f0f, 0x00ff00ff00ff00ff,
0x0000ffff0000ffff, 0x00000000ffffffff};
0x0f0f0f0f0f0f0f0f};
// Start with 1 bit wide buckets of [0,1].
value = ((value >> 1) & mask[0]) + (value & mask[0]);
// Having 2 bit wide buckets of [0,2] now.
value = ((value >> 2) & mask[1]) + (value & mask[1]);
value = ((value >> 4) & mask[2]) + (value & mask[2]);
// Having 4 bit wide buckets of [0,4] now.
value = (value >> 4) + value;
// Having 4 bit wide buckets of [0,8] now.
if (sizeof(T) > 1)
value = ((value >> (sizeof(T) > 1 ? 8 : 0)) & mask[3]) + (value & mask[3]);
if (sizeof(T) > 2)
value = ((value >> (sizeof(T) > 2 ? 16 : 0)) & mask[4]) + (value & mask[4]);
if (sizeof(T) > 4)
value = ((value >> (sizeof(T) > 4 ? 32 : 0)) & mask[5]) + (value & mask[5]);
return static_cast<unsigned>(value);
value = ((value >> (sizeof(T) > 1 ? 8 : 0)) & mask[2]) + (value & mask[2]);
// Having 8 bit wide buckets of [0,16] now.
if (sizeof(T) > 2) value = (value >> (sizeof(T) > 2 ? 16 : 0)) + value;
// Having 8 bit wide buckets of [0,32] now.
if (sizeof(T) > 4) value = (value >> (sizeof(T) > 4 ? 32 : 0)) + value;
// Having 8 bit wide buckets of [0,64] now.
return static_cast<unsigned>(value & 0xff);
#endif
}
// ReverseBits(value) returns |value| in reverse bit order.
template <typename T>
T ReverseBits(T value) {
DCHECK((sizeof(value) == 1) || (sizeof(value) == 2) || (sizeof(value) == 4) ||
(sizeof(value) == 8));
STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
(sizeof(value) == 4) || (sizeof(value) == 8));
T result = 0;
for (unsigned i = 0; i < (sizeof(value) * 8); i++) {
result = (result << 1) | (value & 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment