Skip to content

Commit cff0db0

Browse files
committed
[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
1 parent 79ce9bb commit cff0db0

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ CUDA Support in Clang
153153

154154
- ...
155155

156+
X86 Support in Clang
157+
--------------------
158+
159+
- The x86 intrinsics ``_mm_popcnt_u32`` and ``_mm_popcnt_u64`` may now be used
160+
within constexpr expressions.
161+
156162
Internal API Changes
157163
--------------------
158164

clang/lib/Headers/popcntintrin.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
/* Define the default attributes for the functions in this file. */
1414
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("popcnt")))
1515

16+
#if defined(__cplusplus) && (__cplusplus >= 201103L)
17+
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
18+
#else
19+
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
20+
#endif
21+
1622
/// Counts the number of bits in the source operand having a value of 1.
1723
///
1824
/// \headerfile <x86intrin.h>
@@ -23,7 +29,7 @@
2329
/// An unsigned 32-bit integer operand.
2430
/// \returns A 32-bit integer containing the number of bits with value 1 in the
2531
/// source operand.
26-
static __inline__ int __DEFAULT_FN_ATTRS
32+
static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR
2733
_mm_popcnt_u32(unsigned int __A)
2834
{
2935
return __builtin_popcount(__A);
@@ -40,13 +46,14 @@ _mm_popcnt_u32(unsigned int __A)
4046
/// An unsigned 64-bit integer operand.
4147
/// \returns A 64-bit integer containing the number of bits with value 1 in the
4248
/// source operand.
43-
static __inline__ long long __DEFAULT_FN_ATTRS
49+
static __inline__ long long __DEFAULT_FN_ATTRS_CONSTEXPR
4450
_mm_popcnt_u64(unsigned long long __A)
4551
{
4652
return __builtin_popcountll(__A);
4753
}
4854
#endif /* __x86_64__ */
4955

5056
#undef __DEFAULT_FN_ATTRS
57+
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
5158

5259
#endif /* __POPCNTINTRIN_H */

clang/test/CodeGen/popcnt-builtins.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT
2-
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
3-
1+
// 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
2+
// 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
3+
// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
4+
// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
45

56
#include <x86intrin.h>
67

@@ -39,3 +40,16 @@ long long test__popcntq(unsigned long long __X) {
3940
return __popcntq(__X);
4041
}
4142
#endif
43+
44+
// Test constexpr handling.
45+
#if defined(__cplusplus) && (__cplusplus >= 201103L)
46+
#if defined(__POPCNT__)
47+
char ctpop32_0[_mm_popcnt_u32(0x00000000) == 0 ? 1 : -1];
48+
char ctpop32_1[_mm_popcnt_u32(0x000000F0) == 4 ? 1 : -1];
49+
50+
#ifdef __x86_64__
51+
char ctpop64_0[_mm_popcnt_u64(0x0000000000000000ULL) == 0 ? 1 : -1];
52+
char ctpop64_1[_mm_popcnt_u64(0xF000000000000001ULL) == 5 ? 1 : -1];
53+
#endif
54+
#endif
55+
#endif

0 commit comments

Comments
 (0)