[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
el-ev wrote: This PR is alive again. Kindly ping. https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -230,6 +230,9 @@ Non-comprehensive list of changes in this release
- Deprecated float types support from ``__builtin_elementwise_max`` and
``__builtin_elementwise_min``.
+- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` can now be
el-ev wrote:
Maybe constexpr `BI__builtin_elementwise_{max, min}num` makes more sense.
They're not in constant evaluator either.
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -230,6 +230,9 @@ Non-comprehensive list of changes in this release - Deprecated float types support from ``__builtin_elementwise_max`` and ``__builtin_elementwise_min``. +- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` can now be RKSimon wrote: Reading the release note entry immediately before this one makes we think this isn't worth it... https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/RKSimon edited https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/el-ev edited https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/153563 >From c7ad740d6fcb47681212b3b15648ad14e8ffaeb1 Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Thu, 7 May 2026 11:07:50 +0800 Subject: [PATCH] [clang] constexpr `__builtin_elementwise_{max,min}num` --- clang/docs/ReleaseNotes.rst | 3 + clang/lib/AST/ByteCode/InterpBuiltin.cpp | 122 +++ clang/lib/AST/ExprConstant.cpp | 48 +++- clang/test/Sema/constant-builtins-vector.cpp | 52 4 files changed, 115 insertions(+), 110 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c17143e3c0398..6a4d84d403e48 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -237,6 +237,9 @@ Non-comprehensive list of changes in this release - Deprecated float types support from ``__builtin_elementwise_max`` and ``__builtin_elementwise_min``. +- ``__builtin_elementwise_maxnum`` and ``__builtin_elementwise_minnum`` can now + be used in constant expressions. + - Added header ``endian.h`` which contains byte order helpers specified in POSIX - Added #pragma loop licm(disable) for llvm.loop.licm.disable metadata diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 11ca93c251380..4090a416250b5 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2621,13 +2621,29 @@ static bool interp__builtin_elementwise_fp_binop( Fn, bool IsScalar = false) { assert((Call->getNumArgs() == 2) || (Call->getNumArgs() == 3)); + + // Single floating-point case. + if (!Call->getArg(0)->getType()->isVectorType()) { +assert(!Call->getArg(1)->getType()->isVectorType()); +assert(Call->getNumArgs() == 2); +const Floating &RHS = S.Stk.pop(); +const Floating &LHS = S.Stk.pop(); +std::optional Result = +Fn(LHS.getAPFloat(), RHS.getAPFloat(), std::nullopt); +if (!Result) + return false; +Floating R = S.allocFloat(Result->getSemantics()); +R.copy(*Result); +S.Stk.push(R); +return true; + } + const auto *VT = Call->getArg(0)->getType()->castAs(); assert(VT->getElementType()->isFloatingType()); unsigned NumElems = VT->getNumElements(); // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); + assert(Call->getArg(1)->getType()->isVectorType()); assert(VT->getElementType() == Call->getArg(1)->getType()->castAs()->getElementType()); assert(VT->getNumElements() == @@ -2819,82 +2835,6 @@ interp__builtin_ia32_pack(InterpState &S, CodePtr, const CallExpr *E, return true; } -static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, - const CallExpr *Call, - unsigned BuiltinID) { - assert(Call->getNumArgs() == 2); - - QualType Arg0Type = Call->getArg(0)->getType(); - - // TODO: Support floating-point types. - if (!(Arg0Type->isIntegerType() || -(Arg0Type->isVectorType() && - Arg0Type->castAs()->getElementType()->isIntegerType( -return false; - - if (!Arg0Type->isVectorType()) { -assert(!Call->getArg(1)->getType()->isVectorType()); -APSInt RHS; -if (!popToAPSInt(S, Call->getArg(1), RHS)) - return false; -APSInt LHS; -if (!popToAPSInt(S, Arg0Type, LHS)) - return false; -APInt Result; -if (BuiltinID == Builtin::BI__builtin_elementwise_max) { - Result = std::max(LHS, RHS); -} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { - Result = std::min(LHS, RHS); -} else { - llvm_unreachable("Wrong builtin ID"); -} - -pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType()); -return true; - } - - // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); - const auto *VT = Call->getArg(0)->getType()->castAs(); - assert(VT->getElementType() == - Call->getArg(1)->getType()->castAs()->getElementType()); - assert(VT->getNumElements() == - Call->getArg(1)->getType()->castAs()->getNumElements()); - assert(VT->getElementType()->isIntegralOrEnumerationType()); - - const Pointer &RHS = S.Stk.pop(); - const Pointer &LHS = S.Stk.pop(); - const Pointer &Dst = S.Stk.peek(); - PrimType ElemT = *S.getContext().classify(VT->getElementType()); - unsigned NumElems = VT->getNumElements(); - for (unsigned I = 0; I != NumElems; ++I) { -APSInt Elem1; -APSInt Elem2; -INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.elem(I).toAPSInt(); - Elem2 = RHS.elem(I).toAPSInt(); -}); - -APSInt Result; -if (BuiltinID == Builtin::BI__builtin_elementwise_max) { - Result = APSInt(std::max(Elem1, Elem2), - Call->getType()->isUnsignedI
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
RKSimon wrote: > Is this still needed after #180885? If we intend to still support `__builtin_elementwise_max` for fp types then yes https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -873,6 +875,27 @@ static_assert(__builtin_elementwise_min(1, 2) == 1);
static_assert(__builtin_elementwise_min(-1, 1) == -1);
static_assert(__builtin_elementwise_min(1U, 2U) == 1U);
static_assert(__builtin_elementwise_min(~0U, 0U) == 0U);
+static_assert(__builtin_fabs(__builtin_elementwise_min(1.0f, 2.0f) - 1.0f) <
1e-6);
+static_assert(__builtin_fabs(__builtin_elementwise_min(-1.0f, 1.0f) - (-1.0f))
< 1e-6);
static_assert(__builtin_bit_cast(unsigned,
__builtin_elementwise_min((vector4char){1, -2, 3, -4}, (vector4char){4, -3, 2,
-1})) == (LITTLE_END ? 0xFC02FD01 : 0x01FD02FC));
static_assert(__builtin_bit_cast(unsigned,
__builtin_elementwise_min((vector4uchar){1, 2, 3, 4}, (vector4uchar){4, 3, 2,
1})) == 0x01020201U);
static_assert(__builtin_bit_cast(unsigned long long,
__builtin_elementwise_min((vector4short){1, -2, 3, -4}, (vector4short){4, -3,
2, -1})) == (LITTLE_END ? 0xFFFC0002FFFD0001 : 0x0001FFFD0002FFFC));
+
+#define CHECK_VECTOR4_FLOAT_EQ(v1, v2) \
+static_assert(__builtin_fabs((v1)[0] - (v2)[0]) < 1e-6 && \
+ __builtin_fabs((v1)[1] - (v2)[1]) < 1e-6 && \
+ __builtin_fabs((v1)[2] - (v2)[2]) < 1e-6 && \
+ __builtin_fabs((v1)[3] - (v2)[3]) < 1e-6);
+CHECK_VECTOR4_FLOAT_EQ(
+(__builtin_elementwise_max((vector4float){1.0f, -2.0f, 3.0f, -4.0f},
(vector4float){4.0f, -3.0f, 2.0f, -1.0f})),
el-ev wrote:
Added.
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/153563 >From 23c9920efdb4471fd81e78600c23674c54fa2f1f Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Thu, 7 May 2026 11:07:50 +0800 Subject: [PATCH] [clang] constexpr `__builtin_elementwise_{max,min}` --- clang/docs/ReleaseNotes.rst | 3 + clang/lib/AST/ByteCode/InterpBuiltin.cpp | 118 ++- clang/lib/AST/ExprConstant.cpp | 49 +++- clang/test/Sema/constant-builtins-vector.cpp | 63 +- 4 files changed, 114 insertions(+), 119 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cb19b80b7e994..de042ae1cc651 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -230,6 +230,9 @@ Non-comprehensive list of changes in this release - Deprecated float types support from ``__builtin_elementwise_max`` and ``__builtin_elementwise_min``. +- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` can now be + used in constant expressions for floating-point arguments. + - Added header ``endian.h`` which contains byte order helpers specified in POSIX - Added #pragma loop licm(disable) for llvm.loop.licm.disable metadata diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 11ca93c251380..e025712662582 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2621,13 +2621,29 @@ static bool interp__builtin_elementwise_fp_binop( Fn, bool IsScalar = false) { assert((Call->getNumArgs() == 2) || (Call->getNumArgs() == 3)); + + // Single floating-point case. + if (!Call->getArg(0)->getType()->isVectorType()) { +assert(!Call->getArg(1)->getType()->isVectorType()); +assert(Call->getNumArgs() == 2); +const Floating &RHS = S.Stk.pop(); +const Floating &LHS = S.Stk.pop(); +std::optional Result = +Fn(LHS.getAPFloat(), RHS.getAPFloat(), std::nullopt); +if (!Result) + return false; +Floating R = S.allocFloat(Result->getSemantics()); +R.copy(*Result); +S.Stk.push(R); +return true; + } + const auto *VT = Call->getArg(0)->getType()->castAs(); assert(VT->getElementType()->isFloatingType()); unsigned NumElems = VT->getNumElements(); // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); + assert(Call->getArg(1)->getType()->isVectorType()); assert(VT->getElementType() == Call->getArg(1)->getType()->castAs()->getElementType()); assert(VT->getNumElements() == @@ -2819,82 +2835,6 @@ interp__builtin_ia32_pack(InterpState &S, CodePtr, const CallExpr *E, return true; } -static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, - const CallExpr *Call, - unsigned BuiltinID) { - assert(Call->getNumArgs() == 2); - - QualType Arg0Type = Call->getArg(0)->getType(); - - // TODO: Support floating-point types. - if (!(Arg0Type->isIntegerType() || -(Arg0Type->isVectorType() && - Arg0Type->castAs()->getElementType()->isIntegerType( -return false; - - if (!Arg0Type->isVectorType()) { -assert(!Call->getArg(1)->getType()->isVectorType()); -APSInt RHS; -if (!popToAPSInt(S, Call->getArg(1), RHS)) - return false; -APSInt LHS; -if (!popToAPSInt(S, Arg0Type, LHS)) - return false; -APInt Result; -if (BuiltinID == Builtin::BI__builtin_elementwise_max) { - Result = std::max(LHS, RHS); -} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { - Result = std::min(LHS, RHS); -} else { - llvm_unreachable("Wrong builtin ID"); -} - -pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType()); -return true; - } - - // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); - const auto *VT = Call->getArg(0)->getType()->castAs(); - assert(VT->getElementType() == - Call->getArg(1)->getType()->castAs()->getElementType()); - assert(VT->getNumElements() == - Call->getArg(1)->getType()->castAs()->getNumElements()); - assert(VT->getElementType()->isIntegralOrEnumerationType()); - - const Pointer &RHS = S.Stk.pop(); - const Pointer &LHS = S.Stk.pop(); - const Pointer &Dst = S.Stk.peek(); - PrimType ElemT = *S.getContext().classify(VT->getElementType()); - unsigned NumElems = VT->getNumElements(); - for (unsigned I = 0; I != NumElems; ++I) { -APSInt Elem1; -APSInt Elem2; -INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.elem(I).toAPSInt(); - Elem2 = RHS.elem(I).toAPSInt(); -}); - -APSInt Result; -if (BuiltinID == Builtin::BI__builtin_elementwise_max) { - Result = APSInt(std::max(Elem1, Elem2), - Call->
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
el-ev wrote: Is this still needed after https://github.com/llvm/llvm-project/pull/180885? https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -2339,68 +2339,88 @@ static bool
interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 2);
QualType Arg0Type = Call->getArg(0)->getType();
+ QualType Arg1Type = Call->getArg(1)->getType();
- // TODO: Support floating-point types.
- if (!(Arg0Type->isIntegerType() ||
-(Arg0Type->isVectorType() &&
- Arg0Type->castAs()->getElementType()->isIntegerType(
-return false;
-
- if (!Arg0Type->isVectorType()) {
-assert(!Call->getArg(1)->getType()->isVectorType());
-APSInt RHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
-APSInt LHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
-APInt Result;
+ if (Arg0Type->isIntegerType()) {
+assert(Arg1Type->isIntegerType());
+APSInt RHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type));
+APSInt LHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type));
+APSInt Result;
if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
Result = std::max(LHS, RHS);
} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
Result = std::min(LHS, RHS);
} else {
llvm_unreachable("Wrong builtin ID");
}
+pushInteger(S, Result, Call->getType());
+return true;
+ }
-pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
+ if (Arg0Type->isRealFloatingType()) {
+assert(Arg1Type->isRealFloatingType());
+APFloat RHS = S.Stk.pop().getAPFloat();
+APFloat LHS = S.Stk.pop().getAPFloat();
+Floating Result = S.allocFloat(RHS.getSemantics());
+if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
RKSimon wrote:
we now have interp__builtin_elementwise_int_binop /
interp__builtin_elementwise_fp_binop that could handle this
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/RKSimon requested changes to this pull request. https://github.com/llvm/llvm-project/pull/153563 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -873,6 +875,27 @@ static_assert(__builtin_elementwise_min(1, 2) == 1);
static_assert(__builtin_elementwise_min(-1, 1) == -1);
static_assert(__builtin_elementwise_min(1U, 2U) == 1U);
static_assert(__builtin_elementwise_min(~0U, 0U) == 0U);
+static_assert(__builtin_fabs(__builtin_elementwise_min(1.0f, 2.0f) - 1.0f) <
1e-6);
+static_assert(__builtin_fabs(__builtin_elementwise_min(-1.0f, 1.0f) - (-1.0f))
< 1e-6);
static_assert(__builtin_bit_cast(unsigned,
__builtin_elementwise_min((vector4char){1, -2, 3, -4}, (vector4char){4, -3, 2,
-1})) == (LITTLE_END ? 0xFC02FD01 : 0x01FD02FC));
static_assert(__builtin_bit_cast(unsigned,
__builtin_elementwise_min((vector4uchar){1, 2, 3, 4}, (vector4uchar){4, 3, 2,
1})) == 0x01020201U);
static_assert(__builtin_bit_cast(unsigned long long,
__builtin_elementwise_min((vector4short){1, -2, 3, -4}, (vector4short){4, -3,
2, -1})) == (LITTLE_END ? 0xFFFC0002FFFD0001 : 0x0001FFFD0002FFFC));
+
+#define CHECK_VECTOR4_FLOAT_EQ(v1, v2) \
+static_assert(__builtin_fabs((v1)[0] - (v2)[0]) < 1e-6 && \
+ __builtin_fabs((v1)[1] - (v2)[1]) < 1e-6 && \
+ __builtin_fabs((v1)[2] - (v2)[2]) < 1e-6 && \
+ __builtin_fabs((v1)[3] - (v2)[3]) < 1e-6);
+CHECK_VECTOR4_FLOAT_EQ(
+(__builtin_elementwise_max((vector4float){1.0f, -2.0f, 3.0f, -4.0f},
(vector4float){4.0f, -3.0f, 2.0f, -1.0f})),
shafik wrote:
Can we get NaN and Inf tests?
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
@@ -2339,68 +2339,88 @@ static bool
interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 2);
QualType Arg0Type = Call->getArg(0)->getType();
+ QualType Arg1Type = Call->getArg(1)->getType();
- // TODO: Support floating-point types.
- if (!(Arg0Type->isIntegerType() ||
-(Arg0Type->isVectorType() &&
- Arg0Type->castAs()->getElementType()->isIntegerType(
-return false;
-
- if (!Arg0Type->isVectorType()) {
-assert(!Call->getArg(1)->getType()->isVectorType());
-APSInt RHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
-APSInt LHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
-APInt Result;
+ if (Arg0Type->isIntegerType()) {
+assert(Arg1Type->isIntegerType());
+APSInt RHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type));
+APSInt LHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type));
+APSInt Result;
if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
Result = std::max(LHS, RHS);
} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
Result = std::min(LHS, RHS);
} else {
llvm_unreachable("Wrong builtin ID");
}
+pushInteger(S, Result, Call->getType());
+return true;
+ }
-pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
+ if (Arg0Type->isRealFloatingType()) {
+assert(Arg1Type->isRealFloatingType());
+APFloat RHS = S.Stk.pop().getAPFloat();
+APFloat LHS = S.Stk.pop().getAPFloat();
+Floating Result = S.allocFloat(RHS.getSemantics());
+if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
ckoparkar wrote:
Perhaps it's worth creating helpers to reduce repetition? Something along the
lines of these:
```c++
auto CompareInts = [&BuiltinID](const APSInt &X, const APSInt &Y, APSInt
&Result) {
if (BuiltinID == Builtin::BI__builtin_elementwise_max)
Result = std::max(X, Y);
else if (BuiltinID == Builtin::BI__builtin_elementwise_min)
Result = std::min(X, Y);
else
llvm_unreachable("Wrong builtin ID");
};
auto CompareFloats = [&BuiltinID](const APFloat &X, const APFloat &Y, Floating
&Result) {
if (BuiltinID == Builtin::BI__builtin_elementwise_max)
Result.copy(maxnum(X, Y));
else if (BuiltinID == Builtin::BI__builtin_elementwise_min)
Result.copy(minnum(X, Y));
else
llvm_unreachable("Wrong builtin ID");
};
```
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/153563 >From e43d3d00a7516d538fcd00b7b5635545739b19b4 Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Thu, 14 Aug 2025 18:08:44 +0800 Subject: [PATCH] [clang] constexpr `__builtin_elementwise_{max,min}` --- clang/docs/ReleaseNotes.rst | 4 +- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 102 +++ clang/lib/AST/ExprConstant.cpp | 52 ++ clang/test/Sema/constant-builtins-vector.cpp | 23 + 4 files changed, 120 insertions(+), 61 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d109518bca3f3..5d623bf73fea0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -126,8 +126,8 @@ Non-comprehensive list of changes in this release This feature is enabled by default but can be disabled by compiling with ``-fno-sanitize-annotate-debug-info-traps``. -- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions for integer types can - now be used in constant expressions. +- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions can now be used in + constant expressions. New Compiler Flags -- diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index ee2d532551583..cb5c981c05459 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2339,20 +2339,13 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, assert(Call->getNumArgs() == 2); QualType Arg0Type = Call->getArg(0)->getType(); + QualType Arg1Type = Call->getArg(1)->getType(); - // TODO: Support floating-point types. - if (!(Arg0Type->isIntegerType() || -(Arg0Type->isVectorType() && - Arg0Type->castAs()->getElementType()->isIntegerType( -return false; - - if (!Arg0Type->isVectorType()) { -assert(!Call->getArg(1)->getType()->isVectorType()); -APSInt RHS = popToAPSInt( -S.Stk, *S.getContext().classify(Call->getArg(1)->getType())); -APSInt LHS = popToAPSInt( -S.Stk, *S.getContext().classify(Call->getArg(0)->getType())); -APInt Result; + if (Arg0Type->isIntegerType()) { +assert(Arg1Type->isIntegerType()); +APSInt RHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type)); +APSInt LHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type)); +APSInt Result; if (BuiltinID == Builtin::BI__builtin_elementwise_max) { Result = std::max(LHS, RHS); } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { @@ -2360,47 +2353,74 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, } else { llvm_unreachable("Wrong builtin ID"); } +pushInteger(S, Result, Call->getType()); +return true; + } -pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType()); + if (Arg0Type->isRealFloatingType()) { +assert(Arg1Type->isRealFloatingType()); +APFloat RHS = S.Stk.pop().getAPFloat(); +APFloat LHS = S.Stk.pop().getAPFloat(); +Floating Result = S.allocFloat(RHS.getSemantics()); +if (BuiltinID == Builtin::BI__builtin_elementwise_max) { + Result.copy(maxnum(LHS, RHS)); +} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { + Result.copy(minnum(LHS, RHS)); +} else { + llvm_unreachable("Wrong builtin ID"); +} +S.Stk.push(Result); return true; } // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); - const auto *VT = Call->getArg(0)->getType()->castAs(); - assert(VT->getElementType() == - Call->getArg(1)->getType()->castAs()->getElementType()); - assert(VT->getNumElements() == - Call->getArg(1)->getType()->castAs()->getNumElements()); - assert(VT->getElementType()->isIntegralOrEnumerationType()); + assert(Arg0Type->isVectorType() && Arg1Type->isVectorType()); + + const auto *VT = Arg0Type->castAs(); + QualType ElemType = VT->getElementType(); + unsigned NumElems = VT->getNumElements(); + + assert(ElemType == Arg1Type->castAs()->getElementType()); + assert(NumElems == Arg1Type->castAs()->getNumElements()); + assert(ElemType->isIntegerType() || ElemType->isRealFloatingType()); const Pointer &RHS = S.Stk.pop(); const Pointer &LHS = S.Stk.pop(); const Pointer &Dst = S.Stk.peek(); - PrimType ElemT = *S.getContext().classify(VT->getElementType()); - unsigned NumElems = VT->getNumElements(); + PrimType ElemT = *S.getContext().classify(ElemType); for (unsigned I = 0; I != NumElems; ++I) { -APSInt Elem1; -APSInt Elem2; -INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.elem(I).toAPSInt(); - Elem2 = RHS.elem(I).toAPSInt(); -}); +if (ElemType->isIntegerType()) { + APSInt LHSInt; + APSInt RHSInt; + INT_TYPE_SW
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
github-actions[bot] wrote:
:warning: C/C++ code formatter, clang-format found issues in your code.
:warning:
You can test this locally with the following command:
``bash
git-clang-format --diff HEAD~1 HEAD --extensions cpp --
clang/lib/AST/ByteCode/InterpBuiltin.cpp clang/lib/AST/ExprConstant.cpp
clang/test/Sema/constant-builtins-vector.cpp
``
View the diff from clang-format here.
``diff
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 5375b184b..cb5c981c0 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2396,7 +2396,7 @@ static bool
interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
LHSInt = LHS.elem(I).toAPSInt();
RHSInt = RHS.elem(I).toAPSInt();
});
-
+
APSInt Result;
if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
Result = std::max(LHSInt, RHSInt);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b232cd4a7..6eb1fec44 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11710,12 +11710,14 @@ bool VectorExprEvaluator::VisitCallExpr(const
CallExpr *E) {
APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt();
switch (E->getBuiltinCallee()) {
case Builtin::BI__builtin_elementwise_max:
- ResultElt = APValue(APSInt(std::max(LHS, RHS),
-
DestEltTy->isUnsignedIntegerOrEnumerationType()));
+ ResultElt =
+ APValue(APSInt(std::max(LHS, RHS),
+ DestEltTy->isUnsignedIntegerOrEnumerationType()));
break;
case Builtin::BI__builtin_elementwise_min:
- ResultElt = APValue(APSInt(std::min(LHS, RHS),
-
DestEltTy->isUnsignedIntegerOrEnumerationType()));
+ ResultElt =
+ APValue(APSInt(std::min(LHS, RHS),
+ DestEltTy->isUnsignedIntegerOrEnumerationType()));
break;
}
} else if (DestEltTy->isRealFloatingType()) {
@@ -15929,7 +15931,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr
*E) {
case Builtin::BI__builtin_fmaxf:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf16:
- case Builtin::BI__builtin_fmaxf128:
+ case Builtin::BI__builtin_fmaxf128:
case Builtin::BI__builtin_elementwise_max: {
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
``
https://github.com/llvm/llvm-project/pull/153563
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: Iris Shi (el-ev)
Changes
- Followup of #152294
Added floating point support.
---
Full diff: https://github.com/llvm/llvm-project/pull/153563.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2-2)
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+61-41)
- (modified) clang/lib/AST/ExprConstant.cpp (+32-18)
- (modified) clang/test/Sema/constant-builtins-vector.cpp (+23)
``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d109518bca3f3..5d623bf73fea0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -126,8 +126,8 @@ Non-comprehensive list of changes in this release
This feature is enabled by default but can be disabled by compiling with
``-fno-sanitize-annotate-debug-info-traps``.
-- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions
for integer types can
- now be used in constant expressions.
+- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions
can now be used in
+ constant expressions.
New Compiler Flags
--
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index ee2d532551583..5375b184ba378 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2339,20 +2339,13 @@ static bool
interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 2);
QualType Arg0Type = Call->getArg(0)->getType();
+ QualType Arg1Type = Call->getArg(1)->getType();
- // TODO: Support floating-point types.
- if (!(Arg0Type->isIntegerType() ||
-(Arg0Type->isVectorType() &&
- Arg0Type->castAs()->getElementType()->isIntegerType(
-return false;
-
- if (!Arg0Type->isVectorType()) {
-assert(!Call->getArg(1)->getType()->isVectorType());
-APSInt RHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
-APSInt LHS = popToAPSInt(
-S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
-APInt Result;
+ if (Arg0Type->isIntegerType()) {
+assert(Arg1Type->isIntegerType());
+APSInt RHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type));
+APSInt LHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type));
+APSInt Result;
if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
Result = std::max(LHS, RHS);
} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
@@ -2360,47 +2353,74 @@ static bool
interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
} else {
llvm_unreachable("Wrong builtin ID");
}
+pushInteger(S, Result, Call->getType());
+return true;
+ }
-pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
+ if (Arg0Type->isRealFloatingType()) {
+assert(Arg1Type->isRealFloatingType());
+APFloat RHS = S.Stk.pop().getAPFloat();
+APFloat LHS = S.Stk.pop().getAPFloat();
+Floating Result = S.allocFloat(RHS.getSemantics());
+if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
+ Result.copy(maxnum(LHS, RHS));
+} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
+ Result.copy(minnum(LHS, RHS));
+} else {
+ llvm_unreachable("Wrong builtin ID");
+}
+S.Stk.push(Result);
return true;
}
// Vector case.
- assert(Call->getArg(0)->getType()->isVectorType() &&
- Call->getArg(1)->getType()->isVectorType());
- const auto *VT = Call->getArg(0)->getType()->castAs();
- assert(VT->getElementType() ==
- Call->getArg(1)->getType()->castAs()->getElementType());
- assert(VT->getNumElements() ==
- Call->getArg(1)->getType()->castAs()->getNumElements());
- assert(VT->getElementType()->isIntegralOrEnumerationType());
+ assert(Arg0Type->isVectorType() && Arg1Type->isVectorType());
+
+ const auto *VT = Arg0Type->castAs();
+ QualType ElemType = VT->getElementType();
+ unsigned NumElems = VT->getNumElements();
+
+ assert(ElemType == Arg1Type->castAs()->getElementType());
+ assert(NumElems == Arg1Type->castAs()->getNumElements());
+ assert(ElemType->isIntegerType() || ElemType->isRealFloatingType());
const Pointer &RHS = S.Stk.pop();
const Pointer &LHS = S.Stk.pop();
const Pointer &Dst = S.Stk.peek();
- PrimType ElemT = *S.getContext().classify(VT->getElementType());
- unsigned NumElems = VT->getNumElements();
+ PrimType ElemT = *S.getContext().classify(ElemType);
for (unsigned I = 0; I != NumElems; ++I) {
-APSInt Elem1;
-APSInt Elem2;
-INT_TYPE_SWITCH_NO_BOOL(ElemT, {
- Elem1 = LHS.elem(I).toAPSInt();
- Elem2 = RHS.elem(I).toAPSInt();
-});
+if (ElemType->isIntegerType()) {
+ APSInt LHSInt;
+ APSInt RHSInt;
+ INT_TYPE_SWITCH_NO_BOOL(ElemT, {
+LHSInt = LHS.elem(I).toAPSInt();
+RHSInt = RHS.elem(I).toAPSInt();
+ });
+
[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)
https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/153563 - Followup of #152294 Added floating point support. >From 53685d699f856ccd6bf956e43ed4f29f059c6fca Mon Sep 17 00:00:00 2001 From: Iris Shi <[email protected]> Date: Thu, 14 Aug 2025 18:08:44 +0800 Subject: [PATCH] [clang] constexpr `__builtin_elementwise_{max,min}` --- clang/docs/ReleaseNotes.rst | 4 +- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 102 +++ clang/lib/AST/ExprConstant.cpp | 50 + clang/test/Sema/constant-builtins-vector.cpp | 23 + 4 files changed, 118 insertions(+), 61 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d109518bca3f3..5d623bf73fea0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -126,8 +126,8 @@ Non-comprehensive list of changes in this release This feature is enabled by default but can be disabled by compiling with ``-fno-sanitize-annotate-debug-info-traps``. -- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions for integer types can - now be used in constant expressions. +- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions can now be used in + constant expressions. New Compiler Flags -- diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index ee2d532551583..5375b184ba378 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2339,20 +2339,13 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, assert(Call->getNumArgs() == 2); QualType Arg0Type = Call->getArg(0)->getType(); + QualType Arg1Type = Call->getArg(1)->getType(); - // TODO: Support floating-point types. - if (!(Arg0Type->isIntegerType() || -(Arg0Type->isVectorType() && - Arg0Type->castAs()->getElementType()->isIntegerType( -return false; - - if (!Arg0Type->isVectorType()) { -assert(!Call->getArg(1)->getType()->isVectorType()); -APSInt RHS = popToAPSInt( -S.Stk, *S.getContext().classify(Call->getArg(1)->getType())); -APSInt LHS = popToAPSInt( -S.Stk, *S.getContext().classify(Call->getArg(0)->getType())); -APInt Result; + if (Arg0Type->isIntegerType()) { +assert(Arg1Type->isIntegerType()); +APSInt RHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type)); +APSInt LHS = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type)); +APSInt Result; if (BuiltinID == Builtin::BI__builtin_elementwise_max) { Result = std::max(LHS, RHS); } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { @@ -2360,47 +2353,74 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, } else { llvm_unreachable("Wrong builtin ID"); } +pushInteger(S, Result, Call->getType()); +return true; + } -pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType()); + if (Arg0Type->isRealFloatingType()) { +assert(Arg1Type->isRealFloatingType()); +APFloat RHS = S.Stk.pop().getAPFloat(); +APFloat LHS = S.Stk.pop().getAPFloat(); +Floating Result = S.allocFloat(RHS.getSemantics()); +if (BuiltinID == Builtin::BI__builtin_elementwise_max) { + Result.copy(maxnum(LHS, RHS)); +} else if (BuiltinID == Builtin::BI__builtin_elementwise_min) { + Result.copy(minnum(LHS, RHS)); +} else { + llvm_unreachable("Wrong builtin ID"); +} +S.Stk.push(Result); return true; } // Vector case. - assert(Call->getArg(0)->getType()->isVectorType() && - Call->getArg(1)->getType()->isVectorType()); - const auto *VT = Call->getArg(0)->getType()->castAs(); - assert(VT->getElementType() == - Call->getArg(1)->getType()->castAs()->getElementType()); - assert(VT->getNumElements() == - Call->getArg(1)->getType()->castAs()->getNumElements()); - assert(VT->getElementType()->isIntegralOrEnumerationType()); + assert(Arg0Type->isVectorType() && Arg1Type->isVectorType()); + + const auto *VT = Arg0Type->castAs(); + QualType ElemType = VT->getElementType(); + unsigned NumElems = VT->getNumElements(); + + assert(ElemType == Arg1Type->castAs()->getElementType()); + assert(NumElems == Arg1Type->castAs()->getNumElements()); + assert(ElemType->isIntegerType() || ElemType->isRealFloatingType()); const Pointer &RHS = S.Stk.pop(); const Pointer &LHS = S.Stk.pop(); const Pointer &Dst = S.Stk.peek(); - PrimType ElemT = *S.getContext().classify(VT->getElementType()); - unsigned NumElems = VT->getNumElements(); + PrimType ElemT = *S.getContext().classify(ElemType); for (unsigned I = 0; I != NumElems; ++I) { -APSInt Elem1; -APSInt Elem2; -INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.elem(I).toAPSInt(); - Elem2 = RHS.elem(I).toAPSInt(); -}); +if (ElemType->isIntegerType()) { + AP
