[clang] 00158ae - [clang] Enable constexpr on LZCNT/POPCNT MS extension intrinsics

Simon Pilgrim via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 14 03:33:46 PDT 2023


Author: Alejandro Aguirre
Date: 2023-08-14T11:33:33+01:00
New Revision: 00158ae236ddfdc7dda5ea7a8a20e3921007ba86

URL: https://github.com/llvm/llvm-project/commit/00158ae236ddfdc7dda5ea7a8a20e3921007ba86
DIFF: https://github.com/llvm/llvm-project/commit/00158ae236ddfdc7dda5ea7a8a20e3921007ba86.diff

LOG: [clang] Enable constexpr on LZCNT/POPCNT MS extension intrinsics

As discussed on #46593 - this enables us to use __lzcnt / __popcnt intrinsics inside constexpr code.

Differential Revision: https://reviews.llvm.org/D157420

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/Basic/Builtins.def
    clang/lib/AST/ExprConstant.cpp
    clang/test/CodeGen/ms-intrinsics-other.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 386ffa7b48eb93..c6f781dfe35e89 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -5225,12 +5225,18 @@ The following x86-specific intrinsics can be used in constant expressions:
 * ``_castf64_u64``
 * ``_castu32_f32``
 * ``_castu64_f64``
+* ``__lzcnt16``
+* ``__lzcnt``
+* ``__lzcnt64``
 * ``_mm_popcnt_u32``
 * ``_mm_popcnt_u64``
 * ``_popcnt32``
 * ``_popcnt64``
 * ``__popcntd``
 * ``__popcntq``
+* ``__popcnt16``
+* ``__popcnt``
+* ``__popcnt64``
 * ``__rolb``
 * ``__rolw``
 * ``__rold``

diff  --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 83e4259ea037b9..f5374537a0242c 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -1017,12 +1017,12 @@ LANGBUILTIN(__iso_volatile_store16, "vsD*s",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store32, "viD*i",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__noop,           "i.",  "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt16, "UsUs",    "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt,   "UiUi",    "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt64, "UWiUWi",  "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt16, "UsUs",   "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt,   "UiUi",   "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt16, "UsUs",    "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt,   "UiUi",    "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt64, "UWiUWi",  "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt16, "UsUs",   "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt,   "UiUi",   "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt64, "UWiUWi", "ncE", ALL_MS_LANGUAGES)
 LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl8,  "UcUcUc",    "nE", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl16, "UsUsUc",    "nE", ALL_MS_LANGUAGES)

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index a7e0d5a38698f7..ee2f3b7be1dabd 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12124,11 +12124,21 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
   case Builtin::BI__builtin_clz:
   case Builtin::BI__builtin_clzl:
   case Builtin::BI__builtin_clzll:
-  case Builtin::BI__builtin_clzs: {
+  case Builtin::BI__builtin_clzs:
+  case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
+  case Builtin::BI__lzcnt:
+  case Builtin::BI__lzcnt64: {
     APSInt Val;
     if (!EvaluateInteger(E->getArg(0), Val, Info))
       return false;
-    if (!Val)
+
+    // When the argument is 0, the result of GCC builtins is undefined, whereas
+    // for Microsoft intrinsics, the result is the bit-width of the argument.
+    bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
+                           BuiltinOp != Builtin::BI__lzcnt &&
+                           BuiltinOp != Builtin::BI__lzcnt64;
+
+    if (ZeroIsUndefined && !Val)
       return Error(E);
 
     return Success(Val.countl_zero(), E);
@@ -12267,7 +12277,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
 
   case Builtin::BI__builtin_popcount:
   case Builtin::BI__builtin_popcountl:
-  case Builtin::BI__builtin_popcountll: {
+  case Builtin::BI__builtin_popcountll:
+  case Builtin::BI__popcnt16: // Microsoft variants of popcount
+  case Builtin::BI__popcnt:
+  case Builtin::BI__popcnt64: {
     APSInt Val;
     if (!EvaluateInteger(E->getArg(0), Val, Info))
       return false;

diff  --git a/clang/test/CodeGen/ms-intrinsics-other.c b/clang/test/CodeGen/ms-intrinsics-other.c
index 4bb51087b17765..76f54add749669 100644
--- a/clang/test/CodeGen/ms-intrinsics-other.c
+++ b/clang/test/CodeGen/ms-intrinsics-other.c
@@ -14,6 +14,27 @@
 // RUN:         -triple armv7--darwin -Oz -emit-llvm %s -o - \
 // RUN:         | FileCheck %s --check-prefix=CHECK-ARM
 
+// RUN: %clang_cc1 -x c++ -std=c++11 \
+// RUN:         -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
+// RUN:         -triple x86_64--darwin -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=c++11 \
+// RUN:         -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
+// RUN:         -triple x86_64--linux -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=c++11 \
+// RUN:         -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
+// RUN:         -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s --check-prefix=CHECK-ARM-ARM64
+// RUN: %clang_cc1 -x c++ -std=c++11 \
+// RUN:         -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
+// RUN:         -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s --check-prefix=CHECK-ARM
+// RUN: %clang_cc1 -x c++ -std=c++11 \
+// RUN:         -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
+// RUN:         -triple armv7--darwin -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s --check-prefix=CHECK-ARM
+
 // LP64 targets use 'long' as 'int' for MS intrinsics (-fms-extensions)
 #ifdef __LP64__
 #define LONG int
@@ -21,6 +42,10 @@
 #define LONG long
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 unsigned char test_BitScanForward(unsigned LONG *Index, unsigned LONG Mask) {
   return _BitScanForward(Index, Mask);
 }
@@ -416,3 +441,36 @@ LONG test_InterlockedDecrement_nf(LONG volatile *Addend) {
 // CHECK-ARM: ret i32 [[RESULT]]
 // CHECK-ARM: }
 #endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+// Test constexpr handling.
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+
+char popcnt16_0[__popcnt16(0x0000) == 0 ? 1 : -1];
+char popcnt16_1[__popcnt16(0x10F0) == 5 ? 1 : -1];
+
+char popcnt_0[__popcnt(0x00000000) == 0 ? 1 : -1];
+char popcnt_1[__popcnt(0x100000F0) == 5 ? 1 : -1];
+
+char popcnt64_0[__popcnt64(0x0000000000000000ULL) == 0 ? 1 : -1];
+char popcnt64_1[__popcnt64(0xF00000F000000001ULL) == 9 ? 1 : -1];
+
+#define BITSIZE(x) (sizeof(x) * 8)
+char lzcnt16_0[__lzcnt16(1) == BITSIZE(short) - 1 ? 1 : -1];
+char lzcnt16_1[__lzcnt16(1 << (BITSIZE(short) - 1)) == 0 ? 1 : -1];
+char lzcnt16_2[__lzcnt16(0) == BITSIZE(short) ? 1 : -1];
+
+char lzcnt_0[__lzcnt(1) == BITSIZE(int) - 1 ? 1 : -1];
+char lzcnt_1[__lzcnt(1 << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
+char lzcnt_2[__lzcnt(0) == BITSIZE(int) ? 1 : -1];
+
+char lzcnt64_0[__lzcnt64(1ULL) == BITSIZE(__int64) - 1 ? 1 : -1];
+char lzcnt64_1[__lzcnt64(1ULL << (BITSIZE(__int64) - 1)) == 0 ? 1 : -1];
+char lzcnt64_2[__lzcnt64(0ULL) == BITSIZE(__int64) ? 1 : -1];
+#undef BITSIZE
+
+#endif


        


More information about the cfe-commits mailing list