diff options
author | Vincent <llvm@viceroygroup.ca> | 2025-08-14 19:34:23 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-14 12:34:23 +0100 |
commit | d3bbdc7bdea651658c4964346d34ac470742d90d (patch) | |
tree | aad9e875b76ca6d60d2bb5943647d6a7ea471cd4 /clang/lib/AST/ByteCode/InterpBuiltin.cpp | |
parent | 3bc3b4cf5fe96afed668f24d741e509bae55cdc6 (diff) | |
download | llvm-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.cpp | 76 |
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: |