From 8550c6ccd859dfd01ec62da52cd1aaa54cc828a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 8 Jul 2015 12:17:12 +0300 Subject: [PATCH] Fix AVX2 detection. Replaces calls to __get_cpuid by __cpuid_count on gcc and clang and calls to __cpuid by __cpuidex on MSVC. Unlike __get_cpuid and __cpuid, __cpuid_count and __cpuidex set the ecx register which is required for AVX2 detection. --- src/strategyselector.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/strategyselector.c b/src/strategyselector.c index 972054db..d0b956ab 100644 --- a/src/strategyselector.c +++ b/src/strategyselector.c @@ -182,20 +182,22 @@ typedef struct { // CPUID adapters for different compilers. # if defined(__GNUC__) #include -static INLINE int get_cpuid(unsigned int level, cpuid_t *cpu_info) { - return __get_cpuid(level, &cpu_info->eax, &cpu_info->ebx, &cpu_info->ecx, &cpu_info->edx); +static INLINE int get_cpuid(unsigned level, unsigned sublevel, cpuid_t *cpu_info) { + if (__get_cpuid_max(level & 0x80000000, NULL) < level) return 0; + __cpuid_count(level, sublevel, cpu_info->eax, cpu_info->ebx, cpu_info->ecx, cpu_info->edx); + return 1; } # elif defined(_MSC_VER) #include -static INLINE int get_cpuid(unsigned int level, cpuid_t *cpu_info) { +static INLINE int get_cpuid(unsigned level, unsigned sublevel, cpuid_t *cpu_info) { int vendor_info[4] = { 0, 0, 0, 0 }; - __cpuid(vendor_info, 0); + __cpuidex(vendor_info, 0, 0); // Check highest supported function. if (level > vendor_info[0]) return 0; int ms_cpu_info[4] = { cpu_info->eax, cpu_info->ebx, cpu_info->ecx, cpu_info->edx }; - __cpuid(ms_cpu_info, level); + __cpuidex(ms_cpu_info, level, sublevel); cpu_info->eax = ms_cpu_info[0]; cpu_info->ebx = ms_cpu_info[1]; cpu_info->ecx = ms_cpu_info[2]; @@ -204,7 +206,7 @@ static INLINE int get_cpuid(unsigned int level, cpuid_t *cpu_info) { return 1; } # else -static INLINE int get_cpuid(unsigned int level, cpuid_t *cpu_info) +static INLINE int get_cpuid(unsigned level, unsigned sublevel, cpuid_t *cpu_info) { return 0; } @@ -282,7 +284,7 @@ static void set_hardware_flags(int32_t cpuid) { }; // Dig CPU features with cpuid - get_cpuid(1, &cpuid1); + get_cpuid(1, 0, &cpuid1); // EDX if (cpuid1.edx & CPUID1_EDX_MMX) g_hardware_flags.intel_flags.mmx = 1; @@ -316,7 +318,7 @@ static void set_hardware_flags(int32_t cpuid) { if (g_hardware_flags.intel_flags.avx) { cpuid_t cpuid7 = { 0, 0, 0, 0 }; - get_cpuid(7, &cpuid7); + get_cpuid(7, 0, &cpuid7); if (cpuid7.ebx & CPUID7_EBX_AVX2) g_hardware_flags.intel_flags.avx2 = 1; } }