[clang] [clang] constexpr built-in elementwise popcount function. (PR #117473)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 25 06:51:36 PST 2024
https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/117473
>From 95f2b6b0742b9b5b675f5d2f24aa4eb90c03b18c Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 24 Nov 2024 18:14:51 +0800
Subject: [PATCH 1/6] constexpr elementwise popcount
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Basic/Builtins.td | 2 +-
clang/lib/AST/ExprConstant.cpp | 27 ++++++++++++++++++++
clang/test/Sema/constant_builtins_vector.cpp | 5 ++++
4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8bd06fadfdc984..16a151da38bb5d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -370,6 +370,7 @@ Non-comprehensive list of changes in this release
- ``__builtin_reduce_mul`` function can now be used in constant expressions.
- ``__builtin_reduce_and`` function can now be used in constant expressions.
- ``__builtin_reduce_or`` and ``__builtin_reduce_xor`` functions can now be used in constant expressions.
+- ``__builtin_elementwise_popcount`` function can now be used in constant expressions.
New Compiler Flags
------------------
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 83c90b3d6e681b..246250442ef62c 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1354,7 +1354,7 @@ def ElementwiseLog10 : Builtin {
def ElementwisePopcount : Builtin {
let Spellings = ["__builtin_elementwise_popcount"];
- let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c6a210459240a8..bdd056d0618c6d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11005,6 +11005,7 @@ namespace {
bool VisitUnaryImag(const UnaryOperator *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
+ bool VisitCallExpr(const CallExpr *E);
bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
@@ -11302,6 +11303,32 @@ static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
return false;
}
+bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
+ switch (E->getBuiltinCallee()) {
+ default:
+ return false;
+ case Builtin::BI__builtin_elementwise_popcount: {
+ APValue Source;
+ if (!EvaluateAsRValue(Info, E->getArg(0), Source))
+ return false;
+
+ QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
+ unsigned SourceLen = Source.getVectorLength();
+ SmallVector<APValue, 4> ResultElements;
+ ResultElements.reserve(SourceLen);
+
+ for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+ APSInt Elt = Source.getVectorElt(EltNum).getInt();
+ ResultElements.push_back(
+ APValue(APSInt(APInt(Info.Ctx.getIntWidth(DestTy), Elt.popcount()),
+ DestTy->isUnsignedIntegerOrEnumerationType())));
+ }
+
+ return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+ }
+ }
+}
+
bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
APValue Source;
QualType SourceVecType = E->getSrcExpr()->getType();
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index e84d09b24672b4..76d8bdfda3690a 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -797,3 +797,8 @@ static_assert(__builtin_reduce_xor((vector4int){(int)0x11111111, (int)0x22222222
static_assert(__builtin_reduce_xor((vector4long){(long long)0x1111111111111111L, (long long)0x2222222222222222L, (long long)0x4444444444444444L, (long long)0x8888888888888888L}) == (long long)0xFFFFFFFFFFFFFFFFL);
static_assert(__builtin_reduce_xor((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0xFFFFFFFFU);
static_assert(__builtin_reduce_xor((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0xFFFFFFFFFFFFFFFFUL);
+
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1, 2, 3, 4})) == 5);
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){0, 0xF0F0, ~0, ~0xF0F0})) == 16 * sizeof(int));
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){1L, 2L, 3L, 4L})) == 5L);
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){0L, 0xF0F0L, ~0L, ~0xF0F0L})) == 16 * sizeof(long long));
>From 316f6085fb129de24da3297c1bd8b110d763b23d Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 24 Nov 2024 18:27:55 +0800
Subject: [PATCH 2/6] fix bug
---
clang/lib/AST/ExprConstant.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index bdd056d0618c6d..8a3ced30be9440 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11304,6 +11304,9 @@ static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
}
bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
+ if (!IsConstantEvaluatedBuiltinCall(E))
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
+
switch (E->getBuiltinCallee()) {
default:
return false;
>From 5dba71fda1a412c2e610fb0a2ce05102dba84c1e Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 24 Nov 2024 23:31:26 +0800
Subject: [PATCH 3/6] fix bug; add more test cases
---
clang/lib/AST/ExprConstant.cpp | 1 +
clang/test/Sema/constant_builtins_vector.cpp | 13 +++++++++++++
2 files changed, 14 insertions(+)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8a3ced30be9440..323a371fe957db 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13148,6 +13148,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_popcountl:
case Builtin::BI__builtin_popcountll:
case Builtin::BI__builtin_popcountg:
+ case Builtin::BI__builtin_elementwise_popcount:
case Builtin::BI__popcnt16: // Microsoft variants of popcount
case Builtin::BI__popcnt:
case Builtin::BI__popcnt64: {
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index 76d8bdfda3690a..29149b01c236e3 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -802,3 +802,16 @@ static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){0, 0xF0F0, ~0, ~0xF0F0})) == 16 * sizeof(int));
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){1L, 2L, 3L, 4L})) == 5L);
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){0L, 0xF0F0L, ~0L, ~0xF0F0L})) == 16 * sizeof(long long));
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){1U, 2U, 3U, 4U})) == 5U);
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){0U, 0xF0F0U, ~0U, ~0xF0F0U})) == 16 * sizeof(int));
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){1UL, 2UL, 3UL, 4UL})) == 5L);
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){0UL, 0xF0F0UL, ~0UL, ~0xF0F0UL})) == 16 * sizeof(long long));
+static_assert(__builtin_elementwise_popcount(0) == 0);
+static_assert(__builtin_elementwise_popcount(0xF0F0) == 8);
+static_assert(__builtin_elementwise_popcount(~0) == 8 * sizeof(int));
+static_assert(__builtin_elementwise_popcount(0U) == 0);
+static_assert(__builtin_elementwise_popcount(0xF0F0U) == 8);
+static_assert(__builtin_elementwise_popcount(~0U) == 8 * sizeof(int));
+static_assert(__builtin_elementwise_popcount(0L) == 0);
+static_assert(__builtin_elementwise_popcount(0xF0F0L) == 8);
+static_assert(__builtin_elementwise_popcount(~0LL) == 8 * sizeof(long long));
>From 60216a46a3c332f084aaa2acbb71522725960b6b Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 24 Nov 2024 23:48:21 +0800
Subject: [PATCH 4/6] fix test
---
.../test/CodeGen/builtins-elementwise-math.c | 30 ++-----------------
1 file changed, 3 insertions(+), 27 deletions(-)
diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c
index 748b5e4add7c76..a9e10f77d906fb 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -666,40 +666,16 @@ void test_builtin_elementwise_log2(float f1, float f2, double d1, double d2,
vf2 = __builtin_elementwise_log2(vf1);
}
-void test_builtin_elementwise_popcount(si8 vi1, si8 vi2,
- long long int i1, long long int i2, short si,
- _BitInt(31) bi1, _BitInt(31) bi2) {
-
-
- // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8
- // CHECK-NEXT: call i64 @llvm.ctpop.i64(i64 [[I1]])
+void test_builtin_elementwise_popcount(si8 vi1, si8 vi2, long long int i1,
+ long long int i2, short si,
+ _BitInt(31) bi1, _BitInt(31) bi2) {
i2 = __builtin_elementwise_popcount(i1);
-
- // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16
- // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[VI1]])
vi2 = __builtin_elementwise_popcount(vi1);
-
- // CHECK: [[CVI2:%.+]] = load <8 x i16>, ptr %cvi2, align 16
- // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[CVI2]])
const si8 cvi2 = vi2;
vi2 = __builtin_elementwise_popcount(cvi2);
-
- // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4
- // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
- // CHECK-NEXT: call i31 @llvm.ctpop.i31(i31 [[LOADEDV]])
bi2 = __builtin_elementwise_popcount(bi1);
-
- // CHECK: [[IA1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
- // CHECK-NEXT: call i32 @llvm.ctpop.i32(i32 [[IA1]])
b = __builtin_elementwise_popcount(int_as_one);
-
- // CHECK: call i32 @llvm.ctpop.i32(i32 -10)
b = __builtin_elementwise_popcount(-10);
-
- // CHECK: [[SI:%.+]] = load i16, ptr %si.addr, align 2
- // CHECK-NEXT: [[SI_EXT:%.+]] = sext i16 [[SI]] to i32
- // CHECK-NEXT: [[RES:%.+]] = call i32 @llvm.ctpop.i32(i32 [[SI_EXT]])
- // CHECK-NEXT: = trunc i32 [[RES]] to i16
si = __builtin_elementwise_popcount(si);
}
>From 6ec9aa51e5256caae9030aca347ed74f04140578 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 25 Nov 2024 00:39:05 +0800
Subject: [PATCH 5/6] fix test
---
clang/test/Sema/constant_builtins_vector.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index 29149b01c236e3..672cb1b4387beb 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -804,8 +804,8 @@ static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){0L, 0xF0F0L, ~0L, ~0xF0F0L})) == 16 * sizeof(long long));
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){1U, 2U, 3U, 4U})) == 5U);
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){0U, 0xF0F0U, ~0U, ~0xF0F0U})) == 16 * sizeof(int));
-static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){1UL, 2UL, 3UL, 4UL})) == 5L);
-static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){0UL, 0xF0F0UL, ~0UL, ~0xF0F0UL})) == 16 * sizeof(long long));
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){1UL, 2UL, 3UL, 4UL})) == 5UL);
+static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){0ULL, 0xF0F0ULL, ~0ULL, ~0xF0F0ULL})) == 16 * sizeof(unsigned long long));
static_assert(__builtin_elementwise_popcount(0) == 0);
static_assert(__builtin_elementwise_popcount(0xF0F0) == 8);
static_assert(__builtin_elementwise_popcount(~0) == 8 * sizeof(int));
>From af8ef3ac364c91c47196cd50d19c5cf07c275193 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 25 Nov 2024 22:51:19 +0800
Subject: [PATCH 6/6] address review comments
---
clang/lib/AST/ExprConstant.cpp | 6 ++---
.../test/CodeGen/builtins-elementwise-math.c | 22 +++++++++++++++++++
clang/test/Sema/constant_builtins_vector.cpp | 2 ++
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 323a371fe957db..06cb433eaecf2c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11315,7 +11315,7 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!EvaluateAsRValue(Info, E->getArg(0), Source))
return false;
- QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
+ QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
unsigned SourceLen = Source.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen);
@@ -11323,8 +11323,8 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
APSInt Elt = Source.getVectorElt(EltNum).getInt();
ResultElements.push_back(
- APValue(APSInt(APInt(Info.Ctx.getIntWidth(DestTy), Elt.popcount()),
- DestTy->isUnsignedIntegerOrEnumerationType())));
+ APValue(APSInt(APInt(Info.Ctx.getIntWidth(DestEltTy), Elt.popcount()),
+ DestEltTy->isUnsignedIntegerOrEnumerationType())));
}
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c
index a9e10f77d906fb..f1f34432ca0ea1 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -669,13 +669,35 @@ void test_builtin_elementwise_log2(float f1, float f2, double d1, double d2,
void test_builtin_elementwise_popcount(si8 vi1, si8 vi2, long long int i1,
long long int i2, short si,
_BitInt(31) bi1, _BitInt(31) bi2) {
+ // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8
+ // CHECK-NEXT: call i64 @llvm.ctpop.i64(i64 [[I1]])
i2 = __builtin_elementwise_popcount(i1);
+
+ // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16
+ // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[VI1]])
vi2 = __builtin_elementwise_popcount(vi1);
+
+ // CHECK: [[CVI2:%.+]] = load <8 x i16>, ptr %cvi2, align 16
+ // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[CVI2]])
const si8 cvi2 = vi2;
vi2 = __builtin_elementwise_popcount(cvi2);
+
+ // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4
+ // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31
+ // CHECK-NEXT: call i31 @llvm.ctpop.i31(i31 [[LOADEDV]])
bi2 = __builtin_elementwise_popcount(bi1);
+
+ // CHECK: [[IA1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4
+ // CHECK-NEXT: call i32 @llvm.ctpop.i32(i32 [[IA1]])
b = __builtin_elementwise_popcount(int_as_one);
+
+ // CHECK: store i32 30, ptr @b, align 4
b = __builtin_elementwise_popcount(-10);
+
+ // CHECK: [[SI:%.+]] = load i16, ptr %si.addr, align 2
+ // CHECK-NEXT: [[SI_EXT:%.+]] = sext i16 [[SI]] to i32
+ // CHECK-NEXT: [[RES:%.+]] = call i32 @llvm.ctpop.i32(i32 [[SI_EXT]])
+ // CHECK-NEXT: = trunc i32 [[RES]] to i16
si = __builtin_elementwise_popcount(si);
}
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index 672cb1b4387beb..2bfc0fbe226dfe 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -798,6 +798,8 @@ static_assert(__builtin_reduce_xor((vector4long){(long long)0x1111111111111111L,
static_assert(__builtin_reduce_xor((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0xFFFFFFFFU);
static_assert(__builtin_reduce_xor((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0xFFFFFFFFFFFFFFFFUL);
+static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_popcount((vector4char){1, 2, 3, 4})) == (LITTLE_END ? 0x01020101 : 0x01010201));
+static_assert(__builtin_bit_cast(unsigned long, __builtin_elementwise_popcount((vector4short){0, 0x0F0F, ~0, ~0x0F0F})) == (LITTLE_END ? 0x0008001000080000 : 0x0000000800100008));
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1, 2, 3, 4})) == 5);
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){0, 0xF0F0, ~0, ~0xF0F0})) == 16 * sizeof(int));
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){1L, 2L, 3L, 4L})) == 5L);
More information about the cfe-commits
mailing list