From 881ceef5adda6f1cc5f5a9a15ae74b068bf85dd4 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Fri, 30 Apr 2021 18:45:18 -0700 Subject: [PATCH] Add portable fallback for ctz, clz, and clzll --- include/common/attributes.h | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/include/common/attributes.h b/include/common/attributes.h index 4ccc421..72d5202 100644 --- a/include/common/attributes.h +++ b/include/common/attributes.h @@ -32,6 +32,7 @@ #include #include +#include #ifndef __has_attribute #define __has_attribute(x) 0 @@ -156,7 +157,7 @@ static inline int clzll(const unsigned long long mask) { return clz((unsigned)mask) + 32; } #endif /* _WIN64 */ -#else /* !_MSC_VER */ +#elif defined(__GNUC__) static inline int ctz(const unsigned int mask) { return __builtin_ctz(mask); } @@ -168,7 +169,29 @@ static inline int clz(const unsigned int mask) { static inline int clzll(const unsigned long long mask) { return __builtin_clzll(mask); } -#endif /* !_MSC_VER */ +#else /* __GNUC__ */ +static inline int ctz(const unsigned int mask) { + return ffs(mask) - 1; +} + +static inline int clz(unsigned int mask) { + mask >>= 1; + mask |= mask >> 1; + mask |= mask >> 2; + mask |= mask >> 4; + mask |= mask >> 8; + mask |= mask >> 16; + mask++; + return 32 - ffs(mask); +} + +static inline int clzll(unsigned long long mask) { + if (mask >> 32) + return clz((unsigned)(mask >> 32)); + else + return clz((unsigned)mask) + 32; +} +#endif /* !_MSC_VER && !__GNUC__ */ #ifndef static_assert #define CHECK_OFFSET(type, field, name) \ -- 2.32.0