[clang] [clang] constexpr `__builtin_elementwise_abs` support (PR #152497)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 7 06:41:55 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Vincent (Mr-Anyone)
<details>
<summary>Changes</summary>
Added constant evaluation support for `__builtin_elementwise_abs` on integer and vector type.
fixes #<!-- -->152276
---
Full diff: https://github.com/llvm/llvm-project/pull/152497.diff
7 Files Affected:
- (modified) clang/docs/LanguageExtensions.rst (+2-1)
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/include/clang/Basic/Builtins.td (+1-1)
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+46)
- (modified) clang/lib/AST/ExprConstant.cpp (+16)
- (modified) clang/test/CodeGen/builtins-elementwise-math.c (+1-1)
- (modified) clang/test/Sema/constant-builtins-vector.cpp (+4)
``````````diff
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..e0eefe9461d0c 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..b3a4e011e00b5 100644
--- a/clang/test/Sema/constant-builtins-vector.cpp
+++ b/clang/test/Sema/constant-builtins-vector.cpp
@@ -860,3 +860,7 @@ 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));
``````````
</details>
https://github.com/llvm/llvm-project/pull/152497
More information about the cfe-commits
mailing list