diff options
author | John Naylor <john.naylor@postgresql.org> | 2021-08-16 11:45:21 -0400 |
---|---|---|
committer | John Naylor <john.naylor@postgresql.org> | 2021-08-16 11:51:15 -0400 |
commit | 4864c8e8f184a35ed1c2c51a15e9a455e9fbb398 (patch) | |
tree | db1c9a5350429e3a578803a908f5cbc3f19159a0 /src/include/port/pg_bitutils.h | |
parent | ea499f3d28c657a044f0a948e6b77ac56f28a8f6 (diff) | |
download | postgresql-4864c8e8f184a35ed1c2c51a15e9a455e9fbb398.tar.gz postgresql-4864c8e8f184a35ed1c2c51a15e9a455e9fbb398.zip |
Use direct function calls for pg_popcount{32,64} on non-x86 platforms
Previously, all pg_popcount{32,64} calls were indirected through
a function pointer, even though we had no fast implementation for
non-x86 platforms. Instead, for those platforms use wrappers around
the pg_popcount{32,64}_slow functions.
Review and additional hacking by David Rowley
Reviewed by Álvaro Herrera
Discussion: https://www.postgresql.org/message-id/flat/CAFBsxsE7otwnfA36Ly44zZO%2Bb7AEWHRFANxR1h1kxveEV%3DghLQ%40mail.gmail.com
Diffstat (limited to 'src/include/port/pg_bitutils.h')
-rw-r--r-- | src/include/port/pg_bitutils.h | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 086bd08132f..7dd7fef4f74 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -253,10 +253,40 @@ pg_ceil_log2_64(uint64 num) return pg_leftmost_one_pos64(num - 1) + 1; } -/* Count the number of one-bits in a uint32 or uint64 */ +/* + * With MSVC on x86_64 builds, try using native popcnt instructions via the + * __popcnt and __popcnt64 intrinsics. These don't work the same as GCC's + * __builtin_popcount* intrinsic functions as they always emit popcnt + * instructions. + */ +#if defined(_MSC_VER) && defined(_M_AMD64) +#define HAVE_X86_64_POPCNTQ +#endif + +/* + * On x86_64, we can use the hardware popcount instruction, but only if + * we can verify that the CPU supports it via the cpuid instruction. + * + * Otherwise, we fall back to a hand-rolled implementation. + */ +#ifdef HAVE_X86_64_POPCNTQ +#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID) +#define TRY_POPCNT_FAST 1 +#endif +#endif + +#ifdef TRY_POPCNT_FAST +/* Attempt to use the POPCNT instruction, but perform a runtime check first */ extern int (*pg_popcount32) (uint32 word); extern int (*pg_popcount64) (uint64 word); +#else +/* Use a portable implementation -- no need for a function pointer. */ +extern int pg_popcount32(uint32 word); +extern int pg_popcount64(uint64 word); + +#endif /* TRY_POPCNT_FAST */ + /* Count the number of one-bits in a byte array */ extern uint64 pg_popcount(const char *buf, int bytes); |