Move TZCNT and BSR intrinsics to platform.h, add MSVC versions (#636)

This commit is contained in:
Clinton Ingram 2020-03-19 03:57:56 -07:00 committed by GitHub
parent 0503d8b766
commit 924b2b2b9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 7 deletions

View File

@ -41,6 +41,10 @@
#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN #define BROTLI_X_BIG_ENDIAN BIG_ENDIAN
#endif #endif
#if BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
#include <intrin.h>
#endif
#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG) #if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG)
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
@ -522,6 +526,36 @@ BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)
(A)[(J)] = __brotli_swap_tmp; \ (A)[(J)] = __brotli_swap_tmp; \
} }
#if BROTLI_64_BITS
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
#define BROTLI_TZCNT64 __builtin_ctzll
#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
#if defined(BROTLI_TARGET_X64)
#define BROTLI_TZCNT64 _tzcnt_u64
#else /* BROTLI_TARGET_X64 */
static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {
uint32_t lsb;
_BitScanForward64(&lsb, x);
return lsb;
}
#define BROTLI_TZCNT64 BrotliBsf64Msvc
#endif /* BROTLI_TARGET_X64 */
#endif /* __builtin_ctzll */
#endif /* BROTLI_64_BITS */
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x))
#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
static BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) {
uint32_t msb;
_BitScanReverse(&msb, x);
return msb;
}
#define BROTLI_BSR32 BrotliBsr32Msvc
#endif /* __builtin_clz */
/* Default brotli_alloc_func */ /* Default brotli_alloc_func */
static void* BrotliDefaultAllocFunc(void* opaque, size_t size) { static void* BrotliDefaultAllocFunc(void* opaque, size_t size) {
BROTLI_UNUSED(opaque); BROTLI_UNUSED(opaque);

View File

@ -19,10 +19,8 @@ extern "C" {
#endif #endif
static BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) { static BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) {
/* TODO: generalize and move to platform.h */ #if defined(BROTLI_BSR32)
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \ return BROTLI_BSR32((uint32_t)n);
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
return 31u ^ (uint32_t)__builtin_clz((uint32_t)n);
#else #else
uint32_t result = 0; uint32_t result = 0;
while (n >>= 1) result++; while (n >>= 1) result++;

View File

@ -17,8 +17,7 @@ extern "C" {
#endif #endif
/* Separate implementation for little-endian 64-bit targets, for speed. */ /* Separate implementation for little-endian 64-bit targets, for speed. */
#if defined(__GNUC__) && defined(_LP64) && defined(BROTLI_LITTLE_ENDIAN) #if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN
static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1, static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
const uint8_t* s2, const uint8_t* s2,
size_t limit) { size_t limit) {
@ -32,7 +31,7 @@ static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
} else { } else {
uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^ uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^
BROTLI_UNALIGNED_LOAD64LE(s1 + matched); BROTLI_UNALIGNED_LOAD64LE(s1 + matched);
size_t matching_bits = (size_t)__builtin_ctzll(x); size_t matching_bits = (size_t)BROTLI_TZCNT64(x);
matched += matching_bits >> 3; matched += matching_bits >> 3;
return matched; return matched;
} }