diff --git a/client/hostinfo_win.cpp b/client/hostinfo_win.cpp index 966e384611..fc534a33a3 100644 --- a/client/hostinfo_win.cpp +++ b/client/hostinfo_win.cpp @@ -1025,6 +1025,45 @@ int get_processor_cache(int& cache) { } +// Returns true if the AVX instruction set is supported with the current +// combination of OS and CPU. +// see: http://insufficientlycomplicated.wordpress.com/2011/11/07/detecting-intel-advanced-vector-extensions-avx-in-visual-studio/ +bool is_avx_supported() { + + bool supported = false; + + // If Visual Studio 2010 SP1 or later +#if (_MSC_FULL_VER >= 160040219) + // Checking for AVX requires 3 things: + // 1) CPUID indicates that the OS uses XSAVE and XRSTORE + // instructions (allowing saving YMM registers on context + // switch) + // 2) CPUID indicates support for AVX + // 3) XGETBV indicates the AVX registers will be saved and + // restored on context switch + // + // Note that XGETBV is only available on 686 or later CPUs, so + // the instruction needs to be conditionally run. + int cpuInfo[4]; + __cpuid(cpuInfo, 1); + + bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false; + bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false; + + if (osUsesXSAVE_XRSTORE && cpuAVXSuport) + { + // Check if the OS will save the YMM registers + unsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); + supported = (xcrFeatureMask & 0x6) || false; + } +#endif + + return supported; +} + + + + // Returns the features supported by the processor, use the // Linux CPU processor feature mnemonics. // see: http://msdn.microsoft.com/en-us/library/hskdteyh.aspx @@ -1115,7 +1154,6 @@ int get_processor_features(char* vendor, char* features, int features_size) { FEATURE_TEST(std_supported, (std_ecx & (1 << 22)), "movebe "); FEATURE_TEST(std_supported, (std_ecx & (1 << 23)), "popcnt "); FEATURE_TEST(std_supported, (std_ecx & (1 << 25)), "aes "); - FEATURE_TEST(std_supported, (std_ecx & (1 << 28)), "avx "); FEATURE_TEST(std_supported, (std_ecx & (1 << 29)), "f16c "); FEATURE_TEST(std_supported, (std_ecx & (1 << 30)), "rdrand"); @@ -1123,14 +1161,9 @@ int get_processor_features(char* vendor, char* features, int features_size) { FEATURE_TEST(ext_supported, (ext_edx & (1 << 20)), "nx "); FEATURE_TEST(ext_supported, (ext_edx & (1 << 29)), "lm "); - if (intel_supported) { - // Intel only features - FEATURE_TEST(std_supported, (std_ecx & (1 << 5)), "vmx "); - FEATURE_TEST(std_supported, (std_ecx & (1 << 6)), "smx "); - FEATURE_TEST(std_supported, (std_ecx & (1 << 8)), "tm2 "); - FEATURE_TEST(std_supported, (std_ecx & (1 << 18)), "dca "); - FEATURE_TEST(std_supported, (std_edx & (1 << 31)), "pbe "); + if (is_avx_supported()) { + FEATURE_TEST(std_supported, (std_ecx & (1 << 28)), "avx "); } @@ -1147,6 +1180,17 @@ int get_processor_features(char* vendor, char* features, int features_size) { } + if (intel_supported) { + // Intel only features + FEATURE_TEST(std_supported, (std_ecx & (1 << 5)), "vmx "); + FEATURE_TEST(std_supported, (std_ecx & (1 << 6)), "smx "); + FEATURE_TEST(std_supported, (std_ecx & (1 << 8)), "tm2 "); + FEATURE_TEST(std_supported, (std_ecx & (1 << 18)), "dca "); + + FEATURE_TEST(std_supported, (std_edx & (1 << 31)), "pbe "); + } + + if (amd_supported) { // AMD only features FEATURE_TEST(ext_supported, (ext_ecx & (1 << 2)), "svm ");