On Wed, Jun 24, 2020 at 4:38 PM H.J. Lu <hjl.to...@gmail.com> wrote: > > On Wed, Jun 24, 2020 at 03:46:25PM +0200, Uros Bizjak wrote: > > On Wed, Jun 24, 2020 at 3:37 PM Uros Bizjak <ubiz...@gmail.com> wrote: > > > > > > On Wed, Jun 24, 2020 at 3:06 PM H.J. Lu <hjl.to...@gmail.com> wrote: > > > > > > > > On Wed, Jun 24, 2020 at 02:43:43PM +0200, Uros Bizjak wrote: > > > > > > > > > > > > Here is the updated patch for x86 backend and libgcc. driver-i386.c > > > > > > is unchanged. > > > > > > > > > > Thanks. We should change driver-i386.c very carefully and in an > > > > > independent way from this patch. It is a complex and interwoven web of > > > > > name, model and features check. I propose that we first convert > > > > > various has_xxx checks to a new interface, in as trivial way as > > > > > possible. > > > > > > > > > > > > > Here is the patch to share isa_names_table and use cpuinfo.h to check > > > > ISAs as well as detect newer Intel/AMD processors. > > > > > > > > OK for master? > > > > > > No. Don't use get_intel_cpu and get_amd_cpu in driver-i386.c. > > > > + cpu = get_amd_cpu (&cpu_model, &cpu_model2, cpu_features2); > > + if (cpu == NULL) > > + { > > + if (name == signature_NSC_ebx) > > + processor = PROCESSOR_GEODE; > > + else if (has_feature (FEATURE_SSE2) > > > > Here is where your patch fails. AMD part has early bypass for > > signature_NSC_ebx, so it is detected as NSC processor regardless of > > what is detected by generic code. > > > > Uros. > > Here is the updated patch not to use get_amd_cpu in driver-i386.c. > I believe the usage of get_intel_cpu in driver-i386.c is correct. > > OK for master?
OK, let's go with this version, but look out for fallout. I hope there is some interest from AMD folks to unify and further improve their part of the detection code. Thanks, Uros. > Thanks. > > H.J. > --- > 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 <stdlib.h>, > ../../../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 > +<http://www.gnu.org/licenses/>. */ > + > +/* 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) > - goto done; > - > - __cpuid (1, eax, ebx, ecx, edx); > + struct __processor_model cpu_model = { }; > + struct __processor_model2 cpu_model2 = { }; > + unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { }; > > - 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; > - } > + if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0) > + goto done; > > - /* 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 <assert.h> > +#include <stdlib.h> > #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; > - > - 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)) > - return 0; > + struct __processor_model cpu_model = { 0 }; > + struct __processor_model2 cpu_model2 = { 0 }; > + unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { 0 }; > > - vendor = ebx; > - max_level = eax; > - > - if (max_level < 1) > - return 0; > - > - if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx)) > + if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0) > return 0; > > - model = (eax >> 4) & 0x0f; > - family = (eax >> 8) & 0x0f; > - brand_id = ebx & 0xff; > - extended_model = (eax >> 12) & 0xf0; > - extended_family = (eax >> 20) & 0xff; > + check_features (&cpu_model, cpu_features2); > > - 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; > -- > 2.26.2 >