1
0
Fork 0
mirror of https://git.tukaani.org/xz.git synced 2024-04-04 12:36:23 +02:00

tuklib_integer: Use __builtin_clz() with Clang.

Clang has support for __builtin_clz(), but previously Clang would
fallback to either the MSVC intrinsic or the regular C code. This was
discovered due to a bug where a new version of Clang required the
<intrin.h> header file in order to use the MSVC intrinsics.

Thanks to Anton Kochkov for notifying us about the bug.
This commit is contained in:
Jia Tan 2023-04-19 21:59:03 +08:00 committed by Lasse Collin
parent 3bd906f1f3
commit 8efb6ea63b

View file

@ -588,7 +588,7 @@ bsr32(uint32_t n)
#if defined(__INTEL_COMPILER)
return _bit_scan_reverse(n);
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX == UINT32_MAX
// GCC >= 3.4 has __builtin_clz(), which gives good results on
// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
// either plain BSR (so the XOR gets optimized away) or LZCNT and
@ -642,7 +642,7 @@ clz32(uint32_t n)
#if defined(__INTEL_COMPILER)
return _bit_scan_reverse(n) ^ 31U;
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX == UINT32_MAX
return (uint32_t)__builtin_clz(n);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
@ -697,7 +697,7 @@ ctz32(uint32_t n)
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
return (uint32_t)__builtin_ctz(n);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX == UINT32_MAX
uint32_t i;
__asm__("bsfl %1, %0" : "=r" (i) : "rm" (n));
return i;