https://github.com/Mr-Anyone updated https://github.com/llvm/llvm-project/pull/152497
>From c9216ff7d0aeea10b70696b2303fb5d7ba06b583 Mon Sep 17 00:00:00 2001 From: Vincent <l...@viceroygroup.ca> Date: Thu, 7 Aug 2025 00:24:55 +0800 Subject: [PATCH] [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 b5bb198ca637a..581faef2e40ad 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -759,7 +759,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`` can be called in a ``constexpr`` context. +``__builtin_elementwise_sub_sat``, 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 17e3df467593d..0bf9ec8b446d2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -109,6 +109,8 @@ C23 Feature Support Non-comprehensive list of changes in this release ------------------------------------------------- +- `__builtin_elementwise_abs` can be used in constexpr. + - 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 c81714e9b009d..03f1c0b1c7f4a 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 f908d02c0412d..d5c5db523886f 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1687,6 +1687,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, @@ -2687,6 +2730,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 34af9ccd2e96e..1256c97f84f9c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11594,6 +11594,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; @@ -11618,11 +11619,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: { APValue SourceLHS, SourceRHS; @@ -13315,6 +13323,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 ee8345ff51e5e..5e1d30c986c87 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 bde5c478b2b6f..65c6263140ac3 100644 --- a/clang/test/Sema/constant-builtins-vector.cpp +++ b/clang/test/Sema/constant-builtins-vector.cpp @@ -860,3 +860,9 @@ 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){1, 1, 1, 1})) == (LITTLE_END ? 0x01020304 : 0x04030201)); static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_sub_sat((vector4uchar){5, 4, 3, 2}, (vector4uchar){1, 1, 1, 1})) == (LITTLE_END ? 0x01020304U : 0x04030201U)); 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))); + +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)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits