[clang] [X86] Enable constexpr on LZCNT & BMI intrinsics (PR #94161)

via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 2 07:31:15 PDT 2024


https://github.com/aniplcc created https://github.com/llvm/llvm-project/pull/94161

Closes  #86128.

>From ad4c0e737f3d8de3202e027646c05d916a695e30 Mon Sep 17 00:00:00 2001
From: aniplcc <aniplccode at gmail.com>
Date: Sun, 2 Jun 2024 19:47:10 +0530
Subject: [PATCH 1/2] [X86] Enable constexpr on LZCNT & BMI intrinsics

---
 clang/lib/Headers/bmiintrin.h           |  50 ++++++----
 clang/lib/Headers/lzcntintrin.h         |  13 ++-
 clang/test/CodeGen/X86/bmi-builtins.c   | 125 +++++++++++++++++++++++-
 clang/test/CodeGen/X86/lzcnt-builtins.c |  37 ++++++-
 4 files changed, 198 insertions(+), 27 deletions(-)

diff --git a/clang/lib/Headers/bmiintrin.h b/clang/lib/Headers/bmiintrin.h
index 78bffe68e221a..c5b57a1d1e43c 100644
--- a/clang/lib/Headers/bmiintrin.h
+++ b/clang/lib/Headers/bmiintrin.h
@@ -19,6 +19,11 @@
    to use it as a potentially faster version of BSF. */
 #define __RELAXED_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
 
+#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#define __RELAXED_FN_ATTRS_CONSTEXPR __RELAXED_FN_ATTRS constexpr
+#else
+#define __RELAXED_FN_ATTRS_CONSTEXPR __RELAXED_FN_ATTRS
+
 /// Counts the number of trailing zero bits in the operand.
 ///
 /// \headerfile <x86intrin.h>
@@ -30,7 +35,7 @@
 /// \returns An unsigned 16-bit integer containing the number of trailing zero
 ///    bits in the operand.
 /// \see _tzcnt_u16
-static __inline__ unsigned short __RELAXED_FN_ATTRS
+static __inline__ unsigned short __RELAXED_FN_ATTRS_CONSTEXPR
 __tzcnt_u16(unsigned short __X)
 {
   return __builtin_ia32_tzcnt_u16(__X);
@@ -64,7 +69,7 @@ __tzcnt_u16(unsigned short __X)
 /// \returns An unsigned 32-bit integer containing the number of trailing zero
 ///    bits in the operand.
 /// \see { _mm_tzcnt_32 _tzcnt_u32 }
-static __inline__ unsigned int __RELAXED_FN_ATTRS
+static __inline__ unsigned int __RELAXED_FN_ATTRS_CONSTEXPR
 __tzcnt_u32(unsigned int __X)
 {
   return __builtin_ia32_tzcnt_u32(__X);
@@ -81,7 +86,7 @@ __tzcnt_u32(unsigned int __X)
 /// \returns A 32-bit integer containing the number of trailing zero bits in
 ///    the operand.
 /// \see { __tzcnt_u32 _tzcnt_u32 }
-static __inline__ int __RELAXED_FN_ATTRS
+static __inline__ int __RELAXED_FN_ATTRS_CONSTEXPR
 _mm_tzcnt_32(unsigned int __X)
 {
   return (int)__builtin_ia32_tzcnt_u32(__X);
@@ -117,7 +122,7 @@ _mm_tzcnt_32(unsigned int __X)
 /// \returns An unsigned 64-bit integer containing the number of trailing zero
 ///    bits in the operand.
 /// \see { _mm_tzcnt_64 _tzcnt_u64 }
-static __inline__ unsigned long long __RELAXED_FN_ATTRS
+static __inline__ unsigned long long __RELAXED_FN_ATTRS_CONSTEXPR
 __tzcnt_u64(unsigned long long __X)
 {
   return __builtin_ia32_tzcnt_u64(__X);
@@ -134,7 +139,7 @@ __tzcnt_u64(unsigned long long __X)
 /// \returns An 64-bit integer containing the number of trailing zero bits in
 ///    the operand.
 /// \see { __tzcnt_u64 _tzcnt_u64 }
-static __inline__ long long __RELAXED_FN_ATTRS
+static __inline__ long long __RELAXED_FN_ATTRS_CONSTEXPR
 _mm_tzcnt_64(unsigned long long __X)
 {
   return (long long)__builtin_ia32_tzcnt_u64(__X);
@@ -160,12 +165,18 @@ _mm_tzcnt_64(unsigned long long __X)
 #endif /* __x86_64__ */
 
 #undef __RELAXED_FN_ATTRS
+#undef __RELAXED_FN_ATTRS_CONSTEXPR
 
 #if !defined(__SCE__) || __has_feature(modules) || defined(__BMI__)
 
 /* Define the default attributes for the functions in this file. */
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi")))
 
+#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
+#else
+#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
+
 /// Performs a bitwise AND of the second operand with the one's
 ///    complement of the first operand.
 ///
@@ -180,7 +191,7 @@ _mm_tzcnt_64(unsigned long long __X)
 /// \returns An unsigned integer containing the bitwise AND of the second
 ///    operand with the one's complement of the first operand.
 /// \see _andn_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __andn_u32(unsigned int __X, unsigned int __Y)
 {
   return ~__X & __Y;
@@ -223,7 +234,7 @@ __andn_u32(unsigned int __X, unsigned int __Y)
 /// \returns An unsigned integer whose least significant bits contain the
 ///    extracted bits.
 /// \see _bextr_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __bextr_u32(unsigned int __X, unsigned int __Y)
 {
   return __builtin_ia32_bextr_u32(__X, __Y);
@@ -248,7 +259,7 @@ __bextr_u32(unsigned int __X, unsigned int __Y)
 /// \returns An unsigned integer whose least significant bits contain the
 ///    extracted bits.
 /// \see __bextr_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 _bextr_u32(unsigned int __X, unsigned int __Y, unsigned int __Z)
 {
   return __builtin_ia32_bextr_u32 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
@@ -271,7 +282,7 @@ _bextr_u32(unsigned int __X, unsigned int __Y, unsigned int __Z)
 /// \returns An unsigned integer whose least significant bits contain the
 ///    extracted bits.
 /// \see __bextr_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 _bextr2_u32(unsigned int __X, unsigned int __Y) {
   return __builtin_ia32_bextr_u32(__X, __Y);
 }
@@ -288,7 +299,7 @@ _bextr2_u32(unsigned int __X, unsigned int __Y) {
 /// \returns An unsigned integer containing the result of clearing the bits from
 ///    the source operand.
 /// \see _blsi_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsi_u32(unsigned int __X)
 {
   return __X & -__X;
@@ -324,7 +335,7 @@ __blsi_u32(unsigned int __X)
 ///    An unsigned integer used to create the mask.
 /// \returns An unsigned integer containing the newly created mask.
 /// \see _blsmsk_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsmsk_u32(unsigned int __X)
 {
   return __X ^ (__X - 1);
@@ -360,7 +371,7 @@ __blsmsk_u32(unsigned int __X)
 /// \returns An unsigned integer containing the result of clearing the source
 ///    operand.
 /// \see _blsr_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsr_u32(unsigned int __X)
 {
   return __X & (__X - 1);
@@ -400,7 +411,7 @@ __blsr_u32(unsigned int __X)
 /// \returns An unsigned 64-bit integer containing the bitwise AND of the second
 ///    operand with the one's complement of the first operand.
 /// \see _andn_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 __andn_u64 (unsigned long long __X, unsigned long long __Y)
 {
   return ~__X & __Y;
@@ -444,7 +455,7 @@ __andn_u64 (unsigned long long __X, unsigned long long __Y)
 /// \returns An unsigned 64-bit integer whose least significant bits contain the
 ///    extracted bits.
 /// \see _bextr_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 __bextr_u64(unsigned long long __X, unsigned long long __Y)
 {
   return __builtin_ia32_bextr_u64(__X, __Y);
@@ -469,7 +480,7 @@ __bextr_u64(unsigned long long __X, unsigned long long __Y)
 /// \returns An unsigned 64-bit integer whose least significant bits contain the
 ///    extracted bits.
 /// \see __bextr_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 _bextr_u64(unsigned long long __X, unsigned int __Y, unsigned int __Z)
 {
   return __builtin_ia32_bextr_u64 (__X, ((__Y & 0xff) | ((__Z & 0xff) << 8)));
@@ -492,7 +503,7 @@ _bextr_u64(unsigned long long __X, unsigned int __Y, unsigned int __Z)
 /// \returns An unsigned 64-bit integer whose least significant bits contain the
 ///    extracted bits.
 /// \see __bextr_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 _bextr2_u64(unsigned long long __X, unsigned long long __Y) {
   return __builtin_ia32_bextr_u64(__X, __Y);
 }
@@ -509,7 +520,7 @@ _bextr2_u64(unsigned long long __X, unsigned long long __Y) {
 /// \returns An unsigned 64-bit integer containing the result of clearing the
 ///    bits from the source operand.
 /// \see _blsi_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsi_u64(unsigned long long __X)
 {
   return __X & -__X;
@@ -545,7 +556,7 @@ __blsi_u64(unsigned long long __X)
 ///    An unsigned 64-bit integer used to create the mask.
 /// \returns An unsigned 64-bit integer containing the newly created mask.
 /// \see _blsmsk_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsmsk_u64(unsigned long long __X)
 {
   return __X ^ (__X - 1);
@@ -581,7 +592,7 @@ __blsmsk_u64(unsigned long long __X)
 /// \returns An unsigned 64-bit integer containing the result of clearing the
 ///    source operand.
 /// \see _blsr_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 __blsr_u64(unsigned long long __X)
 {
   return __X & (__X - 1);
@@ -608,6 +619,7 @@ __blsr_u64(unsigned long long __X)
 #endif /* __x86_64__ */
 
 #undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_CONSTEXPR
 
 #endif /* !defined(__SCE__) || __has_feature(modules) || defined(__BMI__) */
 
diff --git a/clang/lib/Headers/lzcntintrin.h b/clang/lib/Headers/lzcntintrin.h
index f4ddce9d0e683..190fe66f3d72f 100644
--- a/clang/lib/Headers/lzcntintrin.h
+++ b/clang/lib/Headers/lzcntintrin.h
@@ -17,6 +17,12 @@
 /* Define the default attributes for the functions in this file. */
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
 
+#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
+#else
+#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
+#endif
+
 #ifndef _MSC_VER
 /// Counts the number of leading zero bits in the operand.
 ///
@@ -42,7 +48,7 @@
 /// \returns An unsigned 32-bit integer containing the number of leading zero
 ///    bits in the operand.
 /// \see _lzcnt_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 __lzcnt32(unsigned int __X)
 {
   return __builtin_ia32_lzcnt_u32(__X);
@@ -59,7 +65,7 @@ __lzcnt32(unsigned int __X)
 /// \returns An unsigned 32-bit integer containing the number of leading zero
 ///    bits in the operand.
 /// \see __lzcnt32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
 _lzcnt_u32(unsigned int __X)
 {
   return __builtin_ia32_lzcnt_u32(__X);
@@ -92,7 +98,7 @@ _lzcnt_u32(unsigned int __X)
 /// \returns An unsigned 64-bit integer containing the number of leading zero
 ///    bits in the operand.
 /// \see __lzcnt64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
 _lzcnt_u64(unsigned long long __X)
 {
   return __builtin_ia32_lzcnt_u64(__X);
@@ -100,5 +106,6 @@ _lzcnt_u64(unsigned long long __X)
 #endif
 
 #undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_CONSTEXPR
 
 #endif /* __LZCNTINTRIN_H */
diff --git a/clang/test/CodeGen/X86/bmi-builtins.c b/clang/test/CodeGen/X86/bmi-builtins.c
index 81405429b9b6c..a34c346dd6177 100644
--- a/clang/test/CodeGen/X86/bmi-builtins.c
+++ b/clang/test/CodeGen/X86/bmi-builtins.c
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,TZCNT
-// RUN: %clang_cc1 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -emit-llvm -o - -Wall -Werror -DTEST_TZCNT | FileCheck %s --check-prefix=TZCNT
-
+// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,TZCNT
+// RUN: %clang_cc1 -x c++ -std=c++11 -std -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,TZCNT
+// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -emit-llvm -o - -Wall -Werror -DTEST_TZCNT | FileCheck %s --check-prefix=TZCNT
+// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -emit-llvm -o - -Wall -Werror -DTEST_TZCNT | FileCheck %s --check-prefix=TZCNT
 
 #include <immintrin.h>
 
@@ -232,3 +233,121 @@ unsigned long long test_blsr_u64(unsigned long long __X) {
 #endif
 
 #endif // !defined(TEST_TZCNT)
+
+// Test constexpr handling.
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+
+char cttz16_0[__tzcnt_u16(0x0000) == 16 ? 1 : -1];
+char cttz16_1[__tzcnt_u16(0x10F0) == 4 ? 1 : -1];
+
+char cttz32_0[__tzcnt_u32(0x0FF00000) == 20 ? 1 : -1];
+char cttz32_1[__tzcnt_u32(0x000000F0) == 4 ? 1 : -1];
+
+char mm_cttz32_0[_mm_tzcnt_u32(0x00030F00) == 8 ? 1 : -1];
+char mm_cttz32_1[_mm_tzcnt_u32(0x01000000) == 24 ? 1 : -1];
+
+//Intel
+char _tzcnt_u16_0[_tzcnt_u16(0x0010) == 4 ? 1 : -1];
+char _tzcnt_u16_1[_tzcnt_u16(0x0100) == 8 ? 1 : -1];
+
+char _tzcnt_u32_0[_tzcnt_u32(0x00110011) == 0 ? 1 : -1;
+char _tzcnt_u32_1[_tzcnt_u32(0x10011000) == 12 ? 1 : -1;
+
+#ifdef __x86_64__
+char mm_cttz64_0[mm_tzcnt_u64(0x0000000000000000ULL) == 0 ? 1 : -1];
+char mm_cttz64_1[mm_tzcnt_u64(0xF000010000000000ULL) == 40 ? 1 : -1];
+
+//Intel
+char __tzcnt_u64_0[__tzcnt_u64(0x0100000000000000ULL) == 56 ? 1 : -1];
+char __tzcnt_u64_1[__tzcnt_u64(0xF000000000000001ULL) == 0 ? 1 : -1];
+#endif //__X86_64__
+
+#if !defined(TEST_TZCNT)
+
+//ANDN
+char andn_u32_0[__andn_u32(0X0FFF0FFF, 0XFFFFFFFF) == 0xF000F000 ? 1 : -1];
+char andn_u32_1[__andn_u32(0x0F0FFFFF, 0xF0F00000) == 0xF0F00000 ? 1 : -1];
+
+//Intel
+char _andn_u32_0[_andn_u32(0xFFFF1FFF, 0x0000F000) == 0x0000E000 ? 1 : -1];
+char _andn_u32_1[_andn_u32(0xF0F0F0F0, 0x01010101) == 0x01010101 ? 1 : -1];
+
+#ifdef __X86_64__
+char andn_u64_0[__andn_u64(0x0000FFFF11110000, 0x0101010101010101) == 0x0101000000000101 ? 1 : -1];
+char andn_u64_1[__andn_u64(0x0FFFFFFFFFFF137F, 0xF00000000000FFFF) == 0xF00000000000EC80 ? 1 : -1];
+
+//Intel
+char _andn_u64_0[_andn_u64(0xFFFF0000FFFF0000, 0x0000FFFF0000FFFF) == 0x0000FFFF0000FFFF ? 1 : -1];
+char _andn_u64_1[_andn_u64(0xFFFFEDCBFFFFA987, 0x0000FFFF0000FF00) == 0x0000123400005600 ? 1 : -1];
+#endif
+
+//BEXTR
+char bextr_u32_0[__bextr_u32(0xFFFF0000, 0x00001010) == 0x0000FFFF ? 1 : -1];
+char bextr_u32_1[__bextr_u32(0x00FFF800, 0x0000100B) == 0x00001FFF ? 1 : -1];
+
+//Intel
+char _bextr_u32_0[_bextr_u32(0x10FFF800, 20, 9) == 0x0000010F ? 1 : -1];
+char _bextr_u32_1[_bextr_u32(0x0000FF10, 16, 16) == 0x00000000 ? 1 : -1];
+
+#ifdef __X86_64__
+char bextr_u64_0[__bextr_u64(0x7FFF00001111FFFF, 0x00002020) == 0x000000007FFF0000 ? 1 : -1];
+char bextr_u64_1[__bextr_u64(0xF0FFF800FFFF1111, 0x00004040) == 0x0000000000000000 ? 1 : -1];
+
+//Intel
+char _bextr_u64_0[_bextr_u64(0x7FFFFFFF10FF1111, 32, 32) == 0x000000007FFFFFFF ? 1 : -1];
+char _bextr_u64_1[_bextr_u64(0x1111FFFF0000FF10, 48, 16) == 0x0000000000001111 ? 1 : -1];
+#endif
+
+//BLSI
+char blsi_u32_0[__blsi_u32(0x0000FFF8) == 0x00000008 ? 1 : -1];
+char blsi_u32_1[__blsi_u32(0x00FF0000) == 0x00010000 ? 1 : -1];
+
+//Intel
+char _blsi_u32_0[_blsi_u32(0x70000B00) == 0x00000100 ? 1 : -1];
+char _blsi_u32_1[_blsi_u32(0x80000000) == 0x80000000 ? 1 : -1];
+
+#ifdef __X86_64__
+char blsi_u64_0[__blsi_u64(0xF0FFF800FFF00000) == 0x100000 ? 1 : -1];
+char blsi_u64_1[__blsi_u64(0x0AE0000000000000) == 0x0020000000000000 ? 1 : -1];
+
+//Intel
+char _blsi_u64_0[_blsi_u64(0xFFFFFC0000000000) == 0x0000040000000000 ? 1 : -1];
+char _blsi_u64_1[_blsi_u64(0x0FE0000000000000) == 0x0020000000000000 ? 1 : -1];
+#endif
+
+//BLSMSK
+char blsmsk_u32_0[__blsmsk_u32(0xF0F0F0F0) == 0x0000001F ? 1 : -1];
+char blsmsk_u32_1[__blsmsk_u32(0x7FFFFC00) == 0x000007FF ? 1 : -1];
+ 
+//Intel
+char _blsmsk_u32_0[_blsmsk_u32(0xB0000000) == 0x1FFFFFFF ? 1 : -1];
+char _blsmsk_u32_1[_blsmsk_u32(0x00000000) == 0xFFFFFFFF ? 1 : -1];
+
+#ifdef __X86_64__
+char blsmsk_u64_0[__blsmsk_u64(0xF0F0F0F000A00000) == 0x00000000003FFFFF ? 1 : -1];
+char blsmsk_u64_1[__blsmsk_u64(0x1111100000000800) == 0x0000000000000FFF ? 1 : -1];
+
+//Intel
+char _blsmsk_u64_0[_blsmsk_u64(0xFFFFFC0000000000) == 0x000007FFFFFFFFFF ? 1 : -1];
+char _blsmsk_u64_1[_blsmsk_u64(0xFFFFFFFFFFFFFFFF) == 0x0000000000000001 ? 1 : -1];
+#endif
+
+//BLSR
+char blsr_u32_0[__blsr_u32(0xB00FFFFF) == 0xB00FFFFE ? 1 : -1];
+char blsr_u32_1[__blsr_u32(0xFFFFFFFF) == 0xFFFFFFFE ? 1 : -1];
+
+//Intel
+char _blsr_u32_0[_blsr_u32(0xB0000000) == 0xA0000000 ? 1 : -1];
+char _blsr_u32_1[_blsr_u32(0x00000000) == 0x00000000 ? 1 : -1];
+
+#ifdef __X86_64__
+char blsr_u64_0[__blsr_u64(0xB00FF70000000000) == 0xB00FF60000000000 ? 1 : -1];
+char blsr_u64_1[__blsr_u64(0xFFFFFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFE ? 1 : -1];
+
+//Intel
+char _blsr_u64_0[_blsr_u64(0xB00FFFFFFFFF0000) == 0xB00FFFFFFFFE0000 ? 1 : -1];
+char _blsr_u64_1[_blsr_u64(0x8000000000000000) == 0x0000000000000000 ? 1 : -1];
+#endif //ifdef __X86_64__
+
+#endif //!(defined(TEST_TZCNT)
+#endif // __cplusplus
diff --git a/clang/test/CodeGen/X86/lzcnt-builtins.c b/clang/test/CodeGen/X86/lzcnt-builtins.c
index 9255207ffaef4..a9c643bae0855 100644
--- a/clang/test/CodeGen/X86/lzcnt-builtins.c
+++ b/clang/test/CodeGen/X86/lzcnt-builtins.c
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lzcnt -emit-llvm -o - | FileCheck %s
-
+// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lzcnt -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lzcnt -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s
 
 #include <immintrin.h>
 
@@ -32,3 +34,34 @@ unsigned long long test__lzcnt_u64(unsigned long long __X)
   // CHECK: @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
   return _lzcnt_u64(__X);
 }
+
+// Test constexpr handling.
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+
+#if defined(_MSC_VER)
+char ms_ctlz16_0[__lzcnt16(0x3FF0) == 2 ? 1 : -1];
+char ms_ctlz16_1[__lzcnt16(0xF000) == 0 ? 1 : -1];
+
+char ms_ctlz32_0[__lzcnt32(0xFFF00000) == 0 ? 1 : -1];
+char ms_ctlz32_1[__lzcnt32(0x000001F0) == 23 ? 1 : -1];
+#endif
+
+#if defined(__LZCNT__)
+char ctlz32_0[_lzcnt_u32(0x00000000) == 0 ? 1 : -1];
+char ctlz32_1[_lzcnt_u32(0x000000F0) == 24 ? 1 : -1];
+#endif
+
+#ifdef __x86_64__
+
+#if defined(_MSC_VER)
+char ms_ctlz64_0[__lzcnt64(0x00000000FFF00000) == 32 ? 1 : -1];
+char ms_ctlz64_1[__lzcnt64(0x00F00000000001F0) == 8 ? 1 : -1];
+#endif
+
+#if defined(__LZCNT__)
+char ctlz64_0[_lzcnt_u64(0x000000000000F000ULL) == 48 ? 1 : -1];
+char ctlz64_1[_lzcnt_u64(0x0100000000000001ULL) == 7 ? 1 : -1];
+#endif
+
+#endif
+#endif

>From 4a6193171376ee1a39ce6a2e408c62cba9a785aa Mon Sep 17 00:00:00 2001
From: aniplcc <aniplccode at gmail.com>
Date: Sun, 2 Jun 2024 19:52:51 +0530
Subject: [PATCH 2/2] format fixes

---
 clang/lib/Headers/bmiintrin.h   |  4 ++--
 clang/lib/Headers/lzcntintrin.h | 11 ++++-------
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Headers/bmiintrin.h b/clang/lib/Headers/bmiintrin.h
index c5b57a1d1e43c..56e62fc98d6dc 100644
--- a/clang/lib/Headers/bmiintrin.h
+++ b/clang/lib/Headers/bmiintrin.h
@@ -19,7 +19,7 @@
    to use it as a potentially faster version of BSF. */
 #define __RELAXED_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
 
-#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
 #define __RELAXED_FN_ATTRS_CONSTEXPR __RELAXED_FN_ATTRS constexpr
 #else
 #define __RELAXED_FN_ATTRS_CONSTEXPR __RELAXED_FN_ATTRS
@@ -172,7 +172,7 @@ _mm_tzcnt_64(unsigned long long __X)
 /* Define the default attributes for the functions in this file. */
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi")))
 
-#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
 #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
 #else
 #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
diff --git a/clang/lib/Headers/lzcntintrin.h b/clang/lib/Headers/lzcntintrin.h
index 190fe66f3d72f..dd2d1d53eed25 100644
--- a/clang/lib/Headers/lzcntintrin.h
+++ b/clang/lib/Headers/lzcntintrin.h
@@ -17,7 +17,7 @@
 /* Define the default attributes for the functions in this file. */
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
 
-#if defined (__cplusplus) && (__cplusplus >= 201103L)
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
 #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
 #else
 #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
@@ -49,8 +49,7 @@
 ///    bits in the operand.
 /// \see _lzcnt_u32
 static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
-__lzcnt32(unsigned int __X)
-{
+__lzcnt32(unsigned int __X) {
   return __builtin_ia32_lzcnt_u32(__X);
 }
 
@@ -66,8 +65,7 @@ __lzcnt32(unsigned int __X)
 ///    bits in the operand.
 /// \see __lzcnt32
 static __inline__ unsigned int __DEFAULT_FN_ATTRS_CONSTEXPR
-_lzcnt_u32(unsigned int __X)
-{
+_lzcnt_u32(unsigned int __X) {
   return __builtin_ia32_lzcnt_u32(__X);
 }
 
@@ -99,8 +97,7 @@ _lzcnt_u32(unsigned int __X)
 ///    bits in the operand.
 /// \see __lzcnt64
 static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CONSTEXPR
-_lzcnt_u64(unsigned long long __X)
-{
+_lzcnt_u64(unsigned long long __X) {
   return __builtin_ia32_lzcnt_u64(__X);
 }
 #endif



More information about the cfe-commits mailing list