[clang] 637a1ae - [clang][bytecode] Implement __builtin_elementwise_popcount (#118307)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 2 07:48:26 PST 2024
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;
More information about the cfe-commits
mailing list