46 #ifndef SIMDJSON_INTERNAL_ISADETECTION_H
47 #define SIMDJSON_INTERNAL_ISADETECTION_H
53 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
60 enum instruction_set {
80 #if defined(__PPC64__)
82 static inline uint32_t detect_supported_architectures() {
83 return instruction_set::ALTIVEC;
86 #elif defined(__aarch64__) || defined(_M_ARM64)
88 static inline uint32_t detect_supported_architectures() {
89 return instruction_set::NEON;
92 #elif defined(__x86_64__) || defined(_M_AMD64)
97 constexpr uint32_t cpuid_avx2_bit = 1 << 5;
98 constexpr uint32_t cpuid_bmi1_bit = 1 << 3;
99 constexpr uint32_t cpuid_bmi2_bit = 1 << 8;
100 constexpr uint32_t cpuid_avx512f_bit = 1 << 16;
101 constexpr uint32_t cpuid_avx512dq_bit = 1 << 17;
102 constexpr uint32_t cpuid_avx512ifma_bit = 1 << 21;
103 constexpr uint32_t cpuid_avx512pf_bit = 1 << 26;
104 constexpr uint32_t cpuid_avx512er_bit = 1 << 27;
105 constexpr uint32_t cpuid_avx512cd_bit = 1 << 28;
106 constexpr uint32_t cpuid_avx512bw_bit = 1 << 30;
107 constexpr uint32_t cpuid_avx512vl_bit = 1U << 31;
108 constexpr uint32_t cpuid_avx512vbmi2_bit = 1 << 6;
109 constexpr uint64_t cpuid_avx256_saved = uint64_t(1) << 2;
110 constexpr uint64_t cpuid_avx512_saved = uint64_t(7) << 5;
111 constexpr uint32_t cpuid_sse42_bit = 1 << 20;
112 constexpr uint32_t cpuid_osxsave = (uint32_t(1) << 26) | (uint32_t(1) << 27);
113 constexpr uint32_t cpuid_pclmulqdq_bit = 1 << 1;
118 static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
120 #if defined(_MSC_VER)
122 __cpuidex(cpu_info, *eax, *ecx);
127 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
128 uint32_t level = *eax;
129 __get_cpuid(level, eax, ebx, ecx, edx);
131 uint32_t a = *eax, b, c = *ecx, d;
132 asm volatile(
"cpuid\n\t" :
"+a"(a),
"=b"(b),
"+c"(c),
"=d"(d));
141 static inline uint64_t xgetbv() {
142 #if defined(_MSC_VER)
145 uint32_t xcr0_lo, xcr0_hi;
146 asm volatile(
"xgetbv\n\t" :
"=a" (xcr0_lo),
"=d" (xcr0_hi) :
"c" (0));
147 return xcr0_lo | (uint64_t(xcr0_hi) << 32);
151 static inline uint32_t detect_supported_architectures() {
152 uint32_t eax, ebx, ecx, edx;
153 uint32_t host_isa = 0x0;
158 cpuid(&eax, &ebx, &ecx, &edx);
160 if (ecx & cpuid_sse42_bit) {
161 host_isa |= instruction_set::SSE42;
166 if (ecx & cpuid_pclmulqdq_bit) {
167 host_isa |= instruction_set::PCLMULQDQ;
171 if ((ecx & cpuid_osxsave) != cpuid_osxsave) {
176 uint64_t xcr0 = xgetbv();
178 if ((xcr0 & cpuid_avx256_saved) == 0) {
185 cpuid(&eax, &ebx, &ecx, &edx);
186 if (ebx & cpuid_avx2_bit) {
187 host_isa |= instruction_set::AVX2;
189 if (ebx & cpuid_bmi1_bit) {
190 host_isa |= instruction_set::BMI1;
193 if (ebx & cpuid_bmi2_bit) {
194 host_isa |= instruction_set::BMI2;
197 if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) {
201 if (ebx & cpuid_avx512f_bit) {
202 host_isa |= instruction_set::AVX512F;
205 if (ebx & cpuid_avx512dq_bit) {
206 host_isa |= instruction_set::AVX512DQ;
209 if (ebx & cpuid_avx512ifma_bit) {
210 host_isa |= instruction_set::AVX512IFMA;
213 if (ebx & cpuid_avx512pf_bit) {
214 host_isa |= instruction_set::AVX512PF;
217 if (ebx & cpuid_avx512er_bit) {
218 host_isa |= instruction_set::AVX512ER;
221 if (ebx & cpuid_avx512cd_bit) {
222 host_isa |= instruction_set::AVX512CD;
225 if (ebx & cpuid_avx512bw_bit) {
226 host_isa |= instruction_set::AVX512BW;
229 if (ebx & cpuid_avx512vl_bit) {
230 host_isa |= instruction_set::AVX512VL;
233 if (ecx & cpuid_avx512vbmi2_bit) {
234 host_isa |= instruction_set::AVX512VBMI2;
242 static inline uint32_t detect_supported_architectures() {
243 return instruction_set::DEFAULT;
We want to support argument-dependent lookup (ADL).