diff --git a/clang/lib/Headers/ia32intrin.h b/clang/lib/Headers/ia32intrin.h --- a/clang/lib/Headers/ia32intrin.h +++ b/clang/lib/Headers/ia32intrin.h @@ -413,6 +413,58 @@ #ifndef _MSC_VER /* These are already provided as builtins for MSVC. */ +#define _BitScanForward(a, b) \ + __extension__({ \ + int c = (int)(b); \ + unsigned char d; \ + if (c != 0) { \ + *(a) = (unsigned)__bsfd(c); \ + d = 1; \ + } else { \ + d = 0; \ + } \ + d; \ + }) +#define _BitScanReverse(a, b) \ + __extension__({ \ + int c = (int)(b); \ + unsigned char d; \ + if (c != 0) { \ + *(a) = (unsigned)__bsrd(c); \ + d = 1; \ + } else { \ + d = 0; \ + } \ + d; \ + }) + +#ifdef __x86_64__ +#define _BitScanForward64(a, b) \ + __extension__({ \ + long long c = (long long)(b); \ + unsigned char d; \ + if (c != 0) { \ + *(a) = (unsigned)__bsfq(c); \ + d = 1; \ + } else { \ + d = 0; \ + } \ + d; \ + }) +#define _BitScanReverse64(a, b) \ + __extension__({ \ + long long c = (long long)(b); \ + unsigned char d; \ + if (c != 0) { \ + *(a) = (unsigned)__bsrq(c); \ + d = 1; \ + } else { \ + d = 0; \ + } \ + d; \ + }) +#endif /* __x86_64__ */ + /* Select the correct function based on the size of long. */ #ifdef __LP64__ #define _lrotl(a,b) __rolq((a), (b)) diff --git a/clang/test/CodeGen/bitscan-builtins.c b/clang/test/CodeGen/bitscan-builtins.c --- a/clang/test/CodeGen/bitscan-builtins.c +++ b/clang/test/CodeGen/bitscan-builtins.c @@ -5,6 +5,32 @@ #include +unsigned char test_BitScanForward(unsigned *index, unsigned mask) { + return _BitScanForward(index, mask); + // CHECK: @test_BitScanForward + // CHECK: %{{.*}} = call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true) +} + +unsigned char test_BitScanReverse(unsigned *index, unsigned mask) { + return _BitScanReverse(index, mask); + // CHECK: @test_BitScanReverse + // CHECK: %[[call:.*]] = call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true) + // CHECK: %{{.*}} = sub nsw i32 31, %[[call]] +} + +unsigned char test_BitScanForward64(unsigned *index, unsigned long long mask) { + return _BitScanForward64(index, mask); + // CHECK: @test_BitScanForward64 + // CHECK: %{{.*}} = call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 true) +} + +unsigned char test_BitScanReverse64(unsigned *index, unsigned long long mask) { + return _BitScanReverse64(index, mask); + // CHECK: @test_BitScanReverse64 + // CHECK: %{{.*}} = call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 true) + // CHECK: %{{.*}} = sub nsw i32 63, %{{.*}} +} + int test_bit_scan_forward(int a) { return _bit_scan_forward(a); // CHECK: @test_bit_scan_forward