[clang] [clang] constexpr built-in elementwise add_sat function. (PR #119082)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 8 04:53:07 PST 2024
https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/119082
>From 2af0eb663a106b712a3c9eb2028dc35014884708 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 8 Dec 2024 01:11:51 +0800
Subject: [PATCH 1/3] constexpr elementwise add_sat
---
clang/docs/LanguageExtensions.rst | 3 +-
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Basic/Builtins.td | 2 +-
clang/lib/AST/ExprConstant.cpp | 35 +++++++++++++++++++
.../test/CodeGen/builtins-elementwise-math.c | 2 +-
clang/test/Sema/constant_builtins_vector.cpp | 8 +++++
6 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 6b950d05fb9bf9..40c0a0e5f1161c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -648,7 +648,8 @@ elementwise to the input.
Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity
The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``,
-``__builtin_elementwise_bitreverse``, can be called in a ``constexpr`` context.
+``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, can be
+called in a ``constexpr`` context.
============================================== ====================================================================== =========================================
Name Operation Supported element types
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59e3a6609123d2..5aeda3ade7573a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -414,6 +414,7 @@ Non-comprehensive list of changes in this release
- ``__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.
- ``__builtin_elementwise_bitreverse`` function can now be used in constant expressions.
+- ``__builtin_elementwise_add_sat`` 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 e2c3d3c535571c..1186ece419fdd2 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1450,7 +1450,7 @@ def ElementwiseFma : Builtin {
def ElementwiseAddSat : Builtin {
let Spellings = ["__builtin_elementwise_add_sat"];
- 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 6b5b95aee35522..001773dc28dedc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11339,6 +11339,31 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+ case Builtin::BI__builtin_elementwise_add_sat: {
+ APValue SourceLHS, SourceRHS;
+ if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
+ !EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
+ return false;
+
+ QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
+ unsigned SourceLen = SourceLHS.getVectorLength();
+ SmallVector<APValue, 4> ResultElements;
+ ResultElements.reserve(SourceLen);
+
+ for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+ APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt();
+ APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt();
+ switch (E->getBuiltinCallee()) {
+ case Builtin::BI__builtin_elementwise_add_sat:
+ ResultElements.push_back(APValue(
+ APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : RHS.uadd_sat(RHS),
+ DestEltTy->isUnsignedIntegerOrEnumerationType())));
+ break;
+ }
+ }
+
+ return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+ }
}
}
@@ -13204,6 +13229,16 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.rotr(Amt.urem(Val.getBitWidth())), E);
}
+ case Builtin::BI__builtin_elementwise_add_sat: {
+ APSInt LHS, RHS;
+ if (!EvaluateInteger(E->getArg(0), LHS, Info) ||
+ !EvaluateInteger(E->getArg(1), RHS, Info))
+ return false;
+
+ APInt Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
+ return Success(APSInt(Result, !LHS.isSigned()), E);
+ }
+
case Builtin::BIstrlen:
case Builtin::BIwcslen:
// A call to strlen is not a constant expression.
diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c
index 82f82dd1ed7944..832691a55e52a1 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -112,7 +112,7 @@ void test_builtin_elementwise_add_sat(float f1, float f2, double d1, double d2,
// CHECK-NEXT: call i32 @llvm.sadd.sat.i32(i32 [[IAS1]], i32 [[B]])
int_as_one = __builtin_elementwise_add_sat(int_as_one, b);
- // CHECK: call i32 @llvm.sadd.sat.i32(i32 1, i32 97)
+ // CHECK: store i64 98, ptr %i1.addr, align 8
i1 = __builtin_elementwise_add_sat(1, 'a');
}
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index 45c729f76418d1..b23889e3c82828 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -822,3 +822,11 @@ static_assert(__builtin_elementwise_bitreverse(0x12345678) == 0x1E6A2C48);
static_assert(__builtin_elementwise_bitreverse(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480);
static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_bitreverse((vector4char){1, 2, 4, 8})) == (LITTLE_END ? 0x10204080 : 0x80402010));
static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_bitreverse((vector4short){1, 2, 4, 8})) == (LITTLE_END ? 0x1000200040008000 : 0x8000400020001000));
+
+static_assert(__builtin_elementwise_add_sat(1, 2) == 3);
+static_assert(__builtin_elementwise_add_sat(1U, 2U) == 3U);
+static_assert(__builtin_elementwise_add_sat(~(1 << 31), 42) == ~(1 << 31));
+static_assert(__builtin_elementwise_add_sat((1 << 31), -42) == (1 << 31));
+static_assert(__builtin_elementwise_add_sat(~0U, 1U) == ~0U);
+static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_add_sat((vector4char){1, 2, 3, 4}, (vector4char){4, 3, 2, 1})) == (LITTLE_END ? 0x05050505 : 0x05050505));
+static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_add_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){-7, -8, -9, -10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000)));
>From b20f08c0e0fbc7a9db4d000cb8360c628c4cdd96 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 8 Dec 2024 18:19:34 +0800
Subject: [PATCH 2/3] merge release notes
---
clang/docs/ReleaseNotes.rst | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5aeda3ade7573a..0add3ef6e92124 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -408,13 +408,10 @@ Non-comprehensive list of changes in this release
The flexible array member (FAM) can now be accessed immediately without causing
issues with the sanitizer because the counter is automatically set.
-- ``__builtin_reduce_add`` function can now be used in constant expressions.
-- ``__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.
-- ``__builtin_elementwise_bitreverse`` function can now be used in constant expressions.
-- ``__builtin_elementwise_add_sat`` function can now be used in constant expressions.
+- The following builtins can now be used in constant expressions: ``__builtin_reduce_add``,
+ ``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
+ ``__builtin_reduce_xor``, ``__builtin_elementwise_popcount``,
+ ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``.
New Compiler Flags
------------------
>From 3ffcc789bc4cadb72f6edd994d2475de2db1d5b8 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 8 Dec 2024 20:52:53 +0800
Subject: [PATCH 3/3] implement constexpr sub sat
---
clang/docs/LanguageExtensions.rst | 4 ++--
clang/docs/ReleaseNotes.rst | 3 ++-
clang/include/clang/Basic/Builtins.td | 2 +-
clang/lib/AST/ExprConstant.cpp | 17 ++++++++++++++++-
clang/test/CodeGen/builtins-elementwise-math.c | 2 +-
clang/test/Sema/constant_builtins_vector.cpp | 8 ++++++++
6 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 40c0a0e5f1161c..6a886a49ea0762 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -648,8 +648,8 @@ elementwise to the input.
Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity
The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``,
-``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, can be
-called in a ``constexpr`` context.
+``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
+``__builtin_elementwise_sub_sat`` can be called in a ``constexpr`` context.
============================================== ====================================================================== =========================================
Name Operation Supported element types
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0add3ef6e92124..638db4aa4a3b9f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -411,7 +411,8 @@ Non-comprehensive list of changes in this release
- The following builtins can now be used in constant expressions: ``__builtin_reduce_add``,
``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
``__builtin_reduce_xor``, ``__builtin_elementwise_popcount``,
- ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``.
+ ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
+ ``__builtin_elementwise_sub_sat``.
New Compiler Flags
------------------
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 1186ece419fdd2..32a09e2ceb3857 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1456,7 +1456,7 @@ def ElementwiseAddSat : Builtin {
def ElementwiseSubSat : Builtin {
let Spellings = ["__builtin_elementwise_sub_sat"];
- 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 001773dc28dedc..86313fbde0b4a7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11339,7 +11339,8 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
- case Builtin::BI__builtin_elementwise_add_sat: {
+ case Builtin::BI__builtin_elementwise_add_sat:
+ case Builtin::BI__builtin_elementwise_sub_sat: {
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
@@ -11359,6 +11360,11 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : RHS.uadd_sat(RHS),
DestEltTy->isUnsignedIntegerOrEnumerationType())));
break;
+ case Builtin::BI__builtin_elementwise_sub_sat:
+ ResultElements.push_back(APValue(
+ APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : RHS.usub_sat(RHS),
+ DestEltTy->isUnsignedIntegerOrEnumerationType())));
+ break;
}
}
@@ -13238,6 +13244,15 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
APInt Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
return Success(APSInt(Result, !LHS.isSigned()), E);
}
+ case Builtin::BI__builtin_elementwise_sub_sat: {
+ APSInt LHS, RHS;
+ if (!EvaluateInteger(E->getArg(0), LHS, Info) ||
+ !EvaluateInteger(E->getArg(1), RHS, Info))
+ return false;
+
+ APInt Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
+ return Success(APSInt(Result, !LHS.isSigned()), E);
+ }
case Builtin::BIstrlen:
case Builtin::BIwcslen:
diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c
index 832691a55e52a1..7f6b5f26eb9307 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -165,7 +165,7 @@ void test_builtin_elementwise_sub_sat(float f1, float f2, double d1, double d2,
// CHECK-NEXT: call i32 @llvm.ssub.sat.i32(i32 [[IAS1]], i32 [[B]])
int_as_one = __builtin_elementwise_sub_sat(int_as_one, b);
- // CHECK: call i32 @llvm.ssub.sat.i32(i32 1, i32 97)
+ // CHECK: store i64 -96, ptr %i1.addr, align 8
i1 = __builtin_elementwise_sub_sat(1, 'a');
}
diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp
index b23889e3c82828..5632428e805019 100644
--- a/clang/test/Sema/constant_builtins_vector.cpp
+++ b/clang/test/Sema/constant_builtins_vector.cpp
@@ -830,3 +830,11 @@ static_assert(__builtin_elementwise_add_sat((1 << 31), -42) == (1 << 31));
static_assert(__builtin_elementwise_add_sat(~0U, 1U) == ~0U);
static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_add_sat((vector4char){1, 2, 3, 4}, (vector4char){4, 3, 2, 1})) == (LITTLE_END ? 0x05050505 : 0x05050505));
static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_add_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){-7, -8, -9, -10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000)));
+
+static_assert(__builtin_elementwise_sub_sat(1, 2) == -1);
+static_assert(__builtin_elementwise_sub_sat(2U, 1U) == 1U);
+static_assert(__builtin_elementwise_sub_sat(~(1 << 31), -42) == ~(1 << 31));
+static_assert(__builtin_elementwise_sub_sat((1 << 31), 42) == (1 << 31));
+static_assert(__builtin_elementwise_sub_sat(0U, 1U) == 0U);
+static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_sub_sat((vector4char){5, 4, 3, 2}, (vector4char){4, 3, 2, 1})) == (LITTLE_END ? 0x01010101 : 0x01010101));
+static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_sub_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){7, 8, 9, 10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000)));
More information about the cfe-commits
mailing list