https://github.com/Mr-Anyone updated 
https://github.com/llvm/llvm-project/pull/152497

>From b48993d25136a769b3b7bf8e8730be1a92ace067 Mon Sep 17 00:00:00 2001
From: Vincent <l...@viceroygroup.ca>
Date: Thu, 7 Aug 2025 00:24:55 +0800
Subject: [PATCH 1/2] [clang] constexpr __builtin_elementwise_abs support

Added constant evaluation of `__builtine_elementwise_abs`
on integer and vector type.

fixes #152276
---
 clang/docs/LanguageExtensions.rst             |  3 +-
 clang/docs/ReleaseNotes.rst                   |  2 +
 clang/include/clang/Basic/Builtins.td         |  2 +-
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      | 46 +++++++++++++++++++
 clang/lib/AST/ExprConstant.cpp                | 16 +++++++
 .../test/CodeGen/builtins-elementwise-math.c  |  2 +-
 clang/test/Sema/constant-builtins-vector.cpp  |  6 +++
 7 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index eef3d0c4ccb9d..2db1bae918ada 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -760,7 +760,8 @@ Unless specified otherwise operation(±0) = ±0 and 
operation(±infinity) = ±in
 The integer elementwise intrinsics, including 
``__builtin_elementwise_popcount``,
 ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
 ``__builtin_elementwise_sub_sat``, ``__builtin_elementwise_max``,
-``__builtin_elementwise_min`` can be called in a ``constexpr`` context.
+``__builtin_elementwise_min``, and ``__builtin_elementwise_abs`` 
+can be called in a ``constexpr`` context.
 
 No implicit promotion of integer types takes place. The mixing of integer types
 of different sizes and signs is forbidden in binary and ternary builtins.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index af576f817700a..b5e2f81bc0527 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -115,6 +115,8 @@ Non-comprehensive list of changes in this release
 -------------------------------------------------
 - Added ``__builtin_elementwise_fshl`` and ``__builtin_elementwise_fshr``.
 
+- Added `__builtin_elementwise_abs`.
+
 - Added ``__builtin_elementwise_minnumnum`` and 
``__builtin_elementwise_maxnumnum``.
 
 - Trapping UBSan (e.g. ``-fsanitize-trap=undefined``) now emits a string 
describing the reason for
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 84206cf8b368b..604c9cddfe051 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1264,7 +1264,7 @@ def NondetermenisticValue : Builtin {
 
 def ElementwiseAbs : Builtin {
   let Spellings = ["__builtin_elementwise_abs"];
-  let Attributes = [NoThrow, Const, CustomTypeChecking];
+  let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
   let Prototype = "void(...)";
 }
 
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 307b77846969f..ebf82486698eb 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1686,6 +1686,49 @@ static bool interp__builtin_vector_reduce(InterpState 
&S, CodePtr OpPC,
   return true;
 }
 
+static bool interp__builtin_elementwise_abs(InterpState &S, CodePtr OpPC,
+                                            const InterpFrame *Frame,
+                                            const CallExpr *Call,
+                                            unsigned BuiltinID) {
+  // FIXME: add support of floating point
+  assert(!Call->getArg(0)->getType()->isFloatingType() &&
+         "floating point is currently not supported");
+
+  assert(Call->getNumArgs() == 1);
+  if (Call->getArg(0)->getType()->isIntegerType()) {
+    PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
+    APSInt Val = popToAPSInt(S.Stk, ArgT);
+
+    pushInteger(S, Val.abs(), Call->getType());
+    return true;
+  }
+
+  // Otherwise, the argument must be a vector.
+  assert(Call->getArg(0)->getType()->isVectorType());
+  const Pointer &Arg = S.Stk.pop<Pointer>();
+  assert(Arg.getFieldDesc()->isPrimitiveArray());
+  const Pointer &Dst = S.Stk.peek<Pointer>();
+  assert(Dst.getFieldDesc()->isPrimitiveArray());
+  assert(Arg.getFieldDesc()->getNumElems() ==
+         Dst.getFieldDesc()->getNumElems());
+
+  QualType ElemType = Arg.getFieldDesc()->getElemQualType();
+  PrimType ElemT = *S.getContext().classify(ElemType);
+  unsigned NumElems = Arg.getNumElems();
+
+  // FIXME: Reading from uninitialized vector elements?
+  for (unsigned I = 0; I != NumElems; ++I) {
+    INT_TYPE_SWITCH_NO_BOOL(ElemT, {
+      Dst.elem<T>(I) = T::from(static_cast<T>(
+          APSInt(Arg.elem<T>(I).toAPSInt().abs(),
+                 ElemType->isUnsignedIntegerOrEnumerationType())));
+    });
+  }
+  Dst.initializeAllElements();
+
+  return true;
+}
+
 /// Can be called with an integer or vector as the first and only parameter.
 static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
                                                  const InterpFrame *Frame,
@@ -2766,6 +2809,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const 
CallExpr *Call,
     return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call,
                                                 BuiltinID);
 
+  case Builtin::BI__builtin_elementwise_abs:
+    return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);
+
   case Builtin::BI__builtin_memcpy:
   case Builtin::BImemcpy:
   case Builtin::BI__builtin_wmemcpy:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 36dd0f5d7a065..1c8d9706788c4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11610,6 +11610,7 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr 
*E) {
   switch (E->getBuiltinCallee()) {
   default:
     return false;
+  case Builtin::BI__builtin_elementwise_abs:
   case Builtin::BI__builtin_elementwise_popcount:
   case Builtin::BI__builtin_elementwise_bitreverse: {
     APValue Source;
@@ -11634,11 +11635,18 @@ bool VectorExprEvaluator::VisitCallExpr(const 
CallExpr *E) {
             APValue(APSInt(Elt.reverseBits(),
                            DestEltTy->isUnsignedIntegerOrEnumerationType())));
         break;
+      case Builtin::BI__builtin_elementwise_abs: {
+        APInt Val = Source.getVectorElt(EltNum).getInt().abs();
+        ResultElements.push_back(APValue(
+            APSInt(Val, DestEltTy->isUnsignedIntegerOrEnumerationType())));
+        break;
+      }
       }
     }
 
     return Success(APValue(ResultElements.data(), ResultElements.size()), E);
   }
+
   case Builtin::BI__builtin_elementwise_add_sat:
   case Builtin::BI__builtin_elementwise_sub_sat:
   case clang::X86::BI__builtin_ia32_pmulhuw128:
@@ -13387,6 +13395,14 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const 
CallExpr *E,
     return Success(Operand, E);
   }
 
+  case Builtin::BI__builtin_elementwise_abs: {
+    APSInt Val;
+    if (!EvaluateInteger(E->getArg(0), Val, Info))
+      return false;
+
+    return Success(Val.abs(), E);
+  }
+
   case Builtin::BI__builtin_expect:
   case Builtin::BI__builtin_expect_with_probability:
     return Visit(E->getArg(0));
diff --git a/clang/test/CodeGen/builtins-elementwise-math.c 
b/clang/test/CodeGen/builtins-elementwise-math.c
index bb5d0351db1a2..e37e5353603a0 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -66,7 +66,7 @@ void test_builtin_elementwise_abs(float f1, float f2, double 
d1, double d2,
   // CHECK-NEXT: call i32 @llvm.abs.i32(i32 [[IA1]], i1 false)
   b = __builtin_elementwise_abs(int_as_one);
 
-  // CHECK:   call i32 @llvm.abs.i32(i32 -10, i1 false)
+  // CHECK:   store i32 %elt.abs11, ptr @b, align 4
   b = __builtin_elementwise_abs(-10);
 
   // CHECK:      [[SI:%.+]] = load i16, ptr %si.addr, align 2
diff --git a/clang/test/Sema/constant-builtins-vector.cpp 
b/clang/test/Sema/constant-builtins-vector.cpp
index bc575dca98d77..85fb4930d09c0 100644
--- a/clang/test/Sema/constant-builtins-vector.cpp
+++ b/clang/test/Sema/constant-builtins-vector.cpp
@@ -876,3 +876,9 @@ static_assert(__builtin_elementwise_min(~0U, 0U) == 0U);
 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));
+
+static_assert(__builtin_elementwise_abs(10) == 10);
+static_assert(__builtin_elementwise_abs(-10) == 10);
+static_assert(__builtin_bit_cast(unsigned, 
__builtin_elementwise_abs((vector4char){-1, -2, -3, 4})) == (LITTLE_END ? 
0x04030201 : 0x01020304));
+// the absolute value of the most negative integer remains the most negative 
integer
+static_assert(__builtin_elementwise_abs((int)(-2147483648)) == 
(int)(-2147483648));

>From 299c16bedeefba098daeb0c72273d58028cdb654 Mon Sep 17 00:00:00 2001
From: Vincent <l...@viceroygroup.ca>
Date: Thu, 14 Aug 2025 00:34:44 +0800
Subject: [PATCH 2/2] Added Floating Support and More Floating Point Test Case

---
 clang/lib/AST/ByteCode/InterpBuiltin.cpp     | 45 +++++++++++++++-----
 clang/lib/AST/ExprConstant.cpp               | 31 +++++++++++---
 clang/test/Sema/constant-builtins-vector.cpp | 16 ++++++-
 3 files changed, 72 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index ebf82486698eb..538917cd0a243 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1690,19 +1690,30 @@ static bool interp__builtin_elementwise_abs(InterpState 
&S, CodePtr OpPC,
                                             const InterpFrame *Frame,
                                             const CallExpr *Call,
                                             unsigned BuiltinID) {
-  // FIXME: add support of floating point
-  assert(!Call->getArg(0)->getType()->isFloatingType() &&
-         "floating point is currently not supported");
-
   assert(Call->getNumArgs() == 1);
   if (Call->getArg(0)->getType()->isIntegerType()) {
     PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
-    APSInt Val = popToAPSInt(S.Stk, ArgT);
 
+    APSInt Val = popToAPSInt(S.Stk, ArgT);
     pushInteger(S, Val.abs(), Call->getType());
     return true;
   }
 
+  if (Call->getArg(0)->getType()->isFloatingType()) {
+    Floating Val = S.Stk.pop<Floating>();
+    if (!Val.isNegative()) {
+      S.Stk.push<Floating>(Val);
+      return true;
+    }
+
+    APFloat F = Val.getAPFloat();
+    F.changeSign();
+    Floating Result = S.allocFloat(Val.getSemantics());
+    Result.copy(F);
+    S.Stk.push<Floating>(Result);
+    return true;
+  }
+
   // Otherwise, the argument must be a vector.
   assert(Call->getArg(0)->getType()->isVectorType());
   const Pointer &Arg = S.Stk.pop<Pointer>();
@@ -1716,13 +1727,25 @@ static bool interp__builtin_elementwise_abs(InterpState 
&S, CodePtr OpPC,
   PrimType ElemT = *S.getContext().classify(ElemType);
   unsigned NumElems = Arg.getNumElems();
 
-  // FIXME: Reading from uninitialized vector elements?
   for (unsigned I = 0; I != NumElems; ++I) {
-    INT_TYPE_SWITCH_NO_BOOL(ElemT, {
-      Dst.elem<T>(I) = T::from(static_cast<T>(
-          APSInt(Arg.elem<T>(I).toAPSInt().abs(),
-                 ElemType->isUnsignedIntegerOrEnumerationType())));
-    });
+    if (ElemType->isIntegerType()) {
+      INT_TYPE_SWITCH_NO_BOOL(ElemT, {
+        Dst.elem<T>(I) = T::from(static_cast<T>(
+            APSInt(Arg.elem<T>(I).toAPSInt().abs(),
+                   ElemType->isUnsignedIntegerOrEnumerationType())));
+      });
+    } else {
+      Floating Val = Arg.elem<Floating>(I);
+      if (!Val.isNegative()) {
+        Dst.elem<Floating>(I) = Val;
+      } else {
+        APFloat F = Val.getAPFloat();
+        F.changeSign();
+        Floating Result = S.allocFloat(Val.getSemantics());
+        Result.copy(F);
+        Dst.elem<Floating>(I) = Result;
+      }
+    }
   }
   Dst.initializeAllElements();
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 1c8d9706788c4..d1cdfc16c5ef7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11610,7 +11610,6 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr 
*E) {
   switch (E->getBuiltinCallee()) {
   default:
     return false;
-  case Builtin::BI__builtin_elementwise_abs:
   case Builtin::BI__builtin_elementwise_popcount:
   case Builtin::BI__builtin_elementwise_bitreverse: {
     APValue Source;
@@ -11635,18 +11634,35 @@ bool VectorExprEvaluator::VisitCallExpr(const 
CallExpr *E) {
             APValue(APSInt(Elt.reverseBits(),
                            DestEltTy->isUnsignedIntegerOrEnumerationType())));
         break;
-      case Builtin::BI__builtin_elementwise_abs: {
-        APInt Val = Source.getVectorElt(EltNum).getInt().abs();
-        ResultElements.push_back(APValue(
-            APSInt(Val, DestEltTy->isUnsignedIntegerOrEnumerationType())));
-        break;
-      }
       }
     }
 
     return Success(APValue(ResultElements.data(), ResultElements.size()), E);
   }
 
+  case Builtin::BI__builtin_elementwise_abs: {
+    APValue Source;
+    if (!EvaluateAsRValue(Info, E->getArg(0), Source))
+      return false;
+
+    QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
+    unsigned SourceLen = Source.getVectorLength();
+    SmallVector<APValue, 4> ResultElements;
+    ResultElements.reserve(SourceLen);
+
+    for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+      APValue CurrentEle = Source.getVectorElt(EltNum);
+      APValue Val = DestEltTy->isFloatingType()
+                        ? APValue(llvm::abs(CurrentEle.getFloat()))
+                        : APValue(APSInt(
+                              CurrentEle.getInt().abs(),
+                              
DestEltTy->isUnsignedIntegerOrEnumerationType()));
+      ResultElements.push_back(Val);
+    }
+
+    return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+  }
+
   case Builtin::BI__builtin_elementwise_add_sat:
   case Builtin::BI__builtin_elementwise_sub_sat:
   case clang::X86::BI__builtin_ia32_pmulhuw128:
@@ -15894,6 +15910,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr 
*E) {
       return Error(E);
     return true;
 
+  case Builtin::BI__builtin_elementwise_abs:
   case Builtin::BI__builtin_fabs:
   case Builtin::BI__builtin_fabsf:
   case Builtin::BI__builtin_fabsl:
diff --git a/clang/test/Sema/constant-builtins-vector.cpp 
b/clang/test/Sema/constant-builtins-vector.cpp
index 85fb4930d09c0..2b7d76e36ce96 100644
--- a/clang/test/Sema/constant-builtins-vector.cpp
+++ b/clang/test/Sema/constant-builtins-vector.cpp
@@ -880,5 +880,17 @@ static_assert(__builtin_bit_cast(unsigned long long, 
__builtin_elementwise_min((
 static_assert(__builtin_elementwise_abs(10) == 10);
 static_assert(__builtin_elementwise_abs(-10) == 10);
 static_assert(__builtin_bit_cast(unsigned, 
__builtin_elementwise_abs((vector4char){-1, -2, -3, 4})) == (LITTLE_END ? 
0x04030201 : 0x01020304));
-// the absolute value of the most negative integer remains the most negative 
integer
-static_assert(__builtin_elementwise_abs((int)(-2147483648)) == 
(int)(-2147483648));
+static_assert(__builtin_elementwise_abs((int)(-2147483648)) == 
(int)(-2147483648)); // the absolute value of the most negative integer remains 
the most negative integer
+
+// check floating point for elementwise abs
+#define CHECK_FOUR_FLOAT_VEC(vec1, vec2) \
+    static_assert(__builtin_fabs(vec1[0] - vec2[0]) < 1e-6); \
+    static_assert(__builtin_fabs(vec1[1] - vec2[1]) < 1e-6); \
+    static_assert(__builtin_fabs(vec1[2] - vec2[2]) < 1e-6); \
+    static_assert(__builtin_fabs(vec1[3] - vec2[3]) < 1e-6);
+
+// checking floating point vector
+CHECK_FOUR_FLOAT_VEC(__builtin_elementwise_abs((vector4float){-1.123, 2.123, 
-3.123, 4.123}), ((vector4float){1.123, 2.123, 3.123, 4.123}))
+CHECK_FOUR_FLOAT_VEC(__builtin_elementwise_abs((vector4double){-1.123, 2.123, 
-3.123, 4.123}), ((vector4double){1.123, 2.123, 3.123, 4.123}))
+static_assert(__builtin_elementwise_abs((float)-1.123) - (float)1.123 < 1e-6); 
// making sure one element works
+#undef CHECK_FOUR_FLOAT_VEC

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to