From 059cc8aca774e50555bc116436348d2898404685 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 29 Mar 2018 13:14:06 +0000 Subject: [PATCH] i386: Enable AVX/AVX512 features only if supported by OSXSAVE 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 | 15 ++++ libgcc/config/i386/cpuinfo.c | 134 +++++++++++++++++++++++------------ 2 files changed, 105 insertions(+), 44 deletions(-) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 5df3c2bd69e..ee8f40fa25b 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,18 @@ +2018-03-29 H.J. Lu + + 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 PR target/85025 diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c index 4eb3f5cd944..1dac110a79a 100644 --- a/libgcc/config/i386/cpuinfo.c +++ b/libgcc/config/i386/cpuinfo.c @@ -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; -- 2.30.2