From 6c35d16a3925958b3a22426de0cb8e04f654b6dd Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 24 Jun 2020 04:39:16 -0700 Subject: [PATCH] x86: Share _isa_names_table and use cpuinfo.h Both driver-i386.c and libgcc use CPUID to detect the processor name as well as available ISAs. To detect the same processor or ISAs, the same detection logic is duplicated in 2 places. Sometimes only one place was up to date or got it right. Sometimes both places got it wrong. 1. Add common/config/i386/i386-isas.h to define _isa_names_table. 2. Use isa_names_table to auto-generate ISA command-line options. 3. Use isa_names_table to auto-generate __builtin_cpu_supports tests. 4. Use common/config/i386/cpuinfo.h to check available ISAs and detect newer Intel processors in driver-i386.c and builtin_target.c. 5. Detection of AMD processors and older processors in driver-i386.c is unchanged. gcc/ PR target/95843 * common/config/i386/i386-isas.h: New file. Extracted from gcc/config/i386/i386-builtins.c. (_isa_names_table): Add option. (ISA_NAMES_TABLE_START): New. (ISA_NAMES_TABLE_END): Likewise. (ISA_NAMES_TABLE_ENTRY): Likewise. (isa_names_table): Defined with ISA_NAMES_TABLE_START, ISA_NAMES_TABLE_END and ISA_NAMES_TABLE_ENTRY. Add more ISAs from enum processor_features. * config/i386/driver-i386.c: Include "common/config/i386/cpuinfo.h" and "common/config/i386/i386-isas.h". (has_feature): New macro. (host_detect_local_cpu): Call cpu_indicator_init to get CPU features. Use has_feature to detect processor features. Call Call get_intel_cpu to get the newer Intel CPU name. Use isa_names_table to generate command-line options. * config/i386/i386-builtins.c: Include "common/config/i386/i386-isas.h". (_arch_names_table): Removed. (isa_names_table): Likewise. gcc/testsuite/ PR target/95843 * gcc.target/i386/builtin_target.c: Include , ../../../common/config/i386/i386-cpuinfo.h and ../../../common/config/i386/cpuinfo.h. (check_amd_cpu_model): Removed. (check_intel_cpu_model): Likewise, (CHECK___builtin_cpu_is): New. (gcc_assert): New. Defined as assert. (gcc_unreachable): New. Defined as abort. (inline): New. Defined as empty. (ISA_NAMES_TABLE_START): Likewise. (ISA_NAMES_TABLE_END): Likewise. (ISA_NAMES_TABLE_ENTRY): New. (check_features): Include "../../../common/config/i386/i386-isas.h". (check_detailed): Call cpu_indicator_init. Always call check_features. Call get_amd_cpu instead of check_amd_cpu_model. Call get_intel_cpu instead of check_intel_cpu_model. --- gcc/common/config/i386/i386-isas.h | 163 +++++ gcc/config/i386/driver-i386.c | 644 +++--------------- gcc/config/i386/i386-builtins.c | 52 +- .../gcc.target/i386/builtin_target.c | 355 +--------- 4 files changed, 306 insertions(+), 908 deletions(-) create mode 100644 gcc/common/config/i386/i386-isas.h diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h new file mode 100644 index 00000000000..08c9dbecc76 --- /dev/null +++ b/gcc/common/config/i386/i386-isas.h @@ -0,0 +1,163 @@ +/* i386 ISA table. + Copyright (C) 2020 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* These are the target attribute strings for which a dispatcher is + available, from fold_builtin_cpu. */ +struct _isa_names_table +{ + const char *const name; + const enum processor_features feature; + const enum feature_priority priority; + const char *const option; +}; + +/* NB: isa_names_table is shared by i386-builtins.c, driver-i386.c and + gcc.target/i386/builtin_target.c. isa_names_table is a static const + array in i386-builtins.c and driver-i386.c. But it is a list of + assert statements in gcc.target/i386/builtin_target.c. */ + +#ifndef ISA_NAMES_TABLE_START +# define ISA_NAMES_TABLE_START \ + static const struct _isa_names_table isa_names_table[] = { +#endif + +#ifndef ISA_NAMES_TABLE_END +# define ISA_NAMES_TABLE_END }; +#endif + +#ifndef ISA_NAMES_TABLE_ENTRY +# define ISA_NAMES_TABLE_ENTRY(name, feature, priority, option) \ + {name, feature, priority, option}, +#endif + +ISA_NAMES_TABLE_START + ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("mmx", FEATURE_MMX, P_MMX, "-mmmx") + ISA_NAMES_TABLE_ENTRY("popcnt", FEATURE_POPCNT, P_POPCNT, "-mpopcnt") + ISA_NAMES_TABLE_ENTRY("sse", FEATURE_SSE, P_SSE, "-msse") + ISA_NAMES_TABLE_ENTRY("sse2", FEATURE_SSE2, P_SSE2, "-msse2") + ISA_NAMES_TABLE_ENTRY("sse3", FEATURE_SSE3, P_SSE3, "-msse3") + ISA_NAMES_TABLE_ENTRY("ssse3", FEATURE_SSSE3, P_SSSE3, "-mssse3") + ISA_NAMES_TABLE_ENTRY("sse4.1", FEATURE_SSE4_1, P_SSE4_1, "-msse4.1") + ISA_NAMES_TABLE_ENTRY("sse4.2", FEATURE_SSE4_2, P_SSE4_2, "-msse4.2") + ISA_NAMES_TABLE_ENTRY("avx", FEATURE_AVX, P_AVX, "-mavx") + ISA_NAMES_TABLE_ENTRY("avx2", FEATURE_AVX2, P_AVX2, "-mavx2") + ISA_NAMES_TABLE_ENTRY("sse4a", FEATURE_SSE4_A, P_SSE4_A, "-msse4a") + ISA_NAMES_TABLE_ENTRY("fma4", FEATURE_FMA4, P_FMA4, "-mfma4") + ISA_NAMES_TABLE_ENTRY("xop", FEATURE_XOP, P_XOP, "-mxop") + ISA_NAMES_TABLE_ENTRY("fma", FEATURE_FMA, P_FMA, "-mfma") + ISA_NAMES_TABLE_ENTRY("avx512f", FEATURE_AVX512F, P_AVX512F, + "-mavx512f") + ISA_NAMES_TABLE_ENTRY("bmi", FEATURE_BMI, P_BMI, "-mbmi") + ISA_NAMES_TABLE_ENTRY("bmi2", FEATURE_BMI2, P_BMI2, "-mbmi2") + ISA_NAMES_TABLE_ENTRY("aes", FEATURE_AES, P_AES, "-maes") + ISA_NAMES_TABLE_ENTRY("pclmul", FEATURE_PCLMUL, P_PCLMUL, "-mpclmul") + ISA_NAMES_TABLE_ENTRY("avx512vl", FEATURE_AVX512VL, P_NONE, + "-mavx512vl") + ISA_NAMES_TABLE_ENTRY("avx512bw", FEATURE_AVX512BW, P_NONE, + "-mavx512bw") + ISA_NAMES_TABLE_ENTRY("avx512dq", FEATURE_AVX512DQ, P_NONE, + "-mavx512dq") + ISA_NAMES_TABLE_ENTRY("avx512cd", FEATURE_AVX512CD, P_NONE, + "-mavx512cd") + ISA_NAMES_TABLE_ENTRY("avx512er", FEATURE_AVX512ER, P_NONE, + "-mavx512er") + ISA_NAMES_TABLE_ENTRY("avx512pf", FEATURE_AVX512PF, P_NONE, + "-mavx512pf") + ISA_NAMES_TABLE_ENTRY("avx512vbmi", FEATURE_AVX512VBMI, P_NONE, + "-mavx512vbmi") + ISA_NAMES_TABLE_ENTRY("avx512ifma", FEATURE_AVX512IFMA, P_NONE, + "-mavx512ifma") + ISA_NAMES_TABLE_ENTRY("avx5124vnniw", FEATURE_AVX5124VNNIW, P_NONE, + "-mavx5124vnniw") + ISA_NAMES_TABLE_ENTRY("avx5124fmaps", FEATURE_AVX5124FMAPS, P_NONE, + "-mavx5124fmaps") + ISA_NAMES_TABLE_ENTRY("avx512vpopcntdq", FEATURE_AVX512VPOPCNTDQ, + P_NONE, "-mavx512vpopcntdq") + ISA_NAMES_TABLE_ENTRY("avx512vbmi2", FEATURE_AVX512VBMI2, P_NONE, + "-mavx512vbmi2") + ISA_NAMES_TABLE_ENTRY("gfni", FEATURE_GFNI, P_NONE, "-mgfni") + ISA_NAMES_TABLE_ENTRY("vpclmulqdq", FEATURE_VPCLMULQDQ, P_NONE, + "-mvpclmulqdq") + ISA_NAMES_TABLE_ENTRY("avx512vnni", FEATURE_AVX512VNNI, P_NONE, + "-mavx512vnni") + ISA_NAMES_TABLE_ENTRY("avx512bitalg", FEATURE_AVX512BITALG, P_NONE, + "-mavx512bitalg") + ISA_NAMES_TABLE_ENTRY("avx512bf16", FEATURE_AVX512BF16, P_NONE, + "-mavx512bf16") + ISA_NAMES_TABLE_ENTRY("avx512vp2intersect", FEATURE_AVX512VP2INTERSECT, + P_NONE, "-mavx512vp2intersect") + ISA_NAMES_TABLE_ENTRY("3dnow", FEATURE_3DNOW, P_NONE, "-m3dnow") + ISA_NAMES_TABLE_ENTRY("3dnowp", FEATURE_3DNOWP, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("adx", FEATURE_ADX, P_NONE, "-madx") + ISA_NAMES_TABLE_ENTRY("abm", FEATURE_ABM, P_NONE, "-mabm") + ISA_NAMES_TABLE_ENTRY("cldemote", FEATURE_CLDEMOTE, P_NONE, + "-mcldemote") + ISA_NAMES_TABLE_ENTRY("clflushopt", FEATURE_CLFLUSHOPT, P_NONE, + "-mclflushopt") + ISA_NAMES_TABLE_ENTRY("clwb", FEATURE_CLWB, P_NONE, "-mclwb") + ISA_NAMES_TABLE_ENTRY("clzero", FEATURE_CLZERO, P_NONE, "-mclzero") + ISA_NAMES_TABLE_ENTRY("cmpxchg16b", FEATURE_CMPXCHG16B, P_NONE, + "-mcx16") + ISA_NAMES_TABLE_ENTRY("cmpxchg8b", FEATURE_CMPXCHG8B, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("enqcmd", FEATURE_ENQCMD, P_NONE, "-menqcmd") + ISA_NAMES_TABLE_ENTRY("f16c", FEATURE_F16C, P_NONE, "-mf16c") + ISA_NAMES_TABLE_ENTRY("fsgsbase", FEATURE_FSGSBASE, P_NONE, + "-mfsgsbase") + ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_NONE, "-mfxsr") + ISA_NAMES_TABLE_ENTRY("hle", FEATURE_HLE, P_NONE, "-mhle") + ISA_NAMES_TABLE_ENTRY("ibt", FEATURE_IBT, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("lahf_lm", FEATURE_LAHF_LM, P_NONE, "-msahf") + ISA_NAMES_TABLE_ENTRY("lm", FEATURE_LM, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("lwp", FEATURE_LWP, P_NONE, "-mlwp") + ISA_NAMES_TABLE_ENTRY("lzcnt", FEATURE_LZCNT, P_NONE, "-mlzcnt") + ISA_NAMES_TABLE_ENTRY("movbe", FEATURE_MOVBE, P_NONE, "-mmovbe") + ISA_NAMES_TABLE_ENTRY("movdir64b", FEATURE_MOVDIR64B, P_NONE, + "-mmovdir64b") + ISA_NAMES_TABLE_ENTRY("movdiri", FEATURE_MOVDIRI, P_NONE, "-mmovdiri") + ISA_NAMES_TABLE_ENTRY("mwaitx", FEATURE_MWAITX, P_NONE, "-mmwaitx") + ISA_NAMES_TABLE_ENTRY("osxsave", FEATURE_OSXSAVE, P_NONE, NULL) + ISA_NAMES_TABLE_ENTRY("pconfig", FEATURE_PCONFIG, P_NONE, "-mpconfig") + ISA_NAMES_TABLE_ENTRY("pku", FEATURE_PKU, P_NONE, "-mpku") + ISA_NAMES_TABLE_ENTRY("prefetchwt1", FEATURE_PREFETCHWT1, P_NONE, + "-mprefetchwt1") + ISA_NAMES_TABLE_ENTRY("prfchw", FEATURE_PRFCHW, P_NONE, "-mprfchw") + ISA_NAMES_TABLE_ENTRY("ptwrite", FEATURE_PTWRITE, P_NONE, "-mptwrite") + ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_NONE, "-mrdpid") + ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_NONE, "-mrdrnd") + ISA_NAMES_TABLE_ENTRY("rdseed", FEATURE_RDSEED, P_NONE, "-mrdseed") + ISA_NAMES_TABLE_ENTRY("rtm", FEATURE_RTM, P_NONE, "-mrtm") + ISA_NAMES_TABLE_ENTRY("serialize", FEATURE_SERIALIZE, P_NONE, + "-mserialize") + ISA_NAMES_TABLE_ENTRY("sgx", FEATURE_SGX, P_NONE, "-msgx") + ISA_NAMES_TABLE_ENTRY("sha", FEATURE_SHA, P_NONE, "-msha") + ISA_NAMES_TABLE_ENTRY("shstk", FEATURE_SHSTK, P_NONE, "-mshstk") + ISA_NAMES_TABLE_ENTRY("tbm", FEATURE_TBM, P_NONE, "-mtbm") + ISA_NAMES_TABLE_ENTRY("tsxldtrk", FEATURE_TSXLDTRK, P_NONE, + "-mtsxldtrk") + ISA_NAMES_TABLE_ENTRY("vaes", FEATURE_VAES, P_NONE, "-mvaes") + ISA_NAMES_TABLE_ENTRY("waitpkg", FEATURE_WAITPKG, P_NONE, "-mwaitpkg") + ISA_NAMES_TABLE_ENTRY("wbnoinvd", FEATURE_WBNOINVD, P_NONE, + "-mwbnoinvd") + ISA_NAMES_TABLE_ENTRY("xsave", FEATURE_XSAVE, P_NONE, "-mxsave") + ISA_NAMES_TABLE_ENTRY("xsavec", FEATURE_XSAVEC, P_NONE, "-mxsavec") + ISA_NAMES_TABLE_ENTRY("xsaveopt", FEATURE_XSAVEOPT, P_NONE, + "-mxsaveopt") + ISA_NAMES_TABLE_ENTRY("xsaves", FEATURE_XSAVES, P_NONE, "-mxsaves") +ISA_NAMES_TABLE_END diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c index 3a816400729..e9e4d6ed023 100644 --- a/gcc/config/i386/driver-i386.c +++ b/gcc/config/i386/driver-i386.c @@ -28,6 +28,8 @@ const char *host_detect_local_cpu (int argc, const char **argv); #if defined(__GNUC__) && (__GNUC__ >= 5 || !defined(__PIC__)) #include "cpuid.h" +#include "common/config/i386/cpuinfo.h" +#include "common/config/i386/i386-isas.h" struct cache_desc { @@ -388,53 +390,13 @@ const char *host_detect_local_cpu (int argc, const char **argv) const char *cache = ""; const char *options = ""; - unsigned int eax, ebx, ecx, edx; + unsigned int ebx, ecx, edx; unsigned int max_level, ext_level; unsigned int vendor; unsigned int model, family; - unsigned int has_sse3, has_ssse3, has_cmpxchg16b; - unsigned int has_cmpxchg8b, has_cmov, has_mmx, has_sse, has_sse2; - - /* Extended features */ - unsigned int has_lahf_lm = 0, has_sse4a = 0; - unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0; - unsigned int has_movbe = 0, has_sse4_1 = 0, has_sse4_2 = 0; - unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0, has_avx2 = 0; - unsigned int has_pclmul = 0, has_abm = 0, has_lwp = 0; - unsigned int has_fma = 0, has_fma4 = 0, has_xop = 0; - unsigned int has_bmi = 0, has_bmi2 = 0, has_tbm = 0, has_lzcnt = 0; - unsigned int has_hle = 0, has_rtm = 0, has_sgx = 0; - unsigned int has_pconfig = 0, has_wbnoinvd = 0; - unsigned int has_rdrnd = 0, has_f16c = 0, has_fsgsbase = 0; - unsigned int has_rdseed = 0, has_prfchw = 0, has_adx = 0; - unsigned int has_osxsave = 0, has_fxsr = 0, has_xsave = 0, has_xsaveopt = 0; - unsigned int has_avx512er = 0, has_avx512pf = 0, has_avx512cd = 0; - unsigned int has_avx512f = 0, has_sha = 0, has_prefetchwt1 = 0; - unsigned int has_clflushopt = 0, has_xsavec = 0, has_xsaves = 0; - unsigned int has_avx512dq = 0, has_avx512bw = 0, has_avx512vl = 0; - unsigned int has_avx512vbmi = 0, has_avx512ifma = 0, has_clwb = 0; - unsigned int has_mwaitx = 0, has_clzero = 0, has_pku = 0, has_rdpid = 0; - unsigned int has_avx5124fmaps = 0, has_avx5124vnniw = 0; - unsigned int has_gfni = 0, has_avx512vbmi2 = 0; - unsigned int has_avx512bitalg = 0; - unsigned int has_avx512vpopcntdq = 0; - unsigned int has_shstk = 0; - unsigned int has_avx512vnni = 0, has_vaes = 0; - unsigned int has_vpclmulqdq = 0; - unsigned int has_avx512vp2intersect = 0; - unsigned int has_movdiri = 0, has_movdir64b = 0; - unsigned int has_enqcmd = 0; - unsigned int has_waitpkg = 0; - unsigned int has_cldemote = 0; - unsigned int has_avx512bf16 = 0; - unsigned int has_serialize = 0; - unsigned int has_tsxldtrk = 0; - - unsigned int has_ptwrite = 0; - bool arch; unsigned int l2sizekb = 0; @@ -447,210 +409,27 @@ const char *host_detect_local_cpu (int argc, const char **argv) if (!arch && strcmp (argv[0], "tune")) return NULL; - max_level = __get_cpuid_max (0, &vendor); - if (max_level < 1) + struct __processor_model cpu_model = { }; + struct __processor_model2 cpu_model2 = { }; + unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { }; + + if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0) goto done; - __cpuid (1, eax, ebx, ecx, edx); - - model = (eax >> 4) & 0x0f; - family = (eax >> 8) & 0x0f; - if (vendor == signature_INTEL_ebx - || vendor == signature_AMD_ebx) - { - unsigned int extended_model, extended_family; - - extended_model = (eax >> 12) & 0xf0; - extended_family = (eax >> 20) & 0xff; - if (family == 0x0f) - { - family += extended_family; - model += extended_model; - } - else if (family == 0x06) - model += extended_model; - } - - has_sse3 = ecx & bit_SSE3; - has_ssse3 = ecx & bit_SSSE3; - has_sse4_1 = ecx & bit_SSE4_1; - has_sse4_2 = ecx & bit_SSE4_2; - has_avx = ecx & bit_AVX; - has_osxsave = ecx & bit_OSXSAVE; - has_cmpxchg16b = ecx & bit_CMPXCHG16B; - has_movbe = ecx & bit_MOVBE; - has_popcnt = ecx & bit_POPCNT; - has_aes = ecx & bit_AES; - has_pclmul = ecx & bit_PCLMUL; - has_fma = ecx & bit_FMA; - has_f16c = ecx & bit_F16C; - has_rdrnd = ecx & bit_RDRND; - has_xsave = ecx & bit_XSAVE; - - has_cmpxchg8b = edx & bit_CMPXCHG8B; - has_cmov = edx & bit_CMOV; - has_mmx = edx & bit_MMX; - has_fxsr = edx & bit_FXSAVE; - has_sse = edx & bit_SSE; - has_sse2 = edx & bit_SSE2; - - if (max_level >= 7) - { - __cpuid_count (7, 0, eax, ebx, ecx, edx); - - has_bmi = ebx & bit_BMI; - has_sgx = ebx & bit_SGX; - has_hle = ebx & bit_HLE; - has_rtm = ebx & bit_RTM; - has_avx2 = ebx & bit_AVX2; - has_bmi2 = ebx & bit_BMI2; - has_fsgsbase = ebx & bit_FSGSBASE; - has_rdseed = ebx & bit_RDSEED; - has_adx = ebx & bit_ADX; - has_avx512f = ebx & bit_AVX512F; - has_avx512er = ebx & bit_AVX512ER; - has_avx512pf = ebx & bit_AVX512PF; - has_avx512cd = ebx & bit_AVX512CD; - has_sha = ebx & bit_SHA; - has_clflushopt = ebx & bit_CLFLUSHOPT; - has_clwb = ebx & bit_CLWB; - has_avx512dq = ebx & bit_AVX512DQ; - has_avx512bw = ebx & bit_AVX512BW; - has_avx512vl = ebx & bit_AVX512VL; - has_avx512ifma = ebx & bit_AVX512IFMA; - - has_prefetchwt1 = ecx & bit_PREFETCHWT1; - has_avx512vbmi = ecx & bit_AVX512VBMI; - has_pku = ecx & bit_OSPKE; - has_avx512vbmi2 = ecx & bit_AVX512VBMI2; - has_avx512vnni = ecx & bit_AVX512VNNI; - has_rdpid = ecx & bit_RDPID; - has_gfni = ecx & bit_GFNI; - has_vaes = ecx & bit_VAES; - has_vpclmulqdq = ecx & bit_VPCLMULQDQ; - has_avx512bitalg = ecx & bit_AVX512BITALG; - has_avx512vpopcntdq = ecx & bit_AVX512VPOPCNTDQ; - has_movdiri = ecx & bit_MOVDIRI; - has_movdir64b = ecx & bit_MOVDIR64B; - has_enqcmd = ecx & bit_ENQCMD; - has_cldemote = ecx & bit_CLDEMOTE; - - has_avx5124vnniw = edx & bit_AVX5124VNNIW; - has_avx5124fmaps = edx & bit_AVX5124FMAPS; - has_avx512vp2intersect = edx & bit_AVX512VP2INTERSECT; - has_serialize = edx & bit_SERIALIZE; - has_tsxldtrk = edx & bit_TSXLDTRK; - - has_shstk = ecx & bit_SHSTK; - has_pconfig = edx & bit_PCONFIG; - has_waitpkg = ecx & bit_WAITPKG; - - __cpuid_count (7, 1, eax, ebx, ecx, edx); - has_avx512bf16 = eax & bit_AVX512BF16; - } - - if (max_level >= 13) - { - __cpuid_count (13, 1, eax, ebx, ecx, edx); - - has_xsaveopt = eax & bit_XSAVEOPT; - has_xsavec = eax & bit_XSAVEC; - has_xsaves = eax & bit_XSAVES; - } - - if (max_level >= 0x14) - { - __cpuid_count (0x14, 0, eax, ebx, ecx, edx); - - has_ptwrite = ebx & bit_PTWRITE; - } - - /* Check cpuid level of extended features. */ - __cpuid (0x80000000, ext_level, ebx, ecx, edx); - - if (ext_level >= 0x80000001) - { - __cpuid (0x80000001, eax, ebx, ecx, edx); - - has_lahf_lm = ecx & bit_LAHF_LM; - has_sse4a = ecx & bit_SSE4a; - has_abm = ecx & bit_ABM; - has_lwp = ecx & bit_LWP; - has_fma4 = ecx & bit_FMA4; - has_xop = ecx & bit_XOP; - has_tbm = ecx & bit_TBM; - has_lzcnt = ecx & bit_LZCNT; - has_prfchw = ecx & bit_PRFCHW; - - has_longmode = edx & bit_LM; - has_3dnowp = edx & bit_3DNOWP; - has_3dnow = edx & bit_3DNOW; - has_mwaitx = ecx & bit_MWAITX; - } - - if (ext_level >= 0x80000008) - { - __cpuid (0x80000008, eax, ebx, ecx, edx); - has_clzero = ebx & bit_CLZERO; - has_wbnoinvd = ebx & bit_WBNOINVD; - } - - /* 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) - - if (has_osxsave) - asm (".byte 0x0f; .byte 0x01; .byte 0xd0" - : "=a" (eax), "=d" (edx) - : "c" (XCR_XFEATURE_ENABLED_MASK)); - else - eax = 0; - - /* Check if AVX registers are supported. */ - if ((eax & XCR_AVX_ENABLED_MASK) != XCR_AVX_ENABLED_MASK) - { - has_avx = 0; - has_avx2 = 0; - has_fma = 0; - has_fma4 = 0; - has_f16c = 0; - has_xop = 0; - has_xsave = 0; - has_xsaveopt = 0; - has_xsaves = 0; - has_xsavec = 0; - } - - /* Check if AVX512F registers are supported. */ - if ((eax & XCR_AVX512F_ENABLED_MASK) != XCR_AVX512F_ENABLED_MASK) - { - has_avx512f = 0; - has_avx512er = 0; - has_avx512pf = 0; - has_avx512cd = 0; - has_avx512dq = 0; - has_avx512bw = 0; - has_avx512vl = 0; - } + vendor = cpu_model.__cpu_vendor; + family = cpu_model2.__cpu_family; + model = cpu_model2.__cpu_model; + max_level = cpu_model2.__cpu_max_level; + ext_level = cpu_model2.__cpu_ext_level; if (!arch) { - if (vendor == signature_AMD_ebx - || vendor == signature_CENTAUR_ebx - || vendor == signature_CYRIX_ebx - || vendor == signature_NSC_ebx) + if (vendor == VENDOR_AMD + || vendor == VENDOR_CENTAUR + || vendor == VENDOR_CYRIX + || vendor == VENDOR_NSC) cache = detect_caches_amd (ext_level); - else if (vendor == signature_INTEL_ebx) + else if (vendor == VENDOR_INTEL) { bool xeon_mp = (family == 15 && model == 6); cache = detect_caches_intel (xeon_mp, max_level, @@ -658,7 +437,11 @@ const char *host_detect_local_cpu (int argc, const char **argv) } } - if (vendor == signature_AMD_ebx) + /* Extended features */ +#define has_feature(f) \ + has_cpu_feature (&cpu_model, cpu_features2, f) + + if (vendor == VENDOR_AMD) { unsigned int name; @@ -670,34 +453,36 @@ const char *host_detect_local_cpu (int argc, const char **argv) if (name == signature_NSC_ebx) processor = PROCESSOR_GEODE; - else if (has_movbe && family == 22) + else if (has_feature (FEATURE_MOVBE) && family == 22) processor = PROCESSOR_BTVER2; - else if (has_clwb) + else if (has_feature (FEATURE_CLWB)) processor = PROCESSOR_ZNVER2; - else if (has_clzero) + else if (has_feature (FEATURE_CLZERO)) processor = PROCESSOR_ZNVER1; - else if (has_avx2) - processor = PROCESSOR_BDVER4; - else if (has_xsaveopt) - processor = PROCESSOR_BDVER3; - else if (has_bmi) - processor = PROCESSOR_BDVER2; - else if (has_xop) + else if (has_feature (FEATURE_AVX2)) + processor = PROCESSOR_BDVER4; + else if (has_feature (FEATURE_XSAVEOPT)) + processor = PROCESSOR_BDVER3; + else if (has_feature (FEATURE_BMI)) + processor = PROCESSOR_BDVER2; + else if (has_feature (FEATURE_XOP)) processor = PROCESSOR_BDVER1; - else if (has_sse4a && has_ssse3) - processor = PROCESSOR_BTVER1; - else if (has_sse4a) + else if (has_feature (FEATURE_SSE4_A) + && has_feature (FEATURE_SSSE3)) + processor = PROCESSOR_BTVER1; + else if (has_feature (FEATURE_SSE4_A)) processor = PROCESSOR_AMDFAM10; - else if (has_sse2 || has_longmode) + else if (has_feature (FEATURE_SSE2) + || has_feature (FEATURE_LM)) processor = PROCESSOR_K8; - else if (has_3dnowp && family == 6) + else if (has_feature (FEATURE_3DNOWP) && family == 6) processor = PROCESSOR_ATHLON; - else if (has_mmx) + else if (has_feature (FEATURE_MMX)) processor = PROCESSOR_K6; else processor = PROCESSOR_PENTIUM; } - else if (vendor == signature_CENTAUR_ebx) + else if (vendor == VENDOR_CENTAUR) { processor = PROCESSOR_GENERIC; @@ -708,12 +493,13 @@ const char *host_detect_local_cpu (int argc, const char **argv) break; case 5: - if (has_3dnow || has_mmx) + if (has_feature (FEATURE_3DNOW) + || has_feature (FEATURE_MMX)) processor = PROCESSOR_I486; break; case 6: - if (has_longmode) + if (has_feature (FEATURE_LM)) processor = PROCESSOR_K8; else if (model >= 9) processor = PROCESSOR_PENTIUMPRO; @@ -749,11 +535,11 @@ const char *host_detect_local_cpu (int argc, const char **argv) /* Default. */ break; case PROCESSOR_I486: - if (arch && vendor == signature_CENTAUR_ebx) + if (arch && vendor == VENDOR_CENTAUR) { if (model >= 6) cpu = "c3"; - else if (has_3dnow) + else if (has_feature (FEATURE_3DNOW)) cpu = "winchip2"; else /* Assume WinChip C6. */ @@ -763,226 +549,104 @@ const char *host_detect_local_cpu (int argc, const char **argv) cpu = "i486"; break; case PROCESSOR_PENTIUM: - if (arch && has_mmx) + if (arch && has_feature (FEATURE_MMX)) cpu = "pentium-mmx"; else cpu = "pentium"; break; case PROCESSOR_PENTIUMPRO: - switch (model) + cpu = get_intel_cpu (&cpu_model, &cpu_model2, cpu_features2, 0); + if (cpu == NULL) { - case 0x1c: - case 0x26: - /* Bonnell. */ - cpu = "bonnell"; - break; - case 0x37: - case 0x4a: - case 0x4d: - case 0x5d: - /* Silvermont. */ - case 0x4c: - case 0x5a: - case 0x75: - /* Airmont. */ - cpu = "silvermont"; - break; - case 0x5c: - case 0x5f: - /* Goldmont. */ - cpu = "goldmont"; - break; - case 0x7a: - /* Goldmont Plus. */ - cpu = "goldmont-plus"; - break; - case 0x86: - case 0x96: - case 0x9c: - /* Tremont. */ - cpu = "tremont"; - break; - case 0x0f: - /* Merom. */ - case 0x17: - case 0x1d: - /* Penryn. */ - cpu = "core2"; - break; - case 0x1a: - case 0x1e: - case 0x1f: - case 0x2e: - /* Nehalem. */ - cpu = "nehalem"; - break; - case 0x25: - case 0x2c: - case 0x2f: - /* Westmere. */ - cpu = "westmere"; - break; - case 0x2a: - case 0x2d: - /* Sandy Bridge. */ - cpu = "sandybridge"; - break; - case 0x3a: - case 0x3e: - /* Ivy Bridge. */ - cpu = "ivybridge"; - break; - case 0x3c: - case 0x3f: - case 0x45: - case 0x46: - /* Haswell. */ - cpu = "haswell"; - break; - case 0x3d: - case 0x47: - case 0x4f: - case 0x56: - /* Broadwell. */ - cpu = "broadwell"; - break; - case 0x4e: - case 0x5e: - /* Skylake. */ - case 0x8e: - case 0x9e: - /* Kaby Lake. */ - case 0xa5: - case 0xa6: - /* Comet Lake. */ - cpu = "skylake"; - break; - case 0x55: - if (has_avx512vnni) - /* Cascade Lake. */ - cpu = "cascadelake"; - else - /* Skylake with AVX-512. */ - cpu = "skylake-avx512"; - break; - case 0x6a: - case 0x6c: - /* Ice Lake server. */ - cpu = "icelake-server"; - break; - case 0x7e: - case 0x7d: - case 0x9d: - /* Ice Lake client. */ - cpu = "icelake-client"; - break; - case 0x8c: - case 0x8d: - /* Tiger Lake. */ - cpu = "tigerlake"; - break; - case 0x57: - /* Knights Landing. */ - cpu = "knl"; - break; - case 0x66: - /* Cannon Lake. */ - cpu = "cannonlake"; - break; - case 0x85: - /* Knights Mill. */ - cpu = "knm"; - break; - default: if (arch) { /* This is unknown family 0x6 CPU. */ - if (has_avx) - { - /* Assume Tiger Lake */ - if (has_avx512vp2intersect) - cpu = "tigerlake"; - /* Assume Cooper Lake */ - else if (has_avx512bf16) - cpu = "cooperlake"; - /* Assume Ice Lake Server. */ - else if (has_wbnoinvd) - cpu = "icelake-server"; + if (has_feature (FEATURE_AVX)) + { + /* Assume Tiger Lake */ + if (has_feature (FEATURE_AVX512VP2INTERSECT)) + cpu = "tigerlake"; + /* Assume Cooper Lake */ + else if (has_feature (FEATURE_AVX512BF16)) + cpu = "cooperlake"; + /* Assume Ice Lake Server. */ + else if (has_feature (FEATURE_WBNOINVD)) + cpu = "icelake-server"; /* Assume Ice Lake. */ - else if (has_avx512bitalg) + else if (has_feature (FEATURE_AVX512BITALG)) cpu = "icelake-client"; /* Assume Cannon Lake. */ - else if (has_avx512vbmi) + else if (has_feature (FEATURE_AVX512VBMI)) cpu = "cannonlake"; /* Assume Knights Mill. */ - else if (has_avx5124vnniw) + else if (has_feature (FEATURE_AVX5124VNNIW)) cpu = "knm"; /* Assume Knights Landing. */ - else if (has_avx512er) + else if (has_feature (FEATURE_AVX512ER)) cpu = "knl"; /* Assume Skylake with AVX-512. */ - else if (has_avx512f) + else if (has_feature (FEATURE_AVX512F)) cpu = "skylake-avx512"; /* Assume Skylake. */ - else if (has_clflushopt) + else if (has_feature (FEATURE_CLFLUSHOPT)) cpu = "skylake"; /* Assume Broadwell. */ - else if (has_adx) + else if (has_feature (FEATURE_ADX)) cpu = "broadwell"; - else if (has_avx2) + else if (has_feature (FEATURE_AVX2)) /* Assume Haswell. */ cpu = "haswell"; else /* Assume Sandy Bridge. */ cpu = "sandybridge"; } - else if (has_sse4_2) + else if (has_feature (FEATURE_SSE4_2)) { - if (has_gfni) + if (has_feature (FEATURE_GFNI)) /* Assume Tremont. */ cpu = "tremont"; - else if (has_sgx) + else if (has_feature (FEATURE_SGX)) /* Assume Goldmont Plus. */ cpu = "goldmont-plus"; - else if (has_xsave) + else if (has_feature (FEATURE_XSAVE)) /* Assume Goldmont. */ cpu = "goldmont"; - else if (has_movbe) + else if (has_feature (FEATURE_MOVBE)) /* Assume Silvermont. */ cpu = "silvermont"; else /* Assume Nehalem. */ cpu = "nehalem"; } - else if (has_ssse3) + else if (has_feature (FEATURE_SSSE3)) { - if (has_movbe) + if (has_feature (FEATURE_MOVBE)) /* Assume Bonnell. */ cpu = "bonnell"; else /* Assume Core 2. */ cpu = "core2"; } - else if (has_longmode) + else if (has_feature (FEATURE_LM)) /* Perhaps some emulator? Assume x86-64, otherwise gcc -march=native would be unusable for 64-bit compilations, as all the CPUs below are 32-bit only. */ cpu = "x86-64"; - else if (has_sse3) + else if (has_feature (FEATURE_SSE3)) { - if (vendor == signature_CENTAUR_ebx) + if (vendor == VENDOR_CENTAUR) /* C7 / Eden "Esther" */ cpu = "c7"; else /* It is Core Duo. */ cpu = "pentium-m"; } - else if (has_sse2) + else if (has_feature (FEATURE_SSE2)) /* It is Pentium M. */ cpu = "pentium-m"; - else if (has_sse) + else if (has_feature (FEATURE_SSE)) { - if (vendor == signature_CENTAUR_ebx) + if (vendor == VENDOR_CENTAUR) { if (model >= 9) /* Eden "Nehemiah" */ @@ -994,7 +658,7 @@ const char *host_detect_local_cpu (int argc, const char **argv) /* It is Pentium III. */ cpu = "pentium3"; } - else if (has_mmx) + else if (has_feature (FEATURE_MMX)) /* It is Pentium II. */ cpu = "pentium2"; else @@ -1004,13 +668,12 @@ const char *host_detect_local_cpu (int argc, const char **argv) else /* For -mtune, we default to -mtune=generic. */ cpu = "generic"; - break; } break; case PROCESSOR_PENTIUM4: - if (has_sse3) + if (has_feature (FEATURE_SSE3)) { - if (has_longmode) + if (has_feature (FEATURE_LM)) cpu = "nocona"; else cpu = "prescott"; @@ -1022,13 +685,13 @@ const char *host_detect_local_cpu (int argc, const char **argv) cpu = "geode"; break; case PROCESSOR_K6: - if (arch && has_3dnow) + if (arch && has_feature (FEATURE_3DNOW)) cpu = "k6-3"; else cpu = "k6"; break; case PROCESSOR_ATHLON: - if (arch && has_sse) + if (arch && has_feature (FEATURE_SSE)) cpu = "athlon-4"; else cpu = "athlon"; @@ -1036,22 +699,22 @@ const char *host_detect_local_cpu (int argc, const char **argv) case PROCESSOR_K8: if (arch) { - if (vendor == signature_CENTAUR_ebx) + if (vendor == VENDOR_CENTAUR) { - if (has_sse4_1) + if (has_feature (FEATURE_SSE4_1)) /* Nano 3000 | Nano dual / quad core | Eden X4 */ cpu = "nano-3000"; - else if (has_ssse3) + else if (has_feature (FEATURE_SSSE3)) /* Nano 1000 | Nano 2000 */ cpu = "nano"; - else if (has_sse3) + else if (has_feature (FEATURE_SSE3)) /* Eden X2 */ cpu = "eden-x2"; else /* Default to k8 */ cpu = "k8"; } - else if (has_sse3) + else if (has_feature (FEATURE_SSE3)) cpu = "k8-sse3"; else cpu = "k8"; @@ -1092,27 +755,27 @@ const char *host_detect_local_cpu (int argc, const char **argv) /* Use something reasonable. */ if (arch) { - if (has_ssse3) + if (has_feature (FEATURE_SSSE3)) cpu = "core2"; - else if (has_sse3) + else if (has_feature (FEATURE_SSE3)) { - if (has_longmode) + if (has_feature (FEATURE_LM)) cpu = "nocona"; else cpu = "prescott"; } - else if (has_longmode) + else if (has_feature (FEATURE_LM)) /* Perhaps some emulator? Assume x86-64, otherwise gcc -march=native would be unusable for 64-bit compilations, as all the CPUs below are 32-bit only. */ cpu = "x86-64"; - else if (has_sse2) + else if (has_feature (FEATURE_SSE2)) cpu = "pentium4"; - else if (has_cmov) + else if (has_feature (FEATURE_CMOV)) cpu = "pentiumpro"; - else if (has_mmx) + else if (has_feature (FEATURE_MMX)) cpu = "pentium-mmx"; - else if (has_cmpxchg8b) + else if (has_feature (FEATURE_CMPXCHG8B)) cpu = "pentium"; } else @@ -1121,101 +784,18 @@ const char *host_detect_local_cpu (int argc, const char **argv) if (arch) { - const char *mmx = has_mmx ? " -mmmx" : " -mno-mmx"; - const char *mmx3dnow = has_3dnow ? " -m3dnow" : " -mno-3dnow"; - const char *sse = has_sse ? " -msse" : " -mno-sse"; - const char *sse2 = has_sse2 ? " -msse2" : " -mno-sse2"; - const char *sse3 = has_sse3 ? " -msse3" : " -mno-sse3"; - const char *ssse3 = has_ssse3 ? " -mssse3" : " -mno-ssse3"; - const char *sse4a = has_sse4a ? " -msse4a" : " -mno-sse4a"; - const char *cx16 = has_cmpxchg16b ? " -mcx16" : " -mno-cx16"; - const char *sahf = has_lahf_lm ? " -msahf" : " -mno-sahf"; - const char *movbe = has_movbe ? " -mmovbe" : " -mno-movbe"; - const char *aes = has_aes ? " -maes" : " -mno-aes"; - const char *sha = has_sha ? " -msha" : " -mno-sha"; - const char *pclmul = has_pclmul ? " -mpclmul" : " -mno-pclmul"; - const char *popcnt = has_popcnt ? " -mpopcnt" : " -mno-popcnt"; - const char *abm = has_abm ? " -mabm" : " -mno-abm"; - const char *lwp = has_lwp ? " -mlwp" : " -mno-lwp"; - const char *fma = has_fma ? " -mfma" : " -mno-fma"; - const char *fma4 = has_fma4 ? " -mfma4" : " -mno-fma4"; - const char *xop = has_xop ? " -mxop" : " -mno-xop"; - const char *bmi = has_bmi ? " -mbmi" : " -mno-bmi"; - const char *pconfig = has_pconfig ? " -mpconfig" : " -mno-pconfig"; - const char *wbnoinvd = has_wbnoinvd ? " -mwbnoinvd" : " -mno-wbnoinvd"; - const char *sgx = has_sgx ? " -msgx" : " -mno-sgx"; - const char *bmi2 = has_bmi2 ? " -mbmi2" : " -mno-bmi2"; - const char *tbm = has_tbm ? " -mtbm" : " -mno-tbm"; - const char *avx = has_avx ? " -mavx" : " -mno-avx"; - const char *avx2 = has_avx2 ? " -mavx2" : " -mno-avx2"; - const char *sse4_2 = has_sse4_2 ? " -msse4.2" : " -mno-sse4.2"; - const char *sse4_1 = has_sse4_1 ? " -msse4.1" : " -mno-sse4.1"; - const char *lzcnt = has_lzcnt ? " -mlzcnt" : " -mno-lzcnt"; - const char *hle = has_hle ? " -mhle" : " -mno-hle"; - const char *rtm = has_rtm ? " -mrtm" : " -mno-rtm"; - const char *rdrnd = has_rdrnd ? " -mrdrnd" : " -mno-rdrnd"; - const char *f16c = has_f16c ? " -mf16c" : " -mno-f16c"; - const char *fsgsbase = has_fsgsbase ? " -mfsgsbase" : " -mno-fsgsbase"; - const char *rdseed = has_rdseed ? " -mrdseed" : " -mno-rdseed"; - const char *prfchw = has_prfchw ? " -mprfchw" : " -mno-prfchw"; - const char *adx = has_adx ? " -madx" : " -mno-adx"; - const char *fxsr = has_fxsr ? " -mfxsr" : " -mno-fxsr"; - const char *xsave = has_xsave ? " -mxsave" : " -mno-xsave"; - const char *xsaveopt = has_xsaveopt ? " -mxsaveopt" : " -mno-xsaveopt"; - const char *avx512f = has_avx512f ? " -mavx512f" : " -mno-avx512f"; - const char *avx512er = has_avx512er ? " -mavx512er" : " -mno-avx512er"; - const char *avx512cd = has_avx512cd ? " -mavx512cd" : " -mno-avx512cd"; - const char *avx512pf = has_avx512pf ? " -mavx512pf" : " -mno-avx512pf"; - const char *prefetchwt1 = has_prefetchwt1 ? " -mprefetchwt1" : " -mno-prefetchwt1"; - const char *clflushopt = has_clflushopt ? " -mclflushopt" : " -mno-clflushopt"; - const char *xsavec = has_xsavec ? " -mxsavec" : " -mno-xsavec"; - const char *xsaves = has_xsaves ? " -mxsaves" : " -mno-xsaves"; - const char *avx512dq = has_avx512dq ? " -mavx512dq" : " -mno-avx512dq"; - const char *avx512bw = has_avx512bw ? " -mavx512bw" : " -mno-avx512bw"; - const char *avx512vl = has_avx512vl ? " -mavx512vl" : " -mno-avx512vl"; - const char *avx512ifma = has_avx512ifma ? " -mavx512ifma" : " -mno-avx512ifma"; - const char *avx512vbmi = has_avx512vbmi ? " -mavx512vbmi" : " -mno-avx512vbmi"; - const char *avx5124vnniw = has_avx5124vnniw ? " -mavx5124vnniw" : " -mno-avx5124vnniw"; - const char *avx512vbmi2 = has_avx512vbmi2 ? " -mavx512vbmi2" : " -mno-avx512vbmi2"; - const char *avx512vnni = has_avx512vnni ? " -mavx512vnni" : " -mno-avx512vnni"; - const char *avx5124fmaps = has_avx5124fmaps ? " -mavx5124fmaps" : " -mno-avx5124fmaps"; - const char *clwb = has_clwb ? " -mclwb" : " -mno-clwb"; - const char *mwaitx = has_mwaitx ? " -mmwaitx" : " -mno-mwaitx"; - const char *clzero = has_clzero ? " -mclzero" : " -mno-clzero"; - const char *pku = has_pku ? " -mpku" : " -mno-pku"; - const char *rdpid = has_rdpid ? " -mrdpid" : " -mno-rdpid"; - const char *gfni = has_gfni ? " -mgfni" : " -mno-gfni"; - const char *shstk = has_shstk ? " -mshstk" : " -mno-shstk"; - const char *vaes = has_vaes ? " -mvaes" : " -mno-vaes"; - const char *vpclmulqdq = has_vpclmulqdq ? " -mvpclmulqdq" : " -mno-vpclmulqdq"; - const char *avx512vp2intersect = has_avx512vp2intersect ? " -mavx512vp2intersect" : " -mno-avx512vp2intersect"; - const char *tsxldtrk = has_tsxldtrk ? " -mtsxldtrk " : " -mno-tsxldtrk"; - const char *avx512bitalg = has_avx512bitalg ? " -mavx512bitalg" : " -mno-avx512bitalg"; - const char *avx512vpopcntdq = has_avx512vpopcntdq ? " -mavx512vpopcntdq" : " -mno-avx512vpopcntdq"; - const char *movdiri = has_movdiri ? " -mmovdiri" : " -mno-movdiri"; - const char *movdir64b = has_movdir64b ? " -mmovdir64b" : " -mno-movdir64b"; - const char *enqcmd = has_enqcmd ? " -menqcmd" : " -mno-enqcmd"; - const char *waitpkg = has_waitpkg ? " -mwaitpkg" : " -mno-waitpkg"; - const char *cldemote = has_cldemote ? " -mcldemote" : " -mno-cldemote"; - const char *serialize = has_serialize ? " -mserialize" : " -mno-serialize"; - const char *ptwrite = has_ptwrite ? " -mptwrite" : " -mno-ptwrite"; - const char *avx512bf16 = has_avx512bf16 ? " -mavx512bf16" : " -mno-avx512bf16"; - - options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3, - sse4a, cx16, sahf, movbe, aes, sha, pclmul, - popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2, - pconfig, wbnoinvd, - tbm, avx, avx2, sse4_2, sse4_1, lzcnt, rtm, - hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx, - fxsr, xsave, xsaveopt, avx512f, avx512er, - avx512cd, avx512pf, prefetchwt1, clflushopt, - xsavec, xsaves, avx512dq, avx512bw, avx512vl, - avx512ifma, avx512vbmi, avx5124fmaps, avx5124vnniw, - clwb, mwaitx, clzero, pku, rdpid, gfni, shstk, - avx512vbmi2, avx512vnni, vaes, vpclmulqdq, - avx512bitalg, avx512vpopcntdq, movdiri, movdir64b, - waitpkg, cldemote, ptwrite, avx512bf16, enqcmd, - avx512vp2intersect, serialize, tsxldtrk, NULL); + unsigned int i; + const char *const neg_option = " -mno-"; + for (i = 0; i < ARRAY_SIZE (isa_names_table); i++) + if (isa_names_table[i].option) + { + if (has_feature (isa_names_table[i].feature)) + options = concat (options, " ", + isa_names_table[i].option, NULL); + else + options = concat (options, neg_option, + isa_names_table[i].option + 2, NULL); + } } done: diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c index 57e709d6c43..2246507a8d5 100644 --- a/gcc/config/i386/i386-builtins.c +++ b/gcc/config/i386/i386-builtins.c @@ -90,6 +90,7 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "dwarf2out.h" #include "i386-builtins.h" +#include "common/config/i386/i386-isas.h" #undef BDESC #undef BDESC_FIRST @@ -1835,57 +1836,6 @@ ix86_builtin_reciprocal (tree fndecl) } } -/* These are the target attribute strings for which a dispatcher is - available, from fold_builtin_cpu. */ -struct _isa_names_table -{ - const char *const name; - const enum processor_features feature; - const enum feature_priority priority; -}; - -static const _isa_names_table isa_names_table[] = -{ - {"cmov", FEATURE_CMOV, P_NONE}, - {"mmx", FEATURE_MMX, P_MMX}, - {"popcnt", FEATURE_POPCNT, P_POPCNT}, - {"sse", FEATURE_SSE, P_SSE}, - {"sse2", FEATURE_SSE2, P_SSE2}, - {"sse3", FEATURE_SSE3, P_SSE3}, - {"ssse3", FEATURE_SSSE3, P_SSSE3}, - {"sse4a", FEATURE_SSE4_A, P_SSE4_A}, - {"sse4.1", FEATURE_SSE4_1, P_SSE4_1}, - {"sse4.2", FEATURE_SSE4_2, P_SSE4_2}, - {"avx", FEATURE_AVX, P_AVX}, - {"fma4", FEATURE_FMA4, P_FMA4}, - {"xop", FEATURE_XOP, P_XOP}, - {"fma", FEATURE_FMA, P_FMA}, - {"avx2", FEATURE_AVX2, P_AVX2}, - {"avx512f", FEATURE_AVX512F, P_AVX512F}, - {"bmi", FEATURE_BMI, P_BMI}, - {"bmi2", FEATURE_BMI2, P_BMI2}, - {"aes", FEATURE_AES, P_AES}, - {"pclmul", FEATURE_PCLMUL, P_PCLMUL}, - {"avx512vl",FEATURE_AVX512VL, P_NONE}, - {"avx512bw",FEATURE_AVX512BW, P_NONE}, - {"avx512dq",FEATURE_AVX512DQ, P_NONE}, - {"avx512cd",FEATURE_AVX512CD, P_NONE}, - {"avx512er",FEATURE_AVX512ER, P_NONE}, - {"avx512pf",FEATURE_AVX512PF, P_NONE}, - {"avx512vbmi",FEATURE_AVX512VBMI, P_NONE}, - {"avx512ifma",FEATURE_AVX512IFMA, P_NONE}, - {"avx5124vnniw",FEATURE_AVX5124VNNIW, P_NONE}, - {"avx5124fmaps",FEATURE_AVX5124FMAPS, P_NONE}, - {"avx512vpopcntdq",FEATURE_AVX512VPOPCNTDQ, P_NONE}, - {"avx512vbmi2", FEATURE_AVX512VBMI2, P_NONE}, - {"gfni", FEATURE_GFNI, P_NONE}, - {"vpclmulqdq", FEATURE_VPCLMULQDQ, P_NONE}, - {"avx512vnni", FEATURE_AVX512VNNI, P_NONE}, - {"avx512bitalg", FEATURE_AVX512BITALG, P_NONE}, - {"avx512bf16", FEATURE_AVX512BF16, P_NONE}, - {"avx512vp2intersect",FEATURE_AVX512VP2INTERSECT, P_NONE} -}; - /* This parses the attribute arguments to target in DECL and determines the right builtin to use to match the platform specification. It returns the priority value for this version decl. If PREDICATE_LIST diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c index 7a8b6e805ed..e87f262a775 100644 --- a/gcc/testsuite/gcc.target/i386/builtin_target.c +++ b/gcc/testsuite/gcc.target/i386/builtin_target.c @@ -7,348 +7,53 @@ /* { dg-do run } */ #include +#include #include "cpuid.h" - -/* Check if the Intel CPU model and sub-model are identified. */ -static void -check_intel_cpu_model (unsigned int family, unsigned int model, - unsigned int brand_id) -{ - /* Parse family and model only if brand ID is 0. */ - if (brand_id == 0) - { - switch (family) - { - case 0x5: - /* Pentium. */ - break; - case 0x6: - switch (model) - { - case 0x1c: - case 0x26: - /* Atom. */ - assert (__builtin_cpu_is ("atom")); - break; - case 0x37: - case 0x4a: - case 0x4d: - case 0x5a: - case 0x5d: - /* Silvermont. */ - assert (__builtin_cpu_is ("silvermont")); - break; - case 0x5c: - case 0x5f: - /* Goldmont. */ - assert (__builtin_cpu_is ("goldmont")); - break; - case 0x7a: - /* Goldmont Plus. */ - assert (__builtin_cpu_is ("goldmont-plus")); - break; - case 0x57: - /* Knights Landing. */ - assert (__builtin_cpu_is ("knl")); - break; - case 0x85: - /* Knights Mill */ - assert (__builtin_cpu_is ("knm")); - break; - case 0x1a: - case 0x1e: - case 0x1f: - case 0x2e: - /* Nehalem. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("nehalem")); - break; - case 0x25: - case 0x2c: - case 0x2f: - /* Westmere. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("westmere")); - break; - case 0x2a: - case 0x2d: - /* Sandy Bridge. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("sandybridge")); - break; - case 0x3a: - case 0x3e: - /* Ivy Bridge. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("ivybridge")); - break; - case 0x3c: - case 0x3f: - case 0x45: - case 0x46: - /* Haswell. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("haswell")); - break; - case 0x3d: - case 0x47: - case 0x4f: - case 0x56: - /* Broadwell. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("broadwell")); - break; - case 0x4e: - case 0x5e: - /* Skylake. */ - case 0x8e: - case 0x9e: - /* Kaby Lake. */ - assert (__builtin_cpu_is ("corei7")); - assert (__builtin_cpu_is ("skylake")); - break; - case 0x55: - { - unsigned int eax, ebx, ecx, edx; - __cpuid_count (7, 0, eax, ebx, ecx, edx); - assert (__builtin_cpu_is ("corei7")); - if (ecx & bit_AVX512VNNI) - /* Cascade Lake. */ - assert (__builtin_cpu_is ("cascadelake")); - else - /* Skylake with AVX-512 support. */ - assert (__builtin_cpu_is ("skylake-avx512")); - break; - } - case 0x66: - /* Cannon Lake. */ - assert (__builtin_cpu_is ("cannonlake")); - break; - case 0x17: - case 0x1d: - /* Penryn. */ - case 0x0f: - /* Merom. */ - assert (__builtin_cpu_is ("core2")); - break; - default: - break; - } - break; - default: - /* We have no idea. */ - break; - } - } -} - -/* Check if the AMD CPU model and sub-model are identified. */ -static void -check_amd_cpu_model (unsigned int family, unsigned int model) -{ - switch (family) - { - /* AMD Family 10h. */ - case 0x10: - switch (model) - { - case 0x2: - /* Barcelona. */ - assert (__builtin_cpu_is ("amdfam10h")); - assert (__builtin_cpu_is ("barcelona")); - break; - case 0x4: - /* Shanghai. */ - assert (__builtin_cpu_is ("amdfam10h")); - assert (__builtin_cpu_is ("shanghai")); - break; - case 0x8: - /* Istanbul. */ - assert (__builtin_cpu_is ("amdfam10h")); - assert (__builtin_cpu_is ("istanbul")); - break; - default: - break; - } - break; - /* AMD Family 15h. */ - case 0x15: - assert (__builtin_cpu_is ("amdfam15h")); - /* Bulldozer version 1. */ - if ( model <= 0xf) - assert (__builtin_cpu_is ("bdver1")); - /* Bulldozer version 2. */ - if (model >= 0x10 && model <= 0x1f) - assert (__builtin_cpu_is ("bdver2")); - break; - default: - break; - } -} +#define CHECK___builtin_cpu_is(cpu) assert (__builtin_cpu_is (cpu)) +#define gcc_assert(a) assert (a) +#define gcc_unreachable() abort () +#define inline +#include "../../../common/config/i386/i386-cpuinfo.h" +#include "../../../common/config/i386/cpuinfo.h" /* Check if the ISA features are identified. */ static void -check_features (unsigned int ecx, unsigned int edx, - int max_cpuid_level) +check_features (struct __processor_model *cpu_model, + unsigned int *cpu_features2) { - unsigned int eax, ebx; - unsigned int ext_level; - - if (edx & bit_CMOV) - assert (__builtin_cpu_supports ("cmov")); - if (edx & bit_MMX) - assert (__builtin_cpu_supports ("mmx")); - if (edx & bit_SSE) - assert (__builtin_cpu_supports ("sse")); - if (edx & bit_SSE2) - assert (__builtin_cpu_supports ("sse2")); - if (ecx & bit_POPCNT) - assert (__builtin_cpu_supports ("popcnt")); - if (ecx & bit_AES) - assert (__builtin_cpu_supports ("aes")); - if (ecx & bit_PCLMUL) - assert (__builtin_cpu_supports ("pclmul")); - if (ecx & bit_SSE3) - assert (__builtin_cpu_supports ("sse3")); - if (ecx & bit_SSSE3) - assert (__builtin_cpu_supports ("ssse3")); - if (ecx & bit_SSE4_1) - assert (__builtin_cpu_supports ("sse4.1")); - if (ecx & bit_SSE4_2) - 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) - { - __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) - assert (__builtin_cpu_supports ("avx512pf")); - if (ebx & bit_AVX512ER) - assert (__builtin_cpu_supports ("avx512er")); - if (ebx & bit_AVX512IFMA) - assert (__builtin_cpu_supports ("avx512ifma")); - if (ecx & bit_AVX512VBMI) - assert (__builtin_cpu_supports ("avx512vbmi")); - if (ecx & bit_AVX512VBMI2) - assert (__builtin_cpu_supports ("avx512vbmi2")); - if (ecx & bit_GFNI) - assert (__builtin_cpu_supports ("gfni")); - if (ecx & bit_VPCLMULQDQ) - assert (__builtin_cpu_supports ("vpclmulqdq")); - if (ecx & bit_AVX512VNNI) - assert (__builtin_cpu_supports ("avx512vnni")); - if (ecx & bit_AVX512BITALG) - assert (__builtin_cpu_supports ("avx512bitalg")); - 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")); - - __cpuid_count (7, 1, eax, ebx, ecx, edx); - if (eax & bit_AVX512BF16) - assert (__builtin_cpu_supports ("avx512bf16")); - } - - /* 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)) -__get_cpuid_output (unsigned int __level, - unsigned int *__eax, unsigned int *__ebx, - unsigned int *__ecx, unsigned int *__edx) -{ - return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); +#define has_feature(f) \ + has_cpu_feature (cpu_model, cpu_features2, f) +#define ISA_NAMES_TABLE_START +#define ISA_NAMES_TABLE_END +#define ISA_NAMES_TABLE_ENTRY(name, feature, priority, option) \ + assert (!!has_feature (feature) == !!__builtin_cpu_supports (name)); +#include "../../../common/config/i386/i386-isas.h" } static int check_detailed () { - unsigned int eax, ebx, ecx, edx; + struct __processor_model cpu_model = { 0 }; + struct __processor_model2 cpu_model2 = { 0 }; + unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { 0 }; - int max_level; - unsigned int vendor; - unsigned int model, family, brand_id; - unsigned int extended_model, extended_family; - - /* Assume cpuid insn present. Run in level 0 to get vendor id. */ - if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx)) + if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0) return 0; - vendor = ebx; - max_level = eax; + check_features (&cpu_model, cpu_features2); - if (max_level < 1) - return 0; - - if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx)) - return 0; - - model = (eax >> 4) & 0x0f; - family = (eax >> 8) & 0x0f; - brand_id = ebx & 0xff; - extended_model = (eax >> 12) & 0xf0; - extended_family = (eax >> 20) & 0xff; - - if (vendor == signature_INTEL_ebx) + switch (cpu_model.__cpu_vendor) { + case VENDOR_INTEL: assert (__builtin_cpu_is ("intel")); - /* Adjust family and model for Intel CPUs. */ - if (family == 0x0f) - { - family += extended_family; - model += extended_model; - } - else if (family == 0x06) - model += extended_model; - check_intel_cpu_model (family, model, brand_id); - check_features (ecx, edx, max_level); - } - else if (vendor == signature_AMD_ebx) - { + get_intel_cpu (&cpu_model, &cpu_model2, cpu_features2, 0); + break; + case VENDOR_AMD: assert (__builtin_cpu_is ("amd")); - /* Adjust model and family for AMD CPUS. */ - if (family == 0x0f) - { - family += extended_family; - model += (extended_model << 4); - } - check_amd_cpu_model (family, model); - check_features (ecx, edx, max_level); + get_amd_cpu (&cpu_model, &cpu_model2, cpu_features2); + break; + default: + break; } return 0;