[X86] Enable constexpr on POPCNT intrinsics (PR31446)

This is a first step patch to enable constexpr support and testing to a large number of x86 intrinsics.

All I've done here is provide a DEFAULT_FN_ATTRS_CONSTEXPR variant to our existing DEFAULT_FN_ATTRS tag approach that adds constexpr on c++ builds. The clang cuda headers do something similar.

I've started with POPCNT mainly as its tiny and are wrappers to generic __builtin_* intrinsics which already act as constexpr.

Differential Revision: https://reviews.llvm.org/D86229
This commit is contained in:
Simon Pilgrim 2020-08-20 21:37:51 +01:00
parent 79ce9bb380
commit cff0db0876
3 changed files with 32 additions and 5 deletions

View File

@ -153,6 +153,12 @@ CUDA Support in Clang
- ...
X86 Support in Clang
--------------------
- The x86 intrinsics ``_mm_popcnt_u32`` and ``_mm_popcnt_u64`` may now be used
within constexpr expressions.
Internal API Changes
--------------------

View File

@ -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 <x86intrin.h>
@ -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 @@ _mm_popcnt_u32(unsigned int __A)
/// 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 @@ _mm_popcnt_u64(unsigned long long __A)
#endif /* __x86_64__ */
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
#endif /* __POPCNTINTRIN_H */

View File

@ -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 <x86intrin.h>
@ -39,3 +40,16 @@ long long test__popcntq(unsigned long long __X) {
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