diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -153,6 +153,12 @@ - ... +X86 Support in Clang +-------------------- + +- The x86 intrinsics ``_mm_popcnt_u32`` and ``_mm_popcnt_u64`` may now be used + within constexpr expressions. + Internal API Changes -------------------- diff --git a/clang/lib/Headers/popcntintrin.h b/clang/lib/Headers/popcntintrin.h --- a/clang/lib/Headers/popcntintrin.h +++ b/clang/lib/Headers/popcntintrin.h @@ -13,6 +13,12 @@ /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("popcnt"))) +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr +#else +#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS +#endif + /// Counts the number of bits in the source operand having a value of 1. /// /// \headerfile @@ -23,7 +29,7 @@ /// An unsigned 32-bit integer operand. /// \returns A 32-bit integer containing the number of bits with value 1 in the /// source operand. -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR _mm_popcnt_u32(unsigned int __A) { return __builtin_popcount(__A); @@ -40,7 +46,7 @@ /// An unsigned 64-bit integer operand. /// \returns A 64-bit integer containing the number of bits with value 1 in the /// source operand. -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS_CONSTEXPR _mm_popcnt_u64(unsigned long long __A) { return __builtin_popcountll(__A); @@ -48,5 +54,6 @@ #endif /* __x86_64__ */ #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS_CONSTEXPR #endif /* __POPCNTINTRIN_H */ diff --git a/clang/test/CodeGen/popcnt-builtins.c b/clang/test/CodeGen/popcnt-builtins.c --- a/clang/test/CodeGen/popcnt-builtins.c +++ b/clang/test/CodeGen/popcnt-builtins.c @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT -// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s - +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s #include @@ -39,3 +40,16 @@ return __popcntq(__X); } #endif + +// Test constexpr handling. +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#if defined(__POPCNT__) +char ctpop32_0[_mm_popcnt_u32(0x00000000) == 0 ? 1 : -1]; +char ctpop32_1[_mm_popcnt_u32(0x000000F0) == 4 ? 1 : -1]; + +#ifdef __x86_64__ +char ctpop64_0[_mm_popcnt_u64(0x0000000000000000ULL) == 0 ? 1 : -1]; +char ctpop64_1[_mm_popcnt_u64(0xF000000000000001ULL) == 5 ? 1 : -1]; +#endif +#endif +#endif