1 /*-------------------------------------------------------------------------
3 * pg_popcount_avx512_choose.c
4 * Test whether we can use the AVX-512 pg_popcount() implementation.
6 * Copyright (c) 2024, PostgreSQL Global Development Group
9 * src/port/pg_popcount_avx512_choose.c
11 *-------------------------------------------------------------------------
15 #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT)
19 #ifdef HAVE_XSAVE_INTRINSICS
20 #include <immintrin.h>
23 #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX)
27 #include "port/pg_bitutils.h"
30 * It's probably unlikely that TRY_POPCNT_FAST won't be set if we are able to
31 * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on
32 * the function pointers that are only used when TRY_POPCNT_FAST is set.
34 #ifdef TRY_POPCNT_FAST
37 * Does CPUID say there's support for XSAVE instructions?
42 unsigned int exx
[4] = {0, 0, 0, 0};
44 #if defined(HAVE__GET_CPUID)
45 __get_cpuid(1, &exx
[0], &exx
[1], &exx
[2], &exx
[3]);
46 #elif defined(HAVE__CPUID)
49 #error cpuid instruction not available
51 return (exx
[2] & (1 << 27)) != 0; /* osxsave */
55 * Does XGETBV say the ZMM registers are enabled?
57 * NB: Caller is responsible for verifying that xsave_available() returns true
58 * before calling this.
61 zmm_regs_available(void)
63 #ifdef HAVE_XSAVE_INTRINSICS
64 return (_xgetbv(0) & 0xe6) == 0xe6;
71 * Does CPUID say there's support for AVX-512 popcount and byte-and-word
75 avx512_popcnt_available(void)
77 unsigned int exx
[4] = {0, 0, 0, 0};
79 #if defined(HAVE__GET_CPUID_COUNT)
80 __get_cpuid_count(7, 0, &exx
[0], &exx
[1], &exx
[2], &exx
[3]);
81 #elif defined(HAVE__CPUIDEX)
84 #error cpuid instruction not available
86 return (exx
[2] & (1 << 14)) != 0 && /* avx512-vpopcntdq */
87 (exx
[1] & (1 << 30)) != 0; /* avx512-bw */
91 * Returns true if the CPU supports the instructions required for the AVX-512
92 * pg_popcount() implementation.
95 pg_popcount_avx512_available(void)
97 return xsave_available() &&
98 zmm_regs_available() &&
99 avx512_popcnt_available();
102 #endif /* TRY_POPCNT_FAST */