Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pg_popcount_avx512_choose.c
4 : : * Test whether we can use the AVX-512 pg_popcount() implementation.
5 : : *
6 : : * Copyright (c) 2024, PostgreSQL Global Development Group
7 : : *
8 : : * IDENTIFICATION
9 : : * src/port/pg_popcount_avx512_choose.c
10 : : *
11 : : *-------------------------------------------------------------------------
12 : : */
13 : : #include "c.h"
14 : :
15 : : #if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT)
16 : : #include <cpuid.h>
17 : : #endif
18 : :
19 : : #ifdef HAVE_XSAVE_INTRINSICS
20 : : #include <immintrin.h>
21 : : #endif
22 : :
23 : : #if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX)
24 : : #include <intrin.h>
25 : : #endif
26 : :
27 : : #include "port/pg_bitutils.h"
28 : :
29 : : /*
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.
33 : : */
34 : : #ifdef TRY_POPCNT_FAST
35 : :
36 : : /*
37 : : * Returns true if the CPU supports the instructions required for the AVX-512
38 : : * pg_popcount() implementation.
39 : : */
40 : : bool
8 nathan@postgresql.or 41 :GNC 7887 : pg_popcount_avx512_available(void)
42 : : {
43 : 7887 : unsigned int exx[4] = {0, 0, 0, 0};
44 : :
45 : : /* Does CPUID say there's support for AVX-512 popcount instructions? */
46 : : #if defined(HAVE__GET_CPUID_COUNT)
47 : 7887 : __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
48 : : #elif defined(HAVE__CPUIDEX)
49 : : __cpuidex(exx, 7, 0);
50 : : #else
51 : : #error cpuid instruction not available
52 : : #endif
53 [ + - ]: 7887 : if ((exx[2] & (1 << 14)) == 0) /* avx512-vpopcntdq */
54 : 7887 : return false;
55 : :
56 : : /* Does CPUID say there's support for AVX-512 byte and word instructions? */
8 nathan@postgresql.or 57 :UNC 0 : memset(exx, 0, sizeof(exx));
58 : : #if defined(HAVE__GET_CPUID_COUNT)
59 : 0 : __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
60 : : #elif defined(HAVE__CPUIDEX)
61 : : __cpuidex(exx, 7, 0);
62 : : #else
63 : : #error cpuid instruction not available
64 : : #endif
65 [ # # ]: 0 : if ((exx[1] & (1 << 30)) == 0) /* avx512-bw */
66 : 0 : return false;
67 : :
68 : : /* Does CPUID say there's support for XSAVE instructions? */
69 : 0 : memset(exx, 0, sizeof(exx));
70 : : #if defined(HAVE__GET_CPUID)
71 : 0 : __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
72 : : #elif defined(HAVE__CPUID)
73 : : __cpuid(exx, 1);
74 : : #else
75 : : #error cpuid instruction not available
76 : : #endif
77 [ # # ]: 0 : if ((exx[2] & (1 << 26)) == 0) /* xsave */
78 : 0 : return false;
79 : :
80 : : /* Does XGETBV say the ZMM registers are enabled? */
81 : : #ifdef HAVE_XSAVE_INTRINSICS
82 : 0 : return (_xgetbv(0) & 0xe0) != 0;
83 : : #else
84 : : return false;
85 : : #endif
86 : : }
87 : :
88 : : #endif /* TRY_POPCNT_FAST */
|