Skip to content

Commit 77654db

Browse files
committed
builtin: better portable bitreverse implementation
This is based on the output generated by clang for __builtin_bitreverse64, which is similar to https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel with the exception of using bswap.
1 parent 5338ca6 commit 77654db

File tree

1 file changed

+42
-36
lines changed

1 file changed

+42
-36
lines changed

builtin/builtin.h

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -849,42 +849,6 @@ PSNIP_BUILTIN__CLRSB_DEFINE_PORTABLE(clrsbll, clzll, long long)
849849
# define psnip_builtin_clrsb64(x) PSNIP_BUILTIN__VARIANT_INT64(psnip,clrsb)(x)
850850
#endif
851851

852-
/*** __builtin_bitreverse ***/
853-
854-
#define PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(f_n, T) \
855-
PSNIP_BUILTIN__FUNCTION \
856-
T psnip_builtin_##f_n(T x) { \
857-
size_t s = sizeof(x) * CHAR_BIT; \
858-
T mask = (T) 0U; \
859-
mask = ~mask; \
860-
while ((s >>= 1) > 0) { \
861-
mask ^= (mask << s); \
862-
x = ((x >> s) & mask) | ((x << s) & ~mask); \
863-
} \
864-
return x; \
865-
}
866-
867-
#if PSNIP_BUILTIN_CLANG_HAS_BUILTIN(__builtin_bitreverse64) && !defined(__EMSCRIPTEN__) && !defined(__ibmxl__)
868-
# define psnip_builtin_bitreverse8(x) __builtin_bitreverse8(x)
869-
# define psnip_builtin_bitreverse16(x) __builtin_bitreverse16(x)
870-
# define psnip_builtin_bitreverse32(x) __builtin_bitreverse32(x)
871-
# define psnip_builtin_bitreverse64(x) __builtin_bitreverse64(x)
872-
#else
873-
PSNIP_BUILTIN__FUNCTION
874-
psnip_uint8_t psnip_builtin_bitreverse8(psnip_uint8_t v) {
875-
return (psnip_uint8_t) ((v * 0x0202020202ULL & 0x010884422010ULL) % 1023);
876-
}
877-
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse16, psnip_uint16_t)
878-
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse32, psnip_uint32_t)
879-
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse64, psnip_uint64_t)
880-
# if defined(PSNIP_BUILTIN_EMULATE_NATIVE)
881-
# define __builtin_bitreverse8(x) psnip_builtin_bitreverse8(x)
882-
# define __builtin_bitreverse16(x) psnip_builtin_bitreverse16(x)
883-
# define __builtin_bitreverse32(x) psnip_builtin_bitreverse32(x)
884-
# define __builtin_bitreverse64(x) psnip_builtin_bitreverse64(x)
885-
# endif
886-
#endif
887-
888852
/*** __builtin_addc ***/
889853

890854
#define PSNIP_BUILTIN__ADDC_DEFINE_PORTABLE(f_n, T) \
@@ -1058,6 +1022,48 @@ psnip_builtin_bswap64(psnip_uint64_t v) {
10581022
# endif
10591023
#endif
10601024

1025+
/*** __builtin_bitreverse ***/
1026+
1027+
#define PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(f_n, b_l, T) \
1028+
PSNIP_BUILTIN__FUNCTION \
1029+
T psnip_builtin_##f_n##b_l(T v) { \
1030+
v = ((v & ((T) 0xf0f0f0f0f0f0f0f0ULL)) >> 4) | \
1031+
((v & ((T) 0x0f0f0f0f0f0f0f0fULL)) << 4); \
1032+
v = ((v & ((T) 0xccccccccccccccccULL)) >> 2) | \
1033+
((v & ((T) 0x3333333333333333ULL)) << 2); \
1034+
v = ((v & ((T) 0xaaaaaaaaaaaaaaaaULL)) >> 1) | \
1035+
((v & ((T) 0x5555555555555555ULL)) << 1); \
1036+
return psnip_builtin_bswap##b_l(v); \
1037+
}
1038+
1039+
#if PSNIP_BUILTIN_CLANG_HAS_BUILTIN(__builtin_bitreverse64) && !defined(__EMSCRIPTEN__) && !defined(__ibmxl__)
1040+
# define psnip_builtin_bitreverse8(x) __builtin_bitreverse8(x)
1041+
# define psnip_builtin_bitreverse16(x) __builtin_bitreverse16(x)
1042+
# define psnip_builtin_bitreverse32(x) __builtin_bitreverse32(x)
1043+
# define psnip_builtin_bitreverse64(x) __builtin_bitreverse64(x)
1044+
#else
1045+
PSNIP_BUILTIN__FUNCTION
1046+
psnip_uint8_t psnip_builtin_bitreverse8(psnip_uint8_t v) {
1047+
return (psnip_uint8_t) ((v * 0x0202020202ULL & 0x010884422010ULL) % 1023);
1048+
}
1049+
#if defined(_MSC_VER)
1050+
# pragma warning(push)
1051+
# pragma warning(disable:4310)
1052+
#endif
1053+
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse, 16, psnip_uint16_t)
1054+
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse, 32, psnip_uint32_t)
1055+
PSNIP_BUILTIN__BITREVERSE_DEFINE_PORTABLE(bitreverse, 64, psnip_uint64_t)
1056+
#if defined(_MSC_VER)
1057+
# pragma warning(pop)
1058+
#endif
1059+
# if defined(PSNIP_BUILTIN_EMULATE_NATIVE)
1060+
# define __builtin_bitreverse8(x) psnip_builtin_bitreverse8(x)
1061+
# define __builtin_bitreverse16(x) psnip_builtin_bitreverse16(x)
1062+
# define __builtin_bitreverse32(x) psnip_builtin_bitreverse32(x)
1063+
# define __builtin_bitreverse64(x) psnip_builtin_bitreverse64(x)
1064+
# endif
1065+
#endif
1066+
10611067
/******
10621068
*** MSVC-style intrinsics
10631069
******/

0 commit comments

Comments
 (0)