Author: Timm Baeder Date: 2024-12-02T16:48:22+01:00 New Revision: 637a1ae85538554b98973861802e842fc30d0f91
URL: https://github.com/llvm/llvm-project/commit/637a1ae85538554b98973861802e842fc30d0f91 DIFF: https://github.com/llvm/llvm-project/commit/637a1ae85538554b98973861802e842fc30d0f91.diff LOG: [clang][bytecode] Implement __builtin_elementwise_popcount (#118307) Added: Modified: clang/lib/AST/ByteCode/InterpBuiltin.cpp clang/test/AST/ByteCode/builtin-functions.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index a217578e4936b4..db3703a60db699 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1742,6 +1742,41 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, 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, + const Function *Func, + const CallExpr *Call) { + assert(Call->getNumArgs() == 1); + if (Call->getArg(0)->getType()->isIntegerType()) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Val = peekToAPSInt(S.Stk, ArgT); + pushInteger(S, Val.popcount(), Call->getType()); + return true; + } + // Otherwise, the argument must be a vector. + assert(Call->getArg(0)->getType()->isVectorType()); + const Pointer &Arg = S.Stk.peek<Pointer>(); + assert(Arg.getFieldDesc()->isPrimitiveArray()); + const Pointer &Dst = S.Stk.peek<Pointer>(primSize(PT_Ptr) * 2); + 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.atIndex(I).deref<T>() = + T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); + }); + } + + return true; +} static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { @@ -2222,6 +2257,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_elementwise_popcount: + if (!interp__builtin_elementwise_popcount(S, OpPC, Frame, F, Call)) + return false; + break; + case Builtin::BI__builtin_memcpy: if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call)) return false; diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index 61b78e8928df4c..9a6a31b5ec4c06 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -1108,6 +1108,28 @@ namespace ReduceXor { #endif } +namespace ElementwisePopcount { + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1, 2, 3, 4})) == 5); +#if __INT_WIDTH__ == 32 + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){0, 0xF0F0, ~0, ~0xF0F0})) == 16 * sizeof(int)); +#endif + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){1L, 2L, 3L, 4L})) == 5L); + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){0L, 0xF0F0L, ~0L, ~0xF0F0L})) == 16 * sizeof(long long)); + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){1U, 2U, 3U, 4U})) == 5U); + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){0U, 0xF0F0U, ~0U, ~0xF0F0U})) == 16 * sizeof(int)); + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){1UL, 2UL, 3UL, 4UL})) == 5UL); + static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){0ULL, 0xF0F0ULL, ~0ULL, ~0xF0F0ULL})) == 16 * sizeof(unsigned long long)); + static_assert(__builtin_elementwise_popcount(0) == 0); + static_assert(__builtin_elementwise_popcount(0xF0F0) == 8); + static_assert(__builtin_elementwise_popcount(~0) == 8 * sizeof(int)); + static_assert(__builtin_elementwise_popcount(0U) == 0); + static_assert(__builtin_elementwise_popcount(0xF0F0U) == 8); + static_assert(__builtin_elementwise_popcount(~0U) == 8 * sizeof(int)); + static_assert(__builtin_elementwise_popcount(0L) == 0); + static_assert(__builtin_elementwise_popcount(0xF0F0L) == 8); + static_assert(__builtin_elementwise_popcount(~0LL) == 8 * sizeof(long long)); +} + namespace BuiltinMemcpy { constexpr int simple() { int a = 12; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits