diff options
author | Justin Pettit <jpettit@ovn.org> | 2019-10-03 09:39:31 -0700 |
---|---|---|
committer | Justin Pettit <jpettit@ovn.org> | 2019-10-03 09:41:03 -0700 |
commit | 0ea07c1df3b982cd0517c44668e89bf1872679da (patch) | |
tree | 8074a78a70d1c0881ad1fcf485c27a74c451969f | |
parent | af1883400e0865f7464b679a93c860a38bcff091 (diff) | |
download | openvswitch-ovn-ddlog-patches.tar.gz |
Export 'count_1bits' function needed by ddlog.ovn-ddlog-patches
-rw-r--r-- | lib/util.c | 50 | ||||
-rw-r--r-- | lib/util.h | 52 |
2 files changed, 50 insertions, 52 deletions
diff --git a/lib/util.c b/lib/util.c index 830e14516..7dd681cca 100644 --- a/lib/util.c +++ b/lib/util.c @@ -1344,7 +1344,38 @@ raw_clz64(uint64_t n) } #endif -#if NEED_COUNT_1BITS_8 +/* unsigned int count_1bits(uint64_t x): + * + * Returns the number of 1-bits in 'x', between 0 and 64 inclusive. */ +#if UINTPTR_MAX == UINT64_MAX +unsigned int +count_1bits(uint64_t x) +{ +#if (__GNUC__ >= 4 && __POPCNT__) || (defined(__aarch64__) && __GNUC__ >= 7) + return __builtin_popcountll(x); +#elif defined(__aarch64__) && __GNUC__ >= 6 + return vaddv_u8(vcnt_u8(vcreate_u8(x))); +#else + /* This portable implementation is the fastest one we know of for 64 + * bits, and about 3x faster than GCC 4.7 __builtin_popcountll(). */ + const uint64_t h55 = UINT64_C(0x5555555555555555); + const uint64_t h33 = UINT64_C(0x3333333333333333); + const uint64_t h0F = UINT64_C(0x0F0F0F0F0F0F0F0F); + const uint64_t h01 = UINT64_C(0x0101010101010101); + x -= (x >> 1) & h55; /* Count of each 2 bits in-place. */ + x = (x & h33) + ((x >> 2) & h33); /* Count of each 4 bits in-place. */ + x = (x + (x >> 4)) & h0F; /* Count of each 8 bits in-place. */ + return (x * h01) >> 56; /* Sum of all bytes. */ +#endif +} +#else /* Not 64-bit. */ +#if __GNUC__ >= 4 && __POPCNT__ +unsigned int +count_1bits_32__(uint32_t x) +{ + return __builtin_popcount(x); +} +#else #define INIT1(X) \ ((((X) & (1 << 0)) != 0) + \ (((X) & (1 << 1)) != 0) + \ @@ -1364,6 +1395,23 @@ raw_clz64(uint64_t n) const uint8_t count_1bits_8[256] = { INIT64(0), INIT64(64), INIT64(128), INIT64(192) }; + +static inline unsigned int +count_1bits_32__(uint32_t x) +{ + /* This portable implementation is the fastest one we know of for 32 bits, + * and faster than GCC __builtin_popcount(). */ + return (count_1bits_8[x & 0xff] + + count_1bits_8[(x >> 8) & 0xff] + + count_1bits_8[(x >> 16) & 0xff] + + count_1bits_8[x >> 24]); +} +#endif +static inline unsigned int +count_1bits(uint64_t x) +{ + return count_1bits_32__(x) + count_1bits_32__(x >> 32); +} #endif /* Returns true if the 'n' bytes starting at 'p' are 'byte'. */ diff --git a/lib/util.h b/lib/util.h index 7ad8758fe..2734d26c5 100644 --- a/lib/util.h +++ b/lib/util.h @@ -357,57 +357,7 @@ log_2_ceil(uint64_t n) return log_2_floor(n) + !is_pow2(n); } -/* unsigned int count_1bits(uint64_t x): - * - * Returns the number of 1-bits in 'x', between 0 and 64 inclusive. */ -#if UINTPTR_MAX == UINT64_MAX -static inline unsigned int -count_1bits(uint64_t x) -{ -#if (__GNUC__ >= 4 && __POPCNT__) || (defined(__aarch64__) && __GNUC__ >= 7) - return __builtin_popcountll(x); -#elif defined(__aarch64__) && __GNUC__ >= 6 - return vaddv_u8(vcnt_u8(vcreate_u8(x))); -#else - /* This portable implementation is the fastest one we know of for 64 - * bits, and about 3x faster than GCC 4.7 __builtin_popcountll(). */ - const uint64_t h55 = UINT64_C(0x5555555555555555); - const uint64_t h33 = UINT64_C(0x3333333333333333); - const uint64_t h0F = UINT64_C(0x0F0F0F0F0F0F0F0F); - const uint64_t h01 = UINT64_C(0x0101010101010101); - x -= (x >> 1) & h55; /* Count of each 2 bits in-place. */ - x = (x & h33) + ((x >> 2) & h33); /* Count of each 4 bits in-place. */ - x = (x + (x >> 4)) & h0F; /* Count of each 8 bits in-place. */ - return (x * h01) >> 56; /* Sum of all bytes. */ -#endif -} -#else /* Not 64-bit. */ -#if __GNUC__ >= 4 && __POPCNT__ -static inline unsigned int -count_1bits_32__(uint32_t x) -{ - return __builtin_popcount(x); -} -#else -#define NEED_COUNT_1BITS_8 1 -extern const uint8_t count_1bits_8[256]; -static inline unsigned int -count_1bits_32__(uint32_t x) -{ - /* This portable implementation is the fastest one we know of for 32 bits, - * and faster than GCC __builtin_popcount(). */ - return (count_1bits_8[x & 0xff] + - count_1bits_8[(x >> 8) & 0xff] + - count_1bits_8[(x >> 16) & 0xff] + - count_1bits_8[x >> 24]); -} -#endif -static inline unsigned int -count_1bits(uint64_t x) -{ - return count_1bits_32__(x) + count_1bits_32__(x >> 32); -} -#endif +unsigned int count_1bits(uint64_t x); /* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x' * is 0. */ |