]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Workaround possible CPUID bug in Sandy Bridge.
authorliuhongt <hongtao.liu@intel.com>
Fri, 4 Aug 2023 01:27:39 +0000 (09:27 +0800)
committerliuhongt <hongtao.liu@intel.com>
Wed, 9 Aug 2023 06:01:24 +0000 (14:01 +0800)
Don't access leaf 7 subleaf 1 unless subleaf 0 says it is
supported via EAX.

Intel documentation says invalid subleaves return 0. We had been
relying on that behavior instead of checking the max sublef number.

It appears that some Sandy Bridge CPUs return at least the subleaf 0
EDX value for subleaf 1. Best guess is that this is a bug in a
microcode patch since all of the bits we're seeing set in EDX were
introduced after Sandy Bridge was originally released.

This is causing avxvnniint16 to be incorrectly enabled with
-march=native on these CPUs.

gcc/ChangeLog:

* common/config/i386/cpuinfo.h (get_available_features): Check
EAX for valid subleaf before use CPUID.

gcc/common/config/i386/cpuinfo.h

index 30ef0d334cad9be96e1a6ad7d691f43a6b323960..9fa4dec2a7e5917155e47c736d607305f21025cf 100644 (file)
@@ -663,6 +663,7 @@ get_available_features (struct __processor_model *cpu_model,
   unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
   unsigned int eax, ebx;
   unsigned int ext_level;
+  unsigned int subleaf_level;
 
   /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
 #define XCR_XFEATURE_ENABLED_MASK      0x0
@@ -762,7 +763,7 @@ get_available_features (struct __processor_model *cpu_model,
   /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
   if (max_cpuid_level >= 7)
     {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      __cpuid_count (7, 0, subleaf_level, ebx, ecx, edx);
       if (ebx & bit_BMI)
        set_feature (FEATURE_BMI);
       if (ebx & bit_SGX)
@@ -874,45 +875,48 @@ get_available_features (struct __processor_model *cpu_model,
            set_feature (FEATURE_AVX512FP16);
        }
 
-      __cpuid_count (7, 1, eax, ebx, ecx, edx);
-      if (eax & bit_HRESET)
-       set_feature (FEATURE_HRESET);
-      if (eax & bit_CMPCCXADD)
-       set_feature(FEATURE_CMPCCXADD);
-      if (edx & bit_PREFETCHI)
-       set_feature (FEATURE_PREFETCHI);
-      if (eax & bit_RAOINT)
-       set_feature (FEATURE_RAOINT);
-      if (avx_usable)
-       {
-         if (eax & bit_AVXVNNI)
-           set_feature (FEATURE_AVXVNNI);
-         if (eax & bit_AVXIFMA)
-           set_feature (FEATURE_AVXIFMA);
-         if (edx & bit_AVXVNNIINT8)
-           set_feature (FEATURE_AVXVNNIINT8);
-         if (edx & bit_AVXNECONVERT)
-           set_feature (FEATURE_AVXNECONVERT);
-         if (edx & bit_AVXVNNIINT16)
-           set_feature (FEATURE_AVXVNNIINT16);
-         if (eax & bit_SM3)
-           set_feature (FEATURE_SM3);
-         if (eax & bit_SHA512)
-           set_feature (FEATURE_SHA512);
-         if (eax & bit_SM4)
-           set_feature (FEATURE_SM4);
-       }
-      if (avx512_usable)
-       {
-         if (eax & bit_AVX512BF16)
-           set_feature (FEATURE_AVX512BF16);
-       }
-      if (amx_usable)
+      if (subleaf_level >= 1)
        {
-         if (eax & bit_AMX_FP16)
-           set_feature (FEATURE_AMX_FP16);
-         if (edx & bit_AMX_COMPLEX)
-           set_feature (FEATURE_AMX_COMPLEX);
+         __cpuid_count (7, 1, eax, ebx, ecx, edx);
+         if (eax & bit_HRESET)
+           set_feature (FEATURE_HRESET);
+         if (eax & bit_CMPCCXADD)
+           set_feature(FEATURE_CMPCCXADD);
+         if (edx & bit_PREFETCHI)
+           set_feature (FEATURE_PREFETCHI);
+         if (eax & bit_RAOINT)
+           set_feature (FEATURE_RAOINT);
+         if (avx_usable)
+           {
+             if (eax & bit_AVXVNNI)
+               set_feature (FEATURE_AVXVNNI);
+             if (eax & bit_AVXIFMA)
+               set_feature (FEATURE_AVXIFMA);
+             if (edx & bit_AVXVNNIINT8)
+               set_feature (FEATURE_AVXVNNIINT8);
+             if (edx & bit_AVXNECONVERT)
+               set_feature (FEATURE_AVXNECONVERT);
+             if (edx & bit_AVXVNNIINT16)
+               set_feature (FEATURE_AVXVNNIINT16);
+             if (eax & bit_SM3)
+               set_feature (FEATURE_SM3);
+             if (eax & bit_SHA512)
+               set_feature (FEATURE_SHA512);
+             if (eax & bit_SM4)
+               set_feature (FEATURE_SM4);
+           }
+         if (avx512_usable)
+           {
+             if (eax & bit_AVX512BF16)
+               set_feature (FEATURE_AVX512BF16);
+           }
+         if (amx_usable)
+           {
+             if (eax & bit_AMX_FP16)
+               set_feature (FEATURE_AMX_FP16);
+             if (edx & bit_AMX_COMPLEX)
+               set_feature (FEATURE_AMX_COMPLEX);
+           }
        }
     }