[clang] [clang] constexpr `__builtin_elementwise_{max, min}` (PR #153563)

2026-05-10 Thread Iris Shi via cfe-commits

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)

2026-05-10 Thread Iris Shi via cfe-commits


@@ -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)

2026-05-10 Thread Simon Pilgrim via cfe-commits


@@ -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)

2026-05-10 Thread Simon Pilgrim via cfe-commits

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)

2026-05-10 Thread Iris Shi via cfe-commits

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)

2026-05-10 Thread Iris Shi via cfe-commits

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)

2026-05-07 Thread Simon Pilgrim via cfe-commits

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)

2026-05-06 Thread Iris Shi via cfe-commits


@@ -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)

2026-05-06 Thread Iris Shi via cfe-commits

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)

2026-05-06 Thread Iris Shi via cfe-commits

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)

2026-03-16 Thread Simon Pilgrim via cfe-commits


@@ -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)

2026-03-16 Thread Simon Pilgrim via cfe-commits

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)

2025-08-29 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2025-08-29 Thread Chaitanya Koparkar via cfe-commits


@@ -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)

2025-08-14 Thread Iris Shi via cfe-commits

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)

2025-08-14 Thread via cfe-commits

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)

2025-08-14 Thread via cfe-commits

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)

2025-08-14 Thread Iris Shi via cfe-commits

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