[PATCH] x86: Share _isa_names_table and use cpuinfo.h

Uros Bizjak ubizjak@gmail.com
Wed Jun 24 13:37:10 GMT 2020


On Wed, Jun 24, 2020 at 3:06 PM H.J. Lu <hjl.tools@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.

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/AMD processors in driver-i386.c and builtin_target.c.
> 5. Detection of 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
>         get_amd_cpu to get the newer AMD CPU name.  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                 | 680 +++---------------
>  gcc/config/i386/i386-builtins.c               |  52 +-
>  .../gcc.target/i386/builtin_target.c          | 355 +--------
>  4 files changed, 303 insertions(+), 947 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..3641d81c80b 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);
> -
> -  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;
> +  struct __processor_model cpu_model = { };
> +  struct __processor_model2 cpu_model2 = { };
> +  unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { };
>
> -  /* 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;
>
> @@ -668,36 +451,23 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>        else
>         name = 0;
>
> -      if (name == signature_NSC_ebx)
> -       processor = PROCESSOR_GEODE;
> -      else if (has_movbe && family == 22)
> -       processor = PROCESSOR_BTVER2;
> -      else if (has_clwb)
> -       processor = PROCESSOR_ZNVER2;
> -      else if (has_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)
> -       processor = PROCESSOR_BDVER1;
> -      else if (has_sse4a && has_ssse3)
> -        processor = PROCESSOR_BTVER1;
> -      else if (has_sse4a)
> -       processor = PROCESSOR_AMDFAM10;
> -      else if (has_sse2 || has_longmode)
> -       processor = PROCESSOR_K8;
> -      else if (has_3dnowp && family == 6)
> -       processor = PROCESSOR_ATHLON;
> -      else if (has_mmx)
> -       processor = PROCESSOR_K6;
> -      else
> -       processor = PROCESSOR_PENTIUM;
> +      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)
> +                  || has_feature (FEATURE_LM))
> +           processor = PROCESSOR_K8;
> +         else if (has_feature (FEATURE_3DNOWP) && family == 6)
> +           processor = PROCESSOR_ATHLON;
> +         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 +478,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 +520,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 +534,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 +643,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 +653,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 +670,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 +684,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";
> @@ -1060,59 +708,32 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>         /* For -mtune, we default to -mtune=k8 */
>         cpu = "k8";
>        break;
> -    case PROCESSOR_AMDFAM10:
> -      cpu = "amdfam10";
> -      break;
> -    case PROCESSOR_BDVER1:
> -      cpu = "bdver1";
> -      break;
> -    case PROCESSOR_BDVER2:
> -      cpu = "bdver2";
> -      break;
> -    case PROCESSOR_BDVER3:
> -      cpu = "bdver3";
> -      break;
> -    case PROCESSOR_BDVER4:
> -      cpu = "bdver4";
> -      break;
> -    case PROCESSOR_ZNVER1:
> -      cpu = "znver1";
> -      break;
> -    case PROCESSOR_ZNVER2:
> -      cpu = "znver2";
> -      break;
> -    case PROCESSOR_BTVER1:
> -      cpu = "btver1";
> -      break;
> -    case PROCESSOR_BTVER2:
> -      cpu = "btver2";
> -      break;
>
>      default:
>        /* 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 +742,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
>


More information about the Gcc-patches mailing list