Skip to content

Commit 637a1ae

Browse files
authored
[clang][bytecode] Implement __builtin_elementwise_popcount (#118307)
1 parent b343f3f commit 637a1ae

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,41 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
17421742
return true;
17431743
}
17441744

1745+
/// Can be called with an integer or vector as the first and only parameter.
1746+
static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
1747+
const InterpFrame *Frame,
1748+
const Function *Func,
1749+
const CallExpr *Call) {
1750+
assert(Call->getNumArgs() == 1);
1751+
if (Call->getArg(0)->getType()->isIntegerType()) {
1752+
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1753+
APSInt Val = peekToAPSInt(S.Stk, ArgT);
1754+
pushInteger(S, Val.popcount(), Call->getType());
1755+
return true;
1756+
}
1757+
// Otherwise, the argument must be a vector.
1758+
assert(Call->getArg(0)->getType()->isVectorType());
1759+
const Pointer &Arg = S.Stk.peek<Pointer>();
1760+
assert(Arg.getFieldDesc()->isPrimitiveArray());
1761+
const Pointer &Dst = S.Stk.peek<Pointer>(primSize(PT_Ptr) * 2);
1762+
assert(Dst.getFieldDesc()->isPrimitiveArray());
1763+
assert(Arg.getFieldDesc()->getNumElems() ==
1764+
Dst.getFieldDesc()->getNumElems());
1765+
1766+
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1767+
PrimType ElemT = *S.getContext().classify(ElemType);
1768+
unsigned NumElems = Arg.getNumElems();
1769+
1770+
// FIXME: Reading from uninitialized vector elements?
1771+
for (unsigned I = 0; I != NumElems; ++I) {
1772+
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1773+
Dst.atIndex(I).deref<T>() =
1774+
T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());
1775+
});
1776+
}
1777+
1778+
return true;
1779+
}
17451780
static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
17461781
const InterpFrame *Frame,
17471782
const Function *Func, const CallExpr *Call) {
@@ -2222,6 +2257,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
22222257
return false;
22232258
break;
22242259

2260+
case Builtin::BI__builtin_elementwise_popcount:
2261+
if (!interp__builtin_elementwise_popcount(S, OpPC, Frame, F, Call))
2262+
return false;
2263+
break;
2264+
22252265
case Builtin::BI__builtin_memcpy:
22262266
if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call))
22272267
return false;

clang/test/AST/ByteCode/builtin-functions.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,28 @@ namespace ReduceXor {
11081108
#endif
11091109
}
11101110

1111+
namespace ElementwisePopcount {
1112+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1, 2, 3, 4})) == 5);
1113+
#if __INT_WIDTH__ == 32
1114+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){0, 0xF0F0, ~0, ~0xF0F0})) == 16 * sizeof(int));
1115+
#endif
1116+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){1L, 2L, 3L, 4L})) == 5L);
1117+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4long){0L, 0xF0F0L, ~0L, ~0xF0F0L})) == 16 * sizeof(long long));
1118+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){1U, 2U, 3U, 4U})) == 5U);
1119+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4uint){0U, 0xF0F0U, ~0U, ~0xF0F0U})) == 16 * sizeof(int));
1120+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){1UL, 2UL, 3UL, 4UL})) == 5UL);
1121+
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4ulong){0ULL, 0xF0F0ULL, ~0ULL, ~0xF0F0ULL})) == 16 * sizeof(unsigned long long));
1122+
static_assert(__builtin_elementwise_popcount(0) == 0);
1123+
static_assert(__builtin_elementwise_popcount(0xF0F0) == 8);
1124+
static_assert(__builtin_elementwise_popcount(~0) == 8 * sizeof(int));
1125+
static_assert(__builtin_elementwise_popcount(0U) == 0);
1126+
static_assert(__builtin_elementwise_popcount(0xF0F0U) == 8);
1127+
static_assert(__builtin_elementwise_popcount(~0U) == 8 * sizeof(int));
1128+
static_assert(__builtin_elementwise_popcount(0L) == 0);
1129+
static_assert(__builtin_elementwise_popcount(0xF0F0L) == 8);
1130+
static_assert(__builtin_elementwise_popcount(~0LL) == 8 * sizeof(long long));
1131+
}
1132+
11111133
namespace BuiltinMemcpy {
11121134
constexpr int simple() {
11131135
int a = 12;

0 commit comments

Comments
 (0)