1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef V8_BASE_BITS_H_ 6#define V8_BASE_BITS_H_ 7 8#include <stdint.h> 9#include <type_traits> 10 11#include "src/base/base-export.h" 12#include "src/base/macros.h" 13#if V8_CC_MSVC 14#include <intrin.h> 15#endif 16#if V8_OS_WIN32 17#include "src/base/win32-headers.h" 18#endif 19 20namespace v8 { 21namespace base { 22namespace bits { 23 24// CountPopulation(value) returns the number of bits set in |value|. 25template <typename T> 26constexpr inline 27 typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8, 28 unsigned>::type 29 CountPopulation(T value) { 30 STATIC_ASSERT(sizeof(T) <= 8); 31#if V8_HAS_BUILTIN_POPCOUNT 32 return sizeof(T) == 8 ? __builtin_popcountll(static_cast<uint64_t>(value)) 33 : __builtin_popcount(static_cast<uint32_t>(value)); 34#else 35 // Fall back to divide-and-conquer popcount (see "Hacker's Delight" by Henry 36 // S. Warren, Jr.), chapter 5-1. 37 constexpr uint64_t mask[] = {0x5555555555555555, 0x3333333333333333, 38 0x0f0f0f0f0f0f0f0f}; 39 // Start with 64 buckets of 1 bits, holding values from [0,1]. 40 value = ((value >> 1) & mask[0]) + (value & mask[0]); 41 // Having 32 buckets of 2 bits, holding values from [0,2] now. 42 value = ((value >> 2) & mask[1]) + (value & mask[1]); 43 // Having 16 buckets of 4 bits, holding values from [0,4] now. 44 value = ((value >> 4) & mask[2]) + (value & mask[2]); 45 // Having 8 buckets of 8 bits, holding values from [0,8] now. 46 // From this point on, the buckets are bigger than the number of bits 47 // required to hold the values, and the buckets are bigger the maximum 48 // result, so there's no need to mask value anymore, since there's no 49 // more risk of overflow between buckets. 50 if (sizeof(T) > 1) value = (value >> (sizeof(T) > 1 ? 8 : 0)) + value; 51 // Having 4 buckets of 16 bits, holding values from [0,16] now. 52 if (sizeof(T) > 2) value = (value >> (sizeof(T) > 2 ? 16 : 0)) + value; 53 // Having 2 buckets of 32 bits, holding values from [0,32] now. 54 if (sizeof(T) > 4) value = (value >> (sizeof(T) > 4 ? 32 : 0)) + value; 55 // Having 1 buckets of 64 bits, holding values from [0,64] now. 56 return static_cast<unsigned>(value & 0xff); 57#endif 58} 59 60// ReverseBits(value) returns |value| in reverse bit order. 61template <typename T> 62T ReverseBits(T value) { 63 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 64 (sizeof(value) == 4) || (sizeof(value) == 8)); 65 T result = 0; 66 for (unsigned i = 0; i < (sizeof(value) * 8); i++) { 67 result = (result << 1) | (value & 1); 68 value >>= 1; 69 } 70 return result; 71} 72 73// CountLeadingZeros(value) returns the number of zero bits following the most 74// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 75// {sizeof(T) * 8}. 76template <typename T, unsigned bits = sizeof(T) * 8> 77inline constexpr 78 typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8, 79 unsigned>::type 80 CountLeadingZeros(T value) { 81 static_assert(bits > 0, "invalid instantiation"); 82#if V8_HAS_BUILTIN_CLZ 83 return value == 0 84 ? bits 85 : bits == 64 86 ? __builtin_clzll(static_cast<uint64_t>(value)) 87 : __builtin_clz(static_cast<uint32_t>(value)) - (32 - bits); 88#else 89 // Binary search algorithm taken from "Hacker's Delight" (by Henry S. Warren, 90 // Jr.), figures 5-11 and 5-12. 91 if (bits == 1) return static_cast<unsigned>(value) ^ 1; 92 T upper_half = value >> (bits / 2); 93 T next_value = upper_half != 0 ? upper_half : value; 94 unsigned add = upper_half != 0 ? 0 : bits / 2; 95 constexpr unsigned next_bits = bits == 1 ? 1 : bits / 2; 96 return CountLeadingZeros<T, next_bits>(next_value) + add; 97#endif 98} 99 100inline constexpr unsigned CountLeadingZeros32(uint32_t value) { 101 return CountLeadingZeros(value); 102} 103inline constexpr unsigned CountLeadingZeros64(uint64_t value) { 104 return CountLeadingZeros(value); 105} 106 107// CountTrailingZeros(value) returns the number of zero bits preceding the 108// least significant 1 bit in |value| if |value| is non-zero, otherwise it 109// returns {sizeof(T) * 8}. 110// See CountTrailingZerosNonZero for an optimized version for the case that 111// |value| is guaranteed to be non-zero. 112template <typename T, unsigned bits = sizeof(T) * 8> 113inline constexpr 114 typename std::enable_if<std::is_integral<T>::value && sizeof(T) <= 8, 115 unsigned>::type 116 CountTrailingZeros(T value) { 117#if V8_HAS_BUILTIN_CTZ 118 return value == 0 ? bits 119 : bits == 64 ? __builtin_ctzll(static_cast<uint64_t>(value)) 120 : __builtin_ctz(static_cast<uint32_t>(value)); 121#else 122 // Fall back to popcount (see "Hacker's Delight" by Henry S. Warren, Jr.), 123 // chapter 5-4. On x64, since is faster than counting in a loop and faster 124 // than doing binary search. 125 using U = typename std::make_unsigned<T>::type; 126 U u = value; 127 return CountPopulation(static_cast<U>(~u & (u - 1u))); 128#endif 129} 130 131inline constexpr unsigned CountTrailingZeros32(uint32_t value) { 132 return CountTrailingZeros(value); 133} 134inline constexpr unsigned CountTrailingZeros64(uint64_t value) { 135 return CountTrailingZeros(value); 136} 137 138// CountTrailingZerosNonZero(value) returns the number of zero bits preceding 139// the least significant 1 bit in |value| if |value| is non-zero, otherwise the 140// behavior is undefined. 141// See CountTrailingZeros for an alternative version that allows |value| == 0. 142template <typename T, unsigned bits = sizeof(T) * 8> 143inline constexpr 144 typename std::enable_if<std::is_integral<T>::value && sizeof(T) <= 8, 145 unsigned>::type 146 CountTrailingZerosNonZero(T value) { 147 DCHECK_NE(0, value); 148#if V8_HAS_BUILTIN_CTZ 149 return bits == 64 ? __builtin_ctzll(static_cast<uint64_t>(value)) 150 : __builtin_ctz(static_cast<uint32_t>(value)); 151#else 152 return CountTrailingZeros<T, bits>(value); 153#endif 154} 155 156// Returns true iff |value| is a power of 2. 157template <typename T, 158 typename = typename std::enable_if<std::is_integral<T>::value || 159 std::is_enum<T>::value>::type> 160constexpr inline bool IsPowerOfTwo(T value) { 161 return value > 0 && (value & (value - 1)) == 0; 162} 163 164// Identical to {CountTrailingZeros}, but only works for powers of 2. 165template <typename T, 166 typename = typename std::enable_if<std::is_integral<T>::value>::type> 167inline constexpr int WhichPowerOfTwo(T value) { 168 DCHECK(IsPowerOfTwo(value)); 169#if V8_HAS_BUILTIN_CTZ 170 STATIC_ASSERT(sizeof(T) <= 8); 171 return sizeof(T) == 8 ? __builtin_ctzll(static_cast<uint64_t>(value)) 172 : __builtin_ctz(static_cast<uint32_t>(value)); 173#else 174 // Fall back to popcount (see "Hacker's Delight" by Henry S. Warren, Jr.), 175 // chapter 5-4. On x64, since is faster than counting in a loop and faster 176 // than doing binary search. 177 using U = typename std::make_unsigned<T>::type; 178 U u = value; 179 return CountPopulation(static_cast<U>(u - 1)); 180#endif 181} 182 183// RoundUpToPowerOfTwo32(value) returns the smallest power of two which is 184// greater than or equal to |value|. If you pass in a |value| that is already a 185// power of two, it is returned as is. |value| must be less than or equal to 186// 0x80000000u. Uses computation based on leading zeros if we have compiler 187// support for that. Falls back to the implementation from "Hacker's Delight" by 188// Henry S. Warren, Jr., figure 3-3, page 48, where the function is called clp2. 189V8_BASE_EXPORT uint32_t RoundUpToPowerOfTwo32(uint32_t value); 190// Same for 64 bit integers. |value| must be <= 2^63 191V8_BASE_EXPORT uint64_t RoundUpToPowerOfTwo64(uint64_t value); 192// Same for size_t integers. 193inline size_t RoundUpToPowerOfTwo(size_t value) { 194 if (sizeof(size_t) == sizeof(uint64_t)) { 195 return RoundUpToPowerOfTwo64(value); 196 } else { 197 // Without windows.h included this line triggers a truncation warning on 198 // 64-bit builds. Presumably windows.h disables the relevant warning. 199 return RoundUpToPowerOfTwo32(static_cast<uint32_t>(value)); 200 } 201} 202 203// RoundDownToPowerOfTwo32(value) returns the greatest power of two which is 204// less than or equal to |value|. If you pass in a |value| that is already a 205// power of two, it is returned as is. 206inline uint32_t RoundDownToPowerOfTwo32(uint32_t value) { 207 if (value > 0x80000000u) return 0x80000000u; 208 uint32_t result = RoundUpToPowerOfTwo32(value); 209 if (result > value) result >>= 1; 210 return result; 211} 212 213 214// Precondition: 0 <= shift < 32 215inline constexpr uint32_t RotateRight32(uint32_t value, uint32_t shift) { 216 return (value >> shift) | (value << ((32 - shift) & 31)); 217} 218 219// Precondition: 0 <= shift < 32 220inline constexpr uint32_t RotateLeft32(uint32_t value, uint32_t shift) { 221 return (value << shift) | (value >> ((32 - shift) & 31)); 222} 223 224// Precondition: 0 <= shift < 64 225inline constexpr uint64_t RotateRight64(uint64_t value, uint64_t shift) { 226 return (value >> shift) | (value << ((64 - shift) & 63)); 227} 228 229// Precondition: 0 <= shift < 64 230inline constexpr uint64_t RotateLeft64(uint64_t value, uint64_t shift) { 231 return (value << shift) | (value >> ((64 - shift) & 63)); 232} 233 234// SignedAddOverflow32(lhs,rhs,val) performs a signed summation of |lhs| and 235// |rhs| and stores the result into the variable pointed to by |val| and 236// returns true if the signed summation resulted in an overflow. 237inline bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 238#if V8_HAS_BUILTIN_SADD_OVERFLOW 239 return __builtin_sadd_overflow(lhs, rhs, val); 240#else 241 uint32_t res = static_cast<uint32_t>(lhs) + static_cast<uint32_t>(rhs); 242 *val = bit_cast<int32_t>(res); 243 return ((res ^ lhs) & (res ^ rhs) & (1U << 31)) != 0; 244#endif 245} 246 247 248// SignedSubOverflow32(lhs,rhs,val) performs a signed subtraction of |lhs| and 249// |rhs| and stores the result into the variable pointed to by |val| and 250// returns true if the signed subtraction resulted in an overflow. 251inline bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 252#if V8_HAS_BUILTIN_SSUB_OVERFLOW 253 return __builtin_ssub_overflow(lhs, rhs, val); 254#else 255 uint32_t res = static_cast<uint32_t>(lhs) - static_cast<uint32_t>(rhs); 256 *val = bit_cast<int32_t>(res); 257 return ((res ^ lhs) & (res ^ ~rhs) & (1U << 31)) != 0; 258#endif 259} 260 261// SignedMulOverflow32(lhs,rhs,val) performs a signed multiplication of |lhs| 262// and |rhs| and stores the result into the variable pointed to by |val| and 263// returns true if the signed multiplication resulted in an overflow. 264V8_BASE_EXPORT bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val); 265 266// SignedAddOverflow64(lhs,rhs,val) performs a signed summation of |lhs| and 267// |rhs| and stores the result into the variable pointed to by |val| and 268// returns true if the signed summation resulted in an overflow. 269inline bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 270 uint64_t res = static_cast<uint64_t>(lhs) + static_cast<uint64_t>(rhs); 271 *val = bit_cast<int64_t>(res); 272 return ((res ^ lhs) & (res ^ rhs) & (1ULL << 63)) != 0; 273} 274 275 276// SignedSubOverflow64(lhs,rhs,val) performs a signed subtraction of |lhs| and 277// |rhs| and stores the result into the variable pointed to by |val| and 278// returns true if the signed subtraction resulted in an overflow. 279inline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 280 uint64_t res = static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs); 281 *val = bit_cast<int64_t>(res); 282 return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0; 283} 284 285// SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and 286// |rhs|, extracts the most significant 32 bits of the result, and returns 287// those. 288V8_BASE_EXPORT int32_t SignedMulHigh32(int32_t lhs, int32_t rhs); 289 290// SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values 291// |lhs| and |rhs|, extracts the most significant 32 bits of the result, and 292// adds the accumulate value |acc|. 293V8_BASE_EXPORT int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, 294 int32_t acc); 295 296// SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 297// truncated to int32. If |rhs| is zero, then zero is returned. If |lhs| 298// is minint and |rhs| is -1, it returns minint. 299V8_BASE_EXPORT int32_t SignedDiv32(int32_t lhs, int32_t rhs); 300 301// SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 302// truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs| 303// is -1, it returns zero. 304V8_BASE_EXPORT int32_t SignedMod32(int32_t lhs, int32_t rhs); 305 306// UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs| 307// and |rhs| and stores the result into the variable pointed to by |val| and 308// returns true if the unsigned summation resulted in an overflow. 309inline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) { 310#if V8_HAS_BUILTIN_SADD_OVERFLOW 311 return __builtin_uadd_overflow(lhs, rhs, val); 312#else 313 *val = lhs + rhs; 314 return *val < (lhs | rhs); 315#endif 316} 317 318 319// UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 320// truncated to uint32. If |rhs| is zero, then zero is returned. 321inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) { 322 return rhs ? lhs / rhs : 0u; 323} 324 325 326// UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 327// truncated to uint32. If |rhs| is zero, then zero is returned. 328inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) { 329 return rhs ? lhs % rhs : 0u; 330} 331 332// Wraparound integer arithmetic without undefined behavior. 333 334inline int32_t WraparoundAdd32(int32_t lhs, int32_t rhs) { 335 return static_cast<int32_t>(static_cast<uint32_t>(lhs) + 336 static_cast<uint32_t>(rhs)); 337} 338 339inline int32_t WraparoundNeg32(int32_t x) { 340 return static_cast<int32_t>(-static_cast<uint32_t>(x)); 341} 342 343// SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|, 344// checks and returns the result. 345V8_BASE_EXPORT int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs); 346 347// SignedSaturatedSub64(lhs, rhs) subtracts |lhs| by |rhs|, 348// checks and returns the result. 349V8_BASE_EXPORT int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs); 350 351} // namespace bits 352} // namespace base 353} // namespace v8 354 355#endif // V8_BASE_BITS_H_ 356