Index: lib/Headers/x86intrin.h =================================================================== --- lib/Headers/x86intrin.h +++ lib/Headers/x86intrin.h @@ -34,6 +34,25 @@ #if !defined(_MSC_VER) || __has_feature(modules) || defined(__BMI__) #include +#else +/* The TZCNT is special in that it's encoded in a backward-compatible way and + * behaves as BSF on non-BMI targets, hence some compilers provide it even + * if the target doesn't support BMI instructions. LLVM won't emit the TZCNT + * instruction if BMI isn't available, but to not break code assuming + * unconditional availability of the tzcnt instruction, provide the intrinsic + * here (with a BMI-independent implementation). */ +#define _tzcnt_u16(a) (__tzcnt_u16((a))) +#define _tzcnt_u32(a) (__tzcnt_u32((a))) +static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__)) +__tzcnt_u16(unsigned short __X) { return __X ? __builtin_ctzs(__X) : 16; } +static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__)) +__tzcnt_u32(unsigned int __X) { return __X ? __builtin_ctz(__X) : 32; } +#ifdef __x86_64__ +#define _tzcnt_u64(a) (__tzcnt_u64((a))) +static __inline__ unsigned long long +__attribute__((__always_inline__, __nodebug__)) +__tzcnt_u64(unsigned long long __X) { return __X ? __builtin_ctzll(__X) : 64; } +#endif /* __x86_64__ */ #endif #if !defined(_MSC_VER) || __has_feature(modules) || defined(__BMI2__) Index: test/Headers/tzcnt.c =================================================================== --- test/Headers/tzcnt.c +++ test/Headers/tzcnt.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple i386-pc-win32 -target-cpu broadwell \ +// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -ffreestanding -emit-obj -o /dev/null -Werror \ +// RUN: -isystem %S/Inputs/include %s + +// RUN: %clang_cc1 -triple x86_64-pc-win32 \ +// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -ffreestanding -emit-obj -o /dev/null -Werror \ +// RUN: -isystem %S/Inputs/include %s +// +// REQUIRES: x86-registered-target + +typedef __SIZE_TYPE__ size_t; +#include + +void f() { + // Check that _tzcnt is available even without BMI; ffmpeg relies on this. + __tzcnt_u16(0); + __tzcnt_u32(0); +#ifdef __x86_64__ + __tzcnt_u64(0); +#endif +}