Skip to content

Commit

Permalink
[SYCL][LIBCLC][NATIVECPU] Fix ldexp and popcount on Native CPU (#15687)
Browse files Browse the repository at this point in the history
`ldexp` in `generic` (for `half`) and `popcount` in `native_cpu` are
implemented using clang builtins. This PR makes it so we call the
correct "overload" of the builtin:
* `__builtin_ldexpf16` for `half`
* `__builtin_popcountg` for unsigned integer types
* for signed integer types the implicit cast to `int` performed by
calling `__builtin_popcount` doesn't work due to sign extension, so we
explicitly cast to `unsigned char` or `unsigned short`, and use
`__builtin_popcountg`.
  • Loading branch information
PietroGhg authored Oct 15, 2024
1 parent 9faf0e0 commit 48a75f4
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
2 changes: 1 addition & 1 deletion libclc/generic/include/math/clc_ldexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ _CLC_DEF _CLC_OVERLOAD double __clc_ldexp(double, int);

#ifdef cl_khr_fp16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
_CLC_DEF _CLC_OVERLOAD float __clc_ldexp(half, int);
_CLC_DEF _CLC_OVERLOAD half __clc_ldexp(half, int);
#endif
2 changes: 1 addition & 1 deletion libclc/generic/libspirv/math/clc_ldexp.cl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,6 @@ _CLC_DEF _CLC_OVERLOAD double __clc_ldexp(double x, int n) {

#pragma OPENCL EXTENSION cl_khr_fp16 : enable

_CLC_DEFINE_BINARY_BUILTIN(half, __clc_ldexp, __builtin_ldexp, half, int)
_CLC_DEFINE_BINARY_BUILTIN(half, __clc_ldexp, __builtin_ldexpf16, half, int)

#endif
28 changes: 21 additions & 7 deletions libclc/native_cpu-unknown-linux/libspirv/integer/popcount.cl
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
#include <clcmacro.h>
#include <spirv/spirv.h>

// We can't use __builtin_popcountg because it supports only unsigned
// types, and we can't use __builtin_popcount because the implicit cast
// to int doesn't work due to sign extension, so we use type punning to
// preserve the bit pattern and avoid sign extension.

#define DEF_POPCOUNT_HELPER(TYPE, UTYPE) \
_CLC_OVERLOAD TYPE __popcount_helper(TYPE c) { \
return __builtin_popcountg(*(UTYPE*)&c); \
}

DEF_POPCOUNT_HELPER(char, unsigned char)
DEF_POPCOUNT_HELPER(schar, unsigned char)
DEF_POPCOUNT_HELPER(short, unsigned short)

_CLC_DEFINE_UNARY_BUILTIN(int, __spirv_ocl_popcount, __builtin_popcount, int)
_CLC_DEFINE_UNARY_BUILTIN(uint, __spirv_ocl_popcount, __builtin_popcount, uint)
_CLC_DEFINE_UNARY_BUILTIN(short, __spirv_ocl_popcount, __builtin_popcount, short)
_CLC_DEFINE_UNARY_BUILTIN(ushort, __spirv_ocl_popcount, __builtin_popcount, ushort)
_CLC_DEFINE_UNARY_BUILTIN(long, __spirv_ocl_popcount, __builtin_popcount, long)
_CLC_DEFINE_UNARY_BUILTIN(ulong, __spirv_ocl_popcount, __builtin_popcount, ulong)
_CLC_DEFINE_UNARY_BUILTIN(char, __spirv_ocl_popcount, __builtin_popcount, char)
_CLC_DEFINE_UNARY_BUILTIN(uchar, __spirv_ocl_popcount, __builtin_popcount, uchar)
_CLC_DEFINE_UNARY_BUILTIN(schar, __spirv_ocl_popcount, __builtin_popcount, schar)
_CLC_DEFINE_UNARY_BUILTIN(short, __spirv_ocl_popcount, __popcount_helper, short)
_CLC_DEFINE_UNARY_BUILTIN(ushort, __spirv_ocl_popcount, __builtin_popcountg, ushort)
_CLC_DEFINE_UNARY_BUILTIN(long, __spirv_ocl_popcount, __builtin_popcountl, long)
_CLC_DEFINE_UNARY_BUILTIN(ulong, __spirv_ocl_popcount, __builtin_popcountl, ulong)
_CLC_DEFINE_UNARY_BUILTIN(char, __spirv_ocl_popcount, __popcount_helper, char)
_CLC_DEFINE_UNARY_BUILTIN(uchar, __spirv_ocl_popcount, __builtin_popcountg, uchar)
_CLC_DEFINE_UNARY_BUILTIN(schar, __spirv_ocl_popcount, __popcount_helper, schar)

0 comments on commit 48a75f4

Please sign in to comment.