[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