i386: Enable AVX/AVX512 features only if supported by OSXSAVE
authorH.J. Lu <hongjiu.lu@intel.com>
Thu, 29 Mar 2018 13:14:06 +0000 (13:14 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Thu, 29 Mar 2018 13:14:06 +0000 (06:14 -0700)
Enable AVX and AVX512 features only if their states are supported by
OSXSAVE.

PR target/85100
* config/i386/cpuinfo.c (XCR_XFEATURE_ENABLED_MASK): New.
(XSTATE_FP): Likewise.
(XSTATE_SSE): Likewise.
(XSTATE_YMM): Likewise.
(XSTATE_OPMASK): Likewise.
(XSTATE_ZMM): Likewise.
(XSTATE_HI_ZMM): Likewise.
(XCR_AVX_ENABLED_MASK): Likewise.
(XCR_AVX512F_ENABLED_MASK): Likewise.
(get_available_features): Enable AVX and AVX512 features only
if their states are supported by OSXSAVE.

From-SVN: r258954

libgcc/ChangeLog
libgcc/config/i386/cpuinfo.c

index 5df3c2bd69e13696a5c3cbe1406cfecf2b24318c..ee8f40fa25b4ab4b8c3dbb94de33e69867f05212 100644 (file)
@@ -1,3 +1,18 @@
+2018-03-29  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/85100
+       * config/i386/cpuinfo.c (XCR_XFEATURE_ENABLED_MASK): New.
+       (XSTATE_FP): Likewise.
+       (XSTATE_SSE): Likewise.
+       (XSTATE_YMM): Likewise.
+       (XSTATE_OPMASK): Likewise.
+       (XSTATE_ZMM): Likewise.
+       (XSTATE_HI_ZMM): Likewise.
+       (XCR_AVX_ENABLED_MASK): Likewise.
+       (XCR_AVX512F_ENABLED_MASK): Likewise.
+       (get_available_features): Enable AVX and AVX512 features only
+       if their states are supported by OSXSAVE.
+
 2018-03-22  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
 
        PR target/85025
index 4eb3f5cd9441e55668b3f2b1ce10902bc9cf8e6b..1dac110a79ac6a4a554f0267faf843dddad5d053 100644 (file)
@@ -240,6 +240,40 @@ get_available_features (unsigned int ecx, unsigned int edx,
   unsigned int features = 0;
   unsigned int features2 = 0;
 
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK      0x0
+#define XSTATE_FP                      0x1
+#define XSTATE_SSE                     0x2
+#define XSTATE_YMM                     0x4
+#define XSTATE_OPMASK                  0x20
+#define XSTATE_ZMM                     0x40
+#define XSTATE_HI_ZMM                  0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+         ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      asm (".byte 0x0f, 0x01, 0xd0"
+          : "=a" (xcrlow), "=d" (xcrhigh)
+          : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+       {
+         avx_usable = 1;
+         avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+                          == XCR_AVX512F_ENABLED_MASK);
+       }
+    }
+
 #define set_feature(f) \
   if (f < 32) features |= (1U << f); else features2 |= (1U << (f - 32))
 
@@ -265,10 +299,13 @@ get_available_features (unsigned int ecx, unsigned int edx,
     set_feature (FEATURE_SSE4_1);
   if (ecx & bit_SSE4_2)
     set_feature (FEATURE_SSE4_2);
-  if (ecx & bit_AVX)
-    set_feature (FEATURE_AVX);
-  if (ecx & bit_FMA)
-    set_feature (FEATURE_FMA);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+       set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+       set_feature (FEATURE_FMA);
+    }
 
   /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
   if (max_cpuid_level >= 7)
@@ -276,44 +313,50 @@ get_available_features (unsigned int ecx, unsigned int edx,
       __cpuid_count (7, 0, eax, ebx, ecx, edx);
       if (ebx & bit_BMI)
        set_feature (FEATURE_BMI);
-      if (ebx & bit_AVX2)
-       set_feature (FEATURE_AVX2);
+      if (avx_usable)
+       {
+         if (ebx & bit_AVX2)
+           set_feature (FEATURE_AVX2);
+       }
       if (ebx & bit_BMI2)
        set_feature (FEATURE_BMI2);
-      if (ebx & bit_AVX512F)
-       set_feature (FEATURE_AVX512F);
-      if (ebx & bit_AVX512VL)
-       set_feature (FEATURE_AVX512VL);
-      if (ebx & bit_AVX512BW)
-       set_feature (FEATURE_AVX512BW);
-      if (ebx & bit_AVX512DQ)
-       set_feature (FEATURE_AVX512DQ);
-      if (ebx & bit_AVX512CD)
-       set_feature (FEATURE_AVX512CD);
-      if (ebx & bit_AVX512PF)
-       set_feature (FEATURE_AVX512PF);
-      if (ebx & bit_AVX512ER)
-       set_feature (FEATURE_AVX512ER);
-      if (ebx & bit_AVX512IFMA)
-       set_feature (FEATURE_AVX512IFMA);
-      if (ecx & bit_AVX512VBMI)
-       set_feature (FEATURE_AVX512VBMI);
-      if (ecx & bit_AVX512VBMI2)
-       set_feature (FEATURE_AVX512VBMI2);
-      if (ecx & bit_GFNI)
-       set_feature (FEATURE_GFNI);
-      if (ecx & bit_VPCLMULQDQ)
-       set_feature (FEATURE_VPCLMULQDQ);
-      if (ecx & bit_AVX512VNNI)
-       set_feature (FEATURE_AVX512VNNI);
-      if (ecx & bit_AVX512BITALG)
-       set_feature (FEATURE_AVX512BITALG);
-      if (ecx & bit_AVX512VPOPCNTDQ)
-       set_feature (FEATURE_AVX512VPOPCNTDQ);
-      if (edx & bit_AVX5124VNNIW)
-       set_feature (FEATURE_AVX5124VNNIW);
-      if (edx & bit_AVX5124FMAPS)
-       set_feature (FEATURE_AVX5124FMAPS);
+      if (avx512_usable)
+       {
+         if (ebx & bit_AVX512F)
+           set_feature (FEATURE_AVX512F);
+         if (ebx & bit_AVX512VL)
+           set_feature (FEATURE_AVX512VL);
+         if (ebx & bit_AVX512BW)
+           set_feature (FEATURE_AVX512BW);
+         if (ebx & bit_AVX512DQ)
+           set_feature (FEATURE_AVX512DQ);
+         if (ebx & bit_AVX512CD)
+           set_feature (FEATURE_AVX512CD);
+         if (ebx & bit_AVX512PF)
+           set_feature (FEATURE_AVX512PF);
+         if (ebx & bit_AVX512ER)
+           set_feature (FEATURE_AVX512ER);
+         if (ebx & bit_AVX512IFMA)
+           set_feature (FEATURE_AVX512IFMA);
+         if (ecx & bit_AVX512VBMI)
+           set_feature (FEATURE_AVX512VBMI);
+         if (ecx & bit_AVX512VBMI2)
+           set_feature (FEATURE_AVX512VBMI2);
+         if (ecx & bit_GFNI)
+           set_feature (FEATURE_GFNI);
+         if (ecx & bit_VPCLMULQDQ)
+           set_feature (FEATURE_VPCLMULQDQ);
+         if (ecx & bit_AVX512VNNI)
+           set_feature (FEATURE_AVX512VNNI);
+         if (ecx & bit_AVX512BITALG)
+           set_feature (FEATURE_AVX512BITALG);
+         if (ecx & bit_AVX512VPOPCNTDQ)
+           set_feature (FEATURE_AVX512VPOPCNTDQ);
+         if (edx & bit_AVX5124VNNIW)
+           set_feature (FEATURE_AVX5124VNNIW);
+         if (edx & bit_AVX5124FMAPS)
+           set_feature (FEATURE_AVX5124FMAPS);
+       }
     }
 
   /* Check cpuid level of extended features.  */
@@ -325,10 +368,13 @@ get_available_features (unsigned int ecx, unsigned int edx,
 
       if (ecx & bit_SSE4a)
        set_feature (FEATURE_SSE4_A);
-      if (ecx & bit_FMA4)
-       set_feature (FEATURE_FMA4);
-      if (ecx & bit_XOP)
-       set_feature (FEATURE_XOP);
+      if (avx_usable)
+       {
+         if (ecx & bit_FMA4)
+           set_feature (FEATURE_FMA4);
+         if (ecx & bit_XOP)
+           set_feature (FEATURE_XOP);
+       }
     }
     
   __cpu_model.__cpu_features[0] = features;