Hello! Attached patch checks all supported __builtin_cpu_supports options. Additionally, it adds a couple of comments and moves some code to prevent future mistakes.
2017-01-12 Uros Bizjak <ubiz...@gmail.com> * gcc.target/i386/builtin_target.c (check_features): Check all supported __builtin_cpu_supports options. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: gcc/config/i386/cpuid.h =================================================================== --- gcc/config/i386/cpuid.h (revision 244369) +++ gcc/config/i386/cpuid.h (working copy) @@ -47,7 +47,7 @@ #define bit_SSE (1 << 25) #define bit_SSE2 (1 << 26) -/* Extended Features */ +/* Extended Features (%eax == 0x80000001) */ /* %ecx */ #define bit_LAHF_LM (1 << 0) #define bit_ABM (1 << 5) @@ -54,7 +54,6 @@ #define bit_SSE4a (1 << 6) #define bit_PRFCHW (1 << 8) #define bit_XOP (1 << 11) -#define bit_AVX512VPOPCNTDQ (1 << 14) #define bit_LWP (1 << 15) #define bit_FMA4 (1 << 16) #define bit_TBM (1 << 21) @@ -61,14 +60,12 @@ #define bit_MWAITX (1 << 29) /* %edx */ -#define bit_AVX5124VNNIW (1 << 2) -#define bit_AVX5124FMAPS (1 << 3) #define bit_MMXEXT (1 << 22) #define bit_LM (1 << 29) #define bit_3DNOWP (1 << 30) #define bit_3DNOW (1 << 31) -/* %ebx. */ +/* %ebx */ #define bit_CLZERO (1 << 0) /* Extended Features (%eax == 7) */ @@ -100,7 +97,12 @@ #define bit_AVX512VBMI (1 << 1) #define bit_PKU (1 << 3) #define bit_OSPKE (1 << 4) +#define bit_AVX512VPOPCNTDQ (1 << 14) +/* %edx */ +#define bit_AVX5124VNNIW (1 << 2) +#define bit_AVX5124FMAPS (1 << 3) + /* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */ #define bit_BNDREGS (1 << 3) #define bit_BNDCSR (1 << 4) Index: gcc/testsuite/gcc.target/i386/builtin_target.c =================================================================== --- gcc/testsuite/gcc.target/i386/builtin_target.c (revision 244369) +++ gcc/testsuite/gcc.target/i386/builtin_target.c (working copy) @@ -163,6 +163,9 @@ check_features (unsigned int ecx, unsigned int edx, int max_cpuid_level) { + unsigned int eax, ebx; + unsigned int ext_level; + if (edx & bit_CMOV) assert (__builtin_cpu_supports ("cmov")); if (edx & bit_MMX) @@ -187,18 +190,27 @@ assert (__builtin_cpu_supports ("sse4.2")); if (ecx & bit_AVX) assert (__builtin_cpu_supports ("avx")); + if (ecx & bit_FMA) + assert (__builtin_cpu_supports ("fma")); /* Get advanced features at level 7 (eax = 7, ecx = 0). */ if (max_cpuid_level >= 7) { - unsigned int eax, ebx, ecx, edx; __cpuid_count (7, 0, eax, ebx, ecx, edx); + if (ebx & bit_BMI) + assert (__builtin_cpu_supports ("bmi")); if (ebx & bit_AVX2) assert (__builtin_cpu_supports ("avx2")); + if (ebx & bit_BMI2) + assert (__builtin_cpu_supports ("bmi2")); if (ebx & bit_AVX512F) assert (__builtin_cpu_supports ("avx512f")); if (ebx & bit_AVX512VL) assert (__builtin_cpu_supports ("avx512vl")); + if (ebx & bit_AVX512BW) + assert (__builtin_cpu_supports ("avx512bw")); + if (ebx & bit_AVX512DQ) + assert (__builtin_cpu_supports ("avx512dq")); if (ebx & bit_AVX512CD) assert (__builtin_cpu_supports ("avx512cd")); if (ebx & bit_AVX512PF) @@ -205,21 +217,32 @@ assert (__builtin_cpu_supports ("avx512pf")); if (ebx & bit_AVX512ER) assert (__builtin_cpu_supports ("avx512er")); - if (ebx & bit_AVX512BW) - assert (__builtin_cpu_supports ("avx512bw")); - if (ebx & bit_AVX512DQ) - assert (__builtin_cpu_supports ("avx512dq")); - if (ecx & bit_AVX512IFMA) + if (ebx & bit_AVX512IFMA) assert (__builtin_cpu_supports ("avx512ifma")); if (ecx & bit_AVX512VBMI) assert (__builtin_cpu_supports ("avx512vbmi")); + if (ecx & bit_AVX512VPOPCNTDQ) + assert (__builtin_cpu_supports ("avx512vpopcntdq")); if (edx & bit_AVX5124VNNIW) assert (__builtin_cpu_supports ("avx5124vnniw")); if (edx & bit_AVX5124FMAPS) assert (__builtin_cpu_supports ("avx5124fmaps")); - if (ecx & bit_AVX512VPOPCNTDQ) - assert (__builtin_cpu_supports ("avx512vpopcntdq")); } + + /* Check cpuid level of extended features. */ + __cpuid (0x80000000, ext_level, ebx, ecx, edx); + + if (ext_level >= 0x80000001) + { + __cpuid (0x80000001, eax, ebx, ecx, edx); + + if (ecx & bit_SSE4a) + assert (__builtin_cpu_supports ("sse4a")); + if (ecx & bit_FMA4) + assert (__builtin_cpu_supports ("fma4")); + if (ecx & bit_XOP) + assert (__builtin_cpu_supports ("xop")); + } } static int __attribute__ ((noinline)) Index: libgcc/config/i386/cpuinfo.c =================================================================== --- libgcc/config/i386/cpuinfo.c (revision 244369) +++ libgcc/config/i386/cpuinfo.c (working copy) @@ -215,6 +215,9 @@ get_available_features (unsigned int ecx, unsigned int edx, int max_cpuid_level) { + unsigned int eax, ebx; + unsigned int ext_level; + unsigned int features = 0; if (edx & bit_CMOV) @@ -247,7 +250,6 @@ /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ if (max_cpuid_level >= 7) { - unsigned int eax, ebx, ecx, edx; __cpuid_count (7, 0, eax, ebx, ecx, edx); if (ebx & bit_BMI) features |= (1 << FEATURE_BMI); @@ -273,20 +275,18 @@ features |= (1 << FEATURE_AVX512IFMA); if (ecx & bit_AVX512VBMI) features |= (1 << FEATURE_AVX512VBMI); + if (ecx & bit_AVX512VPOPCNTDQ) + features |= (1 << FEATURE_AVX512VPOPCNTDQ); if (edx & bit_AVX5124VNNIW) features |= (1 << FEATURE_AVX5124VNNIW); if (edx & bit_AVX5124FMAPS) features |= (1 << FEATURE_AVX5124FMAPS); - if (ecx & bit_AVX512VPOPCNTDQ) - features |= (1 << FEATURE_AVX512VPOPCNTDQ); } - unsigned int ext_level; - unsigned int eax, ebx; /* Check cpuid level of extended features. */ __cpuid (0x80000000, ext_level, ebx, ecx, edx); - if (ext_level > 0x80000000) + if (ext_level >= 0x80000001) { __cpuid (0x80000001, eax, ebx, ecx, edx);