]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
tuklib_integer: Use __builtin_clz() with Clang.
authorJia Tan <jiat0218@gmail.com>
Wed, 19 Apr 2023 13:59:03 +0000 (21:59 +0800)
committerLasse Collin <lasse.collin@tukaani.org>
Wed, 3 May 2023 19:33:10 +0000 (22:33 +0300)
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.

src/common/tuklib_integer.h

index 6f44a7a0ac22413fbe0d5fd4c4b7f94550a0adc4..bfb8683b8c5f386427163a16e41d12c005666c7b 100644 (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;