1 #ifndef X86_BUILTIN_CTZ_H
2 #define X86_BUILTIN_CTZ_H
3 
4 #if defined(_MSC_VER) && !defined(__clang__)
5 #if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) ||  defined(_M_ARM) || defined(_M_ARM64)
6 
7 #include <intrin.h>
8 #ifdef X86_FEATURES
9 #  include "arch/x86/x86.h"
10 #endif
11 
12 /* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0
13  * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked
14  */
__builtin_ctz(uint32_t value)15 static __forceinline unsigned long __builtin_ctz(uint32_t value) {
16 #ifdef X86_FEATURES
17     if (x86_cpu_has_tzcnt)
18         return _tzcnt_u32(value);
19 #endif
20     unsigned long trailing_zero;
21     _BitScanForward(&trailing_zero, value);
22     return trailing_zero;
23 }
24 #define HAVE_BUILTIN_CTZ
25 
26 #ifdef _M_AMD64
27 /* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0
28  * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward64 is not checked
29  */
__builtin_ctzll(uint64_t value)30 static __forceinline unsigned long long __builtin_ctzll(uint64_t value) {
31 #ifdef X86_FEATURES
32     if (x86_cpu_has_tzcnt)
33         return _tzcnt_u64(value);
34 #endif
35     unsigned long trailing_zero;
36     _BitScanForward64(&trailing_zero, value);
37     return trailing_zero;
38 }
39 #define HAVE_BUILTIN_CTZLL
40 #endif
41 
42 #endif
43 #endif
44 #endif
45