| Index: src/compiler-intrinsics.h
|
| diff --git a/src/compiler-intrinsics.h b/src/compiler-intrinsics.h
|
| index b73e8ac750d0747b95693c8481b1592c65bd03c5..82973a21ebfeb5c3bda81515ed6b161a27ef1f42 100644
|
| --- a/src/compiler-intrinsics.h
|
| +++ b/src/compiler-intrinsics.h
|
| @@ -28,21 +28,36 @@
|
| #ifndef V8_COMPILER_INTRINSICS_H_
|
| #define V8_COMPILER_INTRINSICS_H_
|
|
|
| +#include "globals.h"
|
| +#include "checks.h"
|
| +
|
| +
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +// C++ fallback implementations when builtins are not availble.
|
| +int C_CountRedundantLeadingSignBits(int64_t value, int width);
|
| +int C_CountSetBits(uint64_t value, int width);
|
| +
|
| class CompilerIntrinsics {
|
| public:
|
| // Returns number of zero bits preceding least significant 1 bit.
|
| // Undefined for zero value.
|
| INLINE(static int CountTrailingZeros(uint32_t value));
|
| + INLINE(static int CountTrailingZeros(uint64_t value));
|
|
|
| // Returns number of zero bits following most significant 1 bit.
|
| // Undefined for zero value.
|
| INLINE(static int CountLeadingZeros(uint32_t value));
|
| + INLINE(static int CountLeadingZeros(uint64_t value));
|
| +
|
| + // Returns the number of redundant leading sign bits.
|
| + INLINE(static int CountRedundantLeadingSignBits(int32_t value));
|
| + INLINE(static int CountRedundantLeadingSignBits(int64_t value));
|
|
|
| // Returns the number of bits set.
|
| INLINE(static int CountSetBits(uint32_t value));
|
| + INLINE(static int CountSetBits(uint64_t value));
|
| };
|
|
|
| #ifdef __GNUC__
|
| @@ -50,18 +65,53 @@ int CompilerIntrinsics::CountTrailingZeros(uint32_t value) {
|
| return __builtin_ctz(value);
|
| }
|
|
|
| +int CompilerIntrinsics::CountTrailingZeros(uint64_t value) {
|
| + return __builtin_ctzll(value);
|
| +}
|
| +
|
| int CompilerIntrinsics::CountLeadingZeros(uint32_t value) {
|
| return __builtin_clz(value);
|
| }
|
|
|
| +int CompilerIntrinsics::CountLeadingZeros(uint64_t value) {
|
| + return __builtin_clzll(value);
|
| +}
|
| +
|
| +// __builtin_clrsb and derivatives are only availble since GCC4.7.0.
|
| +#define GNUC_AVAILABLE_BUILTIN_CLRSB ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7))
|
| +int CompilerIntrinsics::CountRedundantLeadingSignBits(int32_t value) {
|
| +#if GNUC_AVAILABLE_BUILTIN_CLRSB
|
| + return __builtin_clrsb(value);
|
| +#else
|
| + return C_CountRedundantLeadingSignBits(value, 32);
|
| +#endif
|
| +}
|
| +
|
| +int CompilerIntrinsics::CountRedundantLeadingSignBits(int64_t value) {
|
| +#if GNUC_AVAILABLE_BUILTIN_CLRSB
|
| + return __builtin_clrsbll(value);
|
| +#else
|
| + return C_CountRedundantLeadingSignBits(value, 64);
|
| +#endif
|
| +}
|
| +#undef GNUC_AVAILABLE_BUILTIN_CLRSB
|
| +
|
| int CompilerIntrinsics::CountSetBits(uint32_t value) {
|
| return __builtin_popcount(value);
|
| }
|
|
|
| +int CompilerIntrinsics::CountSetBits(uint64_t value) {
|
| + return __builtin_popcountll(value);
|
| +}
|
| +
|
| #elif defined(_MSC_VER)
|
|
|
| #pragma intrinsic(_BitScanForward)
|
| #pragma intrinsic(_BitScanReverse)
|
| +#if V8_TARGET_ARCH_X64
|
| +#pragma intrinsic(_BitScanForward64)
|
| +#pragma intrinsic(_BitScanReverse64)
|
| +#endif
|
|
|
| int CompilerIntrinsics::CountTrailingZeros(uint32_t value) {
|
| unsigned long result; //NOLINT
|
| @@ -69,26 +119,147 @@ int CompilerIntrinsics::CountTrailingZeros(uint32_t value) {
|
| return static_cast<int>(result);
|
| }
|
|
|
| +int CompilerIntrinsics::CountTrailingZeros(uint64_t value) {
|
| +#if V8_TARGET_ARCH_X64
|
| + unsigned long result; //NOLINT
|
| + _BitScanForward64(&result, static_cast<__int64>(value)); //NOLINT
|
| + return static_cast<int>(result);
|
| +#else
|
| + uint32_t low = value & kMaxUInt32;
|
| + uint32_t high = value >> 32;
|
| + if (low == 0) {
|
| + return 32 + CountTrailingZeros(high);
|
| + } else {
|
| + return CountTrailingZeros(low);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| int CompilerIntrinsics::CountLeadingZeros(uint32_t value) {
|
| unsigned long result; //NOLINT
|
| _BitScanReverse(&result, static_cast<long>(value)); //NOLINT
|
| return 31 - static_cast<int>(result);
|
| }
|
|
|
| +int CompilerIntrinsics::CountLeadingZeros(uint64_t value) {
|
| +#if V8_TARGET_ARCH_X64
|
| + unsigned long result; //NOLINT
|
| + _BitScanReverse64(&result, static_cast<__int64>(value)); //NOLINT
|
| + return 63 - static_cast<int>(result);
|
| +#else
|
| + uint32_t low = value & kMaxUInt32;
|
| + uint32_t high = value >> 32;
|
| + if (high == 0) {
|
| + return 32 + CountLeadingZeros(low);
|
| + } else {
|
| + return CountLeadingZeros(high);
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +int CompilerIntrinsics::CountRedundantLeadingSignBits(int32_t value) {
|
| + uint32_t val = static_cast<uint32_t>((value >= 0) ? value : ~value);
|
| + return CountLeadingZeros(val, width) - 1;
|
| +}
|
| +
|
| +int CompilerIntrinsics::CountRedundantLeadingSignBits(int64_t value) {
|
| + uint64_t val = static_cast<uint64_t>((value >= 0) ? value : ~value);
|
| + return CountLeadingZeros(val, width) - 1;
|
| +}
|
| +
|
| int CompilerIntrinsics::CountSetBits(uint32_t value) {
|
| - // Manually count set bits.
|
| - value = ((value >> 1) & 0x55555555) + (value & 0x55555555);
|
| - value = ((value >> 2) & 0x33333333) + (value & 0x33333333);
|
| - value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
|
| - value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
|
| - value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
|
| - return value;
|
| + return C_CountSetBits(value, 32);
|
| +}
|
| +
|
| +int CompilerIntrinsics::CountSetBits(uint64_t value) {
|
| + return C_CountSetBits(value, 64);
|
| }
|
|
|
| #else
|
| #error Unsupported compiler
|
| #endif
|
|
|
| +
|
| +// Inline function helpers use the intrinsics and disambiguate undefined
|
| +// situations.
|
| +
|
| +inline int CountTrailingZeros(uint32_t value) {
|
| + if (value == 0) {
|
| + // The result of the intrinsics is undefined for 0.
|
| + return 32;
|
| + }
|
| + return CompilerIntrinsics::CountTrailingZeros(value);
|
| +}
|
| +inline int CountTrailingZeros(uint64_t value) {
|
| + if (value == 0) {
|
| + // The result of the intrinsics is undefined for 0.
|
| + return 64;
|
| + }
|
| + return CompilerIntrinsics::CountTrailingZeros(value);
|
| +}
|
| +inline int CountTrailingZeros(uint64_t value, int width) {
|
| + ASSERT((width == 32) || (width == 64));
|
| + if (width == 32) {
|
| + return CountTrailingZeros(static_cast<uint32_t>(value));
|
| + } else {
|
| + return CountTrailingZeros(static_cast<uint64_t>(value));
|
| + }
|
| +}
|
| +
|
| +inline int CountLeadingZeros(uint32_t value) {
|
| + if (value == 0) {
|
| + // The result of the intrinsics is undefined for 0.
|
| + return 32;
|
| + }
|
| + return CompilerIntrinsics::CountLeadingZeros(value);
|
| +}
|
| +inline int CountLeadingZeros(uint64_t value) {
|
| + if (value == 0) {
|
| + // The result of the intrinsics is undefined for 0.
|
| + return 64;
|
| + }
|
| + return CompilerIntrinsics::CountLeadingZeros(value);
|
| +}
|
| +inline int CountLeadingZeros(uint64_t value, int width) {
|
| + ASSERT((width == 32) || (width == 64));
|
| + if (width == 32) {
|
| + return CountLeadingZeros(static_cast<uint32_t>(value));
|
| + } else {
|
| + return CountLeadingZeros(static_cast<uint64_t>(value));
|
| + }
|
| +}
|
| +
|
| +inline int CountRedundantLeadingSignBits(int32_t value) {
|
| + return CompilerIntrinsics::CountRedundantLeadingSignBits(value);
|
| +}
|
| +inline int CountRedundantLeadingSignBits(int64_t value) {
|
| + return CompilerIntrinsics::CountRedundantLeadingSignBits(value);
|
| +}
|
| +inline int CountRedundantLeadingSignBits(int64_t value, int width) {
|
| + ASSERT((width == 32) || (width == 64));
|
| + if (width == 32) {
|
| + return CountRedundantLeadingSignBits(static_cast<int32_t>(value));
|
| + } else {
|
| + return CountRedundantLeadingSignBits(static_cast<int64_t>(value));
|
| + }
|
| +}
|
| +
|
| +inline int CountSetBits(uint32_t value) {
|
| + return CompilerIntrinsics::CountSetBits(value);
|
| +}
|
| +inline int CountSetBits(uint64_t value) {
|
| + return CompilerIntrinsics::CountSetBits(value);
|
| +}
|
| +inline int CountSetBits(uint64_t value, int width) {
|
| + ASSERT((width == 32) || (width == 64));
|
| + if (width == 32) {
|
| + return CountSetBits(static_cast<uint32_t>(value));
|
| + } else {
|
| + return CountSetBits(static_cast<uint64_t>(value));
|
| + }
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|
| #endif // V8_COMPILER_INTRINSICS_H_
|
|
|