diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2019-02-13 20:09:48 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2019-02-13 20:09:48 -0300 |
commit | 109de05cbb034b032cd60f50708716c8ff0afdf2 (patch) | |
tree | d851e8295a7df4f306650cf763948a8149bacb78 /src/port/pg_bitutils.c | |
parent | 80c468b4a454881b56e1c73c6fedcb2978c5b415 (diff) | |
download | postgresql-109de05cbb034b032cd60f50708716c8ff0afdf2.tar.gz postgresql-109de05cbb034b032cd60f50708716c8ff0afdf2.zip |
Fix portability issues in pg_bitutils
We were using uint64 function arguments as "long int" arguments to
compiler builtins, which fails on machines where long ints are 32 bits:
the upper half of the uint64 was being ignored. Fix by using the "ll"
builtin variants instead, which on those machines take 64 bit arguments.
Also, remove configure tests for __builtin_popcountl() (as well as
"long" variants for ctz and clz): the theory here is that any compiler
version will provide all widths or none, so one test suffices. Were
this theory to be wrong, we'd have to add tests for
__builtin_popcountll() and friends, which would be tedious.
Per failures in buildfarm member lapwing and ensuing discussion.
Diffstat (limited to 'src/port/pg_bitutils.c')
-rw-r--r-- | src/port/pg_bitutils.c | 73 |
1 files changed, 35 insertions, 38 deletions
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 97422e05040..aac394fe927 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -23,87 +23,62 @@ #include "port/pg_bitutils.h" -#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_POPCOUNT) || defined(HAVE__BUILTIN_POPCOUNTL)) -static bool pg_popcount_available(void); -#endif - #if defined(HAVE__BUILTIN_POPCOUNT) && defined(HAVE__GET_CPUID) +static bool pg_popcount_available(void); static int pg_popcount32_choose(uint32 word); static int pg_popcount32_sse42(uint32 word); -#endif -static int pg_popcount32_slow(uint32 word); - -#if defined(HAVE__BUILTIN_POPCOUNTL) && defined(HAVE__GET_CPUID) static int pg_popcount64_choose(uint64 word); static int pg_popcount64_sse42(uint64 word); #endif +static int pg_popcount32_slow(uint32 word); static int pg_popcount64_slow(uint64 word); -#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_CTZ) || defined(HAVE__BUILTIN_CTZL) || defined(HAVE__BUILTIN_CLZ) || defined(HAVE__BUILTIN_CLZL)) +#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_CTZ) || defined(HAVE__BUILTIN_CLZ)) static bool pg_lzcnt_available(void); #endif #if defined(HAVE__BUILTIN_CTZ) && defined(HAVE__GET_CPUID) static int pg_rightmost_one32_choose(uint32 word); static int pg_rightmost_one32_abm(uint32 word); -#endif -static int pg_rightmost_one32_slow(uint32 word); - -#if defined(HAVE__BUILTIN_CTZL) && defined(HAVE__GET_CPUID) static int pg_rightmost_one64_choose(uint64 word); static int pg_rightmost_one64_abm(uint64 word); #endif +static int pg_rightmost_one32_slow(uint32 word); static int pg_rightmost_one64_slow(uint64 word); #if defined(HAVE__BUILTIN_CLZ) && defined(HAVE__GET_CPUID) static int pg_leftmost_one32_choose(uint32 word); static int pg_leftmost_one32_abm(uint32 word); -#endif -static int pg_leftmost_one32_slow(uint32 word); - -#if defined(HAVE__BUILTIN_CLZL) && defined(HAVE__GET_CPUID) static int pg_leftmost_one64_choose(uint64 word); static int pg_leftmost_one64_abm(uint64 word); #endif +static int pg_leftmost_one32_slow(uint32 word); static int pg_leftmost_one64_slow(uint64 word); #if defined(HAVE__BUILTIN_POPCOUNT) && defined(HAVE__GET_CPUID) int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; -#else -int (*pg_popcount32) (uint32 word) = pg_popcount32_slow; -#endif - -#if defined(HAVE__BUILTIN_POPCOUNTL) && defined(HAVE__GET_CPUID) int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; #else +int (*pg_popcount32) (uint32 word) = pg_popcount32_slow; int (*pg_popcount64) (uint64 word) = pg_popcount64_slow; #endif #if defined(HAVE__BUILTIN_CTZ) && defined(HAVE__GET_CPUID) int (*pg_rightmost_one32) (uint32 word) = pg_rightmost_one32_choose; -#else -int (*pg_rightmost_one32) (uint32 word) = pg_rightmost_one32_slow; -#endif - -#if defined(HAVE__BUILTIN_CTZL) && defined(HAVE__GET_CPUID) int (*pg_rightmost_one64) (uint64 word) = pg_rightmost_one64_choose; #else +int (*pg_rightmost_one32) (uint32 word) = pg_rightmost_one32_slow; int (*pg_rightmost_one64) (uint64 word) = pg_rightmost_one64_slow; #endif #if defined(HAVE__BUILTIN_CLZ) && defined(HAVE__GET_CPUID) int (*pg_leftmost_one32) (uint32 word) = pg_leftmost_one32_choose; -#else -int (*pg_leftmost_one32) (uint32 word) = pg_leftmost_one32_slow; -#endif - -#if defined(HAVE__BUILTIN_CLZL) && defined(HAVE__GET_CPUID) int (*pg_leftmost_one64) (uint64 word) = pg_leftmost_one64_choose; #else +int (*pg_leftmost_one32) (uint32 word) = pg_leftmost_one32_slow; int (*pg_leftmost_one64) (uint64 word) = pg_leftmost_one64_slow; #endif - /* Array marking the number of 1-bits for each value of 0-255. */ static const uint8 number_of_ones[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, @@ -172,7 +147,7 @@ static const uint8 leftmost_one_pos[256] = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; -#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_POPCOUNT) || defined(HAVE__BUILTIN_POPCOUNTL)) +#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_POPCOUNT) static bool pg_popcount_available(void) @@ -279,7 +254,7 @@ pg_popcount(const char *buf, int bytes) return popcnt; } -#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_POPCOUNTL) +#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_POPCOUNT) /* * This gets called on the first call. It replaces the function pointer @@ -299,7 +274,14 @@ pg_popcount64_choose(uint64 word) static int pg_popcount64_sse42(uint64 word) { +#if defined(HAVE_LONG_INT_64) return __builtin_popcountl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return __builtin_popcountll(word); +#else + /* shouldn't happen */ +#error must have a working 64-bit integer datatype +#endif } #endif @@ -322,7 +304,7 @@ pg_popcount64_slow(uint64 word) return result; } -#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_CTZ) || defined(HAVE__BUILTIN_CTZL) || defined(HAVE__BUILTIN_CLZ) || defined(HAVE__BUILTIN_CLZL)) +#if defined(HAVE__GET_CPUID) && (defined(HAVE__BUILTIN_CTZ) || defined(HAVE__BUILTIN_CLZ)) static bool pg_lzcnt_available(void) @@ -388,7 +370,7 @@ pg_rightmost_one32_slow(uint32 word) return result; } -#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_CTZL) +#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_CTZ) /* * This gets called on the first call. It replaces the function pointer * so that subsequent calls are routed directly to the chosen implementation. @@ -407,7 +389,14 @@ pg_rightmost_one64_choose(uint64 word) static int pg_rightmost_one64_abm(uint64 word) { +#if defined(HAVE_LONG_INT_64) return __builtin_ctzl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return __builtin_ctzll(word); +#else + /* shouldn't happen */ +#error must have a working 64-bit integer datatype +#endif } #endif @@ -474,7 +463,7 @@ pg_leftmost_one32_slow(uint32 word) return shift + leftmost_one_pos[(word >> shift) & 255]; } -#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_CLZL) +#if defined(HAVE__GET_CPUID) && defined(HAVE__BUILTIN_CLZ) /* * This gets called on the first call. It replaces the function pointer * so that subsequent calls are routed directly to the chosen implementation. @@ -493,7 +482,15 @@ pg_leftmost_one64_choose(uint64 word) static int pg_leftmost_one64_abm(uint64 word) { +#if defined(HAVE_LONG_INT_64) return 63 - __builtin_clzl(word); +#elif defined(HAVE_LONG_LONG_INT_64) + return 63 - __builtin_clzll(word); +#else + /* shouldn't happen */ +#error must have a working 64-bit integer datatype +#endif + } #endif |