46 #ifndef SIMDJSON_INTERNAL_ISADETECTION_H
47 #define SIMDJSON_INTERNAL_ISADETECTION_H
53 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
61 enum instruction_set {
81 #if defined(__PPC64__)
83 static inline uint32_t detect_supported_architectures() {
84 return instruction_set::ALTIVEC;
87 #elif defined(__arm__) || defined(__aarch64__)
89 #if defined(__ARM_NEON)
91 static inline uint32_t detect_supported_architectures() {
92 return instruction_set::NEON;
97 static inline uint32_t detect_supported_architectures() {
98 return instruction_set::DEFAULT;
103 #elif defined(__x86_64__) || defined(_M_AMD64)
108 constexpr uint32_t cpuid_avx2_bit = 1 << 5;
109 constexpr uint32_t cpuid_bmi1_bit = 1 << 3;
110 constexpr uint32_t cpuid_bmi2_bit = 1 << 8;
111 constexpr uint32_t cpuid_avx512f_bit = 1 << 16;
112 constexpr uint32_t cpuid_avx512dq_bit = 1 << 17;
113 constexpr uint32_t cpuid_avx512ifma_bit = 1 << 21;
114 constexpr uint32_t cpuid_avx512pf_bit = 1 << 26;
115 constexpr uint32_t cpuid_avx512er_bit = 1 << 27;
116 constexpr uint32_t cpuid_avx512cd_bit = 1 << 28;
117 constexpr uint32_t cpuid_avx512bw_bit = 1 << 30;
118 constexpr uint32_t cpuid_avx512vl_bit = 1U << 31;
119 constexpr uint32_t cpuid_avx512vbmi2_bit = 1 << 6;
120 constexpr uint32_t cpuid_sse42_bit = 1 << 20;
121 constexpr uint32_t cpuid_pclmulqdq_bit = 1 << 1;
126 static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
128 #if defined(_MSC_VER)
130 __cpuid(cpu_info, *eax);
135 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
136 uint32_t level = *eax;
137 __get_cpuid(level, eax, ebx, ecx, edx);
139 uint32_t a = *eax, b, c = *ecx, d;
140 asm volatile(
"cpuid\n\t" :
"+a"(a),
"=b"(b),
"+c"(c),
"=d"(d));
148 static inline uint32_t detect_supported_architectures() {
149 uint32_t eax, ebx, ecx, edx;
150 uint32_t host_isa = 0x0;
155 cpuid(&eax, &ebx, &ecx, &edx);
156 if (ebx & cpuid_avx2_bit) {
157 host_isa |= instruction_set::AVX2;
159 if (ebx & cpuid_bmi1_bit) {
160 host_isa |= instruction_set::BMI1;
163 if (ebx & cpuid_bmi2_bit) {
164 host_isa |= instruction_set::BMI2;
167 if (ebx & cpuid_avx512f_bit) {
168 host_isa |= instruction_set::AVX512F;
171 if (ebx & cpuid_avx512dq_bit) {
172 host_isa |= instruction_set::AVX512DQ;
175 if (ebx & cpuid_avx512ifma_bit) {
176 host_isa |= instruction_set::AVX512IFMA;
179 if (ebx & cpuid_avx512pf_bit) {
180 host_isa |= instruction_set::AVX512PF;
183 if (ebx & cpuid_avx512er_bit) {
184 host_isa |= instruction_set::AVX512ER;
187 if (ebx & cpuid_avx512cd_bit) {
188 host_isa |= instruction_set::AVX512CD;
191 if (ebx & cpuid_avx512bw_bit) {
192 host_isa |= instruction_set::AVX512BW;
195 if (ebx & cpuid_avx512vl_bit) {
196 host_isa |= instruction_set::AVX512VL;
199 if (ecx & cpuid_avx512vbmi2_bit) {
200 host_isa |= instruction_set::AVX512VBMI2;
205 cpuid(&eax, &ebx, &ecx, &edx);
207 if (ecx & cpuid_sse42_bit) {
208 host_isa |= instruction_set::SSE42;
211 if (ecx & cpuid_pclmulqdq_bit) {
212 host_isa |= instruction_set::PCLMULQDQ;
220 static inline uint32_t detect_supported_architectures() {
221 return instruction_set::DEFAULT;
We want to support argument-dependent lookup (ADL).