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/port/pg_bitutils.c | |
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/port/pg_bitutils.c')
-rw-r--r-- | src/port/pg_bitutils.c | 48 |
1 files changed, 22 insertions, 26 deletions
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 10676b285ca..9d0e2016c31 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -103,29 +103,6 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -/* - * 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 __builtin_popcount if the compiler has that, - * or a hand-rolled implementation if not. - */ -#ifdef HAVE_X86_64_POPCNTQ -#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID) -#define TRY_POPCNT_FAST 1 -#endif -#endif - static int pg_popcount32_slow(uint32 word); static int pg_popcount64_slow(uint64 word); @@ -138,9 +115,6 @@ static int pg_popcount64_fast(uint64 word); int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; 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 /* TRY_POPCNT_FAST */ #ifdef TRY_POPCNT_FAST @@ -291,6 +265,28 @@ pg_popcount64_slow(uint64 word) #endif /* HAVE__BUILTIN_POPCOUNT */ } +#ifndef TRY_POPCNT_FAST + +/* + * When the POPCNT instruction is not available, there's no point in using + * function pointers to vary the implementation between the fast and slow + * method. We instead just make these actual external functions when + * TRY_POPCNT_FAST is not defined. The compiler should be able to inline + * the slow versions here. + */ +int +pg_popcount32(uint32 word) +{ + return pg_popcount32_slow(word); +} + +int +pg_popcount64(uint64 word) +{ + return pg_popcount64_slow(word); +} + +#endif /* !TRY_POPCNT_FAST */ /* * pg_popcount |