aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
authorVincent <llvm@viceroygroup.ca>2025-08-14 19:34:23 +0800
committerGitHub <noreply@github.com>2025-08-14 12:34:23 +0100
commitd3bbdc7bdea651658c4964346d34ac470742d90d (patch)
treeaad9e875b76ca6d60d2bb5943647d6a7ea471cd4 /clang/lib/AST/ByteCode/InterpBuiltin.cpp
parent3bc3b4cf5fe96afed668f24d741e509bae55cdc6 (diff)
downloadllvm-d3bbdc7bdea651658c4964346d34ac470742d90d.zip
llvm-d3bbdc7bdea651658c4964346d34ac470742d90d.tar.gz
llvm-d3bbdc7bdea651658c4964346d34ac470742d90d.tar.bz2
[clang] constexpr `__builtin_elementwise_abs` support (#152497)
Added constant evaluation support for `__builtin_elementwise_abs` on integer, float and vector type. fixes #152276 --------- Co-authored-by: Simon Pilgrim <llvm-dev@redking.me.uk>
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp76
1 files changed, 66 insertions, 10 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index ee2d532..b602b97 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -598,6 +598,17 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
return true;
}
+static inline Floating abs(InterpState &S, const Floating &In) {
+ if (!In.isNegative())
+ return In;
+
+ Floating Output = S.allocFloat(In.getSemantics());
+ APFloat New = In.getAPFloat();
+ New.changeSign();
+ Output.copy(New);
+ return Output;
+}
+
// The C standard says "fabs raises no floating-point exceptions,
// even if x is a signaling NaN. The returned value is independent of
// the current rounding direction mode." Therefore constant folding can
@@ -606,16 +617,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Floating &Val = S.Stk.pop<Floating>();
- APFloat F = Val.getAPFloat();
- if (!F.isNegative()) {
- S.Stk.push<Floating>(Val);
- return true;
- }
-
- Floating Result = S.allocFloat(Val.getSemantics());
- F.changeSign();
- Result.copy(F);
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(abs(S, Val));
return true;
}
@@ -1686,6 +1688,57 @@ 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) {
+ assert(Call->getNumArgs() == 1);
+ QualType Ty = Call->getArg(0)->getType();
+ if (Ty->isIntegerType()) {
+ PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
+
+ pushInteger(S, Val.abs(), Call->getType());
+ return true;
+ }
+
+ if (Ty->isFloatingType()) {
+ Floating Val = S.Stk.pop<Floating>();
+ Floating Result = abs(S, Val);
+ 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>();
+ 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();
+ // we can either have a vector of integer or a vector of floating point
+ for (unsigned I = 0; I != NumElems; ++I) {
+ 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);
+ Dst.elem<Floating>(I) = abs(S, Val);
+ }
+ }
+ 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,
@@ -2774,6 +2827,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: