public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] x86: Update Intel processor detection
@ 2020-05-18 11:58 H.J. Lu
  2020-05-18 12:18 ` Uros Bizjak
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-18 11:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: Uros Bizjak

Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
and Tiger Lake processor families.

OK for master?

Thanks.

H.J.
--
	* config/i386/driver-i386.c (host_detect_local_cpu): Support
	Intel Airmont, Tremont, Comet Lake, Ice Lake and Tiger Lake
	processor families.
---
 gcc/config/i386/driver-i386.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 6926f0beb0a..7612ddfb846 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -777,9 +777,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	case 0x37:
 	case 0x4a:
 	case 0x4d:
-	case 0x5a:
 	case 0x5d:
 	  /* Silvermont.  */
+	case 0x4c:
+	case 0x5a:
+	case 0x75:
+	  /* Airmont.  */
 	  cpu = "silvermont";
 	  break;
 	case 0x5c:
@@ -791,6 +794,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	  /* Goldmont Plus.  */
 	  cpu = "goldmont-plus";
 	  break;
+	case 0x86:
+	case 0x96:
+	case 0x9c:
+	  /* Tremont.  */
+	  cpu = "tremont";
+	  break;
 	case 0x0f:
 	  /* Merom.  */
 	case 0x17:
@@ -841,6 +850,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	case 0x8e:
 	case 0x9e:
 	  /* Kaby Lake.  */
+	case 0xa5:
+	case 0xa6:
+	  /* Comet Lake.  */
 	  cpu = "skylake";
 	  break;
 	case 0x55:
@@ -851,6 +863,22 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	    /* 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";
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Update Intel processor detection
  2020-05-18 11:58 [PATCH] x86: Update Intel processor detection H.J. Lu
@ 2020-05-18 12:18 ` Uros Bizjak
  2020-05-18 12:34   ` H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Uros Bizjak @ 2020-05-18 12:18 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> and Tiger Lake processor families.
>
> OK for master?

OK.

Please also update cpuinfo.c from libgcc and corresponding
gcc.target/i386/builtin_target.c testcase.

Thanks,
Uros.

> Thanks.
>
> H.J.
> --
>         * config/i386/driver-i386.c (host_detect_local_cpu): Support
>         Intel Airmont, Tremont, Comet Lake, Ice Lake and Tiger Lake
>         processor families.
> ---
>  gcc/config/i386/driver-i386.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
> index 6926f0beb0a..7612ddfb846 100644
> --- a/gcc/config/i386/driver-i386.c
> +++ b/gcc/config/i386/driver-i386.c
> @@ -777,9 +777,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>         case 0x37:
>         case 0x4a:
>         case 0x4d:
> -       case 0x5a:
>         case 0x5d:
>           /* Silvermont.  */
> +       case 0x4c:
> +       case 0x5a:
> +       case 0x75:
> +         /* Airmont.  */
>           cpu = "silvermont";
>           break;
>         case 0x5c:
> @@ -791,6 +794,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>           /* Goldmont Plus.  */
>           cpu = "goldmont-plus";
>           break;
> +       case 0x86:
> +       case 0x96:
> +       case 0x9c:
> +         /* Tremont.  */
> +         cpu = "tremont";
> +         break;
>         case 0x0f:
>           /* Merom.  */
>         case 0x17:
> @@ -841,6 +850,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>         case 0x8e:
>         case 0x9e:
>           /* Kaby Lake.  */
> +       case 0xa5:
> +       case 0xa6:
> +         /* Comet Lake.  */
>           cpu = "skylake";
>           break;
>         case 0x55:
> @@ -851,6 +863,22 @@ const char *host_detect_local_cpu (int argc, const char **argv)
>             /* 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";
> --
> 2.26.2
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Update Intel processor detection
  2020-05-18 12:18 ` Uros Bizjak
@ 2020-05-18 12:34   ` H.J. Lu
  2020-05-18 12:43     ` Uros Bizjak
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-18 12:34 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > and Tiger Lake processor families.
> >
> > OK for master?
>
> OK.

I am checking in my patch.

> Please also update cpuinfo.c from libgcc and corresponding

I will take a look to see if we share the same CPU detection code between
libgcc and config/i386/driver-i386.c.

> gcc.target/i386/builtin_target.c testcase.
>
> Thanks,
> Uros.
>
> > Thanks.
> >
> > H.J.
> > --
> >         * config/i386/driver-i386.c (host_detect_local_cpu): Support
> >         Intel Airmont, Tremont, Comet Lake, Ice Lake and Tiger Lake
> >         processor families.
> > ---
> >  gcc/config/i386/driver-i386.c | 30 +++++++++++++++++++++++++++++-
> >  1 file changed, 29 insertions(+), 1 deletion(-)
> >
> > diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
> > index 6926f0beb0a..7612ddfb846 100644
> > --- a/gcc/config/i386/driver-i386.c
> > +++ b/gcc/config/i386/driver-i386.c
> > @@ -777,9 +777,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
> >         case 0x37:
> >         case 0x4a:
> >         case 0x4d:
> > -       case 0x5a:
> >         case 0x5d:
> >           /* Silvermont.  */
> > +       case 0x4c:
> > +       case 0x5a:
> > +       case 0x75:
> > +         /* Airmont.  */
> >           cpu = "silvermont";
> >           break;
> >         case 0x5c:
> > @@ -791,6 +794,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
> >           /* Goldmont Plus.  */
> >           cpu = "goldmont-plus";
> >           break;
> > +       case 0x86:
> > +       case 0x96:
> > +       case 0x9c:
> > +         /* Tremont.  */
> > +         cpu = "tremont";
> > +         break;
> >         case 0x0f:
> >           /* Merom.  */
> >         case 0x17:
> > @@ -841,6 +850,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
> >         case 0x8e:
> >         case 0x9e:
> >           /* Kaby Lake.  */
> > +       case 0xa5:
> > +       case 0xa6:
> > +         /* Comet Lake.  */
> >           cpu = "skylake";
> >           break;
> >         case 0x55:
> > @@ -851,6 +863,22 @@ const char *host_detect_local_cpu (int argc, const char **argv)
> >             /* 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";
> > --
> > 2.26.2
> >



-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Update Intel processor detection
  2020-05-18 12:34   ` H.J. Lu
@ 2020-05-18 12:43     ` Uros Bizjak
  2020-05-18 12:57       ` H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Uros Bizjak @ 2020-05-18 12:43 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > and Tiger Lake processor families.
> > >
> > > OK for master?
> >
> > OK.
>
> I am checking in my patch.
>
> > Please also update cpuinfo.c from libgcc and corresponding
>
> I will take a look to see if we share the same CPU detection code between
> libgcc and config/i386/driver-i386.c.

I don't think it will bring any benefit, this is mainly one huge
switch statement that maps to different stuff in libgcc and
driver-i386.

Uros.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Update Intel processor detection
  2020-05-18 12:43     ` Uros Bizjak
@ 2020-05-18 12:57       ` H.J. Lu
  2020-05-19  2:16         ` [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386 H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-18 12:57 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > and Tiger Lake processor families.
> > > >
> > > > OK for master?
> > >
> > > OK.
> >
> > I am checking in my patch.
> >
> > > Please also update cpuinfo.c from libgcc and corresponding
> >
> > I will take a look to see if we share the same CPU detection code between
> > libgcc and config/i386/driver-i386.c.
>
> I don't think it will bring any benefit, this is mainly one huge
> switch statement that maps to different stuff in libgcc and
> driver-i386.

libgcc and config/i386/driver-i386.c differ even before my patch.
I think we can do better.


-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-18 12:57       ` H.J. Lu
@ 2020-05-19  2:16         ` H.J. Lu
  2020-05-19  5:56           ` Uros Bizjak
  2020-05-19  9:17           ` Thomas Koenig
  0 siblings, 2 replies; 30+ messages in thread
From: H.J. Lu @ 2020-05-19  2:16 UTC (permalink / raw)
  To: Uros Bizjak, GNU GFortran; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1421 bytes --]

On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > and Tiger Lake processor families.
> > > > >
> > > > > OK for master?
> > > >
> > > > OK.
> > >
> > > I am checking in my patch.
> > >
> > > > Please also update cpuinfo.c from libgcc and corresponding
> > >
> > > I will take a look to see if we share the same CPU detection code between
> > > libgcc and config/i386/driver-i386.c.
> >
> > I don't think it will bring any benefit, this is mainly one huge
> > switch statement that maps to different stuff in libgcc and
> > driver-i386.
>
> libgcc and config/i386/driver-i386.c differ even before my patch.
> I think we can do better.
>

Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
and libgfortran to detect the specific type of Intel CPU.  Update
libgfortran to use has_cpu_feature to detect x86 CPU features.

Tested on Linux/x86 and Linux/x86-64.  OK for master?

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 65578 bytes --]

From 3f75ee91b68c196660df21f43c3c2121fb63e69a Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
and libgfortran to detect the specific type of Intel CPU.  Update
libgfortran to use has_cpu_feature to detect x86 CPU features.

gcc/

	* common/config/i386/cpuinfo.h: Moved from libgcc/config/i386.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Add
	an argument for AVX512VNNI.  Use CHECK___builtin_cpu_is.  Return
	Intel CPU name.
	(has_cpu_feature): New function.
	* config/i386/driver-i386.c: Include
	"common/config/i386/cpuinfo.h".
	(host_detect_local_cpu): Call get_intel_cpu to get Intel CPU
	name.

gcc/testsuite/

	* gcc.target/i386/builtin_target.c: Include <stddef.h> and
	../../../common/config/i386/cpuinfo.h.
	(CHECK___builtin_cpu_is): New.
	(inline): New.  Defined as empty.
	(check_intel_cpu_model): Removed.
	(check_detailed): Call get_intel_cpu instead of
	check_intel_cpu_model.

libgcc/

	* config/i386/cpuinfo.h: Moved to ... gcc/common/config/i386.
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Make it static in libgcc_s.so.1.
	(get_intel_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_available_features): Always set __cpu_features2.
	(__cpu_indicator_init): Call get_available_features before
	calling get_intel_cpu.  Pass has_cpu_feature (FEATURE_AVX512VNNI)
	to get_intel_cpu.

libgfortran/

	* m4/matmul.m4: Include <common/config/i386/cpuinfo.h> instead
	of <config/i386/cpuinfo.h>.  Use has_cpu_feature.
	* generated/matmul_c10.c: Regenerated.
	* generated/matmul_c16.c: Likewise.
	* generated/matmul_c4.c: Likewise.
	* generated/matmul_c8.c: Likewise.
	* generated/matmul_i1.c: Likewise.
	* generated/matmul_i16.c: Likewise.
	* generated/matmul_i2.c: Likewise.
	* generated/matmul_i4.c: Likewise.
	* generated/matmul_i8.c: Likewise.
	* generated/matmul_r10.c: Likewise.
	* generated/matmul_r16.c: Likewise.
	* generated/matmul_r4.c: Likewise.
	* generated/matmul_r8.c: Likewise.
---
 gcc/common/config/i386/cpuinfo.h              | 365 ++++++++++++++++++
 gcc/config/i386/driver-i386.c                 | 131 +------
 .../gcc.target/i386/builtin_target.c          | 141 +------
 libgcc/config/i386/cpuinfo.c                  | 162 +-------
 libgcc/config/i386/cpuinfo.h                  | 135 -------
 libgfortran/generated/matmul_c10.c            |  18 +-
 libgfortran/generated/matmul_c16.c            |  18 +-
 libgfortran/generated/matmul_c4.c             |  18 +-
 libgfortran/generated/matmul_c8.c             |  18 +-
 libgfortran/generated/matmul_i1.c             |  18 +-
 libgfortran/generated/matmul_i16.c            |  18 +-
 libgfortran/generated/matmul_i2.c             |  18 +-
 libgfortran/generated/matmul_i4.c             |  18 +-
 libgfortran/generated/matmul_i8.c             |  18 +-
 libgfortran/generated/matmul_r10.c            |  18 +-
 libgfortran/generated/matmul_r16.c            |  18 +-
 libgfortran/generated/matmul_r4.c             |  18 +-
 libgfortran/generated/matmul_r8.c             |  18 +-
 libgfortran/m4/matmul.m4                      |  18 +-
 19 files changed, 518 insertions(+), 668 deletions(-)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 delete mode 100644 libgcc/config/i386/cpuinfo.h

diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..8fe85d2c177
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,365 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Processor Vendor and Models. */
+
+enum processor_vendor
+{
+  VENDOR_INTEL = 1,
+  VENDOR_AMD,
+  VENDOR_OTHER,
+  VENDOR_MAX
+};
+
+/* Any new types or subtypes have to be inserted at the end. */
+
+enum processor_types
+{
+  INTEL_BONNELL = 1,
+  INTEL_CORE2,
+  INTEL_COREI7,
+  AMDFAM10H,
+  AMDFAM15H,
+  INTEL_SILVERMONT,
+  INTEL_KNL,
+  AMD_BTVER1,
+  AMD_BTVER2,
+  AMDFAM17H,
+  INTEL_KNM,
+  INTEL_GOLDMONT,
+  INTEL_GOLDMONT_PLUS,
+  INTEL_TREMONT,
+  CPU_TYPE_MAX
+};
+
+enum processor_subtypes
+{
+  INTEL_COREI7_NEHALEM = 1,
+  INTEL_COREI7_WESTMERE,
+  INTEL_COREI7_SANDYBRIDGE,
+  AMDFAM10H_BARCELONA,
+  AMDFAM10H_SHANGHAI,
+  AMDFAM10H_ISTANBUL,
+  AMDFAM15H_BDVER1,
+  AMDFAM15H_BDVER2,
+  AMDFAM15H_BDVER3,
+  AMDFAM15H_BDVER4,
+  AMDFAM17H_ZNVER1,
+  INTEL_COREI7_IVYBRIDGE,
+  INTEL_COREI7_HASWELL,
+  INTEL_COREI7_BROADWELL,
+  INTEL_COREI7_SKYLAKE,
+  INTEL_COREI7_SKYLAKE_AVX512,
+  INTEL_COREI7_CANNONLAKE,
+  INTEL_COREI7_ICELAKE_CLIENT,
+  INTEL_COREI7_ICELAKE_SERVER,
+  AMDFAM17H_ZNVER2,
+  INTEL_COREI7_CASCADELAKE,
+  INTEL_COREI7_TIGERLAKE,
+  INTEL_COREI7_COOPERLAKE,
+  CPU_SUBTYPE_MAX
+};
+
+/* ISA Features supported. New features have to be inserted at the end.  */
+
+enum processor_features
+{
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_SSE4_A,
+  FEATURE_FMA4,
+  FEATURE_XOP,
+  FEATURE_FMA,
+  FEATURE_AVX512F,
+  FEATURE_BMI,
+  FEATURE_BMI2,
+  FEATURE_AES,
+  FEATURE_PCLMUL,
+  FEATURE_AVX512VL,
+  FEATURE_AVX512BW,
+  FEATURE_AVX512DQ,
+  FEATURE_AVX512CD,
+  FEATURE_AVX512ER,
+  FEATURE_AVX512PF,
+  FEATURE_AVX512VBMI,
+  FEATURE_AVX512IFMA,
+  FEATURE_AVX5124VNNIW,
+  FEATURE_AVX5124FMAPS,
+  FEATURE_AVX512VPOPCNTDQ,
+  FEATURE_AVX512VBMI2,
+  FEATURE_GFNI,
+  FEATURE_VPCLMULQDQ,
+  FEATURE_AVX512VNNI,
+  FEATURE_AVX512BITALG,
+  FEATURE_AVX512BF16
+};
+
+extern struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  unsigned int __cpu_features[1];
+} __cpu_model;
+extern unsigned int __cpu_features2;
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       unsigned int family, unsigned int model,
+	       unsigned int brand_id, int has_avx512vnni)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || family != 0x6)
+    return cpu;
+
+  switch (model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_avx512vnni)
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (enum processor_features f)
+{
+  if (f < 32)
+    return __cpu_model.__cpu_features[0] & (1U << (f & 31));
+  else
+    return __cpu_features2 & (1U << ((f - 32) & 31));
+}
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 7612ddfb846..37f455c0df8 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "common/config/i386/cpuinfo.h"
 
 const char *host_detect_local_cpu (int argc, const char **argv);
 
@@ -741,6 +742,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	}
     }
 
+  struct __processor_model cpu_model;
+
   switch (processor)
     {
     case PROCESSOR_I386:
@@ -767,131 +770,10 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	cpu = "pentium";
       break;
     case PROCESSOR_PENTIUMPRO:
-      switch (model)
+      cpu = get_intel_cpu (&cpu_model, family, model, 0,
+			   has_avx512vnni);
+      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.  */
@@ -1002,7 +884,6 @@ 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:
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..d4f29b6748a 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,140 +7,11 @@
 /* { dg-do run } */
 
 #include <assert.h>
+#include <stddef.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;
-	}
-    }
-}
+#define CHECK___builtin_cpu_is(cpu) assert (__builtin_cpu_is (cpu))
+#define inline
+#include "../../../common/config/i386/cpuinfo.h"
 
 /* Check if the AMD CPU model and sub-model are identified.  */
 static void
@@ -326,6 +197,7 @@ check_detailed ()
 
   if (vendor == signature_INTEL_ebx)
     {
+      struct __processor_model cpu_model;
       assert (__builtin_cpu_is ("intel"));
       /* Adjust family and model for Intel CPUs.  */
       if (family == 0x0f)
@@ -335,7 +207,8 @@ check_detailed ()
 	}
       else if (family == 0x06)
 	model += extended_model;
-      check_intel_cpu_model (family, model, brand_id);
+      get_intel_cpu (&cpu_model, family, model, brand_id,
+		     __builtin_cpu_supports ("avx512vnni"));
       check_features (ecx, edx, max_level);
     }
   else if (vendor == signature_AMD_ebx)
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index 00322c58622..b64156dbeed 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#ifdef SHARED
+static
+#endif
+/* We want to move away from __cpu_model in libgcc_s.so.1 and the
+   size of __cpu_model is part of ABI.  So, new features that don't
+   fit into __cpu_model.__cpu_features[0] go into extra variables
+   in libgcc.a only, preferrably hidden.  NB: Declare __cpu_features2
+   before including "cpuinfo.h" so that has_cpu_feature can be used in
+   libgfortran.  */
+unsigned int __cpu_features2;
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,13 +49,6 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
-/* We want to move away from __cpu_model in libgcc_s.so.1 and the
-   size of __cpu_model is part of ABI.  So, new features that don't
-   fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
 
 
 /* Get the specific type of AMD CPU.  */
@@ -116,140 +119,6 @@ get_amd_cpu (unsigned int family, unsigned int model)
     }
 }
 
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
 /* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
    the max possible level of CPUID insn.  */
 static void
@@ -411,11 +280,7 @@ get_available_features (unsigned int ecx, unsigned int edx,
     }
     
   __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
   __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
 }
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
@@ -477,10 +342,11 @@ __cpu_indicator_init (void)
       else if (family == 0x06)
 	model += extended_model;
 
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
       /* Find available features. */
       get_available_features (ecx, edx, max_level);
+      /* Get CPU type.  */
+      get_intel_cpu (&__cpu_model, family, model, brand_id,
+		     has_cpu_feature (FEATURE_AVX512VNNI));
       __cpu_model.__cpu_vendor = VENDOR_INTEL;
     }
   else if (vendor == signature_AMD_ebx)
diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
deleted file mode 100644
index 41c4a49a98d..00000000000
--- a/libgcc/config/i386/cpuinfo.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Get CPU type and Features for x86 processors.
-   Copyright (C) 2012-2020 Free Software Foundation, Inc.
-   Contributed by Sriraman Tallam (tmsriram@google.com)
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-/* Processor Vendor and Models. */
-
-enum processor_vendor
-{
-  VENDOR_INTEL = 1,
-  VENDOR_AMD,
-  VENDOR_OTHER,
-  VENDOR_MAX
-};
-
-/* Any new types or subtypes have to be inserted at the end. */
-
-enum processor_types
-{
-  INTEL_BONNELL = 1,
-  INTEL_CORE2,
-  INTEL_COREI7,
-  AMDFAM10H,
-  AMDFAM15H,
-  INTEL_SILVERMONT,
-  INTEL_KNL,
-  AMD_BTVER1,
-  AMD_BTVER2,  
-  AMDFAM17H,
-  INTEL_KNM,
-  INTEL_GOLDMONT,
-  INTEL_GOLDMONT_PLUS,
-  INTEL_TREMONT,
-  CPU_TYPE_MAX
-};
-
-enum processor_subtypes
-{
-  INTEL_COREI7_NEHALEM = 1,
-  INTEL_COREI7_WESTMERE,
-  INTEL_COREI7_SANDYBRIDGE,
-  AMDFAM10H_BARCELONA,
-  AMDFAM10H_SHANGHAI,
-  AMDFAM10H_ISTANBUL,
-  AMDFAM15H_BDVER1,
-  AMDFAM15H_BDVER2,
-  AMDFAM15H_BDVER3,
-  AMDFAM15H_BDVER4,
-  AMDFAM17H_ZNVER1,
-  INTEL_COREI7_IVYBRIDGE,
-  INTEL_COREI7_HASWELL,
-  INTEL_COREI7_BROADWELL,
-  INTEL_COREI7_SKYLAKE,
-  INTEL_COREI7_SKYLAKE_AVX512,
-  INTEL_COREI7_CANNONLAKE,
-  INTEL_COREI7_ICELAKE_CLIENT,
-  INTEL_COREI7_ICELAKE_SERVER,
-  AMDFAM17H_ZNVER2,
-  INTEL_COREI7_CASCADELAKE,
-  INTEL_COREI7_TIGERLAKE,
-  INTEL_COREI7_COOPERLAKE,
-  CPU_SUBTYPE_MAX
-};
-
-/* ISA Features supported. New features have to be inserted at the end.  */
-
-enum processor_features
-{
-  FEATURE_CMOV = 0,
-  FEATURE_MMX,
-  FEATURE_POPCNT,
-  FEATURE_SSE,
-  FEATURE_SSE2,
-  FEATURE_SSE3,
-  FEATURE_SSSE3,
-  FEATURE_SSE4_1,
-  FEATURE_SSE4_2,
-  FEATURE_AVX,
-  FEATURE_AVX2,
-  FEATURE_SSE4_A,
-  FEATURE_FMA4,
-  FEATURE_XOP,
-  FEATURE_FMA,
-  FEATURE_AVX512F,
-  FEATURE_BMI,
-  FEATURE_BMI2,
-  FEATURE_AES,
-  FEATURE_PCLMUL,
-  FEATURE_AVX512VL,
-  FEATURE_AVX512BW,
-  FEATURE_AVX512DQ,
-  FEATURE_AVX512CD,
-  FEATURE_AVX512ER,
-  FEATURE_AVX512PF,
-  FEATURE_AVX512VBMI,
-  FEATURE_AVX512IFMA,
-  FEATURE_AVX5124VNNIW,
-  FEATURE_AVX5124FMAPS,
-  FEATURE_AVX512VPOPCNTDQ,
-  FEATURE_AVX512VBMI2,
-  FEATURE_GFNI,
-  FEATURE_VPCLMULQDQ,
-  FEATURE_AVX512VNNI,
-  FEATURE_AVX512BITALG,
-  FEATURE_AVX512BF16
-};
-
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
diff --git a/libgfortran/generated/matmul_c10.c b/libgfortran/generated/matmul_c10.c
index e866a6a4df1..36438bc7f69 100644
--- a/libgfortran/generated/matmul_c10.c
+++ b/libgfortran/generated/matmul_c10.c
@@ -2367,7 +2367,7 @@ matmul_c10_vanilla (gfc_array_c10 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c10 (gfc_array_c10 * const restrict retarray, 
 	gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c10_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c10_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c10_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c10_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c10_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c16.c b/libgfortran/generated/matmul_c16.c
index e6605e89282..472b638a665 100644
--- a/libgfortran/generated/matmul_c16.c
+++ b/libgfortran/generated/matmul_c16.c
@@ -2367,7 +2367,7 @@ matmul_c16_vanilla (gfc_array_c16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c16 (gfc_array_c16 * const restrict retarray, 
 	gfc_array_c16 * const restrict a, gfc_array_c16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c4.c b/libgfortran/generated/matmul_c4.c
index e012fa200fd..4ddc84af01f 100644
--- a/libgfortran/generated/matmul_c4.c
+++ b/libgfortran/generated/matmul_c4.c
@@ -2367,7 +2367,7 @@ matmul_c4_vanilla (gfc_array_c4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c4 (gfc_array_c4 * const restrict retarray, 
 	gfc_array_c4 * const restrict a, gfc_array_c4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c8.c b/libgfortran/generated/matmul_c8.c
index 8c19b49deae..0bb00981c92 100644
--- a/libgfortran/generated/matmul_c8.c
+++ b/libgfortran/generated/matmul_c8.c
@@ -2367,7 +2367,7 @@ matmul_c8_vanilla (gfc_array_c8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c8 (gfc_array_c8 * const restrict retarray, 
 	gfc_array_c8 * const restrict a, gfc_array_c8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i1.c b/libgfortran/generated/matmul_i1.c
index 8ae4194366e..73a3085187d 100644
--- a/libgfortran/generated/matmul_i1.c
+++ b/libgfortran/generated/matmul_i1.c
@@ -2367,7 +2367,7 @@ matmul_i1_vanilla (gfc_array_i1 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i1 (gfc_array_i1 * const restrict retarray, 
 	gfc_array_i1 * const restrict a, gfc_array_i1 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i1_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i1_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i1_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i1_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i1_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i16.c b/libgfortran/generated/matmul_i16.c
index cfbf9206c18..0a2f6906947 100644
--- a/libgfortran/generated/matmul_i16.c
+++ b/libgfortran/generated/matmul_i16.c
@@ -2367,7 +2367,7 @@ matmul_i16_vanilla (gfc_array_i16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i16 (gfc_array_i16 * const restrict retarray, 
 	gfc_array_i16 * const restrict a, gfc_array_i16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i2.c b/libgfortran/generated/matmul_i2.c
index 5a4aeed78e3..4ce8b43f7ae 100644
--- a/libgfortran/generated/matmul_i2.c
+++ b/libgfortran/generated/matmul_i2.c
@@ -2367,7 +2367,7 @@ matmul_i2_vanilla (gfc_array_i2 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i2 (gfc_array_i2 * const restrict retarray, 
 	gfc_array_i2 * const restrict a, gfc_array_i2 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i2_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i2_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i2_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i2_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i2_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i4.c b/libgfortran/generated/matmul_i4.c
index 80592a04d14..228b55fcd5e 100644
--- a/libgfortran/generated/matmul_i4.c
+++ b/libgfortran/generated/matmul_i4.c
@@ -2367,7 +2367,7 @@ matmul_i4_vanilla (gfc_array_i4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i4 (gfc_array_i4 * const restrict retarray, 
 	gfc_array_i4 * const restrict a, gfc_array_i4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i8.c b/libgfortran/generated/matmul_i8.c
index 7e4c5bcc1bb..3854ee8da77 100644
--- a/libgfortran/generated/matmul_i8.c
+++ b/libgfortran/generated/matmul_i8.c
@@ -2367,7 +2367,7 @@ matmul_i8_vanilla (gfc_array_i8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i8 (gfc_array_i8 * const restrict retarray, 
 	gfc_array_i8 * const restrict a, gfc_array_i8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r10.c b/libgfortran/generated/matmul_r10.c
index d97aa41315e..33699848382 100644
--- a/libgfortran/generated/matmul_r10.c
+++ b/libgfortran/generated/matmul_r10.c
@@ -2367,7 +2367,7 @@ matmul_r10_vanilla (gfc_array_r10 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r10 (gfc_array_r10 * const restrict retarray, 
 	gfc_array_r10 * const restrict a, gfc_array_r10 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r10_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r10_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r10_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r10_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r10_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r16.c b/libgfortran/generated/matmul_r16.c
index 82e8b502ba3..ff505796087 100644
--- a/libgfortran/generated/matmul_r16.c
+++ b/libgfortran/generated/matmul_r16.c
@@ -2367,7 +2367,7 @@ matmul_r16_vanilla (gfc_array_r16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r16 (gfc_array_r16 * const restrict retarray, 
 	gfc_array_r16 * const restrict a, gfc_array_r16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r4.c b/libgfortran/generated/matmul_r4.c
index 36ce7daf781..517e74fb80e 100644
--- a/libgfortran/generated/matmul_r4.c
+++ b/libgfortran/generated/matmul_r4.c
@@ -2367,7 +2367,7 @@ matmul_r4_vanilla (gfc_array_r4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r4 (gfc_array_r4 * const restrict retarray, 
 	gfc_array_r4 * const restrict a, gfc_array_r4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r8.c b/libgfortran/generated/matmul_r8.c
index 9a81df189d5..d47dd818c49 100644
--- a/libgfortran/generated/matmul_r8.c
+++ b/libgfortran/generated/matmul_r8.c
@@ -2367,7 +2367,7 @@ matmul_r8_vanilla (gfc_array_r8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r8 (gfc_array_r8 * const restrict retarray, 
 	gfc_array_r8 * const restrict a, gfc_array_r8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/m4/matmul.m4 b/libgfortran/m4/matmul.m4
index 83f4ae63339..f277b9c7cc8 100644
--- a/libgfortran/m4/matmul.m4
+++ b/libgfortran/m4/matmul.m4
@@ -134,7 +134,7 @@ internal_proto('matmul_name`);
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_'rtype_code` ('rtype` * const restrict retarray, 
 	'rtype` * const restrict a, 'rtype` * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -155,7 +155,7 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_'rtype_code`_avx512f;
 	      goto store;
@@ -164,8 +164,8 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_'rtype_code`_avx2;
 	      goto store;
@@ -174,7 +174,7 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_'rtype_code`_avx;
 	      goto store;
@@ -184,16 +184,16 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_'rtype_code`_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_'rtype_code`_avx128_fma4;
 	    goto store;
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19  2:16         ` [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386 H.J. Lu
@ 2020-05-19  5:56           ` Uros Bizjak
  2020-05-19 19:57             ` V2 " H.J. Lu
  2020-05-19  9:17           ` Thomas Koenig
  1 sibling, 1 reply; 30+ messages in thread
From: Uros Bizjak @ 2020-05-19  5:56 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 4:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > >
> > > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > > and Tiger Lake processor families.
> > > > > >
> > > > > > OK for master?
> > > > >
> > > > > OK.
> > > >
> > > > I am checking in my patch.
> > > >
> > > > > Please also update cpuinfo.c from libgcc and corresponding
> > > >
> > > > I will take a look to see if we share the same CPU detection code between
> > > > libgcc and config/i386/driver-i386.c.
> > >
> > > I don't think it will bring any benefit, this is mainly one huge
> > > switch statement that maps to different stuff in libgcc and
> > > driver-i386.
> >
> > libgcc and config/i386/driver-i386.c differ even before my patch.
> > I think we can do better.
> >
>
> Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> and libgfortran to detect the specific type of Intel CPU.  Update
> libgfortran to use has_cpu_feature to detect x86 CPU features.
>
> Tested on Linux/x86 and Linux/x86-64.  OK for master?

Handling only Intel targets and not others is a sure way for patch to
be ignored.

Uros.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19  2:16         ` [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386 H.J. Lu
  2020-05-19  5:56           ` Uros Bizjak
@ 2020-05-19  9:17           ` Thomas Koenig
  1 sibling, 0 replies; 30+ messages in thread
From: Thomas Koenig @ 2020-05-19  9:17 UTC (permalink / raw)
  To: H.J. Lu, Uros Bizjak, GNU GFortran; +Cc: gcc-patches

Am 19.05.20 um 04:16 schrieb H.J. Lu via Fortran:
> Tested on Linux/x86 and Linux/x86-64.  OK for master?

Libfortran parts are OK.

Regards

	Thomas

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19  5:56           ` Uros Bizjak
@ 2020-05-19 19:57             ` H.J. Lu
  2020-05-19 21:06               ` Uros Bizjak
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-19 19:57 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: GNU GFortran, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

On Mon, May 18, 2020 at 10:56 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, May 19, 2020 at 4:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > >
> > > > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > > > and Tiger Lake processor families.
> > > > > > >
> > > > > > > OK for master?
> > > > > >
> > > > > > OK.
> > > > >
> > > > > I am checking in my patch.
> > > > >
> > > > > > Please also update cpuinfo.c from libgcc and corresponding
> > > > >
> > > > > I will take a look to see if we share the same CPU detection code between
> > > > > libgcc and config/i386/driver-i386.c.
> > > >
> > > > I don't think it will bring any benefit, this is mainly one huge
> > > > switch statement that maps to different stuff in libgcc and
> > > > driver-i386.
> > >
> > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > I think we can do better.
> > >
> >
> > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > and libgfortran to detect the specific type of Intel CPU.  Update
> > libgfortran to use has_cpu_feature to detect x86 CPU features.
> >
> > Tested on Linux/x86 and Linux/x86-64.  OK for master?
>
> Handling only Intel targets and not others is a sure way for patch to
> be ignored.
>

Here is the updated patch to cover AMD CPU.  It also fixes:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220

OK for master?

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 87746 bytes --]

From 113c797d59102d400b3a7342192f68b789bba0de Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
and libgfortran to detect the specific type of Intel and AMD CPUs.  Use
the same enum processor_features in libgcc and x86 backend.  Add static
assert to x86 backend to verify that libgcc and x86 backend are in sync.

Update processor feature check in in libgcc:

1. Update FEATURE_GFNI check to support SSE, AVX and AVX512 versions of
GFNI.
2. Add missing FEATURE_AVX512VP2INTERSECT.
3. Add FEATURE_XSAVEOPT, FEATURE_CLWB and FEATURE_CLZERO for get_amd_cpu.
4. Always set __cpu_features2 for has_cpu_feature.

Update libgfortran to use has_cpu_feature to detect x86 CPU features.

gcc/

	PR target/95212
	PR target/95220
	* common/config/i386/cpuinfo.h: Moved from libgcc/config/i386.
	(processor_features): Add FEATURE_AVX512VP2INTERSECT,
	FEATURE_XSAVEOPT, FEATURE_CLWB and FEATURE_CLZERO.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Add
	arguments for BMI, AVX2, XOP, XSAVEOPT, CLWB and CLZERO.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Add
	an argument for AVX512VNNI.  Use CHECK___builtin_cpu_is.  Return
	Intel CPU name.
	(has_cpu_feature): New function.
	* config/i386/driver-i386.c: Include
	"common/config/i386/cpuinfo.h".
	(host_detect_local_cpu): Call get_amd_cpu to get AMD CPU name.
	Call get_intel_cpu to get Intel CPU name.
	* config/i386/i386-builtins.c: Include
	"common/config/i386/cpuinfo.h".
	(processor_features): Removed.  Replace F_XXX with FEATURE_XXX.
	(isa_names_table): Add xsaveopt, clwb and clzero.
	(CHECK_processor_vendor, CHECK_processor_types,
	CHECK_processor_subtypes): New.  Add static assert to x86
	backend to verify that libgcc and x86 backend are in sync.

gcc/testsuite/

	PR target/95212
	PR target/95220
	* gcc.target/i386/builtin_target.c: Include <stddef.h> and
	../../../common/config/i386/cpuinfo.h.
	(CHECK___builtin_cpu_is): New.
	(inline): New.  Defined as empty.
	(check_amd_cpu_model): Removed.
	(check_intel_cpu_model): Likewise,
	(check_detailed): Call get_amd_cpu instead of check_amd_cpu_model.
	Call get_intel_cpu instead of check_intel_cpu_model.

libgcc/

	PR target/95212
	PR target/95220
	* config/i386/cpuinfo.h: Moved to ... gcc/common/config/i386.
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Make it static in libgcc_s.so.1.
	(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_intel_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_available_features): Fix FEATURE_GFNI check.  Also check
	FEATURE_AVX512VP2INTERSECT, FEATURE_XSAVEOPT, FEATURE_CLWB and
	FEATURE_CLZERO.  Always set __cpu_features2.
	(__cpu_indicator_init): Call get_available_features before
	calling get_amd_cpu.  Pass has_cpu_feature (FEATURE_XXX) to
	get_amd_cpu.  Call get_available_features before calling
	get_intel_cpu.  Pass has_cpu_feature (FEATURE_AVX512VNNI) to
	get_intel_cpu.

libgfortran/

	PR target/95212
	PR target/95220
	* m4/matmul.m4: Include <common/config/i386/cpuinfo.h> instead
	of <config/i386/cpuinfo.h>.  Use has_cpu_feature.
	* generated/matmul_c10.c: Regenerated.
	* generated/matmul_c16.c: Likewise.
	* generated/matmul_c4.c: Likewise.
	* generated/matmul_c8.c: Likewise.
	* generated/matmul_i1.c: Likewise.
	* generated/matmul_i16.c: Likewise.
	* generated/matmul_i2.c: Likewise.
	* generated/matmul_i4.c: Likewise.
	* generated/matmul_i8.c: Likewise.
	* generated/matmul_r10.c: Likewise.
	* generated/matmul_r16.c: Likewise.
	* generated/matmul_r4.c: Likewise.
	* generated/matmul_r8.c: Likewise.
---
 gcc/common/config/i386/cpuinfo.h              | 519 ++++++++++++++++++
 gcc/config/i386/driver-i386.c                 | 221 ++------
 gcc/config/i386/i386-builtins.c               | 203 ++++---
 .../gcc.target/i386/builtin_target.c          | 194 +------
 libgcc/config/i386/cpuinfo.c                  | 263 ++-------
 libgcc/config/i386/cpuinfo.h                  | 135 -----
 libgfortran/generated/matmul_c10.c            |  18 +-
 libgfortran/generated/matmul_c16.c            |  18 +-
 libgfortran/generated/matmul_c4.c             |  18 +-
 libgfortran/generated/matmul_c8.c             |  18 +-
 libgfortran/generated/matmul_i1.c             |  18 +-
 libgfortran/generated/matmul_i16.c            |  18 +-
 libgfortran/generated/matmul_i2.c             |  18 +-
 libgfortran/generated/matmul_i4.c             |  18 +-
 libgfortran/generated/matmul_i8.c             |  18 +-
 libgfortran/generated/matmul_r10.c            |  18 +-
 libgfortran/generated/matmul_r16.c            |  18 +-
 libgfortran/generated/matmul_r4.c             |  18 +-
 libgfortran/generated/matmul_r8.c             |  18 +-
 libgfortran/m4/matmul.m4                      |  18 +-
 20 files changed, 855 insertions(+), 932 deletions(-)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 delete mode 100644 libgcc/config/i386/cpuinfo.h

diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..ae4dcdb4e97
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,519 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Processor Vendor and Models. */
+
+enum processor_vendor
+{
+  VENDOR_INTEL = 1,
+  VENDOR_AMD,
+  VENDOR_OTHER,
+  VENDOR_MAX
+};
+
+/* Any new types or subtypes have to be inserted at the end. */
+
+enum processor_types
+{
+  INTEL_BONNELL = 1,
+  INTEL_CORE2,
+  INTEL_COREI7,
+  AMDFAM10H,
+  AMDFAM15H,
+  INTEL_SILVERMONT,
+  INTEL_KNL,
+  AMD_BTVER1,
+  AMD_BTVER2,
+  AMDFAM17H,
+  INTEL_KNM,
+  INTEL_GOLDMONT,
+  INTEL_GOLDMONT_PLUS,
+  INTEL_TREMONT,
+  CPU_TYPE_MAX
+};
+
+enum processor_subtypes
+{
+  INTEL_COREI7_NEHALEM = 1,
+  INTEL_COREI7_WESTMERE,
+  INTEL_COREI7_SANDYBRIDGE,
+  AMDFAM10H_BARCELONA,
+  AMDFAM10H_SHANGHAI,
+  AMDFAM10H_ISTANBUL,
+  AMDFAM15H_BDVER1,
+  AMDFAM15H_BDVER2,
+  AMDFAM15H_BDVER3,
+  AMDFAM15H_BDVER4,
+  AMDFAM17H_ZNVER1,
+  INTEL_COREI7_IVYBRIDGE,
+  INTEL_COREI7_HASWELL,
+  INTEL_COREI7_BROADWELL,
+  INTEL_COREI7_SKYLAKE,
+  INTEL_COREI7_SKYLAKE_AVX512,
+  INTEL_COREI7_CANNONLAKE,
+  INTEL_COREI7_ICELAKE_CLIENT,
+  INTEL_COREI7_ICELAKE_SERVER,
+  AMDFAM17H_ZNVER2,
+  INTEL_COREI7_CASCADELAKE,
+  INTEL_COREI7_TIGERLAKE,
+  INTEL_COREI7_COOPERLAKE,
+  CPU_SUBTYPE_MAX
+};
+
+/* ISA Features supported. New features have to be inserted at the end.  */
+
+enum processor_features
+{
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_SSE4_A,
+  FEATURE_FMA4,
+  FEATURE_XOP,
+  FEATURE_FMA,
+  FEATURE_AVX512F,
+  FEATURE_BMI,
+  FEATURE_BMI2,
+  FEATURE_AES,
+  FEATURE_PCLMUL,
+  FEATURE_AVX512VL,
+  FEATURE_AVX512BW,
+  FEATURE_AVX512DQ,
+  FEATURE_AVX512CD,
+  FEATURE_AVX512ER,
+  FEATURE_AVX512PF,
+  FEATURE_AVX512VBMI,
+  FEATURE_AVX512IFMA,
+  FEATURE_AVX5124VNNIW,
+  FEATURE_AVX5124FMAPS,
+  FEATURE_AVX512VPOPCNTDQ,
+  FEATURE_AVX512VBMI2,
+  FEATURE_GFNI,
+  FEATURE_VPCLMULQDQ,
+  FEATURE_AVX512VNNI,
+  FEATURE_AVX512BITALG,
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_AVX512BF16,
+  FEATURE_XSAVEOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO
+};
+
+extern struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  unsigned int __cpu_features[1];
+} __cpu_model;
+extern unsigned int __cpu_features2;
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model, unsigned int family,
+	     unsigned int model, int has_bmi, int has_avx2, int has_xop,
+	     int has_xsaveopt, int has_clwb, int has_clzero)
+{
+  const char *cpu = NULL;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_avx2)
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_xsaveopt)
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_bmi)
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_xop)
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_clwb)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_clzero)
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       unsigned int family, unsigned int model,
+	       unsigned int brand_id, int has_avx512vnni)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || family != 0x6)
+    return cpu;
+
+  switch (model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_avx512vnni)
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (enum processor_features f)
+{
+  if (f < 32)
+    return __cpu_model.__cpu_features[0] & (1U << (f & 31));
+  else
+    return __cpu_features2 & (1U << ((f - 32) & 31));
+}
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 7612ddfb846..2126d154500 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "common/config/i386/cpuinfo.h"
 
 const char *host_detect_local_cpu (int argc, const char **argv);
 
@@ -656,6 +657,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	}
     }
 
+  struct __processor_model cpu_model;
+
   if (vendor == signature_AMD_ebx)
     {
       unsigned int name;
@@ -666,34 +669,21 @@ 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, family, model, has_bmi, has_avx2,
+			 has_xop, has_xsaveopt, has_clwb, has_clzero);
+      if (cpu == NULL)
+	{
+	  if (name == signature_NSC_ebx)
+	    processor = PROCESSOR_GEODE;
+	  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;
+	}
     }
   else if (vendor == signature_CENTAUR_ebx)
     {
@@ -767,145 +757,24 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	cpu = "pentium";
       break;
     case PROCESSOR_PENTIUMPRO:
-      switch (model)
+      cpu = get_intel_cpu (&cpu_model, family, model, 0,
+			   has_avx512vnni);
+      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";
+		{
+		  /* 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";
 		/* Assume Ice Lake.  */
 		else if (has_avx512bitalg)
 		  cpu = "icelake-client";
@@ -1002,7 +871,6 @@ 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:
@@ -1058,33 +926,6 @@ 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.  */
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 4b203635428..d358c7e6a2b 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/cpuinfo.h"
 
 #undef BDESC
 #undef BDESC_FIRST
@@ -1872,50 +1873,6 @@ enum feature_priority
   P_PROC_AVX512F
 };
 
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512VP2INTERSECT,
-  F_AVX512BF16,
-  F_MAX
-};
-
 /* These are the values for vendor types and cpu types  and subtypes
    in cpuinfo.c.  Cpu types and subtypes should be subtracted by
    the corresponding start value.  */
@@ -1964,6 +1921,85 @@ enum processor_model
   M_INTEL_COREI7_COOPERLAKE
 };
 
+/* Check aganst enum processor_vendor.  */
+#define CHECK_processor_vendor(t, e) \
+  static_assert ((int) (t) == (int) (e), "Incorrect " #t)
+CHECK_processor_vendor (M_INTEL, VENDOR_INTEL);
+CHECK_processor_vendor (M_AMD, VENDOR_AMD);
+
+/* Check aganst enum processor_types.  */
+#define CHECK_processor_types(t, e) \
+  static_assert ((int) (t) - (M_CPU_TYPE_START) \
+		 == (int) (e), "Incorrect " #t)
+CHECK_processor_types (M_INTEL_BONNELL, INTEL_BONNELL);
+CHECK_processor_types (M_INTEL_CORE2, INTEL_CORE2);
+CHECK_processor_types (M_INTEL_COREI7, INTEL_COREI7);
+CHECK_processor_types (M_AMDFAM10H, AMDFAM10H);
+CHECK_processor_types (M_AMDFAM15H, AMDFAM15H);
+CHECK_processor_types (M_INTEL_SILVERMONT, INTEL_SILVERMONT);
+CHECK_processor_types (M_INTEL_KNL, INTEL_KNL);
+CHECK_processor_types (M_AMD_BTVER1, AMD_BTVER1);
+CHECK_processor_types (M_AMD_BTVER2, AMD_BTVER2);
+CHECK_processor_types (M_AMDFAM17H, AMDFAM17H);
+CHECK_processor_types (M_INTEL_KNM, INTEL_KNM);
+CHECK_processor_types (M_INTEL_GOLDMONT, INTEL_GOLDMONT);
+CHECK_processor_types (M_INTEL_GOLDMONT_PLUS, INTEL_GOLDMONT_PLUS);
+CHECK_processor_types (M_INTEL_TREMONT, INTEL_TREMONT);
+CHECK_processor_types (M_INTEL_TREMONT, (int) CPU_TYPE_MAX - 1);
+
+/* Check aganst enum processor_subtypes.  */
+#define CHECK_processor_subtypes(t, e) \
+  static_assert ((int) (t) - (M_CPU_SUBTYPE_START) \
+		 == (int) (e), "Incorrect " #t)
+CHECK_processor_subtypes (M_INTEL_COREI7_NEHALEM,
+			  INTEL_COREI7_NEHALEM);
+CHECK_processor_subtypes (M_INTEL_COREI7_WESTMERE,
+			  INTEL_COREI7_WESTMERE);
+CHECK_processor_subtypes (M_INTEL_COREI7_SANDYBRIDGE,
+			  INTEL_COREI7_SANDYBRIDGE);
+CHECK_processor_subtypes (M_AMDFAM10H_BARCELONA,
+			  AMDFAM10H_BARCELONA);
+CHECK_processor_subtypes (M_AMDFAM10H_SHANGHAI,
+			  AMDFAM10H_SHANGHAI);
+CHECK_processor_subtypes (M_AMDFAM10H_ISTANBUL,
+			  AMDFAM10H_ISTANBUL);
+CHECK_processor_subtypes (M_AMDFAM15H_BDVER1,
+			  AMDFAM15H_BDVER1);
+CHECK_processor_subtypes (M_AMDFAM15H_BDVER2,
+			  AMDFAM15H_BDVER2);
+CHECK_processor_subtypes (M_AMDFAM15H_BDVER3,
+			  AMDFAM15H_BDVER3);
+CHECK_processor_subtypes (M_AMDFAM15H_BDVER4,
+			  AMDFAM15H_BDVER4);
+CHECK_processor_subtypes (M_AMDFAM17H_ZNVER1,
+			  AMDFAM17H_ZNVER1);
+CHECK_processor_subtypes (M_INTEL_COREI7_IVYBRIDGE,
+			  INTEL_COREI7_IVYBRIDGE);
+CHECK_processor_subtypes (M_INTEL_COREI7_HASWELL,
+			  INTEL_COREI7_HASWELL);
+CHECK_processor_subtypes (M_INTEL_COREI7_BROADWELL,
+			  INTEL_COREI7_BROADWELL);
+CHECK_processor_subtypes (M_INTEL_COREI7_SKYLAKE,
+			  INTEL_COREI7_SKYLAKE);
+CHECK_processor_subtypes (M_INTEL_COREI7_SKYLAKE_AVX512,
+			  INTEL_COREI7_SKYLAKE_AVX512);
+CHECK_processor_subtypes (M_INTEL_COREI7_CANNONLAKE,
+			  INTEL_COREI7_CANNONLAKE);
+CHECK_processor_subtypes (M_INTEL_COREI7_ICELAKE_CLIENT,
+			  INTEL_COREI7_ICELAKE_CLIENT);
+CHECK_processor_subtypes (M_INTEL_COREI7_ICELAKE_SERVER,
+			  INTEL_COREI7_ICELAKE_SERVER);
+CHECK_processor_subtypes (M_AMDFAM17H_ZNVER2,
+			  AMDFAM17H_ZNVER2);
+CHECK_processor_subtypes (M_INTEL_COREI7_CASCADELAKE,
+			  INTEL_COREI7_CASCADELAKE);
+CHECK_processor_subtypes (M_INTEL_COREI7_TIGERLAKE,
+			  INTEL_COREI7_TIGERLAKE);
+CHECK_processor_subtypes (M_INTEL_COREI7_COOPERLAKE,
+			  INTEL_COREI7_COOPERLAKE);
+CHECK_processor_subtypes (M_INTEL_COREI7_COOPERLAKE,
+			  (int) CPU_SUBTYPE_MAX - 1);
+
 struct _arch_names_table
 {
   const char *const name;
@@ -2026,44 +2062,47 @@ struct _isa_names_table
 
 static const _isa_names_table isa_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_ZERO},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_ZERO},
-  {"avx512bw",F_AVX512BW, P_ZERO},
-  {"avx512dq",F_AVX512DQ, P_ZERO},
-  {"avx512cd",F_AVX512CD, P_ZERO},
-  {"avx512er",F_AVX512ER, P_ZERO},
-  {"avx512pf",F_AVX512PF, P_ZERO},
-  {"avx512vbmi",F_AVX512VBMI, P_ZERO},
-  {"avx512ifma",F_AVX512IFMA, P_ZERO},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_ZERO},
-  {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
-  {"gfni",	F_GFNI,	P_ZERO},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
-  {"avx512vnni", F_AVX512VNNI, P_ZERO},
-  {"avx512bitalg", F_AVX512BITALG, P_ZERO},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO},
-  {"avx512bf16", F_AVX512BF16, P_ZERO}
+  {"cmov",    FEATURE_CMOV,	P_ZERO},
+  {"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_ZERO},
+  {"avx512bw",FEATURE_AVX512BW, P_ZERO},
+  {"avx512dq",FEATURE_AVX512DQ, P_ZERO},
+  {"avx512cd",FEATURE_AVX512CD, P_ZERO},
+  {"avx512er",FEATURE_AVX512ER, P_ZERO},
+  {"avx512pf",FEATURE_AVX512PF, P_ZERO},
+  {"avx512vbmi",FEATURE_AVX512VBMI, P_ZERO},
+  {"avx512ifma",FEATURE_AVX512IFMA, P_ZERO},
+  {"avx5124vnniw",FEATURE_AVX5124VNNIW, P_ZERO},
+  {"avx5124fmaps",FEATURE_AVX5124FMAPS, P_ZERO},
+  {"avx512vpopcntdq",FEATURE_AVX512VPOPCNTDQ,	P_ZERO},
+  {"avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO},
+  {"gfni",	FEATURE_GFNI,	P_ZERO},
+  {"vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO},
+  {"avx512vnni", FEATURE_AVX512VNNI, P_ZERO},
+  {"avx512bitalg", FEATURE_AVX512BITALG, P_ZERO},
+  {"avx512vp2intersect",FEATURE_AVX512VP2INTERSECT, P_ZERO},
+  {"avx512bf16", FEATURE_AVX512BF16, P_ZERO},
+  {"xsaveopt", FEATURE_XSAVEOPT, P_ZERO},
+  {"clwb", FEATURE_CLWB, P_ZERO},
+  {"clzero", FEATURE_CLZERO, P_ZERO}
 };
 
 /* This parses the attribute arguments to target in DECL and determines
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..b11dcb71151 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,184 +7,11 @@
 /* { dg-do run } */
 
 #include <assert.h>
+#include <stddef.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 inline
+#include "../../../common/config/i386/cpuinfo.h"
 
 /* Check if the ISA features are identified.  */
 static void
@@ -305,6 +132,8 @@ check_detailed ()
   unsigned int model, family, brand_id;
   unsigned int extended_model, extended_family;
 
+  struct __processor_model cpu_model;
+
   /* Assume cpuid insn present. Run in level 0 to get vendor id. */
   if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
     return 0;
@@ -335,7 +164,8 @@ check_detailed ()
 	}
       else if (family == 0x06)
 	model += extended_model;
-      check_intel_cpu_model (family, model, brand_id);
+      get_intel_cpu (&cpu_model, family, model, brand_id,
+		     __builtin_cpu_supports ("avx512vnni"));
       check_features (ecx, edx, max_level);
     }
   else if (vendor == signature_AMD_ebx)
@@ -347,7 +177,13 @@ check_detailed ()
 	  family += extended_family;
 	  model += (extended_model << 4);
 	}
-      check_amd_cpu_model (family, model);
+      get_amd_cpu (&cpu_model, family, model,
+		   __builtin_cpu_supports ("bmi"),
+		   __builtin_cpu_supports ("avx2"),
+		   __builtin_cpu_supports ("xop"),
+		   __builtin_cpu_supports ("xsaveopt"),
+		   __builtin_cpu_supports ("clwb"),
+		   __builtin_cpu_supports ("clzero"));
       check_features (ecx, edx, max_level);
     }
 
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index 00322c58622..edeffe24ff3 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#ifdef SHARED
+static
+#endif
+/* We want to move away from __cpu_model in libgcc_s.so.1 and the
+   size of __cpu_model is part of ABI.  So, new features that don't
+   fit into __cpu_model.__cpu_features[0] go into extra variables
+   in libgcc.a only, preferrably hidden.  NB: Declare __cpu_features2
+   before including "cpuinfo.h" so that has_cpu_feature can be used in
+   libgfortran.  */
+unsigned int __cpu_features2;
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,216 +49,7 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
-/* We want to move away from __cpu_model in libgcc_s.so.1 and the
-   size of __cpu_model is part of ABI.  So, new features that don't
-   fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
 
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
 
 /* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
    the max possible level of CPUID insn.  */
@@ -349,6 +150,10 @@ get_available_features (unsigned int ecx, unsigned int edx,
 	}
       if (ebx & bit_BMI2)
 	set_feature (FEATURE_BMI2);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
       if (avx512_usable)
 	{
 	  if (ebx & bit_AVX512F)
@@ -371,8 +176,6 @@ get_available_features (unsigned int ecx, unsigned int edx,
 	    set_feature (FEATURE_AVX512VBMI);
 	  if (ecx & bit_AVX512VBMI2)
 	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_GFNI)
-	    set_feature (FEATURE_GFNI);
 	  if (ecx & bit_VPCLMULQDQ)
 	    set_feature (FEATURE_VPCLMULQDQ);
 	  if (ecx & bit_AVX512VNNI)
@@ -385,6 +188,8 @@ get_available_features (unsigned int ecx, unsigned int edx,
 	    set_feature (FEATURE_AVX5124VNNIW);
 	  if (edx & bit_AVX5124FMAPS)
 	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
 
 	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
 	  if (eax & bit_AVX512BF16)
@@ -392,6 +197,14 @@ get_available_features (unsigned int ecx, unsigned int edx,
 	}
     }
 
+  /* Get Advanced Features at level 13 (eax = 13, ecx = 1). */
+  if (max_cpuid_level >= 13)
+    {
+      __cpuid_count (7, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+    }
+
   /* Check cpuid level of extended features.  */
   __cpuid (0x80000000, ext_level, ebx, ecx, edx);
 
@@ -410,12 +223,15 @@ get_available_features (unsigned int ecx, unsigned int edx,
 	}
     }
     
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+    }
+
   __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
   __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
 }
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
@@ -477,10 +293,11 @@ __cpu_indicator_init (void)
       else if (family == 0x06)
 	model += extended_model;
 
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
       /* Find available features. */
       get_available_features (ecx, edx, max_level);
+      /* Get CPU type.  */
+      get_intel_cpu (&__cpu_model, family, model, brand_id,
+		     has_cpu_feature (FEATURE_AVX512VNNI));
       __cpu_model.__cpu_vendor = VENDOR_INTEL;
     }
   else if (vendor == signature_AMD_ebx)
@@ -492,10 +309,16 @@ __cpu_indicator_init (void)
 	  model += extended_model;
 	}
 
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
       /* Find available features. */
       get_available_features (ecx, edx, max_level);
+      /* Get CPU type.  */
+      get_amd_cpu (&__cpu_model, family, model,
+		   has_cpu_feature (FEATURE_BMI),
+		   has_cpu_feature (FEATURE_AVX2),
+		   has_cpu_feature (FEATURE_XOP),
+		   has_cpu_feature (FEATURE_XSAVEOPT),
+		   has_cpu_feature (FEATURE_CLWB),
+		   has_cpu_feature (FEATURE_CLZERO));
       __cpu_model.__cpu_vendor = VENDOR_AMD;
     }
   else
diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
deleted file mode 100644
index 41c4a49a98d..00000000000
--- a/libgcc/config/i386/cpuinfo.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Get CPU type and Features for x86 processors.
-   Copyright (C) 2012-2020 Free Software Foundation, Inc.
-   Contributed by Sriraman Tallam (tmsriram@google.com)
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-/* Processor Vendor and Models. */
-
-enum processor_vendor
-{
-  VENDOR_INTEL = 1,
-  VENDOR_AMD,
-  VENDOR_OTHER,
-  VENDOR_MAX
-};
-
-/* Any new types or subtypes have to be inserted at the end. */
-
-enum processor_types
-{
-  INTEL_BONNELL = 1,
-  INTEL_CORE2,
-  INTEL_COREI7,
-  AMDFAM10H,
-  AMDFAM15H,
-  INTEL_SILVERMONT,
-  INTEL_KNL,
-  AMD_BTVER1,
-  AMD_BTVER2,  
-  AMDFAM17H,
-  INTEL_KNM,
-  INTEL_GOLDMONT,
-  INTEL_GOLDMONT_PLUS,
-  INTEL_TREMONT,
-  CPU_TYPE_MAX
-};
-
-enum processor_subtypes
-{
-  INTEL_COREI7_NEHALEM = 1,
-  INTEL_COREI7_WESTMERE,
-  INTEL_COREI7_SANDYBRIDGE,
-  AMDFAM10H_BARCELONA,
-  AMDFAM10H_SHANGHAI,
-  AMDFAM10H_ISTANBUL,
-  AMDFAM15H_BDVER1,
-  AMDFAM15H_BDVER2,
-  AMDFAM15H_BDVER3,
-  AMDFAM15H_BDVER4,
-  AMDFAM17H_ZNVER1,
-  INTEL_COREI7_IVYBRIDGE,
-  INTEL_COREI7_HASWELL,
-  INTEL_COREI7_BROADWELL,
-  INTEL_COREI7_SKYLAKE,
-  INTEL_COREI7_SKYLAKE_AVX512,
-  INTEL_COREI7_CANNONLAKE,
-  INTEL_COREI7_ICELAKE_CLIENT,
-  INTEL_COREI7_ICELAKE_SERVER,
-  AMDFAM17H_ZNVER2,
-  INTEL_COREI7_CASCADELAKE,
-  INTEL_COREI7_TIGERLAKE,
-  INTEL_COREI7_COOPERLAKE,
-  CPU_SUBTYPE_MAX
-};
-
-/* ISA Features supported. New features have to be inserted at the end.  */
-
-enum processor_features
-{
-  FEATURE_CMOV = 0,
-  FEATURE_MMX,
-  FEATURE_POPCNT,
-  FEATURE_SSE,
-  FEATURE_SSE2,
-  FEATURE_SSE3,
-  FEATURE_SSSE3,
-  FEATURE_SSE4_1,
-  FEATURE_SSE4_2,
-  FEATURE_AVX,
-  FEATURE_AVX2,
-  FEATURE_SSE4_A,
-  FEATURE_FMA4,
-  FEATURE_XOP,
-  FEATURE_FMA,
-  FEATURE_AVX512F,
-  FEATURE_BMI,
-  FEATURE_BMI2,
-  FEATURE_AES,
-  FEATURE_PCLMUL,
-  FEATURE_AVX512VL,
-  FEATURE_AVX512BW,
-  FEATURE_AVX512DQ,
-  FEATURE_AVX512CD,
-  FEATURE_AVX512ER,
-  FEATURE_AVX512PF,
-  FEATURE_AVX512VBMI,
-  FEATURE_AVX512IFMA,
-  FEATURE_AVX5124VNNIW,
-  FEATURE_AVX5124FMAPS,
-  FEATURE_AVX512VPOPCNTDQ,
-  FEATURE_AVX512VBMI2,
-  FEATURE_GFNI,
-  FEATURE_VPCLMULQDQ,
-  FEATURE_AVX512VNNI,
-  FEATURE_AVX512BITALG,
-  FEATURE_AVX512BF16
-};
-
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
diff --git a/libgfortran/generated/matmul_c10.c b/libgfortran/generated/matmul_c10.c
index e866a6a4df1..36438bc7f69 100644
--- a/libgfortran/generated/matmul_c10.c
+++ b/libgfortran/generated/matmul_c10.c
@@ -2367,7 +2367,7 @@ matmul_c10_vanilla (gfc_array_c10 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c10 (gfc_array_c10 * const restrict retarray, 
 	gfc_array_c10 * const restrict a, gfc_array_c10 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c10_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c10_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c10_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c10 (gfc_array_c10 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c10_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c10_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c16.c b/libgfortran/generated/matmul_c16.c
index e6605e89282..472b638a665 100644
--- a/libgfortran/generated/matmul_c16.c
+++ b/libgfortran/generated/matmul_c16.c
@@ -2367,7 +2367,7 @@ matmul_c16_vanilla (gfc_array_c16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c16 (gfc_array_c16 * const restrict retarray, 
 	gfc_array_c16 * const restrict a, gfc_array_c16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c16 (gfc_array_c16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c4.c b/libgfortran/generated/matmul_c4.c
index e012fa200fd..4ddc84af01f 100644
--- a/libgfortran/generated/matmul_c4.c
+++ b/libgfortran/generated/matmul_c4.c
@@ -2367,7 +2367,7 @@ matmul_c4_vanilla (gfc_array_c4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c4 (gfc_array_c4 * const restrict retarray, 
 	gfc_array_c4 * const restrict a, gfc_array_c4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c4 (gfc_array_c4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_c8.c b/libgfortran/generated/matmul_c8.c
index 8c19b49deae..0bb00981c92 100644
--- a/libgfortran/generated/matmul_c8.c
+++ b/libgfortran/generated/matmul_c8.c
@@ -2367,7 +2367,7 @@ matmul_c8_vanilla (gfc_array_c8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_c8 (gfc_array_c8 * const restrict retarray, 
 	gfc_array_c8 * const restrict a, gfc_array_c8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_c8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_c8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_c8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_c8 (gfc_array_c8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_c8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_c8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i1.c b/libgfortran/generated/matmul_i1.c
index 8ae4194366e..73a3085187d 100644
--- a/libgfortran/generated/matmul_i1.c
+++ b/libgfortran/generated/matmul_i1.c
@@ -2367,7 +2367,7 @@ matmul_i1_vanilla (gfc_array_i1 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i1 (gfc_array_i1 * const restrict retarray, 
 	gfc_array_i1 * const restrict a, gfc_array_i1 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i1_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i1_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i1_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i1 (gfc_array_i1 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i1_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i1_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i16.c b/libgfortran/generated/matmul_i16.c
index cfbf9206c18..0a2f6906947 100644
--- a/libgfortran/generated/matmul_i16.c
+++ b/libgfortran/generated/matmul_i16.c
@@ -2367,7 +2367,7 @@ matmul_i16_vanilla (gfc_array_i16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i16 (gfc_array_i16 * const restrict retarray, 
 	gfc_array_i16 * const restrict a, gfc_array_i16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i16 (gfc_array_i16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i2.c b/libgfortran/generated/matmul_i2.c
index 5a4aeed78e3..4ce8b43f7ae 100644
--- a/libgfortran/generated/matmul_i2.c
+++ b/libgfortran/generated/matmul_i2.c
@@ -2367,7 +2367,7 @@ matmul_i2_vanilla (gfc_array_i2 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i2 (gfc_array_i2 * const restrict retarray, 
 	gfc_array_i2 * const restrict a, gfc_array_i2 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i2_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i2_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i2_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i2 (gfc_array_i2 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i2_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i2_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i4.c b/libgfortran/generated/matmul_i4.c
index 80592a04d14..228b55fcd5e 100644
--- a/libgfortran/generated/matmul_i4.c
+++ b/libgfortran/generated/matmul_i4.c
@@ -2367,7 +2367,7 @@ matmul_i4_vanilla (gfc_array_i4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i4 (gfc_array_i4 * const restrict retarray, 
 	gfc_array_i4 * const restrict a, gfc_array_i4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i4 (gfc_array_i4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_i8.c b/libgfortran/generated/matmul_i8.c
index 7e4c5bcc1bb..3854ee8da77 100644
--- a/libgfortran/generated/matmul_i8.c
+++ b/libgfortran/generated/matmul_i8.c
@@ -2367,7 +2367,7 @@ matmul_i8_vanilla (gfc_array_i8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_i8 (gfc_array_i8 * const restrict retarray, 
 	gfc_array_i8 * const restrict a, gfc_array_i8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_i8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_i8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_i8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_i8 (gfc_array_i8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_i8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_i8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r10.c b/libgfortran/generated/matmul_r10.c
index d97aa41315e..33699848382 100644
--- a/libgfortran/generated/matmul_r10.c
+++ b/libgfortran/generated/matmul_r10.c
@@ -2367,7 +2367,7 @@ matmul_r10_vanilla (gfc_array_r10 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r10 (gfc_array_r10 * const restrict retarray, 
 	gfc_array_r10 * const restrict a, gfc_array_r10 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r10_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r10_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r10_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r10 (gfc_array_r10 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r10_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r10_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r16.c b/libgfortran/generated/matmul_r16.c
index 82e8b502ba3..ff505796087 100644
--- a/libgfortran/generated/matmul_r16.c
+++ b/libgfortran/generated/matmul_r16.c
@@ -2367,7 +2367,7 @@ matmul_r16_vanilla (gfc_array_r16 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r16 (gfc_array_r16 * const restrict retarray, 
 	gfc_array_r16 * const restrict a, gfc_array_r16 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r16_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r16_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r16_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r16 (gfc_array_r16 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r16_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r16_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r4.c b/libgfortran/generated/matmul_r4.c
index 36ce7daf781..517e74fb80e 100644
--- a/libgfortran/generated/matmul_r4.c
+++ b/libgfortran/generated/matmul_r4.c
@@ -2367,7 +2367,7 @@ matmul_r4_vanilla (gfc_array_r4 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r4 (gfc_array_r4 * const restrict retarray, 
 	gfc_array_r4 * const restrict a, gfc_array_r4 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r4_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r4_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r4_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r4 (gfc_array_r4 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r4_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r4_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/generated/matmul_r8.c b/libgfortran/generated/matmul_r8.c
index 9a81df189d5..d47dd818c49 100644
--- a/libgfortran/generated/matmul_r8.c
+++ b/libgfortran/generated/matmul_r8.c
@@ -2367,7 +2367,7 @@ matmul_r8_vanilla (gfc_array_r8 * const restrict retarray,
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_r8 (gfc_array_r8 * const restrict retarray, 
 	gfc_array_r8 * const restrict a, gfc_array_r8 * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -2388,7 +2388,7 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_r8_avx512f;
 	      goto store;
@@ -2397,8 +2397,8 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_r8_avx2;
 	      goto store;
@@ -2407,7 +2407,7 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_r8_avx;
 	      goto store;
@@ -2417,16 +2417,16 @@ void matmul_r8 (gfc_array_r8 * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_r8_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_r8_avx128_fma4;
 	    goto store;
diff --git a/libgfortran/m4/matmul.m4 b/libgfortran/m4/matmul.m4
index 83f4ae63339..f277b9c7cc8 100644
--- a/libgfortran/m4/matmul.m4
+++ b/libgfortran/m4/matmul.m4
@@ -134,7 +134,7 @@ internal_proto('matmul_name`);
 
 /* Currently, this is i386 only.  Adjust for other architectures.  */
 
-#include <config/i386/cpuinfo.h>
+#include <common/config/i386/cpuinfo.h>
 void matmul_'rtype_code` ('rtype` * const restrict retarray, 
 	'rtype` * const restrict a, 'rtype` * const restrict b, int try_blas,
 	int blas_limit, blas_call gemm)
@@ -155,7 +155,7 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 	{
           /* Run down the available processors in order of preference.  */
 #ifdef HAVE_AVX512F
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX512F))
+	  if (has_cpu_feature (FEATURE_AVX512F))
 	    {
 	      matmul_fn = matmul_'rtype_code`_avx512f;
 	      goto store;
@@ -164,8 +164,8 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 #endif  /* HAVE_AVX512F */
 
 #ifdef HAVE_AVX2
-      	  if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX2))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	  if (has_cpu_feature (FEATURE_AVX2)
+	      && has_cpu_feature (FEATURE_FMA))
 	    {
 	      matmul_fn = matmul_'rtype_code`_avx2;
 	      goto store;
@@ -174,7 +174,7 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
 #endif
 
 #ifdef HAVE_AVX
-      	  if (__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
+	  if (has_cpu_feature (FEATURE_AVX))
  	    {
               matmul_fn = matmul_'rtype_code`_avx;
 	      goto store;
@@ -184,16 +184,16 @@ void matmul_'rtype_code` ('rtype` * const restrict retarray,
     else if (__cpu_model.__cpu_vendor == VENDOR_AMD)
       {
 #if defined(HAVE_AVX) && defined(HAVE_FMA3) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	    && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA))
 	  {
             matmul_fn = matmul_'rtype_code`_avx128_fma3;
 	    goto store;
 	  }
 #endif
 #if defined(HAVE_AVX) && defined(HAVE_FMA4) && defined(HAVE_AVX128)
-        if ((__cpu_model.__cpu_features[0] & (1 << FEATURE_AVX))
-	     && (__cpu_model.__cpu_features[0] & (1 << FEATURE_FMA4)))
+	if (has_cpu_feature (FEATURE_AVX)
+	    && has_cpu_feature (FEATURE_FMA4))
 	  {
             matmul_fn = matmul_'rtype_code`_avx128_fma4;
 	    goto store;
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19 19:57             ` V2 " H.J. Lu
@ 2020-05-19 21:06               ` Uros Bizjak
  2020-05-19 21:39                 ` H.J. Lu
  2020-05-20  1:30                 ` V2 " H.J. Lu
  0 siblings, 2 replies; 30+ messages in thread
From: Uros Bizjak @ 2020-05-19 21:06 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 9:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, May 18, 2020 at 10:56 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Tue, May 19, 2020 at 4:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > > >
> > > > > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > > > > and Tiger Lake processor families.
> > > > > > > >
> > > > > > > > OK for master?
> > > > > > >
> > > > > > > OK.
> > > > > >
> > > > > > I am checking in my patch.
> > > > > >
> > > > > > > Please also update cpuinfo.c from libgcc and corresponding
> > > > > >
> > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > libgcc and config/i386/driver-i386.c.
> > > > >
> > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > switch statement that maps to different stuff in libgcc and
> > > > > driver-i386.
> > > >
> > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > I think we can do better.
> > > >
> > >
> > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > >
> > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> >
> > Handling only Intel targets and not others is a sure way for patch to
> > be ignored.
> >
>
> Here is the updated patch to cover AMD CPU.  It also fixes:
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
>
> OK for master?

Huh... I didn't think the solution will be this messy... I have to
rethink the approach a bit.

Can you in the meantime please prepare a simple patch to fix the above
mentioned PRs and eventually backport it to other release branches? It
should be simple enough to be committed under obvious rule.

Thanks,
Uros.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19 21:06               ` Uros Bizjak
@ 2020-05-19 21:39                 ` H.J. Lu
  2020-05-20  6:10                   ` Uros Bizjak
  2020-05-20  1:30                 ` V2 " H.J. Lu
  1 sibling, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-19 21:39 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 2:07 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, May 19, 2020 at 9:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 10:56 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Tue, May 19, 2020 at 4:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > > > >
> > > > > > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > > > > > and Tiger Lake processor families.
> > > > > > > > >
> > > > > > > > > OK for master?
> > > > > > > >
> > > > > > > > OK.
> > > > > > >
> > > > > > > I am checking in my patch.
> > > > > > >
> > > > > > > > Please also update cpuinfo.c from libgcc and corresponding
> > > > > > >
> > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > >
> > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > driver-i386.
> > > > >
> > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > I think we can do better.
> > > > >
> > > >
> > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > >
> > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > >
> > > Handling only Intel targets and not others is a sure way for patch to
> > > be ignored.
> > >
> >
> > Here is the updated patch to cover AMD CPU.  It also fixes:
> >
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> >
> > OK for master?
>
> Huh... I didn't think the solution will be this messy... I have to
> rethink the approach a bit.

That is what will happen when we have the same info in more than one place
There should only one place for CPU info.

> Can you in the meantime please prepare a simple patch to fix the above
> mentioned PRs and eventually backport it to other release branches? It
> should be simple enough to be committed under obvious rule.
>

Done:

https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546088.html

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19 21:06               ` Uros Bizjak
  2020-05-19 21:39                 ` H.J. Lu
@ 2020-05-20  1:30                 ` H.J. Lu
  1 sibling, 0 replies; 30+ messages in thread
From: H.J. Lu @ 2020-05-20  1:30 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 2:07 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, May 19, 2020 at 9:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, May 18, 2020 at 10:56 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Tue, May 19, 2020 at 4:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 5:57 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 5:43 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, May 18, 2020 at 2:34 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, May 18, 2020 at 5:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Mon, May 18, 2020 at 1:58 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > > > >
> > > > > > > > > Add cpu model numbers for Intel Airmont, Tremont, Comet Lake, Ice Lake
> > > > > > > > > and Tiger Lake processor families.
> > > > > > > > >
> > > > > > > > > OK for master?
> > > > > > > >
> > > > > > > > OK.
> > > > > > >
> > > > > > > I am checking in my patch.
> > > > > > >
> > > > > > > > Please also update cpuinfo.c from libgcc and corresponding
> > > > > > >
> > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > >
> > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > driver-i386.
> > > > >
> > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > I think we can do better.
> > > > >
> > > >
> > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > >
> > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > >
> > > Handling only Intel targets and not others is a sure way for patch to
> > > be ignored.
> > >
> >
> > Here is the updated patch to cover AMD CPU.  It also fixes:
> >
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> >
> > OK for master?
>
> Huh... I didn't think the solution will be this messy... I have to
> rethink the approach a bit.
>

These can avoid duplication in i386-builtins.c:

/* These are the values for vendor types, cpu types and subtypes in
   cpuinfo.h.  Cpu types and subtypes should be subtracted by the
   corresponding start value.  */

#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
#define M_CPU_SUBTYPE_START \
  (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
#define M_VENDOR(a) (a)
#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)

static const _arch_names_table arch_names_table[] =
{
  {"amd", M_VENDOR (VENDOR_AMD)},
  {"intel", M_VENDOR (VENDOR_INTEL)},
  {"atom", M_CPU_TYPE (INTEL_BONNELL)},
  {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
  {"core2", M_CPU_TYPE (INTEL_CORE2)},
  {"corei7", M_CPU_TYPE (INTEL_COREI7)},
  {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
  {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
  {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
  {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
  {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
  {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
  {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
  {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
  {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
  {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
  {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
  {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
  {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
  {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
  {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
  {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
  {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
  {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
  {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
  {"knl", M_CPU_TYPE (INTEL_KNL)},
  {"knm", M_CPU_TYPE (INTEL_KNM)},
  {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
  {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
  {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
  {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
  {"btver1", M_CPU_TYPE (AMD_BTVER1)},
  {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
  {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
  {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
  {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
  {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
  {"btver2", M_CPU_TYPE (AMD_BTVER2)},
  {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
  {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
  {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
};


-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-19 21:39                 ` H.J. Lu
@ 2020-05-20  6:10                   ` Uros Bizjak
  2020-05-20 11:21                     ` H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Uros Bizjak @ 2020-05-20  6:10 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 11:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> > > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > > >
> > > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > > driver-i386.
> > > > > >
> > > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > > I think we can do better.
> > > > > >
> > > > >
> > > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > > >
> > > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > > >
> > > > Handling only Intel targets and not others is a sure way for patch to
> > > > be ignored.
> > > >
> > >
> > > Here is the updated patch to cover AMD CPU.  It also fixes:
> > >
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> > >
> > > OK for master?
> >
> > Huh... I didn't think the solution will be this messy... I have to
> > rethink the approach a bit.
>
> That is what will happen when we have the same info in more than one place
> There should only one place for CPU info.

Looking at the patch, it is clear that cpuinfo.c and driver-i386.c
should stay apart. They are two different things, and they are
orthogonal to each other; one can be updated without affecting the
other one. driver-i386.c handles way more targets than cpuinfo.c and
your patch only handles a subset of them. The unification does not
bring any benefit, it even complicates things more.

I think that unifying libgcc and i386-builtins.c is the way to go.
libgfortran should benefit from this unification, too.

Uros.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-20  6:10                   ` Uros Bizjak
@ 2020-05-20 11:21                     ` H.J. Lu
  2020-05-21 17:37                       ` H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-20 11:21 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: GNU GFortran, gcc-patches

On Tue, May 19, 2020 at 11:10 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, May 19, 2020 at 11:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> > > > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > > > >
> > > > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > > > driver-i386.
> > > > > > >
> > > > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > > > I think we can do better.
> > > > > > >
> > > > > >
> > > > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > > > >
> > > > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > > > >
> > > > > Handling only Intel targets and not others is a sure way for patch to
> > > > > be ignored.
> > > > >
> > > >
> > > > Here is the updated patch to cover AMD CPU.  It also fixes:
> > > >
> > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> > > >
> > > > OK for master?
> > >
> > > Huh... I didn't think the solution will be this messy... I have to
> > > rethink the approach a bit.
> >
> > That is what will happen when we have the same info in more than one place
> > There should only one place for CPU info.
>
> Looking at the patch, it is clear that cpuinfo.c and driver-i386.c
> should stay apart. They are two different things, and they are
> orthogonal to each other; one can be updated without affecting the
> other one. driver-i386.c handles way more targets than cpuinfo.c and
> your patch only handles a subset of them. The unification does not
> bring any benefit, it even complicates things more.

There should one place to check a CPU feature, not 2.  It can
be done with a proper cpuinfo.h.

> I think that unifying libgcc and i386-builtins.c is the way to go.
> libgfortran should benefit from this unification, too.
>

libgfortran shouldn't include cpuinfo.h.  It should use __builtin_cpu_is
and  __builtin_cpu_supports.

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V2 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-20 11:21                     ` H.J. Lu
@ 2020-05-21 17:37                       ` H.J. Lu
  2020-05-22 14:51                         ` V3 " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-21 17:37 UTC (permalink / raw)
  To: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener
  Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2497 bytes --]

On Wed, May 20, 2020 at 4:21 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, May 19, 2020 at 11:10 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Tue, May 19, 2020 at 11:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > > > > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > > > > >
> > > > > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > > > > driver-i386.
> > > > > > > >
> > > > > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > > > > I think we can do better.
> > > > > > > >
> > > > > > >
> > > > > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > > > > >
> > > > > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > > > > >
> > > > > > Handling only Intel targets and not others is a sure way for patch to
> > > > > > be ignored.
> > > > > >
> > > > >
> > > > > Here is the updated patch to cover AMD CPU.  It also fixes:
> > > > >
> > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> > > > >
> > > > > OK for master?
> > > >
> > > > Huh... I didn't think the solution will be this messy... I have to
> > > > rethink the approach a bit.
> > >
> > > That is what will happen when we have the same info in more than one place
> > > There should only one place for CPU info.
> >
> > Looking at the patch, it is clear that cpuinfo.c and driver-i386.c
> > should stay apart. They are two different things, and they are
> > orthogonal to each other; one can be updated without affecting the
> > other one. driver-i386.c handles way more targets than cpuinfo.c and
> > your patch only handles a subset of them. The unification does not
> > bring any benefit, it even complicates things more.
>
> There should one place to check a CPU feature, not 2.  It can
> be done with a proper cpuinfo.h.
>

This updated patch does it.   It removes duplicated codes and
simplifies the implementation.  With this patch, we just to update
a single place to add the new ISA support.


--
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: application/x-patch, Size: 102193 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V3 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-21 17:37                       ` H.J. Lu
@ 2020-05-22 14:51                         ` H.J. Lu
  2020-05-25  9:52                           ` Martin Liška
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-22 14:51 UTC (permalink / raw)
  To: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener
  Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3091 bytes --]

On Thu, May 21, 2020 at 10:37 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, May 20, 2020 at 4:21 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, May 19, 2020 at 11:10 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Tue, May 19, 2020 at 11:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > > > > > > > > > I will take a look to see if we share the same CPU detection code between
> > > > > > > > > > > libgcc and config/i386/driver-i386.c.
> > > > > > > > > >
> > > > > > > > > > I don't think it will bring any benefit, this is mainly one huge
> > > > > > > > > > switch statement that maps to different stuff in libgcc and
> > > > > > > > > > driver-i386.
> > > > > > > > >
> > > > > > > > > libgcc and config/i386/driver-i386.c differ even before my patch.
> > > > > > > > > I think we can do better.
> > > > > > > > >
> > > > > > > >
> > > > > > > > Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
> > > > > > > > can be shared by libgcc, GCC driver, gcc.target/i386/builtin_target.c
> > > > > > > > and libgfortran to detect the specific type of Intel CPU.  Update
> > > > > > > > libgfortran to use has_cpu_feature to detect x86 CPU features.
> > > > > > > >
> > > > > > > > Tested on Linux/x86 and Linux/x86-64.  OK for master?
> > > > > > >
> > > > > > > Handling only Intel targets and not others is a sure way for patch to
> > > > > > > be ignored.
> > > > > > >
> > > > > >
> > > > > > Here is the updated patch to cover AMD CPU.  It also fixes:
> > > > > >
> > > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95212
> > > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95220
> > > > > >
> > > > > > OK for master?
> > > > >
> > > > > Huh... I didn't think the solution will be this messy... I have to
> > > > > rethink the approach a bit.
> > > >
> > > > That is what will happen when we have the same info in more than one place
> > > > There should only one place for CPU info.
> > >
> > > Looking at the patch, it is clear that cpuinfo.c and driver-i386.c
> > > should stay apart. They are two different things, and they are
> > > orthogonal to each other; one can be updated without affecting the
> > > other one. driver-i386.c handles way more targets than cpuinfo.c and
> > > your patch only handles a subset of them. The unification does not
> > > bring any benefit, it even complicates things more.
> >
> > There should one place to check a CPU feature, not 2.  It can
> > be done with a proper cpuinfo.h.
> >
>
> This updated patch does it.   It removes duplicated codes and
> simplifies the implementation.  With this patch, we just to update
> a single place to add the new ISA support.
>

Here is the updated patch to add common/config/i386/cpuinfo-builtins.h.
SIZE_OF_CPU_FEATURES is now defined with CPU_FEATURE_MAX
so that we can simply just add a new feature to enum processor_features
and __cpu_features2 will have the correct size to cover all features.
fold_builtin_cpu is changed to work with any SIZE_OF_CPU_FEATURES
values.

Tested on Linux/x86-64 and Linux/x86.   OK for master?

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 97888 bytes --]

From 74bf612b8f33937cc33dcea46baabf2bf56eb9ee Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
can be shared by libgcc, GCC driver and gcc.target/i386/builtin_target.c
to detect the specific type of Intel and AMD CPUs:

1. Use the same enum processor_features in libgcc and x86 backend.
2. Add more processor features to enum processor_features.
3. Add M_VENDOR, M_CPU_TYPE and M_CPU_SUBTYPE in i386-builtins.c to
avoid duplication in.
4. Use cpu_indicator_init, has_cpu_feature, get_amd_cpu and get_intel_cpu
in driver-i386.c and builtin_target.c.

gcc/

	PR target/95259
	* common/config/i386/cpuinfo-builtins.h: Moved from
	libgcc/config/i386/cpuinfo.h.
	(processor_vendor): Add VENDOR_CENTAUR, VENDOR_CYRIX, VENDOR_NSC
	and BUILTIN_VENDOR_MAX.
	(processor_types): Add BUILTIN_CPU_TYPE_MAX.
	(processor_features): Add FEATURE_3DNOW, FEATURE_3DNOWP,
	FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
	FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
	FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
	FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
	FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
	FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
	FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE, FEATURE_PCONFIG,
	FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
	(__processor_model): Moved to cpuinfo.h.
	(__cpu_model): Removed.
	(__cpu_features2): Likewise.
	(SIZE_OF_CPU_FEATURES): New.
	* common/config/i386/cpuinfo.h: Moved from
	libgcc/config/i386/cpuinfo.c.
	(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
	(__processor_model2): New.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(has_cpu_feature): New function.
	(set_cpu_feature): Likewise.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	Use CHECK___builtin_cpu_is.  Return Intel CPU name.
	(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
	Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
	FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
	FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
	FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
	FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
	FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
	FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE,
	FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT and FEATURE_XSAVES
	(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
	Also update cpu_model2.
	* config/i386/driver-i386.c: Include
	"common/config/i386/cpuinfo.h".
	(host_detect_local_cpu): Call cpu_indicator_init to get CPU
	features.  Use has_cpu_feature to detect processor features.
	Call get_amd_cpu to get AMD CPU name.  Call get_intel_cpu to
	get Intel CPU name.
	* config/i386/i386-builtins.c: Include
	"common/config/i386/cpuinfo-builtins.h".
	(processor_features): Removed.  Replace F_XXX with FEATURE_XXX.
	(processor_model): Removed.
	(_arch_names_table): Use "const int" on model.
	(M_CPU_TYPE_START): New.
	(M_CPU_SUBTYPE_START): Likewise.
	(M_VENDOR): Likewise.
	(M_CPU_TYPE): Likewise.
	(M_CPU_SUBTYPE): Likewise.
	(arch_names_table): Replace M_XXX with M_VENDOR, M_CPU_TYPE and
	M_CPU_SUBTYPE.
	(isa_names_table): Add more ISAs from enum processor_features.
	(fold_builtin_cpu): Change __cpu_features2 to an array.

gcc/testsuite/

	PR target/95259
	* gcc.target/i386/builtin_target.c: Include <stdlib.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.
	(check_features): Use has_cpu_feature to check processor features.
	(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.

libgcc/

	PR target/95259
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Changed to array.
	(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_intel_cpu): Likewise.
	(get_available_features): Likewise.
	(__cpu_indicator_init): Call cpu_indicator_init.
	* config/i386/cpuinfo.h: Moved to
	gcc/common/config/i386/cpuinfo-builtins.h.
---
 .../common/config/i386/cpuinfo-builtins.h     |  70 +-
 gcc/common/config/i386/cpuinfo.h              | 834 ++++++++++++++++++
 gcc/config/i386/driver-i386.c                 | 598 ++++---------
 gcc/config/i386/i386-builtins.c               | 339 ++++---
 .../gcc.target/i386/builtin_target.c          | 500 ++++-------
 libgcc/config/i386/cpuinfo.c                  | 464 +---------
 6 files changed, 1416 insertions(+), 1389 deletions(-)
 rename libgcc/config/i386/cpuinfo.h => gcc/common/config/i386/cpuinfo-builtins.h (71%)
 create mode 100644 gcc/common/config/i386/cpuinfo.h

diff --git a/libgcc/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo-builtins.h
similarity index 71%
rename from libgcc/config/i386/cpuinfo.h
rename to gcc/common/config/i386/cpuinfo-builtins.h
index 0f97510cde1..7a20dcf9ef8 100644
--- a/libgcc/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo-builtins.h
@@ -30,6 +30,10 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
+  BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
 
@@ -45,13 +49,14 @@ enum processor_types
   INTEL_SILVERMONT,
   INTEL_KNL,
   AMD_BTVER1,
-  AMD_BTVER2,  
+  AMD_BTVER2,
   AMDFAM17H,
   INTEL_KNM,
   INTEL_GOLDMONT,
   INTEL_GOLDMONT_PLUS,
   INTEL_TREMONT,
-  CPU_TYPE_MAX
+  CPU_TYPE_MAX,
+  BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
 };
 
 enum processor_subtypes
@@ -123,14 +128,57 @@ enum processor_features
   FEATURE_AVX512VNNI,
   FEATURE_AVX512BITALG,
   FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_3DNOW,
+  FEATURE_3DNOWP,
+  FEATURE_ADX,
+  FEATURE_ABM,
+  FEATURE_CLDEMOTE,
+  FEATURE_CLFLUSHOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO,
+  FEATURE_CMPXCHG16B,
+  FEATURE_CMPXCHG8B,
+  FEATURE_ENQCMD,
+  FEATURE_F16C,
+  FEATURE_FSGSBASE,
+  FEATURE_FXSAVE,
+  FEATURE_HLE,
+  FEATURE_IBT,
+  FEATURE_LAHF_LM,
+  FEATURE_LM,
+  FEATURE_LWP,
+  FEATURE_LZCNT,
+  FEATURE_MOVBE,
+  FEATURE_MOVDIR64B,
+  FEATURE_MOVDIRI,
+  FEATURE_MWAITX,
+  FEATURE_OSPKE,
+  FEATURE_OSXSAVE,
+  FEATURE_PCONFIG,
+  FEATURE_PKU,
+  FEATURE_PREFETCHWT1,
+  FEATURE_PRFCHW,
+  FEATURE_PTWRITE,
+  FEATURE_RDPID,
+  FEATURE_RDRND,
+  FEATURE_RDSEED,
+  FEATURE_RTM,
+  FEATURE_SERIALIZE,
+  FEATURE_SGX,
+  FEATURE_SHA,
+  FEATURE_SHSTK,
+  FEATURE_TBM,
+  FEATURE_TSXLDTRK,
+  FEATURE_VAES,
+  FEATURE_WAITPKG,
+  FEATURE_WBNOINVD,
+  FEATURE_XSAVE,
+  FEATURE_XSAVEC,
+  FEATURE_XSAVEOPT,
+  FEATURE_XSAVES,
+  CPU_FEATURE_MAX
 };
 
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..9f75bb0c0f0
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,834 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "cpuinfo-builtins.h"
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+  unsigned int __cpu_family;
+  unsigned int __cpu_model;
+  unsigned int __cpu_max_level;
+  unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    return cpu_model->__cpu_features[0] & (1U << (f & 31));
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+  gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+      {
+	cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+	return;
+      }
+  gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+	     struct __processor_model2 *cpu_model2,
+	     unsigned int *cpu_features2)
+{
+  const char *cpu = NULL;
+  unsigned int family = cpu_model2->__cpu_family;
+  unsigned int model = cpu_model2->__cpu_model;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_AVX2))
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XSAVEOPT))
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_BMI))
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XOP))
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLWB))
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLZERO))
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       struct __processor_model2 *cpu_model2,
+	       unsigned int *cpu_features2,
+	       unsigned int brand_id)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+    return cpu;
+
+  switch (cpu_model2->__cpu_model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_cpu_feature (cpu_model, cpu_features2,
+			   FEATURE_AVX512VNNI))
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one.  */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+			struct __processor_model2 *cpu_model2,
+			unsigned int *cpu_features2,
+			unsigned int ecx, unsigned int edx)
+{
+  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+  unsigned int eax, ebx;
+  unsigned int ext_level;
+
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+#define XSTATE_FP			0x1
+#define XSTATE_SSE			0x2
+#define XSTATE_YMM			0x4
+#define XSTATE_OPMASK			0x20
+#define XSTATE_ZMM			0x40
+#define XSTATE_HI_ZMM			0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      __asm__ (".byte 0x0f, 0x01, 0xd0"
+	       : "=a" (xcrlow), "=d" (xcrhigh)
+	       : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+	{
+	  avx_usable = 1;
+	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+			   == XCR_AVX512F_ENABLED_MASK);
+	}
+    }
+
+#define set_feature(f) \
+  set_cpu_feature (cpu_model, cpu_features2, f)
+
+  if (edx & bit_CMOV)
+    set_feature (FEATURE_CMOV);
+  if (edx & bit_MMX)
+    set_feature (FEATURE_MMX);
+  if (edx & bit_SSE)
+    set_feature (FEATURE_SSE);
+  if (edx & bit_SSE2)
+    set_feature (FEATURE_SSE2);
+  if (edx & bit_CMPXCHG8B)
+    set_feature (FEATURE_CMPXCHG8B);
+  if (edx & bit_FXSAVE)
+    set_feature (FEATURE_FXSAVE);
+
+  if (ecx & bit_POPCNT)
+    set_feature (FEATURE_POPCNT);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_PCLMUL)
+    set_feature (FEATURE_PCLMUL);
+  if (ecx & bit_SSE3)
+    set_feature (FEATURE_SSE3);
+  if (ecx & bit_SSSE3)
+    set_feature (FEATURE_SSSE3);
+  if (ecx & bit_SSE4_1)
+    set_feature (FEATURE_SSE4_1);
+  if (ecx & bit_SSE4_2)
+    set_feature (FEATURE_SSE4_2);
+  if (ecx & bit_OSXSAVE)
+    set_feature (FEATURE_OSXSAVE);
+  if (ecx & bit_CMPXCHG16B)
+    set_feature (FEATURE_CMPXCHG16B);
+  if (ecx & bit_MOVBE)
+    set_feature (FEATURE_MOVBE);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_F16C)
+    set_feature (FEATURE_F16C);
+  if (ecx & bit_RDRND)
+    set_feature (FEATURE_RDRND);
+  if (ecx & bit_XSAVE)
+    set_feature (FEATURE_XSAVE);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+	set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+	set_feature (FEATURE_FMA);
+    }
+
+  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+  if (max_cpuid_level >= 7)
+    {
+      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_BMI)
+	set_feature (FEATURE_BMI);
+      if (ebx & bit_SGX)
+	set_feature (FEATURE_SGX);
+      if (ebx & bit_HLE)
+	set_feature (FEATURE_HLE);
+      if (ebx & bit_RTM)
+	set_feature (FEATURE_RTM);
+      if (avx_usable)
+	{
+	  if (ebx & bit_AVX2)
+	    set_feature (FEATURE_AVX2);
+	  if (ecx & bit_VPCLMULQDQ)
+	    set_feature (FEATURE_VPCLMULQDQ);
+	}
+      if (ebx & bit_BMI2)
+	set_feature (FEATURE_BMI2);
+      if (ebx & bit_FSGSBASE)
+	set_feature (FEATURE_FSGSBASE);
+      if (ebx & bit_RDSEED)
+	set_feature (FEATURE_RDSEED);
+      if (ebx & bit_ADX)
+	set_feature (FEATURE_ADX);
+      if (ebx & bit_SHA)
+	set_feature (FEATURE_SHA);
+      if (ebx & bit_CLFLUSHOPT)
+	set_feature (FEATURE_CLFLUSHOPT);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
+      if (ecx & bit_PREFETCHWT1)
+	set_feature (FEATURE_PREFETCHWT1);
+      if (ecx & bit_OSPKE)
+	set_feature (FEATURE_OSPKE);
+      if (ecx & bit_RDPID)
+	set_feature (FEATURE_RDPID);
+      if (ecx & bit_VAES)
+	set_feature (FEATURE_VAES);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ecx & bit_MOVDIRI)
+	set_feature (FEATURE_MOVDIRI);
+      if (ecx & bit_MOVDIR64B)
+	set_feature (FEATURE_MOVDIR64B);
+      if (ecx & bit_ENQCMD)
+	set_feature (FEATURE_ENQCMD);
+      if (ecx & bit_CLDEMOTE)
+	set_feature (FEATURE_CLDEMOTE);
+      if (ecx & bit_WAITPKG)
+	set_feature (FEATURE_WAITPKG);
+      if (ecx & bit_SHSTK)
+	set_feature (FEATURE_SHSTK);
+      if (edx & bit_SERIALIZE)
+	set_feature (FEATURE_SERIALIZE);
+      if (edx & bit_TSXLDTRK)
+	set_feature (FEATURE_TSXLDTRK);
+      if (edx & bit_PCONFIG)
+	set_feature (FEATURE_PCONFIG);
+      if (edx & bit_IBT)
+	set_feature (FEATURE_IBT);
+      if (avx512_usable)
+	{
+	  if (ebx & bit_AVX512F)
+	    set_feature (FEATURE_AVX512F);
+	  if (ebx & bit_AVX512VL)
+	    set_feature (FEATURE_AVX512VL);
+	  if (ebx & bit_AVX512BW)
+	    set_feature (FEATURE_AVX512BW);
+	  if (ebx & bit_AVX512DQ)
+	    set_feature (FEATURE_AVX512DQ);
+	  if (ebx & bit_AVX512CD)
+	    set_feature (FEATURE_AVX512CD);
+	  if (ebx & bit_AVX512PF)
+	    set_feature (FEATURE_AVX512PF);
+	  if (ebx & bit_AVX512ER)
+	    set_feature (FEATURE_AVX512ER);
+	  if (ebx & bit_AVX512IFMA)
+	    set_feature (FEATURE_AVX512IFMA);
+	  if (ecx & bit_AVX512VBMI)
+	    set_feature (FEATURE_AVX512VBMI);
+	  if (ecx & bit_AVX512VBMI2)
+	    set_feature (FEATURE_AVX512VBMI2);
+	  if (ecx & bit_AVX512VNNI)
+	    set_feature (FEATURE_AVX512VNNI);
+	  if (ecx & bit_AVX512BITALG)
+	    set_feature (FEATURE_AVX512BITALG);
+	  if (ecx & bit_AVX512VPOPCNTDQ)
+	    set_feature (FEATURE_AVX512VPOPCNTDQ);
+	  if (edx & bit_AVX5124VNNIW)
+	    set_feature (FEATURE_AVX5124VNNIW);
+	  if (edx & bit_AVX5124FMAPS)
+	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
+
+	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+	  if (eax & bit_AVX512BF16)
+	    set_feature (FEATURE_AVX512BF16);
+	}
+    }
+
+  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+  if (max_cpuid_level >= 0xd)
+    {
+      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+      if (eax & bit_XSAVEC)
+	set_feature (FEATURE_XSAVEC);
+      if (eax & bit_XSAVES)
+	set_feature (FEATURE_XSAVES);
+    }
+
+  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+  if (max_cpuid_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_PTWRITE)
+	set_feature (FEATURE_PTWRITE);
+    }
+
+  /* Check cpuid level of extended features.  */
+  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+  cpu_model2->__cpu_ext_level = ext_level;
+
+  if (ext_level >= 0x80000001)
+    {
+      __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+      if (ecx & bit_SSE4a)
+	set_feature (FEATURE_SSE4_A);
+      if (ecx & bit_LAHF_LM)
+	set_feature (FEATURE_LAHF_LM);
+      if (ecx & bit_ABM)
+	set_feature (FEATURE_ABM);
+      if (ecx & bit_LWP)
+	set_feature (FEATURE_LWP);
+      if (ecx & bit_TBM)
+	set_feature (FEATURE_TBM);
+      if (ecx & bit_LZCNT)
+	set_feature (FEATURE_LZCNT);
+      if (ecx & bit_PRFCHW)
+	set_feature (FEATURE_PRFCHW);
+      if (ecx & bit_MWAITX)
+	set_feature (FEATURE_MWAITX);
+
+      if (edx & bit_LM)
+	set_feature (FEATURE_LM);
+      if (edx & bit_3DNOWP)
+	set_feature (FEATURE_3DNOWP);
+      if (edx & bit_3DNOW)
+	set_feature (FEATURE_3DNOW);
+
+      if (avx_usable)
+	{
+	  if (ecx & bit_FMA4)
+	    set_feature (FEATURE_FMA4);
+	  if (ecx & bit_XOP)
+	    set_feature (FEATURE_XOP);
+	}
+    }
+
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+      if (ebx & bit_WBNOINVD)
+	set_feature (FEATURE_WBNOINVD);
+    }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+		    struct __processor_model2 *cpu_model2,
+		    unsigned int *cpu_features2)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  int max_level;
+  unsigned int vendor;
+  unsigned int model, family, brand_id;
+  unsigned int extended_model, extended_family;
+
+  /* This function needs to run just once.  */
+  if (cpu_model->__cpu_vendor)
+    return 0;
+
+  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  vendor = ebx;
+  max_level = eax;
+
+  if (max_level < 1)
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  cpu_model2->__cpu_max_level = max_level;
+
+  model = (eax >> 4) & 0x0f;
+  family = (eax >> 8) & 0x0f;
+  brand_id = ebx & 0xff;
+  extended_model = (eax >> 12) & 0xf0;
+  extended_family = (eax >> 20) & 0xff;
+
+  if (vendor == signature_INTEL_ebx)
+    {
+      /* Adjust model and family for Intel CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+      else if (family == 0x06)
+	model += extended_model;
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+      cpu_model->__cpu_vendor = VENDOR_INTEL;
+    }
+  else if (vendor == signature_AMD_ebx)
+    {
+      /* Adjust model and family for AMD CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+      cpu_model->__cpu_vendor = VENDOR_AMD;
+    }
+  else if (vendor == signature_CENTAUR_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+  else if (vendor == signature_CYRIX_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CYRIX;
+  else if (vendor == signature_NSC_ebx)
+    cpu_model->__cpu_vendor = VENDOR_NSC;
+  else
+    cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+  return 0;
+}
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 3a816400729..a686e3bb712 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -28,6 +28,7 @@ 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"
 
 struct cache_desc
 {
@@ -388,7 +389,7 @@ 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;
 
@@ -399,41 +400,40 @@ const char *host_detect_local_cpu (int argc, const char **argv)
   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;
+  unsigned int has_lahf_lm, has_sse4a;
+  unsigned int has_longmode, has_3dnowp, has_3dnow;
+  unsigned int has_movbe, has_sse4_1, has_sse4_2;
+  unsigned int has_popcnt, has_aes, has_avx, has_avx2;
+  unsigned int has_pclmul, has_abm, has_lwp;
+  unsigned int has_fma, has_fma4, has_xop;
+  unsigned int has_bmi, has_bmi2, has_tbm, has_lzcnt;
+  unsigned int has_hle, has_rtm, has_sgx;
+  unsigned int has_pconfig, has_wbnoinvd;
+  unsigned int has_rdrnd, has_f16c, has_fsgsbase;
+  unsigned int has_rdseed, has_prfchw, has_adx;
+  unsigned int has_fxsr, has_xsave, has_xsaveopt;
+  unsigned int has_avx512er, has_avx512pf, has_avx512cd;
+  unsigned int has_avx512f, has_sha, has_prefetchwt1;
+  unsigned int has_clflushopt, has_xsavec, has_xsaves;
+  unsigned int has_avx512dq, has_avx512bw, has_avx512vl;
+  unsigned int has_avx512vbmi, has_avx512ifma, has_clwb;
+  unsigned int has_mwaitx, has_clzero, has_pku, has_rdpid;
+  unsigned int has_avx5124fmaps, has_avx5124vnniw;
+  unsigned int has_gfni, has_avx512vbmi2;
+  unsigned int has_avx512bitalg;
+  unsigned int has_avx512vpopcntdq;
+  unsigned int has_shstk;
+  unsigned int has_avx512vnni, has_vaes;
+  unsigned int has_vpclmulqdq;
+  unsigned int has_avx512vp2intersect;
+  unsigned int has_movdiri, has_movdir64b;
+  unsigned int has_enqcmd;
+  unsigned int has_waitpkg;
+  unsigned int has_cldemote;
+  unsigned int has_avx512bf16;
+  unsigned int has_serialize;
+  unsigned int has_tsxldtrk;
+  unsigned int has_ptwrite;
 
   bool arch;
 
@@ -447,210 +447,114 @@ 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;
-    }
+  struct __processor_model cpu_model = { };
+  struct __processor_model2 cpu_model2 = { };
+  unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { };
 
-  /* 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;
+  if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0)
+    goto done;
 
-  /* 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;
-    }
+  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;
 
-  /* 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;
-    }
+  /* Extended features */
+#define has_feature(f) \
+  has_cpu_feature (&cpu_model, cpu_features2, f)
+  has_cmov = has_feature (FEATURE_CMOV);
+  has_mmx = has_feature (FEATURE_MMX);
+  has_popcnt = has_feature (FEATURE_POPCNT);
+  has_sse = has_feature (FEATURE_SSE);
+  has_sse2 = has_feature (FEATURE_SSE2);
+  has_sse3 = has_feature (FEATURE_SSE3);
+  has_ssse3 = has_feature (FEATURE_SSSE3);
+  has_sse4_1 = has_feature (FEATURE_SSE4_1);
+  has_sse4_2 = has_feature (FEATURE_SSE4_2);
+  has_avx = has_feature (FEATURE_AVX);
+  has_avx2 = has_feature (FEATURE_AVX2);
+  has_sse4a = has_feature (FEATURE_SSE4_A);
+  has_fma4 = has_feature (FEATURE_FMA4);
+  has_xop = has_feature (FEATURE_XOP);
+  has_fma = has_feature (FEATURE_FMA);
+  has_avx512f = has_feature (FEATURE_AVX512F);
+  has_bmi = has_feature (FEATURE_BMI);
+  has_bmi2 = has_feature (FEATURE_BMI2);
+  has_aes = has_feature (FEATURE_AES);
+  has_pclmul = has_feature (FEATURE_PCLMUL);
+  has_avx512vl = has_feature (FEATURE_AVX512VL);
+  has_avx512bw = has_feature (FEATURE_AVX512BW);
+  has_avx512dq = has_feature (FEATURE_AVX512DQ);
+  has_avx512cd = has_feature (FEATURE_AVX512CD);
+  has_avx512er = has_feature (FEATURE_AVX512ER);
+  has_avx512pf = has_feature (FEATURE_AVX512PF);
+  has_avx512vbmi = has_feature (FEATURE_AVX512VBMI);
+  has_avx512ifma = has_feature (FEATURE_AVX512IFMA);
+  has_avx5124vnniw = has_feature (FEATURE_AVX5124VNNIW);
+  has_avx5124fmaps = has_feature (FEATURE_AVX5124FMAPS);
+  has_avx512vpopcntdq = has_feature (FEATURE_AVX512VPOPCNTDQ);
+  has_avx512vbmi2 = has_feature (FEATURE_AVX512VBMI2);
+  has_gfni = has_feature (FEATURE_GFNI);
+  has_vpclmulqdq = has_feature (FEATURE_VPCLMULQDQ);
+  has_avx512vnni = has_feature (FEATURE_AVX512VNNI);
+  has_avx512bitalg = has_feature (FEATURE_AVX512BITALG);
+  has_avx512bf16 = has_feature (FEATURE_AVX512BF16);
+  has_avx512vp2intersect = has_feature (FEATURE_AVX512VP2INTERSECT);
+  has_3dnow = has_feature (FEATURE_3DNOW);
+  has_3dnowp = has_feature (FEATURE_3DNOWP);
+  has_adx = has_feature (FEATURE_ADX);
+  has_abm = has_feature (FEATURE_ABM);
+  has_cldemote = has_feature (FEATURE_CLDEMOTE);
+  has_clflushopt = has_feature (FEATURE_CLFLUSHOPT);
+  has_clwb = has_feature (FEATURE_CLWB);
+  has_clzero = has_feature (FEATURE_CLZERO);
+  has_cmpxchg16b = has_feature (FEATURE_CMPXCHG16B);
+  has_cmpxchg8b = has_feature (FEATURE_CMPXCHG8B);
+  has_enqcmd = has_feature (FEATURE_ENQCMD);
+  has_f16c = has_feature (FEATURE_F16C);
+  has_fsgsbase = has_feature (FEATURE_FSGSBASE);
+  has_fxsr = has_feature (FEATURE_FXSAVE);
+  has_hle = has_feature (FEATURE_HLE);
+  has_lahf_lm = has_feature (FEATURE_LAHF_LM);
+  has_longmode = has_feature (FEATURE_LM);
+  has_lwp = has_feature (FEATURE_LWP);
+  has_lzcnt = has_feature (FEATURE_LZCNT);
+  has_movbe = has_feature (FEATURE_MOVBE);
+  has_movdir64b = has_feature (FEATURE_MOVDIR64B);
+  has_movdiri = has_feature (FEATURE_MOVDIRI);
+  has_mwaitx = has_feature (FEATURE_MWAITX);
+  has_pconfig = has_feature (FEATURE_PCONFIG);
+  has_pku = has_feature (FEATURE_PKU);
+  has_prefetchwt1 = has_feature (FEATURE_PREFETCHWT1);
+  has_prfchw = has_feature (FEATURE_PRFCHW);
+  has_ptwrite = has_feature (FEATURE_PTWRITE);
+  has_rdpid = has_feature (FEATURE_RDPID);
+  has_rdrnd = has_feature (FEATURE_RDRND);
+  has_rdseed = has_feature (FEATURE_RDSEED);
+  has_rtm = has_feature (FEATURE_RTM);
+  has_serialize = has_feature (FEATURE_SERIALIZE);
+  has_sgx = has_feature (FEATURE_SGX);
+  has_sha = has_feature (FEATURE_SHA);
+  has_shstk = has_feature (FEATURE_SHSTK);
+  has_tbm = has_feature (FEATURE_TBM);
+  has_tsxldtrk = has_feature (FEATURE_TSXLDTRK);
+  has_vaes = has_feature (FEATURE_VAES);
+  has_waitpkg = has_feature (FEATURE_WAITPKG);
+  has_wbnoinvd = has_feature (FEATURE_WBNOINVD);
+  has_xsave = has_feature (FEATURE_XSAVE);
+  has_xsavec = has_feature (FEATURE_XSAVEC);
+  has_xsaveopt = has_feature (FEATURE_XSAVEOPT);
+  has_xsaves = has_feature (FEATURE_XSAVES);
 
   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 +562,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	}
     }
 
-  if (vendor == signature_AMD_ebx)
+  if (vendor == VENDOR_AMD)
     {
       unsigned int name;
 
@@ -668,36 +572,22 @@ 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_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;
+	}
     }
-  else if (vendor == signature_CENTAUR_ebx)
+  else if (vendor == VENDOR_CENTAUR)
     {
       processor = PROCESSOR_GENERIC;
 
@@ -749,7 +639,7 @@ 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";
@@ -769,145 +659,23 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	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";
+		{
+		  /* 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";
 		/* Assume Ice Lake.  */
 		else if (has_avx512bitalg)
 		  cpu = "icelake-client";
@@ -970,7 +738,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 		cpu = "x86-64";
 	      else if (has_sse3)
 		{
-		  if (vendor == signature_CENTAUR_ebx)
+		  if (vendor == VENDOR_CENTAUR)
 		    /* C7 / Eden "Esther" */
 		    cpu = "c7";
 		  else
@@ -982,7 +750,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 		cpu = "pentium-m";
 	      else if (has_sse)
 		{
-		  if (vendor == signature_CENTAUR_ebx)
+		  if (vendor == VENDOR_CENTAUR)
 		    {
 		      if (model >= 9)
 			/* Eden "Nehemiah" */
@@ -1004,7 +772,6 @@ 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:
@@ -1036,7 +803,7 @@ 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)
 		/* Nano 3000 | Nano dual / quad core | Eden X4 */
@@ -1060,33 +827,6 @@ 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.  */
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index be3ed0158f2..41c4a8780e9 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/cpuinfo-builtins.h"
 
 #undef BDESC
 #undef BDESC_FIRST
@@ -1872,147 +1873,66 @@ enum feature_priority
   P_PROC_AVX512F
 };
 
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512BF16,
-  F_AVX512VP2INTERSECT,
-  F_MAX
-};
-
-/* These are the values for vendor types and cpu types  and subtypes
-   in cpuinfo.c.  Cpu types and subtypes should be subtracted by
-   the corresponding start value.  */
-enum processor_model
-{
-  M_INTEL = 1,
-  M_AMD,
-  M_CPU_TYPE_START,
-  M_INTEL_BONNELL,
-  M_INTEL_CORE2,
-  M_INTEL_COREI7,
-  M_AMDFAM10H,
-  M_AMDFAM15H,
-  M_INTEL_SILVERMONT,
-  M_INTEL_KNL,
-  M_AMD_BTVER1,
-  M_AMD_BTVER2,
-  M_AMDFAM17H,
-  M_INTEL_KNM,
-  M_INTEL_GOLDMONT,
-  M_INTEL_GOLDMONT_PLUS,
-  M_INTEL_TREMONT,
-  M_CPU_SUBTYPE_START,
-  M_INTEL_COREI7_NEHALEM,
-  M_INTEL_COREI7_WESTMERE,
-  M_INTEL_COREI7_SANDYBRIDGE,
-  M_AMDFAM10H_BARCELONA,
-  M_AMDFAM10H_SHANGHAI,
-  M_AMDFAM10H_ISTANBUL,
-  M_AMDFAM15H_BDVER1,
-  M_AMDFAM15H_BDVER2,
-  M_AMDFAM15H_BDVER3,
-  M_AMDFAM15H_BDVER4,
-  M_AMDFAM17H_ZNVER1,
-  M_INTEL_COREI7_IVYBRIDGE,
-  M_INTEL_COREI7_HASWELL,
-  M_INTEL_COREI7_BROADWELL,
-  M_INTEL_COREI7_SKYLAKE,
-  M_INTEL_COREI7_SKYLAKE_AVX512,
-  M_INTEL_COREI7_CANNONLAKE,
-  M_INTEL_COREI7_ICELAKE_CLIENT,
-  M_INTEL_COREI7_ICELAKE_SERVER,
-  M_AMDFAM17H_ZNVER2,
-  M_INTEL_COREI7_CASCADELAKE,
-  M_INTEL_COREI7_TIGERLAKE,
-  M_INTEL_COREI7_COOPERLAKE
-};
-
 struct _arch_names_table
 {
   const char *const name;
-  const enum processor_model model;
+  const int model;
 };
 
+/* These are the values for vendor types, cpu types and subtypes in
+   cpuinfo.h.  Cpu types and subtypes should be subtracted by the
+   corresponding start value.  */
+
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+  (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
+
 static const _arch_names_table arch_names_table[] =
 {
-  {"amd", M_AMD},
-  {"intel", M_INTEL},
-  {"atom", M_INTEL_BONNELL},
-  {"slm", M_INTEL_SILVERMONT},
-  {"core2", M_INTEL_CORE2},
-  {"corei7", M_INTEL_COREI7},
-  {"nehalem", M_INTEL_COREI7_NEHALEM},
-  {"westmere", M_INTEL_COREI7_WESTMERE},
-  {"sandybridge", M_INTEL_COREI7_SANDYBRIDGE},
-  {"ivybridge", M_INTEL_COREI7_IVYBRIDGE},
-  {"haswell", M_INTEL_COREI7_HASWELL},
-  {"broadwell", M_INTEL_COREI7_BROADWELL},
-  {"skylake", M_INTEL_COREI7_SKYLAKE},
-  {"skylake-avx512", M_INTEL_COREI7_SKYLAKE_AVX512},
-  {"cannonlake", M_INTEL_COREI7_CANNONLAKE},
-  {"icelake-client", M_INTEL_COREI7_ICELAKE_CLIENT},
-  {"icelake-server", M_INTEL_COREI7_ICELAKE_SERVER},
-  {"cascadelake", M_INTEL_COREI7_CASCADELAKE},
-  {"tigerlake", M_INTEL_COREI7_TIGERLAKE},
-  {"cooperlake", M_INTEL_COREI7_COOPERLAKE},
-  {"bonnell", M_INTEL_BONNELL},
-  {"silvermont", M_INTEL_SILVERMONT},
-  {"goldmont", M_INTEL_GOLDMONT},
-  {"goldmont-plus", M_INTEL_GOLDMONT_PLUS},
-  {"tremont", M_INTEL_TREMONT},
-  {"knl", M_INTEL_KNL},
-  {"knm", M_INTEL_KNM},
-  {"amdfam10h", M_AMDFAM10H},
-  {"barcelona", M_AMDFAM10H_BARCELONA},
-  {"shanghai", M_AMDFAM10H_SHANGHAI},
-  {"istanbul", M_AMDFAM10H_ISTANBUL},
-  {"btver1", M_AMD_BTVER1},
-  {"amdfam15h", M_AMDFAM15H},
-  {"bdver1", M_AMDFAM15H_BDVER1},
-  {"bdver2", M_AMDFAM15H_BDVER2},
-  {"bdver3", M_AMDFAM15H_BDVER3},
-  {"bdver4", M_AMDFAM15H_BDVER4},
-  {"btver2", M_AMD_BTVER2},
-  {"amdfam17h", M_AMDFAM17H},
-  {"znver1", M_AMDFAM17H_ZNVER1},
-  {"znver2", M_AMDFAM17H_ZNVER2},
+  {"amd", M_VENDOR (VENDOR_AMD)},
+  {"intel", M_VENDOR (VENDOR_INTEL)},
+  {"atom", M_CPU_TYPE (INTEL_BONNELL)},
+  {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"core2", M_CPU_TYPE (INTEL_CORE2)},
+  {"corei7", M_CPU_TYPE (INTEL_COREI7)},
+  {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
+  {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
+  {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
+  {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
+  {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
+  {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
+  {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
+  {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
+  {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
+  {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
+  {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
+  {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
+  {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
+  {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
+  {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
+  {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
+  {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
+  {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
+  {"knl", M_CPU_TYPE (INTEL_KNL)},
+  {"knm", M_CPU_TYPE (INTEL_KNM)},
+  {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
+  {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
+  {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
+  {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
+  {"btver1", M_CPU_TYPE (AMD_BTVER1)},
+  {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
+  {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
+  {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
+  {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
+  {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
+  {"btver2", M_CPU_TYPE (AMD_BTVER2)},
+  {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
+  {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
+  {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
 };
 
 /* These are the target attribute strings for which a dispatcher is
@@ -2026,44 +1946,92 @@ struct _isa_names_table
 
 static const _isa_names_table isa_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_ZERO},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_ZERO},
-  {"avx512bw",F_AVX512BW, P_ZERO},
-  {"avx512dq",F_AVX512DQ, P_ZERO},
-  {"avx512cd",F_AVX512CD, P_ZERO},
-  {"avx512er",F_AVX512ER, P_ZERO},
-  {"avx512pf",F_AVX512PF, P_ZERO},
-  {"avx512vbmi",F_AVX512VBMI, P_ZERO},
-  {"avx512ifma",F_AVX512IFMA, P_ZERO},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_ZERO},
-  {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
-  {"gfni",	F_GFNI,	P_ZERO},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
-  {"avx512vnni", F_AVX512VNNI, P_ZERO},
-  {"avx512bitalg", F_AVX512BITALG, P_ZERO},
-  {"avx512bf16", F_AVX512BF16, P_ZERO},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO}
+  {"cmov",    FEATURE_CMOV,	P_ZERO},
+  {"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_ZERO},
+  {"avx512bw",FEATURE_AVX512BW, P_ZERO},
+  {"avx512dq",FEATURE_AVX512DQ, P_ZERO},
+  {"avx512cd",FEATURE_AVX512CD, P_ZERO},
+  {"avx512er",FEATURE_AVX512ER, P_ZERO},
+  {"avx512pf",FEATURE_AVX512PF, P_ZERO},
+  {"avx512vbmi",FEATURE_AVX512VBMI, P_ZERO},
+  {"avx512ifma",FEATURE_AVX512IFMA, P_ZERO},
+  {"avx5124vnniw",FEATURE_AVX5124VNNIW, P_ZERO},
+  {"avx5124fmaps",FEATURE_AVX5124FMAPS, P_ZERO},
+  {"avx512vpopcntdq",FEATURE_AVX512VPOPCNTDQ,	P_ZERO},
+  {"avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO},
+  {"gfni",	FEATURE_GFNI,	P_ZERO},
+  {"vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO},
+  {"avx512vnni", FEATURE_AVX512VNNI, P_ZERO},
+  {"avx512bitalg", FEATURE_AVX512BITALG, P_ZERO},
+  {"avx512bf16", FEATURE_AVX512BF16, P_ZERO},
+  {"avx512vp2intersect",FEATURE_AVX512VP2INTERSECT, P_ZERO},
+  {"3dnow", FEATURE_3DNOW, P_ZERO},
+  {"3dnowp", FEATURE_3DNOWP, P_ZERO},
+  {"adx", FEATURE_ADX, P_ZERO},
+  {"abm", FEATURE_ABM, P_ZERO},
+  {"cldemote", FEATURE_CLDEMOTE, P_ZERO},
+  {"clflushopt", FEATURE_CLFLUSHOPT, P_ZERO},
+  {"clwb", FEATURE_CLWB, P_ZERO},
+  {"clzero", FEATURE_CLZERO, P_ZERO},
+  {"cmpxchg16b", FEATURE_CMPXCHG16B, P_ZERO},
+  {"cmpxchg8b", FEATURE_CMPXCHG8B, P_ZERO},
+  {"enqcmd", FEATURE_ENQCMD, P_ZERO},
+  {"f16c", FEATURE_F16C, P_ZERO},
+  {"fsgsbase", FEATURE_FSGSBASE, P_ZERO},
+  {"fxsave", FEATURE_FXSAVE, P_ZERO},
+  {"hle", FEATURE_HLE, P_ZERO},
+  {"ibt", FEATURE_IBT, P_ZERO},
+  {"lahf_lm", FEATURE_LAHF_LM, P_ZERO},
+  {"lm", FEATURE_LM, P_ZERO},
+  {"lwp", FEATURE_LWP, P_ZERO},
+  {"lzcnt", FEATURE_LZCNT, P_ZERO},
+  {"movbe", FEATURE_MOVBE, P_ZERO},
+  {"movdir64b", FEATURE_MOVDIR64B, P_ZERO},
+  {"movdiri", FEATURE_MOVDIRI, P_ZERO},
+  {"mwaitx", FEATURE_MWAITX, P_ZERO},
+  {"ospke", FEATURE_OSPKE, P_ZERO},
+  {"osxsave", FEATURE_OSXSAVE, P_ZERO},
+  {"pconfig", FEATURE_PCONFIG, P_ZERO},
+  {"pku", FEATURE_PKU, P_ZERO},
+  {"prefetchwt1", FEATURE_PREFETCHWT1, P_ZERO},
+  {"prfchw", FEATURE_PRFCHW, P_ZERO},
+  {"ptwrite", FEATURE_PTWRITE, P_ZERO},
+  {"rdpid", FEATURE_RDPID, P_ZERO},
+  {"rdrnd", FEATURE_RDRND, P_ZERO},
+  {"rdseed", FEATURE_RDSEED, P_ZERO},
+  {"rtm", FEATURE_RTM, P_ZERO},
+  {"serialize", FEATURE_SERIALIZE, P_ZERO},
+  {"sgx", FEATURE_SGX, P_ZERO},
+  {"sha", FEATURE_SHA, P_ZERO},
+  {"shstk", FEATURE_SHSTK, P_ZERO},
+  {"tbm", FEATURE_TBM, P_ZERO},
+  {"tsxldtrk", FEATURE_TSXLDTRK, P_ZERO},
+  {"vaes", FEATURE_VAES, P_ZERO},
+  {"waitpkg", FEATURE_WAITPKG, P_ZERO},
+  {"wbnoinvd", FEATURE_WBNOINVD, P_ZERO},
+  {"xsave", FEATURE_XSAVE, P_ZERO},
+  {"xsavec", FEATURE_XSAVEC, P_ZERO},
+  {"xsaveopt", FEATURE_XSAVEOPT, P_ZERO},
+  {"xsaves", FEATURE_XSAVES, P_ZERO}
 };
 
 /* This parses the attribute arguments to target in DECL and determines
@@ -2509,16 +2477,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
 
       if (isa_names_table[i].feature >= 32)
 	{
-	  tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+	  tree index_type
+	    = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+	  tree type = build_array_type (unsigned_type_node, index_type);
+	  tree __cpu_features2_var = make_var_decl (type,
 						    "__cpu_features2");
 
 	  varpool_node::add (__cpu_features2_var);
-	  field_val = (1U << (isa_names_table[i].feature - 32));
-	  /* Return __cpu_features2 & field_val  */
-	  final = build2 (BIT_AND_EXPR, unsigned_type_node,
-			  __cpu_features2_var,
-			  build_int_cstu (unsigned_type_node, field_val));
-	  return build1 (CONVERT_EXPR, integer_type_node, final);
+	  for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+	    if (isa_names_table[i].feature < (32 + 32 + j * 32))
+	      {
+		field_val = (1U << (isa_names_table[i].feature
+				    - (32 + j * 32)));
+		tree index = size_int (j);
+		array_elt = build4 (ARRAY_REF, unsigned_type_node,
+				    __cpu_features2_var,
+				    index, NULL_TREE, NULL_TREE);
+		/* Return __cpu_features2[index] & field_val  */
+		final = build2 (BIT_AND_EXPR, unsigned_type_node,
+				array_elt,
+				build_int_cstu (unsigned_type_node,
+						field_val));
+		return build1 (CONVERT_EXPR, integer_type_node, final);
+	      }
 	}
 
       field = TYPE_FIELDS (__processor_model_type);
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..95e2318fd8b 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,348 +7,220 @@
 /* { 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/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;
+#define has_feature(f) \
+  has_cpu_feature (cpu_model, cpu_features2, f)
 
-  if (edx & bit_CMOV)
+  if (has_feature (FEATURE_CMOV))
     assert (__builtin_cpu_supports ("cmov"));
-  if (edx & bit_MMX)
+  if (has_feature (FEATURE_MMX))
     assert (__builtin_cpu_supports ("mmx"));
-  if (edx & bit_SSE)
+  if (has_feature (FEATURE_POPCNT))
+    assert (__builtin_cpu_supports ("popcnt"));
+  if (has_feature (FEATURE_SSE))
     assert (__builtin_cpu_supports ("sse"));
-  if (edx & bit_SSE2)
+  if (has_feature (FEATURE_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)
+  if (has_feature (FEATURE_SSE3))
     assert (__builtin_cpu_supports ("sse3"));
-  if (ecx & bit_SSSE3)
+  if (has_feature (FEATURE_SSSE3))
     assert (__builtin_cpu_supports ("ssse3"));
-  if (ecx & bit_SSE4_1)
+  if (has_feature (FEATURE_SSE4_1))
     assert (__builtin_cpu_supports ("sse4.1"));
-  if (ecx & bit_SSE4_2)
+  if (has_feature (FEATURE_SSE4_2))
     assert (__builtin_cpu_supports ("sse4.2"));
-  if (ecx & bit_AVX)
+  if (has_feature (FEATURE_AVX))
     assert (__builtin_cpu_supports ("avx"));
-  if (ecx & bit_FMA)
+  if (has_feature (FEATURE_AVX2))
+    assert (__builtin_cpu_supports ("avx2"));
+  if (has_feature (FEATURE_SSE4_A))
+    assert (__builtin_cpu_supports ("sse4a"));
+  if (has_feature (FEATURE_FMA4))
+    assert (__builtin_cpu_supports ("fma4"));
+  if (has_feature (FEATURE_XOP))
+    assert (__builtin_cpu_supports ("xop"));
+  if (has_feature (FEATURE_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);
+  if (has_feature (FEATURE_AVX512F))
+    assert (__builtin_cpu_supports ("avx512f"));
+  if (has_feature (FEATURE_BMI))
+    assert (__builtin_cpu_supports ("bmi"));
+  if (has_feature (FEATURE_BMI2))
+    assert (__builtin_cpu_supports ("bmi2"));
+  if (has_feature (FEATURE_AES))
+    assert (__builtin_cpu_supports ("aes"));
+  if (has_feature (FEATURE_PCLMUL))
+    assert (__builtin_cpu_supports ("pclmul"));
+  if (has_feature (FEATURE_AVX512VL))
+    assert (__builtin_cpu_supports ("avx512vl"));
+  if (has_feature (FEATURE_AVX512BW))
+    assert (__builtin_cpu_supports ("avx512bw"));
+  if (has_feature (FEATURE_AVX512DQ))
+    assert (__builtin_cpu_supports ("avx512dq"));
+  if (has_feature (FEATURE_AVX512CD))
+    assert (__builtin_cpu_supports ("avx512cd"));
+  if (has_feature (FEATURE_AVX512ER))
+    assert (__builtin_cpu_supports ("avx512er"));
+  if (has_feature (FEATURE_AVX512PF))
+    assert (__builtin_cpu_supports ("avx512pf"));
+  if (has_feature (FEATURE_AVX512VBMI))
+    assert (__builtin_cpu_supports ("avx512vbmi"));
+  if (has_feature (FEATURE_AVX512IFMA))
+    assert (__builtin_cpu_supports ("avx512ifma"));
+  if (has_feature (FEATURE_AVX5124VNNIW))
+    assert (__builtin_cpu_supports ("avx5124vnniw"));
+  if (has_feature (FEATURE_AVX5124FMAPS))
+    assert (__builtin_cpu_supports ("avx5124fmaps"));
+  if (has_feature (FEATURE_AVX512VPOPCNTDQ))
+    assert (__builtin_cpu_supports ("avx512vpopcntdq"));
+  if (has_feature (FEATURE_AVX512VBMI2))
+    assert (__builtin_cpu_supports ("avx512vbmi2"));
+  if (has_feature (FEATURE_GFNI))
+    assert (__builtin_cpu_supports ("gfni"));
+  if (has_feature (FEATURE_VPCLMULQDQ))
+    assert (__builtin_cpu_supports ("vpclmulqdq"));
+  if (has_feature (FEATURE_AVX512VNNI))
+    assert (__builtin_cpu_supports ("avx512vnni"));
+  if (has_feature (FEATURE_AVX512BITALG))
+    assert (__builtin_cpu_supports ("avx512bitalg"));
+  if (has_feature (FEATURE_AVX512BF16))
+    assert (__builtin_cpu_supports ("avx512bf16"));
+  if (has_feature (FEATURE_AVX512VP2INTERSECT))
+    assert (__builtin_cpu_supports ("avx512vp2intersect"));
+  if (has_feature (FEATURE_3DNOW))
+    assert (__builtin_cpu_supports ("3dnow"));
+  if (has_feature (FEATURE_3DNOWP))
+    assert (__builtin_cpu_supports ("3dnowp"));
+  if (has_feature (FEATURE_ADX))
+    assert (__builtin_cpu_supports ("adx"));
+  if (has_feature (FEATURE_ABM))
+    assert (__builtin_cpu_supports ("abm"));
+  if (has_feature (FEATURE_CLDEMOTE))
+    assert (__builtin_cpu_supports ("cldemote"));
+  if (has_feature (FEATURE_CLFLUSHOPT))
+    assert (__builtin_cpu_supports ("clflushopt"));
+  if (has_feature (FEATURE_CLWB))
+    assert (__builtin_cpu_supports ("clwb"));
+  if (has_feature (FEATURE_CLZERO))
+    assert (__builtin_cpu_supports ("clzero"));
+  if (has_feature (FEATURE_CMPXCHG16B))
+    assert (__builtin_cpu_supports ("cmpxchg16b"));
+  if (has_feature (FEATURE_CMPXCHG8B))
+    assert (__builtin_cpu_supports ("cmpxchg8b"));
+  if (has_feature (FEATURE_ENQCMD))
+    assert (__builtin_cpu_supports ("enqcmd"));
+  if (has_feature (FEATURE_F16C))
+    assert (__builtin_cpu_supports ("f16c"));
+  if (has_feature (FEATURE_FSGSBASE))
+    assert (__builtin_cpu_supports ("fsgsbase"));
+  if (has_feature (FEATURE_FXSAVE))
+    assert (__builtin_cpu_supports ("fxsave"));
+  if (has_feature (FEATURE_HLE))
+    assert (__builtin_cpu_supports ("hle"));
+  if (has_feature (FEATURE_IBT))
+    assert (__builtin_cpu_supports ("ibt"));
+  if (has_feature (FEATURE_LAHF_LM))
+    assert (__builtin_cpu_supports ("lahf_lm"));
+  if (has_feature (FEATURE_LM))
+    assert (__builtin_cpu_supports ("lm"));
+  if (has_feature (FEATURE_LWP))
+    assert (__builtin_cpu_supports ("lwp"));
+  if (has_feature (FEATURE_LZCNT))
+    assert (__builtin_cpu_supports ("lzcnt"));
+  if (has_feature (FEATURE_MOVBE))
+    assert (__builtin_cpu_supports ("movbe"));
+  if (has_feature (FEATURE_MOVDIR64B))
+    assert (__builtin_cpu_supports ("movdir64b"));
+  if (has_feature (FEATURE_MOVDIRI))
+    assert (__builtin_cpu_supports ("movdiri"));
+  if (has_feature (FEATURE_MWAITX))
+    assert (__builtin_cpu_supports ("mwaitx"));
+  if (has_feature (FEATURE_OSPKE))
+    assert (__builtin_cpu_supports ("ospke"));
+  if (has_feature (FEATURE_OSXSAVE))
+    assert (__builtin_cpu_supports ("osxsave"));
+  if (has_feature (FEATURE_PCONFIG))
+    assert (__builtin_cpu_supports ("pconfig"));
+  if (has_feature (FEATURE_PKU))
+    assert (__builtin_cpu_supports ("pku"));
+  if (has_feature (FEATURE_PREFETCHWT1))
+    assert (__builtin_cpu_supports ("prefetchwt1"));
+  if (has_feature (FEATURE_PRFCHW))
+    assert (__builtin_cpu_supports ("prfchw"));
+  if (has_feature (FEATURE_PTWRITE))
+    assert (__builtin_cpu_supports ("ptwrite"));
+  if (has_feature (FEATURE_RDPID))
+    assert (__builtin_cpu_supports ("rdpid"));
+  if (has_feature (FEATURE_RDRND))
+    assert (__builtin_cpu_supports ("rdrnd"));
+  if (has_feature (FEATURE_RDSEED))
+    assert (__builtin_cpu_supports ("rdseed"));
+  if (has_feature (FEATURE_RTM))
+    assert (__builtin_cpu_supports ("rtm"));
+  if (has_feature (FEATURE_SERIALIZE))
+    assert (__builtin_cpu_supports ("serialize"));
+  if (has_feature (FEATURE_SGX))
+    assert (__builtin_cpu_supports ("sgx"));
+  if (has_feature (FEATURE_SHA))
+    assert (__builtin_cpu_supports ("sha"));
+  if (has_feature (FEATURE_SHSTK))
+    assert (__builtin_cpu_supports ("shstk"));
+  if (has_feature (FEATURE_TBM))
+    assert (__builtin_cpu_supports ("tbm"));
+  if (has_feature (FEATURE_TSXLDTRK))
+    assert (__builtin_cpu_supports ("tsxldtrk"));
+  if (has_feature (FEATURE_VAES))
+    assert (__builtin_cpu_supports ("vaes"));
+  if (has_feature (FEATURE_WAITPKG))
+    assert (__builtin_cpu_supports ("waitpkg"));
+  if (has_feature (FEATURE_WBNOINVD))
+    assert (__builtin_cpu_supports ("wbnoinvd"));
+  if (has_feature (FEATURE_XSAVE))
+    assert (__builtin_cpu_supports ("xsave"));
+  if (has_feature (FEATURE_XSAVEC))
+    assert (__builtin_cpu_supports ("xsavec"));
+  if (has_feature (FEATURE_XSAVEOPT))
+    assert (__builtin_cpu_supports ("xsaveopt"));
+  if (has_feature (FEATURE_XSAVES))
+    assert (__builtin_cpu_supports ("xsaves"));
 }
 
 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;
+  struct __processor_model cpu_model = { 0 };
+  struct __processor_model2 cpu_model2 = { 0 };
+  unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { 0 };
 
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
+  if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0)
     return 0;
 
-  vendor = ebx;
-  max_level = eax;
+  check_features (&cpu_model, cpu_features2);
 
-  if (max_level < 1)
-    return 0;
-
-  if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
-    return 0;
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
+  switch (cpu_model.__cpu_vendor)
     {
+    case VENDOR_INTEL:
       assert (__builtin_cpu_is ("intel"));
-      /* Adjust family and model for Intel CPUs.  */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-      check_intel_cpu_model (family, model, brand_id);
-      check_features (ecx, edx, max_level);
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
+      get_intel_cpu (&cpu_model, &cpu_model2, cpu_features2, 0);
+      break;
+    case VENDOR_AMD:
       assert (__builtin_cpu_is ("amd"));
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += (extended_model << 4);
-	}
-      check_amd_cpu_model (family, model);
-      check_features (ecx, edx, max_level);
+      get_amd_cpu (&cpu_model, &cpu_model2, cpu_features2);
+      break;
+    default:
+      break;
     }
 
   return 0;
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index cf5f0884bb4..49c5107546f 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +39,14 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
    size of __cpu_model is part of ABI.  So, new features that don't
    fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
-
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
-/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
-   the max possible level of CPUID insn.  */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
-			int max_cpuid_level)
-{
-  unsigned int eax, ebx;
-  unsigned int ext_level;
-
-  unsigned int features = 0;
-  unsigned int features2 = 0;
-
-  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
-#define XCR_XFEATURE_ENABLED_MASK	0x0
-#define XSTATE_FP			0x1
-#define XSTATE_SSE			0x2
-#define XSTATE_YMM			0x4
-#define XSTATE_OPMASK			0x20
-#define XSTATE_ZMM			0x40
-#define XSTATE_HI_ZMM			0x80
-
-#define XCR_AVX_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
-  /* Check if AVX and AVX512 are usable.  */
-  int avx_usable = 0;
-  int avx512_usable = 0;
-  if ((ecx & bit_OSXSAVE))
-    {
-      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
-         ZMM16-ZMM31 states are supported by OSXSAVE.  */
-      unsigned int xcrlow;
-      unsigned int xcrhigh;
-      asm (".byte 0x0f, 0x01, 0xd0"
-	   : "=a" (xcrlow), "=d" (xcrhigh)
-	   : "c" (XCR_XFEATURE_ENABLED_MASK));
-      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
-	{
-	  avx_usable = 1;
-	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
-			   == XCR_AVX512F_ENABLED_MASK);
-	}
-    }
-
-#define set_feature(f) \
-  do						\
-    {						\
-      if (f < 32)				\
-	features |= (1U << (f & 31));		\
-      else					\
-	features2 |= (1U << ((f - 32) & 31));	\
-    }						\
-  while (0)
-
-  if (edx & bit_CMOV)
-    set_feature (FEATURE_CMOV);
-  if (edx & bit_MMX)
-    set_feature (FEATURE_MMX);
-  if (edx & bit_SSE)
-    set_feature (FEATURE_SSE);
-  if (edx & bit_SSE2)
-    set_feature (FEATURE_SSE2);
-  if (ecx & bit_POPCNT)
-    set_feature (FEATURE_POPCNT);
-  if (ecx & bit_AES)
-    set_feature (FEATURE_AES);
-  if (ecx & bit_PCLMUL)
-    set_feature (FEATURE_PCLMUL);
-  if (ecx & bit_SSE3)
-    set_feature (FEATURE_SSE3);
-  if (ecx & bit_SSSE3)
-    set_feature (FEATURE_SSSE3);
-  if (ecx & bit_SSE4_1)
-    set_feature (FEATURE_SSE4_1);
-  if (ecx & bit_SSE4_2)
-    set_feature (FEATURE_SSE4_2);
-  if (avx_usable)
-    {
-      if (ecx & bit_AVX)
-	set_feature (FEATURE_AVX);
-      if (ecx & bit_FMA)
-	set_feature (FEATURE_FMA);
-    }
-
-  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
-  if (max_cpuid_level >= 7)
-    {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
-      if (ebx & bit_BMI)
-	set_feature (FEATURE_BMI);
-      if (avx_usable)
-	{
-	  if (ebx & bit_AVX2)
-	    set_feature (FEATURE_AVX2);
-	  if (ecx & bit_VPCLMULQDQ)
-	    set_feature (FEATURE_VPCLMULQDQ);
-	}
-      if (ebx & bit_BMI2)
-	set_feature (FEATURE_BMI2);
-      if (ecx & bit_GFNI)
-	set_feature (FEATURE_GFNI);
-      if (avx512_usable)
-	{
-	  if (ebx & bit_AVX512F)
-	    set_feature (FEATURE_AVX512F);
-	  if (ebx & bit_AVX512VL)
-	    set_feature (FEATURE_AVX512VL);
-	  if (ebx & bit_AVX512BW)
-	    set_feature (FEATURE_AVX512BW);
-	  if (ebx & bit_AVX512DQ)
-	    set_feature (FEATURE_AVX512DQ);
-	  if (ebx & bit_AVX512CD)
-	    set_feature (FEATURE_AVX512CD);
-	  if (ebx & bit_AVX512PF)
-	    set_feature (FEATURE_AVX512PF);
-	  if (ebx & bit_AVX512ER)
-	    set_feature (FEATURE_AVX512ER);
-	  if (ebx & bit_AVX512IFMA)
-	    set_feature (FEATURE_AVX512IFMA);
-	  if (ecx & bit_AVX512VBMI)
-	    set_feature (FEATURE_AVX512VBMI);
-	  if (ecx & bit_AVX512VBMI2)
-	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_AVX512VNNI)
-	    set_feature (FEATURE_AVX512VNNI);
-	  if (ecx & bit_AVX512BITALG)
-	    set_feature (FEATURE_AVX512BITALG);
-	  if (ecx & bit_AVX512VPOPCNTDQ)
-	    set_feature (FEATURE_AVX512VPOPCNTDQ);
-	  if (edx & bit_AVX5124VNNIW)
-	    set_feature (FEATURE_AVX5124VNNIW);
-	  if (edx & bit_AVX5124FMAPS)
-	    set_feature (FEATURE_AVX5124FMAPS);
-	  if (edx & bit_AVX512VP2INTERSECT)
-	    set_feature (FEATURE_AVX512VP2INTERSECT);
+   in libgcc.a only, preferably hidden.
 
-	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
-	  if (eax & bit_AVX512BF16)
-	    set_feature (FEATURE_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)
-	set_feature (FEATURE_SSE4_A);
-      if (avx_usable)
-	{
-	  if (ecx & bit_FMA4)
-	    set_feature (FEATURE_FMA4);
-	  if (ecx & bit_XOP)
-	    set_feature (FEATURE_XOP);
-	}
-    }
-    
-  __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
-  __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
-}
+   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+   smaller array, it can only access the first few elements.  */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
    the right values.  This needs to run only once.  This constructor is
@@ -429,85 +57,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
 __cpu_indicator_init (void)
 {
-  unsigned int eax, ebx, ecx, edx;
-
-  int max_level;
-  unsigned int vendor;
-  unsigned int model, family, brand_id;
-  unsigned int extended_model, extended_family;
-
-  /* This function needs to run just once.  */
-  if (__cpu_model.__cpu_vendor)
-    return 0;
-
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  vendor = ebx;
-  max_level = eax;
-
-  if (max_level < 1)
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
-    {
-      /* Adjust model and family for Intel CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_INTEL;
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_AMD;
-    }
-  else
-    __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
-  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
-  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
-  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
-  return 0;
+  struct __processor_model2 cpu_model2;
+  return cpu_indicator_init (&__cpu_model, &cpu_model2,
+			     __cpu_features2);
 }
 
 #if defined SHARED && defined USE_ELF_SYMVER
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V3 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-22 14:51                         ` V3 " H.J. Lu
@ 2020-05-25  9:52                           ` Martin Liška
  2020-05-25 17:42                             ` V4 " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Martin Liška @ 2020-05-25  9:52 UTC (permalink / raw)
  To: H.J. Lu, Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law,
	Richard Biener
  Cc: gcc-patches

Hello.

I really welcome the unification patch and I have some comments (ideas):

1)

> +static inline int
> +has_cpu_feature (struct __processor_model *cpu_model,
> +              unsigned int *cpu_features2,
> +              enum processor_features f)
> +{
> +  unsigned int i;
> +  if (f < 32)
> +    return cpu_model->__cpu_features[0] & (1U << (f & 31));
> +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> +    if (f < (32 + 32 + i * 32))
> +    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
> +  gcc_unreachable ();
> +}
> +
> +static inline void
> +set_cpu_feature (struct __processor_model *cpu_model,
> +              unsigned int *cpu_features2,
> +              enum processor_features f)
> +{
> +  unsigned int i;
> +  if (f < 32)
> +    {
> +      cpu_model->__cpu_features[0] |= (1U << (f & 31));
> +      return;
> +    }
> +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> +    if (f < (32 + 32 + i * 32))
> +      {
> +     cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
> +     return;
> +      }
> +  gcc_unreachable ();
> +}

Can you please add comment about the '32 + 32' and '32 + i * 32', it's unclear from the patch.

2) Can we remove all the:

> +  unsigned int has_lahf_lm, has_sse4a;
> +  unsigned int has_longmode, has_3dnowp, has_3dnow;
> +  unsigned int has_movbe, has_sse4_1, has_sse4_2;
> +  unsigned int has_popcnt, has_aes, has_avx, has_avx2;
> +  unsigned int has_pclmul, has_abm, has_lwp;
> +  unsigned int has_fma, has_fma4, has_xop;
> +  unsigned int has_bmi, has_bmi2, has_tbm, has_lzcnt;

...

> +  has_sse4a = has_feature (FEATURE_SSE4_A);
> +  has_fma4 = has_feature (FEATURE_FMA4);
> +  has_xop = has_feature (FEATURE_XOP);
> +  has_fma = has_feature (FEATURE_FMA);

...

   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";
...

       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);

and instead mark flags in 'isa_names_table' that should be used for -match=native option emission.
We know names of the flags, their value (has_feature) and so we can generate that automatically?

3) Similarly we can we do automatically all the:

+  if (has_feature (FEATURE_AVX512VBMI2))
+    assert (__builtin_cpu_supports ("avx512vbmi2"));

We should have both information in 'isa_names_table'.

Thanks,
Martin

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V4 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-25  9:52                           ` Martin Liška
@ 2020-05-25 17:42                             ` H.J. Lu
  2020-05-26  9:30                               ` Martin Liška
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-25 17:42 UTC (permalink / raw)
  To: Martin Liška
  Cc: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law,
	Richard Biener, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3822 bytes --]

On Mon, May 25, 2020 at 2:52 AM Martin Liška <mliska@suse.cz> wrote:
>
> Hello.
>
> I really welcome the unification patch and I have some comments (ideas):
>
> 1)
>
> > +static inline int
> > +has_cpu_feature (struct __processor_model *cpu_model,
> > +              unsigned int *cpu_features2,
> > +              enum processor_features f)
> > +{
> > +  unsigned int i;
> > +  if (f < 32)
> > +    return cpu_model->__cpu_features[0] & (1U << (f & 31));
> > +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> > +    if (f < (32 + 32 + i * 32))
> > +    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
> > +  gcc_unreachable ();
> > +}
> > +
> > +static inline void
> > +set_cpu_feature (struct __processor_model *cpu_model,
> > +              unsigned int *cpu_features2,
> > +              enum processor_features f)
> > +{
> > +  unsigned int i;
> > +  if (f < 32)
> > +    {
> > +      cpu_model->__cpu_features[0] |= (1U << (f & 31));
> > +      return;
> > +    }
> > +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> > +    if (f < (32 + 32 + i * 32))
> > +      {
> > +     cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
> > +     return;
> > +      }
> > +  gcc_unreachable ();
> > +}
>
> Can you please add comment about the '32 + 32' and '32 + i * 32', it's unclear from the patch.

Done.

> 2) Can we remove all the:
>
> > +  unsigned int has_lahf_lm, has_sse4a;
> > +  unsigned int has_longmode, has_3dnowp, has_3dnow;
> > +  unsigned int has_movbe, has_sse4_1, has_sse4_2;
> > +  unsigned int has_popcnt, has_aes, has_avx, has_avx2;
> > +  unsigned int has_pclmul, has_abm, has_lwp;
> > +  unsigned int has_fma, has_fma4, has_xop;
> > +  unsigned int has_bmi, has_bmi2, has_tbm, has_lzcnt;
>
> ...
>
> > +  has_sse4a = has_feature (FEATURE_SSE4_A);
> > +  has_fma4 = has_feature (FEATURE_FMA4);
> > +  has_xop = has_feature (FEATURE_XOP);
> > +  has_fma = has_feature (FEATURE_FMA);
>
> ...
>
>    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";
> ...
>
>        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);
>
> and instead mark flags in 'isa_names_table' that should be used for -match=native option emission.
> We know names of the flags, their value (has_feature) and so we can generate that automatically?

Done.

> 3) Similarly we can we do automatically all the:
>
> +  if (has_feature (FEATURE_AVX512VBMI2))
> +    assert (__builtin_cpu_supports ("avx512vbmi2"));
>
> We should have both information in 'isa_names_table'.
>

Done.

Here is the updated patch.  OK for master?

Thanks,

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 102877 bytes --]

From 481d178dfd97334cf5d0ab0565833524e3579c07 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

Move cpuinfo.h from libgcc to common/config/i386 and move isa_names_table
to common/config/i386 so that get_intel_cpu can be shared by libgcc, GCC
driver and gcc.target/i386/builtin_target.c to detect the specific type
of Intel and AMD CPUs:

1. Use the same enum processor_features in libgcc and x86 backend.
2. Add more processor features to enum processor_features.
3. Use the same isa_names_table in i386-builtins.c, driver-i386.c and
gcc.target/i386/builtin_target.c.
4. Use isa_names_table to generate ISA command-line options.
5. Use isa_names_table to generate __builtin_cpu_supports tests.
6. Add M_VENDOR, M_CPU_TYPE and M_CPU_SUBTYPE in i386-builtins.c to
avoid duplication in.
7. Use cpu_indicator_init, has_cpu_feature, get_amd_cpu and get_intel_cpu
in driver-i386.c and builtin_target.c.

gcc/

	PR target/95259
	* common/config/i386/cpuinfo-builtins.h: Moved from
	libgcc/config/i386/cpuinfo.h.
	(processor_vendor): Add VENDOR_CENTAUR, VENDOR_CYRIX, VENDOR_NSC
	and BUILTIN_VENDOR_MAX.
	(processor_types): Add BUILTIN_CPU_TYPE_MAX.
	(processor_features): Add FEATURE_3DNOW, FEATURE_3DNOWP,
	FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
	FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
	FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
	FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
	FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
	FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
	FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE, FEATURE_PCONFIG,
	FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
	(__processor_model): Moved to cpuinfo.h.
	(__cpu_model): Removed.
	(__cpu_features2): Likewise.
	(SIZE_OF_CPU_FEATURES): New.
	* common/config/i386/cpuinfo.h: Moved from
	libgcc/config/i386/cpuinfo.c.
	(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
	(__processor_model2): New.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(has_cpu_feature): New function.
	(set_cpu_feature): Likewise.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	Use CHECK___builtin_cpu_is.  Return Intel CPU name.
	(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
	Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
	FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
	FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
	FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
	FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
	FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
	FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE,
	FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT and FEATURE_XSAVES
	(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
	Also update cpu_model2.
	* 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.  Replace F_XXX
	with FEATURE_XXX.  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".
	(host_detect_local_cpu): Call cpu_indicator_init to get CPU
	features.  Use has_cpu_feature to detect processor features.
	Call get_amd_cpu to get AMD CPU name.  Call get_intel_cpu to
	get Intel CPU name.  Use isa_names_table to generate ISA
	command-line options.
	* config/i386/i386-builtins.c: Include
	"common/config/i386/cpuinfo.h" and
	"common/config/i386/i386-isas.h".
	(feature_priority): Moved to common/config/i386/i386-isas.h.
	(processor_features): Removed.
	(processor_model): Removed.
	(_arch_names_table): Use "const int" on model.
	(M_CPU_TYPE_START): New.
	(M_CPU_SUBTYPE_START): Likewise.
	(M_VENDOR): Likewise.
	(M_CPU_TYPE): Likewise.
	(M_CPU_SUBTYPE): Likewise.
	(arch_names_table): Replace M_XXX with M_VENDOR, M_CPU_TYPE and
	M_CPU_SUBTYPE.
	(isa_names_table): Moved to common/config/i386/i386-isas.h.
	(fold_builtin_cpu): Change __cpu_features2 to an array.

gcc/testsuite/

	PR target/95259
	* gcc.target/i386/builtin_target.c: Include <stdlib.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.

libgcc/

	PR target/95259
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Changed to array.
	(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_intel_cpu): Likewise.
	(get_available_features): Likewise.
	(__cpu_indicator_init): Call cpu_indicator_init.
	* config/i386/cpuinfo.h: Moved to
	gcc/common/config/i386/cpuinfo-builtins.h.
---
 .../common/config/i386/cpuinfo-builtins.h     |  70 +-
 gcc/common/config/i386/cpuinfo.h              | 845 ++++++++++++++++++
 gcc/common/config/i386/i386-isas.h            | 201 +++++
 gcc/config/i386/driver-i386.c                 | 648 +++-----------
 gcc/config/i386/i386-builtins.c               | 302 ++-----
 .../gcc.target/i386/builtin_target.c          | 354 +-------
 libgcc/config/i386/cpuinfo.c                  | 464 +---------
 7 files changed, 1337 insertions(+), 1547 deletions(-)
 rename libgcc/config/i386/cpuinfo.h => gcc/common/config/i386/cpuinfo-builtins.h (71%)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 create mode 100644 gcc/common/config/i386/i386-isas.h

diff --git a/libgcc/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo-builtins.h
similarity index 71%
rename from libgcc/config/i386/cpuinfo.h
rename to gcc/common/config/i386/cpuinfo-builtins.h
index 0f97510cde1..7a20dcf9ef8 100644
--- a/libgcc/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo-builtins.h
@@ -30,6 +30,10 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
+  BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
 
@@ -45,13 +49,14 @@ enum processor_types
   INTEL_SILVERMONT,
   INTEL_KNL,
   AMD_BTVER1,
-  AMD_BTVER2,  
+  AMD_BTVER2,
   AMDFAM17H,
   INTEL_KNM,
   INTEL_GOLDMONT,
   INTEL_GOLDMONT_PLUS,
   INTEL_TREMONT,
-  CPU_TYPE_MAX
+  CPU_TYPE_MAX,
+  BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
 };
 
 enum processor_subtypes
@@ -123,14 +128,57 @@ enum processor_features
   FEATURE_AVX512VNNI,
   FEATURE_AVX512BITALG,
   FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_3DNOW,
+  FEATURE_3DNOWP,
+  FEATURE_ADX,
+  FEATURE_ABM,
+  FEATURE_CLDEMOTE,
+  FEATURE_CLFLUSHOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO,
+  FEATURE_CMPXCHG16B,
+  FEATURE_CMPXCHG8B,
+  FEATURE_ENQCMD,
+  FEATURE_F16C,
+  FEATURE_FSGSBASE,
+  FEATURE_FXSAVE,
+  FEATURE_HLE,
+  FEATURE_IBT,
+  FEATURE_LAHF_LM,
+  FEATURE_LM,
+  FEATURE_LWP,
+  FEATURE_LZCNT,
+  FEATURE_MOVBE,
+  FEATURE_MOVDIR64B,
+  FEATURE_MOVDIRI,
+  FEATURE_MWAITX,
+  FEATURE_OSPKE,
+  FEATURE_OSXSAVE,
+  FEATURE_PCONFIG,
+  FEATURE_PKU,
+  FEATURE_PREFETCHWT1,
+  FEATURE_PRFCHW,
+  FEATURE_PTWRITE,
+  FEATURE_RDPID,
+  FEATURE_RDRND,
+  FEATURE_RDSEED,
+  FEATURE_RTM,
+  FEATURE_SERIALIZE,
+  FEATURE_SGX,
+  FEATURE_SHA,
+  FEATURE_SHSTK,
+  FEATURE_TBM,
+  FEATURE_TSXLDTRK,
+  FEATURE_VAES,
+  FEATURE_WAITPKG,
+  FEATURE_WBNOINVD,
+  FEATURE_XSAVE,
+  FEATURE_XSAVEC,
+  FEATURE_XSAVEOPT,
+  FEATURE_XSAVES,
+  CPU_FEATURE_MAX
 };
 
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..13f4b0e51e5
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,845 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "cpuinfo-builtins.h"
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  /* The first 32 features are stored as bitmasks in __cpu_features.
+     The rest of features are stored as bitmasks in a separate array
+     of unsigned int.  */
+  unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+  unsigned int __cpu_family;
+  unsigned int __cpu_model;
+  unsigned int __cpu_max_level;
+  unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      return cpu_model->__cpu_features[0] & (1U << (f & 31));
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+  gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+      {
+	cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+	return;
+      }
+  gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+	     struct __processor_model2 *cpu_model2,
+	     unsigned int *cpu_features2)
+{
+  const char *cpu = NULL;
+  unsigned int family = cpu_model2->__cpu_family;
+  unsigned int model = cpu_model2->__cpu_model;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_AVX2))
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XSAVEOPT))
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_BMI))
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XOP))
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLWB))
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLZERO))
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       struct __processor_model2 *cpu_model2,
+	       unsigned int *cpu_features2,
+	       unsigned int brand_id)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+    return cpu;
+
+  switch (cpu_model2->__cpu_model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_cpu_feature (cpu_model, cpu_features2,
+			   FEATURE_AVX512VNNI))
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one.  */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+			struct __processor_model2 *cpu_model2,
+			unsigned int *cpu_features2,
+			unsigned int ecx, unsigned int edx)
+{
+  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+  unsigned int eax, ebx;
+  unsigned int ext_level;
+
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+#define XSTATE_FP			0x1
+#define XSTATE_SSE			0x2
+#define XSTATE_YMM			0x4
+#define XSTATE_OPMASK			0x20
+#define XSTATE_ZMM			0x40
+#define XSTATE_HI_ZMM			0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      __asm__ (".byte 0x0f, 0x01, 0xd0"
+	       : "=a" (xcrlow), "=d" (xcrhigh)
+	       : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+	{
+	  avx_usable = 1;
+	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+			   == XCR_AVX512F_ENABLED_MASK);
+	}
+    }
+
+#define set_feature(f) \
+  set_cpu_feature (cpu_model, cpu_features2, f)
+
+  if (edx & bit_CMOV)
+    set_feature (FEATURE_CMOV);
+  if (edx & bit_MMX)
+    set_feature (FEATURE_MMX);
+  if (edx & bit_SSE)
+    set_feature (FEATURE_SSE);
+  if (edx & bit_SSE2)
+    set_feature (FEATURE_SSE2);
+  if (edx & bit_CMPXCHG8B)
+    set_feature (FEATURE_CMPXCHG8B);
+  if (edx & bit_FXSAVE)
+    set_feature (FEATURE_FXSAVE);
+
+  if (ecx & bit_POPCNT)
+    set_feature (FEATURE_POPCNT);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_PCLMUL)
+    set_feature (FEATURE_PCLMUL);
+  if (ecx & bit_SSE3)
+    set_feature (FEATURE_SSE3);
+  if (ecx & bit_SSSE3)
+    set_feature (FEATURE_SSSE3);
+  if (ecx & bit_SSE4_1)
+    set_feature (FEATURE_SSE4_1);
+  if (ecx & bit_SSE4_2)
+    set_feature (FEATURE_SSE4_2);
+  if (ecx & bit_OSXSAVE)
+    set_feature (FEATURE_OSXSAVE);
+  if (ecx & bit_CMPXCHG16B)
+    set_feature (FEATURE_CMPXCHG16B);
+  if (ecx & bit_MOVBE)
+    set_feature (FEATURE_MOVBE);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_F16C)
+    set_feature (FEATURE_F16C);
+  if (ecx & bit_RDRND)
+    set_feature (FEATURE_RDRND);
+  if (ecx & bit_XSAVE)
+    set_feature (FEATURE_XSAVE);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+	set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+	set_feature (FEATURE_FMA);
+    }
+
+  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+  if (max_cpuid_level >= 7)
+    {
+      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_BMI)
+	set_feature (FEATURE_BMI);
+      if (ebx & bit_SGX)
+	set_feature (FEATURE_SGX);
+      if (ebx & bit_HLE)
+	set_feature (FEATURE_HLE);
+      if (ebx & bit_RTM)
+	set_feature (FEATURE_RTM);
+      if (avx_usable)
+	{
+	  if (ebx & bit_AVX2)
+	    set_feature (FEATURE_AVX2);
+	  if (ecx & bit_VPCLMULQDQ)
+	    set_feature (FEATURE_VPCLMULQDQ);
+	}
+      if (ebx & bit_BMI2)
+	set_feature (FEATURE_BMI2);
+      if (ebx & bit_FSGSBASE)
+	set_feature (FEATURE_FSGSBASE);
+      if (ebx & bit_RDSEED)
+	set_feature (FEATURE_RDSEED);
+      if (ebx & bit_ADX)
+	set_feature (FEATURE_ADX);
+      if (ebx & bit_SHA)
+	set_feature (FEATURE_SHA);
+      if (ebx & bit_CLFLUSHOPT)
+	set_feature (FEATURE_CLFLUSHOPT);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
+      if (ecx & bit_PREFETCHWT1)
+	set_feature (FEATURE_PREFETCHWT1);
+      if (ecx & bit_OSPKE)
+	set_feature (FEATURE_OSPKE);
+      if (ecx & bit_RDPID)
+	set_feature (FEATURE_RDPID);
+      if (ecx & bit_VAES)
+	set_feature (FEATURE_VAES);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ecx & bit_MOVDIRI)
+	set_feature (FEATURE_MOVDIRI);
+      if (ecx & bit_MOVDIR64B)
+	set_feature (FEATURE_MOVDIR64B);
+      if (ecx & bit_ENQCMD)
+	set_feature (FEATURE_ENQCMD);
+      if (ecx & bit_CLDEMOTE)
+	set_feature (FEATURE_CLDEMOTE);
+      if (ecx & bit_WAITPKG)
+	set_feature (FEATURE_WAITPKG);
+      if (ecx & bit_SHSTK)
+	set_feature (FEATURE_SHSTK);
+      if (edx & bit_SERIALIZE)
+	set_feature (FEATURE_SERIALIZE);
+      if (edx & bit_TSXLDTRK)
+	set_feature (FEATURE_TSXLDTRK);
+      if (edx & bit_PCONFIG)
+	set_feature (FEATURE_PCONFIG);
+      if (edx & bit_IBT)
+	set_feature (FEATURE_IBT);
+      if (avx512_usable)
+	{
+	  if (ebx & bit_AVX512F)
+	    set_feature (FEATURE_AVX512F);
+	  if (ebx & bit_AVX512VL)
+	    set_feature (FEATURE_AVX512VL);
+	  if (ebx & bit_AVX512BW)
+	    set_feature (FEATURE_AVX512BW);
+	  if (ebx & bit_AVX512DQ)
+	    set_feature (FEATURE_AVX512DQ);
+	  if (ebx & bit_AVX512CD)
+	    set_feature (FEATURE_AVX512CD);
+	  if (ebx & bit_AVX512PF)
+	    set_feature (FEATURE_AVX512PF);
+	  if (ebx & bit_AVX512ER)
+	    set_feature (FEATURE_AVX512ER);
+	  if (ebx & bit_AVX512IFMA)
+	    set_feature (FEATURE_AVX512IFMA);
+	  if (ecx & bit_AVX512VBMI)
+	    set_feature (FEATURE_AVX512VBMI);
+	  if (ecx & bit_AVX512VBMI2)
+	    set_feature (FEATURE_AVX512VBMI2);
+	  if (ecx & bit_AVX512VNNI)
+	    set_feature (FEATURE_AVX512VNNI);
+	  if (ecx & bit_AVX512BITALG)
+	    set_feature (FEATURE_AVX512BITALG);
+	  if (ecx & bit_AVX512VPOPCNTDQ)
+	    set_feature (FEATURE_AVX512VPOPCNTDQ);
+	  if (edx & bit_AVX5124VNNIW)
+	    set_feature (FEATURE_AVX5124VNNIW);
+	  if (edx & bit_AVX5124FMAPS)
+	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
+
+	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+	  if (eax & bit_AVX512BF16)
+	    set_feature (FEATURE_AVX512BF16);
+	}
+    }
+
+  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+  if (max_cpuid_level >= 0xd)
+    {
+      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+      if (eax & bit_XSAVEC)
+	set_feature (FEATURE_XSAVEC);
+      if (eax & bit_XSAVES)
+	set_feature (FEATURE_XSAVES);
+    }
+
+  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+  if (max_cpuid_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_PTWRITE)
+	set_feature (FEATURE_PTWRITE);
+    }
+
+  /* Check cpuid level of extended features.  */
+  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+  cpu_model2->__cpu_ext_level = ext_level;
+
+  if (ext_level >= 0x80000001)
+    {
+      __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+      if (ecx & bit_SSE4a)
+	set_feature (FEATURE_SSE4_A);
+      if (ecx & bit_LAHF_LM)
+	set_feature (FEATURE_LAHF_LM);
+      if (ecx & bit_ABM)
+	set_feature (FEATURE_ABM);
+      if (ecx & bit_LWP)
+	set_feature (FEATURE_LWP);
+      if (ecx & bit_TBM)
+	set_feature (FEATURE_TBM);
+      if (ecx & bit_LZCNT)
+	set_feature (FEATURE_LZCNT);
+      if (ecx & bit_PRFCHW)
+	set_feature (FEATURE_PRFCHW);
+      if (ecx & bit_MWAITX)
+	set_feature (FEATURE_MWAITX);
+
+      if (edx & bit_LM)
+	set_feature (FEATURE_LM);
+      if (edx & bit_3DNOWP)
+	set_feature (FEATURE_3DNOWP);
+      if (edx & bit_3DNOW)
+	set_feature (FEATURE_3DNOW);
+
+      if (avx_usable)
+	{
+	  if (ecx & bit_FMA4)
+	    set_feature (FEATURE_FMA4);
+	  if (ecx & bit_XOP)
+	    set_feature (FEATURE_XOP);
+	}
+    }
+
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+      if (ebx & bit_WBNOINVD)
+	set_feature (FEATURE_WBNOINVD);
+    }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+		    struct __processor_model2 *cpu_model2,
+		    unsigned int *cpu_features2)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  int max_level;
+  unsigned int vendor;
+  unsigned int model, family, brand_id;
+  unsigned int extended_model, extended_family;
+
+  /* This function needs to run just once.  */
+  if (cpu_model->__cpu_vendor)
+    return 0;
+
+  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  vendor = ebx;
+  max_level = eax;
+
+  if (max_level < 1)
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  cpu_model2->__cpu_max_level = max_level;
+
+  model = (eax >> 4) & 0x0f;
+  family = (eax >> 8) & 0x0f;
+  brand_id = ebx & 0xff;
+  extended_model = (eax >> 12) & 0xf0;
+  extended_family = (eax >> 20) & 0xff;
+
+  if (vendor == signature_INTEL_ebx)
+    {
+      /* Adjust model and family for Intel CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+      else if (family == 0x06)
+	model += extended_model;
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+      cpu_model->__cpu_vendor = VENDOR_INTEL;
+    }
+  else if (vendor == signature_AMD_ebx)
+    {
+      /* Adjust model and family for AMD CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+      cpu_model->__cpu_vendor = VENDOR_AMD;
+    }
+  else if (vendor == signature_CENTAUR_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+  else if (vendor == signature_CYRIX_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CYRIX;
+  else if (vendor == signature_NSC_ebx)
+    cpu_model->__cpu_vendor = VENDOR_NSC;
+  else
+    cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+  return 0;
+}
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
new file mode 100644
index 00000000000..3cde6d4a26d
--- /dev/null
+++ b/gcc/common/config/i386/i386-isas.h
@@ -0,0 +1,201 @@
+/* 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/>.  */
+
+/* Priority of i386 features, greater value is higher priority.   This is
+   used to decide the order in which function dispatch must happen.  For
+   instance, a version specialized for SSE4.2 should be checked for dispatch
+   before a version for SSE3, as SSE4.2 implies SSE3.  */
+enum feature_priority
+{
+  P_ZERO = 0,
+  P_MMX,
+  P_SSE,
+  P_SSE2,
+  P_SSE3,
+  P_SSSE3,
+  P_PROC_SSSE3,
+  P_SSE4_A,
+  P_PROC_SSE4_A,
+  P_SSE4_1,
+  P_SSE4_2,
+  P_PROC_SSE4_2,
+  P_POPCNT,
+  P_AES,
+  P_PCLMUL,
+  P_AVX,
+  P_PROC_AVX,
+  P_BMI,
+  P_PROC_BMI,
+  P_FMA4,
+  P_XOP,
+  P_PROC_XOP,
+  P_FMA,
+  P_PROC_FMA,
+  P_BMI2,
+  P_AVX2,
+  P_PROC_AVX2,
+  P_AVX512F,
+  P_PROC_AVX512F
+};
+
+/* 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_ZERO, 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_ZERO,
+			"-mavx512vl")
+  ISA_NAMES_TABLE_ENTRY("avx512bw", FEATURE_AVX512BW, P_ZERO,
+			"-mavx512bw")
+  ISA_NAMES_TABLE_ENTRY("avx512dq", FEATURE_AVX512DQ, P_ZERO,
+			"-mavx512dq")
+  ISA_NAMES_TABLE_ENTRY("avx512cd", FEATURE_AVX512CD, P_ZERO,
+			"-mavx512cd")
+  ISA_NAMES_TABLE_ENTRY("avx512er", FEATURE_AVX512ER, P_ZERO,
+			"-mavx512er")
+  ISA_NAMES_TABLE_ENTRY("avx512pf", FEATURE_AVX512PF, P_ZERO,
+			"-mavx512pf")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi", FEATURE_AVX512VBMI, P_ZERO,
+			"-mavx512vbmi")
+  ISA_NAMES_TABLE_ENTRY("avx512ifma", FEATURE_AVX512IFMA, P_ZERO,
+			"-mavx512ifma")
+  ISA_NAMES_TABLE_ENTRY("avx5124vnniw", FEATURE_AVX5124VNNIW, P_ZERO,
+			"-mavx5124vnniw")
+  ISA_NAMES_TABLE_ENTRY("avx5124fmaps", FEATURE_AVX5124FMAPS, P_ZERO,
+			"-mavx5124fmaps")
+  ISA_NAMES_TABLE_ENTRY("avx512vpopcntdq", FEATURE_AVX512VPOPCNTDQ,
+			P_ZERO, "-mavx512vpopcntdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO,
+			"-mavx512vbmi2")
+  ISA_NAMES_TABLE_ENTRY("gfni", FEATURE_GFNI, P_ZERO, "-mgfni")
+  ISA_NAMES_TABLE_ENTRY("vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO,
+			"-mvpclmulqdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vnni", FEATURE_AVX512VNNI, P_ZERO,
+			"-mavx512vnni")
+  ISA_NAMES_TABLE_ENTRY("avx512bitalg", FEATURE_AVX512BITALG, P_ZERO,
+			"-mavx512bitalg")
+  ISA_NAMES_TABLE_ENTRY("avx512bf16", FEATURE_AVX512BF16, P_ZERO,
+			"-mavx512bf16")
+  ISA_NAMES_TABLE_ENTRY("avx512vp2intersect", FEATURE_AVX512VP2INTERSECT,
+			P_ZERO, "-mavx512vp2intersect")
+  ISA_NAMES_TABLE_ENTRY("3dnow", FEATURE_3DNOW, P_ZERO, "-m3dnow")
+  ISA_NAMES_TABLE_ENTRY("3dnowp", FEATURE_3DNOWP, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("adx", FEATURE_ADX, P_ZERO, "-madx")
+  ISA_NAMES_TABLE_ENTRY("abm", FEATURE_ABM, P_ZERO, "-mabm")
+  ISA_NAMES_TABLE_ENTRY("cldemote", FEATURE_CLDEMOTE, P_ZERO,
+			"-mcldemote")
+  ISA_NAMES_TABLE_ENTRY("clflushopt", FEATURE_CLFLUSHOPT, P_ZERO,
+			"-mclflushopt")
+  ISA_NAMES_TABLE_ENTRY("clwb", FEATURE_CLWB, P_ZERO, "-mclwb")
+  ISA_NAMES_TABLE_ENTRY("clzero", FEATURE_CLZERO, P_ZERO, "-mclzero")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg16b", FEATURE_CMPXCHG16B, P_ZERO,
+			"-mcx16")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg8b", FEATURE_CMPXCHG8B, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("enqcmd", FEATURE_ENQCMD, P_ZERO, "-menqcmd")
+  ISA_NAMES_TABLE_ENTRY("f16c", FEATURE_F16C, P_ZERO, "-mf16c")
+  ISA_NAMES_TABLE_ENTRY("fsgsbase", FEATURE_FSGSBASE, P_ZERO,
+			"-mfsgsbase")
+  ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
+  ISA_NAMES_TABLE_ENTRY("hle", FEATURE_HLE, P_ZERO, "-mhle")
+  ISA_NAMES_TABLE_ENTRY("ibt", FEATURE_IBT, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lahf_lm", FEATURE_LAHF_LM, P_ZERO, "-msahf")
+  ISA_NAMES_TABLE_ENTRY("lm", FEATURE_LM, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lwp", FEATURE_LWP, P_ZERO, "-mlwp")
+  ISA_NAMES_TABLE_ENTRY("lzcnt", FEATURE_LZCNT, P_ZERO, "-mlzcnt")
+  ISA_NAMES_TABLE_ENTRY("movbe", FEATURE_MOVBE, P_ZERO, "-mmovbe")
+  ISA_NAMES_TABLE_ENTRY("movdir64b", FEATURE_MOVDIR64B, P_ZERO,
+			"-mmovdir64b")
+  ISA_NAMES_TABLE_ENTRY("movdiri", FEATURE_MOVDIRI, P_ZERO, "-mmovdiri")
+  ISA_NAMES_TABLE_ENTRY("mwaitx", FEATURE_MWAITX, P_ZERO, "-mmwaitx")
+  ISA_NAMES_TABLE_ENTRY("ospke", FEATURE_OSPKE, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("osxsave", FEATURE_OSXSAVE, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("pconfig", FEATURE_PCONFIG, P_ZERO, "-mpconfig")
+  ISA_NAMES_TABLE_ENTRY("pku", FEATURE_PKU, P_ZERO, "-mpku")
+  ISA_NAMES_TABLE_ENTRY("prefetchwt1", FEATURE_PREFETCHWT1, P_ZERO,
+			"-mprefetchwt1")
+  ISA_NAMES_TABLE_ENTRY("prfchw", FEATURE_PRFCHW, P_ZERO, "-mprfchw")
+  ISA_NAMES_TABLE_ENTRY("ptwrite", FEATURE_PTWRITE, P_ZERO, "-mptwrite")
+  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
+  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
+  ISA_NAMES_TABLE_ENTRY("rdseed", FEATURE_RDSEED, P_ZERO, "-mrdseed")
+  ISA_NAMES_TABLE_ENTRY("rtm", FEATURE_RTM, P_ZERO, "-mrtm")
+  ISA_NAMES_TABLE_ENTRY("serialize", FEATURE_SERIALIZE, P_ZERO,
+			"-mserialize")
+  ISA_NAMES_TABLE_ENTRY("sgx", FEATURE_SGX, P_ZERO, "-msgx")
+  ISA_NAMES_TABLE_ENTRY("sha", FEATURE_SHA, P_ZERO, "-msha")
+  ISA_NAMES_TABLE_ENTRY("shstk", FEATURE_SHSTK, P_ZERO, "-mshstk")
+  ISA_NAMES_TABLE_ENTRY("tbm", FEATURE_TBM, P_ZERO, "-mtbm")
+  ISA_NAMES_TABLE_ENTRY("tsxldtrk", FEATURE_TSXLDTRK, P_ZERO,
+			"-mtsxldtrk")
+  ISA_NAMES_TABLE_ENTRY("vaes", FEATURE_VAES, P_ZERO, "-mvaes")
+  ISA_NAMES_TABLE_ENTRY("waitpkg", FEATURE_WAITPKG, P_ZERO, "-mwaitpkg")
+  ISA_NAMES_TABLE_ENTRY("wbnoinvd", FEATURE_WBNOINVD, P_ZERO,
+			"-mwbnoinvd")
+  ISA_NAMES_TABLE_ENTRY("xsave", FEATURE_XSAVE, P_ZERO, "-mxsave")
+  ISA_NAMES_TABLE_ENTRY("xsavec", FEATURE_XSAVEC, P_ZERO, "-mxsavec")
+  ISA_NAMES_TABLE_ENTRY("xsaveopt", FEATURE_XSAVEOPT, P_ZERO,
+			"-mxsaveopt")
+  ISA_NAMES_TABLE_ENTRY("xsaves", FEATURE_XSAVES, P_ZERO, "-mxsaves")
+ISA_NAMES_TABLE_END
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 3a816400729..66f5516444e 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,52 +390,42 @@ 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;
+  unsigned int has_longmode;
+  unsigned int has_mmx;
+  unsigned int has_3dnow;
+  unsigned int has_3dnowp;
+  unsigned int has_sse;
+  unsigned int has_sse2;
+  unsigned int has_sse3;
+  unsigned int has_ssse3;
+  unsigned int has_sse4_1;
+  unsigned int has_sse4_2;
+  unsigned int has_avx;
+  unsigned int has_avx2;
+  unsigned int has_avx512f;
+  unsigned int has_avx5124vnniw;
+  unsigned int has_avx512bf16;
+  unsigned int has_avx512bitalg;
+  unsigned int has_avx512er;
+  unsigned int has_avx512vbmi;
+  unsigned int has_avx512vp2intersect;
+  unsigned int has_adx;
+  unsigned int has_clflushopt;
+  unsigned int has_cmov;
+  unsigned int has_cmpxchg8b;
+  unsigned int has_gfni;
+  unsigned int has_movbe;
+  unsigned int has_sgx;
+  unsigned int has_wbnoinvd;
+  unsigned int has_xsave;
 
   bool arch;
 
@@ -447,210 +439,59 @@ 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;
-    }
+  struct __processor_model cpu_model = { };
+  struct __processor_model2 cpu_model2 = { };
+  unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { };
 
-  if (ext_level >= 0x80000008)
-    {
-      __cpuid (0x80000008, eax, ebx, ecx, edx);
-      has_clzero = ebx & bit_CLZERO;
-      has_wbnoinvd = ebx & bit_WBNOINVD;
-    }
+  if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0)
+    goto done;
 
-  /* 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;
+  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;
 
-  /* Check if AVX registers are supported.  */
-  if ((eax & XCR_AVX_ENABLED_MASK) != XCR_AVX_ENABLED_MASK)
-    {
-      has_avx = 0;
-      has_avx2 = 0;
-      has_fma = 0;
-      has_fma4 = 0;
-      has_f16c = 0;
-      has_xop = 0;
-      has_xsave = 0;
-      has_xsaveopt = 0;
-      has_xsaves = 0;
-      has_xsavec = 0;
-    }
-
-  /* Check if AVX512F registers are supported.  */
-  if ((eax & XCR_AVX512F_ENABLED_MASK) != XCR_AVX512F_ENABLED_MASK)
-    {
-      has_avx512f = 0;
-      has_avx512er = 0;
-      has_avx512pf = 0;
-      has_avx512cd = 0;
-      has_avx512dq = 0;
-      has_avx512bw = 0;
-      has_avx512vl = 0;
-    }
+  /* Extended features */
+#define has_feature(f) \
+  has_cpu_feature (&cpu_model, cpu_features2, f)
+  has_longmode = has_feature (FEATURE_LM);
+  has_mmx = has_feature (FEATURE_MMX);
+  has_3dnow = has_feature (FEATURE_3DNOW);
+  has_3dnowp = has_feature (FEATURE_3DNOWP);
+  has_sse = has_feature (FEATURE_SSE);
+  has_sse2 = has_feature (FEATURE_SSE2);
+  has_sse3 = has_feature (FEATURE_SSE3);
+  has_ssse3 = has_feature (FEATURE_SSSE3);
+  has_sse4_1 = has_feature (FEATURE_SSE4_1);
+  has_sse4_2 = has_feature (FEATURE_SSE4_2);
+  has_avx = has_feature (FEATURE_AVX);
+  has_avx2 = has_feature (FEATURE_AVX2);
+  has_avx512f = has_feature (FEATURE_AVX512F);
+  has_avx5124vnniw = has_feature (FEATURE_AVX5124VNNIW);
+  has_avx512bf16 = has_feature (FEATURE_AVX512BF16);
+  has_avx512bitalg = has_feature (FEATURE_AVX512BITALG);
+  has_avx512er = has_feature (FEATURE_AVX512ER);
+  has_avx512vbmi = has_feature (FEATURE_AVX512VBMI);
+  has_avx512vp2intersect = has_feature (FEATURE_AVX512VP2INTERSECT);
+  has_adx = has_feature (FEATURE_ADX);
+  has_clflushopt = has_feature (FEATURE_CLFLUSHOPT);
+  has_cmov = has_feature (FEATURE_CMOV);
+  has_cmpxchg8b = has_feature (FEATURE_CMPXCHG8B);
+  has_gfni = has_feature (FEATURE_GFNI);
+  has_movbe = has_feature (FEATURE_MOVBE);
+  has_sgx = has_feature (FEATURE_SGX);
+  has_wbnoinvd = has_feature (FEATURE_WBNOINVD);
+  has_xsave = has_feature (FEATURE_XSAVE);
 
   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 +499,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	}
     }
 
-  if (vendor == signature_AMD_ebx)
+  if (vendor == VENDOR_AMD)
     {
       unsigned int name;
 
@@ -668,36 +509,22 @@ 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_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;
+	}
     }
-  else if (vendor == signature_CENTAUR_ebx)
+  else if (vendor == VENDOR_CENTAUR)
     {
       processor = PROCESSOR_GENERIC;
 
@@ -749,7 +576,7 @@ 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";
@@ -769,145 +596,23 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 	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";
+		{
+		  /* 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";
 		/* Assume Ice Lake.  */
 		else if (has_avx512bitalg)
 		  cpu = "icelake-client";
@@ -970,7 +675,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 		cpu = "x86-64";
 	      else if (has_sse3)
 		{
-		  if (vendor == signature_CENTAUR_ebx)
+		  if (vendor == VENDOR_CENTAUR)
 		    /* C7 / Eden "Esther" */
 		    cpu = "c7";
 		  else
@@ -982,7 +687,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 		cpu = "pentium-m";
 	      else if (has_sse)
 		{
-		  if (vendor == signature_CENTAUR_ebx)
+		  if (vendor == VENDOR_CENTAUR)
 		    {
 		      if (model >= 9)
 			/* Eden "Nehemiah" */
@@ -1004,7 +709,6 @@ 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:
@@ -1036,7 +740,7 @@ 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)
 		/* Nano 3000 | Nano dual / quad core | Eden X4 */
@@ -1060,33 +764,6 @@ 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.  */
@@ -1121,101 +798,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 be3ed0158f2..fbbc957510a 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -90,6 +90,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "dwarf2out.h"
 #include "i386-builtins.h"
+#include "common/config/i386/cpuinfo-builtins.h"
+#include "common/config/i386/i386-isas.h"
 
 #undef BDESC
 #undef BDESC_FIRST
@@ -1835,235 +1837,66 @@ ix86_builtin_reciprocal (tree fndecl)
     }
 }
 
-/* Priority of i386 features, greater value is higher priority.   This is
-   used to decide the order in which function dispatch must happen.  For
-   instance, a version specialized for SSE4.2 should be checked for dispatch
-   before a version for SSE3, as SSE4.2 implies SSE3.  */
-enum feature_priority
-{
-  P_ZERO = 0,
-  P_MMX,
-  P_SSE,
-  P_SSE2,
-  P_SSE3,
-  P_SSSE3,
-  P_PROC_SSSE3,
-  P_SSE4_A,
-  P_PROC_SSE4_A,
-  P_SSE4_1,
-  P_SSE4_2,
-  P_PROC_SSE4_2,
-  P_POPCNT,
-  P_AES,
-  P_PCLMUL,
-  P_AVX,
-  P_PROC_AVX,
-  P_BMI,
-  P_PROC_BMI,
-  P_FMA4,
-  P_XOP,
-  P_PROC_XOP,
-  P_FMA,
-  P_PROC_FMA,
-  P_BMI2,
-  P_AVX2,
-  P_PROC_AVX2,
-  P_AVX512F,
-  P_PROC_AVX512F
-};
-
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512BF16,
-  F_AVX512VP2INTERSECT,
-  F_MAX
-};
-
-/* These are the values for vendor types and cpu types  and subtypes
-   in cpuinfo.c.  Cpu types and subtypes should be subtracted by
-   the corresponding start value.  */
-enum processor_model
-{
-  M_INTEL = 1,
-  M_AMD,
-  M_CPU_TYPE_START,
-  M_INTEL_BONNELL,
-  M_INTEL_CORE2,
-  M_INTEL_COREI7,
-  M_AMDFAM10H,
-  M_AMDFAM15H,
-  M_INTEL_SILVERMONT,
-  M_INTEL_KNL,
-  M_AMD_BTVER1,
-  M_AMD_BTVER2,
-  M_AMDFAM17H,
-  M_INTEL_KNM,
-  M_INTEL_GOLDMONT,
-  M_INTEL_GOLDMONT_PLUS,
-  M_INTEL_TREMONT,
-  M_CPU_SUBTYPE_START,
-  M_INTEL_COREI7_NEHALEM,
-  M_INTEL_COREI7_WESTMERE,
-  M_INTEL_COREI7_SANDYBRIDGE,
-  M_AMDFAM10H_BARCELONA,
-  M_AMDFAM10H_SHANGHAI,
-  M_AMDFAM10H_ISTANBUL,
-  M_AMDFAM15H_BDVER1,
-  M_AMDFAM15H_BDVER2,
-  M_AMDFAM15H_BDVER3,
-  M_AMDFAM15H_BDVER4,
-  M_AMDFAM17H_ZNVER1,
-  M_INTEL_COREI7_IVYBRIDGE,
-  M_INTEL_COREI7_HASWELL,
-  M_INTEL_COREI7_BROADWELL,
-  M_INTEL_COREI7_SKYLAKE,
-  M_INTEL_COREI7_SKYLAKE_AVX512,
-  M_INTEL_COREI7_CANNONLAKE,
-  M_INTEL_COREI7_ICELAKE_CLIENT,
-  M_INTEL_COREI7_ICELAKE_SERVER,
-  M_AMDFAM17H_ZNVER2,
-  M_INTEL_COREI7_CASCADELAKE,
-  M_INTEL_COREI7_TIGERLAKE,
-  M_INTEL_COREI7_COOPERLAKE
-};
-
 struct _arch_names_table
 {
   const char *const name;
-  const enum processor_model model;
+  const int model;
 };
 
-static const _arch_names_table arch_names_table[] =
-{
-  {"amd", M_AMD},
-  {"intel", M_INTEL},
-  {"atom", M_INTEL_BONNELL},
-  {"slm", M_INTEL_SILVERMONT},
-  {"core2", M_INTEL_CORE2},
-  {"corei7", M_INTEL_COREI7},
-  {"nehalem", M_INTEL_COREI7_NEHALEM},
-  {"westmere", M_INTEL_COREI7_WESTMERE},
-  {"sandybridge", M_INTEL_COREI7_SANDYBRIDGE},
-  {"ivybridge", M_INTEL_COREI7_IVYBRIDGE},
-  {"haswell", M_INTEL_COREI7_HASWELL},
-  {"broadwell", M_INTEL_COREI7_BROADWELL},
-  {"skylake", M_INTEL_COREI7_SKYLAKE},
-  {"skylake-avx512", M_INTEL_COREI7_SKYLAKE_AVX512},
-  {"cannonlake", M_INTEL_COREI7_CANNONLAKE},
-  {"icelake-client", M_INTEL_COREI7_ICELAKE_CLIENT},
-  {"icelake-server", M_INTEL_COREI7_ICELAKE_SERVER},
-  {"cascadelake", M_INTEL_COREI7_CASCADELAKE},
-  {"tigerlake", M_INTEL_COREI7_TIGERLAKE},
-  {"cooperlake", M_INTEL_COREI7_COOPERLAKE},
-  {"bonnell", M_INTEL_BONNELL},
-  {"silvermont", M_INTEL_SILVERMONT},
-  {"goldmont", M_INTEL_GOLDMONT},
-  {"goldmont-plus", M_INTEL_GOLDMONT_PLUS},
-  {"tremont", M_INTEL_TREMONT},
-  {"knl", M_INTEL_KNL},
-  {"knm", M_INTEL_KNM},
-  {"amdfam10h", M_AMDFAM10H},
-  {"barcelona", M_AMDFAM10H_BARCELONA},
-  {"shanghai", M_AMDFAM10H_SHANGHAI},
-  {"istanbul", M_AMDFAM10H_ISTANBUL},
-  {"btver1", M_AMD_BTVER1},
-  {"amdfam15h", M_AMDFAM15H},
-  {"bdver1", M_AMDFAM15H_BDVER1},
-  {"bdver2", M_AMDFAM15H_BDVER2},
-  {"bdver3", M_AMDFAM15H_BDVER3},
-  {"bdver4", M_AMDFAM15H_BDVER4},
-  {"btver2", M_AMD_BTVER2},
-  {"amdfam17h", M_AMDFAM17H},
-  {"znver1", M_AMDFAM17H_ZNVER1},
-  {"znver2", M_AMDFAM17H_ZNVER2},
-};
+/* These are the values for vendor types, cpu types and subtypes in
+   cpuinfo.h.  Cpu types and subtypes should be subtracted by the
+   corresponding start value.  */
 
-/* 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;
-};
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+  (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
 
-static const _isa_names_table isa_names_table[] =
+static const _arch_names_table arch_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_ZERO},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_ZERO},
-  {"avx512bw",F_AVX512BW, P_ZERO},
-  {"avx512dq",F_AVX512DQ, P_ZERO},
-  {"avx512cd",F_AVX512CD, P_ZERO},
-  {"avx512er",F_AVX512ER, P_ZERO},
-  {"avx512pf",F_AVX512PF, P_ZERO},
-  {"avx512vbmi",F_AVX512VBMI, P_ZERO},
-  {"avx512ifma",F_AVX512IFMA, P_ZERO},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_ZERO},
-  {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
-  {"gfni",	F_GFNI,	P_ZERO},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
-  {"avx512vnni", F_AVX512VNNI, P_ZERO},
-  {"avx512bitalg", F_AVX512BITALG, P_ZERO},
-  {"avx512bf16", F_AVX512BF16, P_ZERO},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO}
+  {"amd", M_VENDOR (VENDOR_AMD)},
+  {"intel", M_VENDOR (VENDOR_INTEL)},
+  {"atom", M_CPU_TYPE (INTEL_BONNELL)},
+  {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"core2", M_CPU_TYPE (INTEL_CORE2)},
+  {"corei7", M_CPU_TYPE (INTEL_COREI7)},
+  {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
+  {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
+  {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
+  {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
+  {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
+  {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
+  {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
+  {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
+  {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
+  {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
+  {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
+  {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
+  {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
+  {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
+  {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
+  {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
+  {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
+  {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
+  {"knl", M_CPU_TYPE (INTEL_KNL)},
+  {"knm", M_CPU_TYPE (INTEL_KNM)},
+  {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
+  {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
+  {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
+  {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
+  {"btver1", M_CPU_TYPE (AMD_BTVER1)},
+  {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
+  {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
+  {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
+  {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
+  {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
+  {"btver2", M_CPU_TYPE (AMD_BTVER2)},
+  {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
+  {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
+  {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
 };
 
 /* This parses the attribute arguments to target in DECL and determines
@@ -2509,16 +2342,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
 
       if (isa_names_table[i].feature >= 32)
 	{
-	  tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+	  tree index_type
+	    = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+	  tree type = build_array_type (unsigned_type_node, index_type);
+	  tree __cpu_features2_var = make_var_decl (type,
 						    "__cpu_features2");
 
 	  varpool_node::add (__cpu_features2_var);
-	  field_val = (1U << (isa_names_table[i].feature - 32));
-	  /* Return __cpu_features2 & field_val  */
-	  final = build2 (BIT_AND_EXPR, unsigned_type_node,
-			  __cpu_features2_var,
-			  build_int_cstu (unsigned_type_node, field_val));
-	  return build1 (CONVERT_EXPR, integer_type_node, final);
+	  for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+	    if (isa_names_table[i].feature < (32 + 32 + j * 32))
+	      {
+		field_val = (1U << (isa_names_table[i].feature
+				    - (32 + j * 32)));
+		tree index = size_int (j);
+		array_elt = build4 (ARRAY_REF, unsigned_type_node,
+				    __cpu_features2_var,
+				    index, NULL_TREE, NULL_TREE);
+		/* Return __cpu_features2[index] & field_val  */
+		final = build2 (BIT_AND_EXPR, unsigned_type_node,
+				array_elt,
+				build_int_cstu (unsigned_type_node,
+						field_val));
+		return build1 (CONVERT_EXPR, integer_type_node, final);
+	      }
 	}
 
       field = TYPE_FIELDS (__processor_model_type);
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..368c0a54efe 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,348 +7,52 @@
 /* { 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/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;
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index cf5f0884bb4..49c5107546f 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +39,14 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
    size of __cpu_model is part of ABI.  So, new features that don't
    fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
-
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
-/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
-   the max possible level of CPUID insn.  */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
-			int max_cpuid_level)
-{
-  unsigned int eax, ebx;
-  unsigned int ext_level;
-
-  unsigned int features = 0;
-  unsigned int features2 = 0;
-
-  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
-#define XCR_XFEATURE_ENABLED_MASK	0x0
-#define XSTATE_FP			0x1
-#define XSTATE_SSE			0x2
-#define XSTATE_YMM			0x4
-#define XSTATE_OPMASK			0x20
-#define XSTATE_ZMM			0x40
-#define XSTATE_HI_ZMM			0x80
-
-#define XCR_AVX_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
-  /* Check if AVX and AVX512 are usable.  */
-  int avx_usable = 0;
-  int avx512_usable = 0;
-  if ((ecx & bit_OSXSAVE))
-    {
-      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
-         ZMM16-ZMM31 states are supported by OSXSAVE.  */
-      unsigned int xcrlow;
-      unsigned int xcrhigh;
-      asm (".byte 0x0f, 0x01, 0xd0"
-	   : "=a" (xcrlow), "=d" (xcrhigh)
-	   : "c" (XCR_XFEATURE_ENABLED_MASK));
-      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
-	{
-	  avx_usable = 1;
-	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
-			   == XCR_AVX512F_ENABLED_MASK);
-	}
-    }
-
-#define set_feature(f) \
-  do						\
-    {						\
-      if (f < 32)				\
-	features |= (1U << (f & 31));		\
-      else					\
-	features2 |= (1U << ((f - 32) & 31));	\
-    }						\
-  while (0)
-
-  if (edx & bit_CMOV)
-    set_feature (FEATURE_CMOV);
-  if (edx & bit_MMX)
-    set_feature (FEATURE_MMX);
-  if (edx & bit_SSE)
-    set_feature (FEATURE_SSE);
-  if (edx & bit_SSE2)
-    set_feature (FEATURE_SSE2);
-  if (ecx & bit_POPCNT)
-    set_feature (FEATURE_POPCNT);
-  if (ecx & bit_AES)
-    set_feature (FEATURE_AES);
-  if (ecx & bit_PCLMUL)
-    set_feature (FEATURE_PCLMUL);
-  if (ecx & bit_SSE3)
-    set_feature (FEATURE_SSE3);
-  if (ecx & bit_SSSE3)
-    set_feature (FEATURE_SSSE3);
-  if (ecx & bit_SSE4_1)
-    set_feature (FEATURE_SSE4_1);
-  if (ecx & bit_SSE4_2)
-    set_feature (FEATURE_SSE4_2);
-  if (avx_usable)
-    {
-      if (ecx & bit_AVX)
-	set_feature (FEATURE_AVX);
-      if (ecx & bit_FMA)
-	set_feature (FEATURE_FMA);
-    }
-
-  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
-  if (max_cpuid_level >= 7)
-    {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
-      if (ebx & bit_BMI)
-	set_feature (FEATURE_BMI);
-      if (avx_usable)
-	{
-	  if (ebx & bit_AVX2)
-	    set_feature (FEATURE_AVX2);
-	  if (ecx & bit_VPCLMULQDQ)
-	    set_feature (FEATURE_VPCLMULQDQ);
-	}
-      if (ebx & bit_BMI2)
-	set_feature (FEATURE_BMI2);
-      if (ecx & bit_GFNI)
-	set_feature (FEATURE_GFNI);
-      if (avx512_usable)
-	{
-	  if (ebx & bit_AVX512F)
-	    set_feature (FEATURE_AVX512F);
-	  if (ebx & bit_AVX512VL)
-	    set_feature (FEATURE_AVX512VL);
-	  if (ebx & bit_AVX512BW)
-	    set_feature (FEATURE_AVX512BW);
-	  if (ebx & bit_AVX512DQ)
-	    set_feature (FEATURE_AVX512DQ);
-	  if (ebx & bit_AVX512CD)
-	    set_feature (FEATURE_AVX512CD);
-	  if (ebx & bit_AVX512PF)
-	    set_feature (FEATURE_AVX512PF);
-	  if (ebx & bit_AVX512ER)
-	    set_feature (FEATURE_AVX512ER);
-	  if (ebx & bit_AVX512IFMA)
-	    set_feature (FEATURE_AVX512IFMA);
-	  if (ecx & bit_AVX512VBMI)
-	    set_feature (FEATURE_AVX512VBMI);
-	  if (ecx & bit_AVX512VBMI2)
-	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_AVX512VNNI)
-	    set_feature (FEATURE_AVX512VNNI);
-	  if (ecx & bit_AVX512BITALG)
-	    set_feature (FEATURE_AVX512BITALG);
-	  if (ecx & bit_AVX512VPOPCNTDQ)
-	    set_feature (FEATURE_AVX512VPOPCNTDQ);
-	  if (edx & bit_AVX5124VNNIW)
-	    set_feature (FEATURE_AVX5124VNNIW);
-	  if (edx & bit_AVX5124FMAPS)
-	    set_feature (FEATURE_AVX5124FMAPS);
-	  if (edx & bit_AVX512VP2INTERSECT)
-	    set_feature (FEATURE_AVX512VP2INTERSECT);
+   in libgcc.a only, preferably hidden.
 
-	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
-	  if (eax & bit_AVX512BF16)
-	    set_feature (FEATURE_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)
-	set_feature (FEATURE_SSE4_A);
-      if (avx_usable)
-	{
-	  if (ecx & bit_FMA4)
-	    set_feature (FEATURE_FMA4);
-	  if (ecx & bit_XOP)
-	    set_feature (FEATURE_XOP);
-	}
-    }
-    
-  __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
-  __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
-}
+   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+   smaller array, it can only access the first few elements.  */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
    the right values.  This needs to run only once.  This constructor is
@@ -429,85 +57,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
 __cpu_indicator_init (void)
 {
-  unsigned int eax, ebx, ecx, edx;
-
-  int max_level;
-  unsigned int vendor;
-  unsigned int model, family, brand_id;
-  unsigned int extended_model, extended_family;
-
-  /* This function needs to run just once.  */
-  if (__cpu_model.__cpu_vendor)
-    return 0;
-
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  vendor = ebx;
-  max_level = eax;
-
-  if (max_level < 1)
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
-    {
-      /* Adjust model and family for Intel CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_INTEL;
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_AMD;
-    }
-  else
-    __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
-  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
-  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
-  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
-  return 0;
+  struct __processor_model2 cpu_model2;
+  return cpu_indicator_init (&__cpu_model, &cpu_model2,
+			     __cpu_features2);
 }
 
 #if defined SHARED && defined USE_ELF_SYMVER
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V4 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-25 17:42                             ` V4 " H.J. Lu
@ 2020-05-26  9:30                               ` Martin Liška
  2020-05-26 11:59                                 ` V5 " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Martin Liška @ 2020-05-26  9:30 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law,
	Richard Biener, gcc-patches

On 5/25/20 7:42 PM, H.J. Lu wrote:
> Here is the updated patch.  OK for master?

Thank you for the updated patch.

I have still few nits:

1) I would make all the:

> +  has_sse3 = has_feature (FEATURE_SSE3);

a macro. The local variable seems to superfluous.

2) can we automatically deduce option name:

> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")

I mean "-m" + "rdrnd" == "-mrdrnd" ?

Martin


^ permalink raw reply	[flat|nested] 30+ messages in thread

* V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-26  9:30                               ` Martin Liška
@ 2020-05-26 11:59                                 ` H.J. Lu
  2020-05-26 13:27                                   ` Martin Liška
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-05-26 11:59 UTC (permalink / raw)
  To: Martin Liška
  Cc: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law,
	Richard Biener, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1092 bytes --]

On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
>
> On 5/25/20 7:42 PM, H.J. Lu wrote:
> > Here is the updated patch.  OK for master?
>
> Thank you for the updated patch.
>
> I have still few nits:
>
> 1) I would make all the:
>
> > +  has_sse3 = has_feature (FEATURE_SSE3);
>
> a macro. The local variable seems to superfluous.

Done.

> 2) can we automatically deduce option name:
>
> > +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
>
> I mean "-m" + "rdrnd" == "-mrdrnd" ?

The new option field serves 2 purposes:

1. Not all features have a corresponding command-line option

ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)

     for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
        if (isa_names_table[i].option)

2. Some feature has a different name in the command-line option.

  ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")

Here is the updated patch.   OK for master?

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 106219 bytes --]

From 48a429a02c91937ba2a4bd37f42304c2ce59bb28 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

Move cpuinfo.h from libgcc to common/config/i386 and move isa_names_table
to common/config/i386 so that get_intel_cpu can be shared by libgcc, GCC
driver and gcc.target/i386/builtin_target.c to detect the specific type
of Intel and AMD CPUs:

1. Use the same enum processor_features in libgcc and x86 backend.
2. Add more processor features to enum processor_features.
3. Use the same isa_names_table in i386-builtins.c, driver-i386.c and
gcc.target/i386/builtin_target.c.
4. Use isa_names_table to generate ISA command-line options.
5. Use isa_names_table to generate __builtin_cpu_supports tests.
6. Add M_VENDOR, M_CPU_TYPE and M_CPU_SUBTYPE in i386-builtins.c to
avoid duplication in.
7. Use cpu_indicator_init, has_cpu_feature, get_amd_cpu and get_intel_cpu
in driver-i386.c and builtin_target.c.

gcc/

	PR target/95259
	* common/config/i386/cpuinfo-builtins.h: Moved from
	libgcc/config/i386/cpuinfo.h.
	(processor_vendor): Add VENDOR_CENTAUR, VENDOR_CYRIX, VENDOR_NSC
	and BUILTIN_VENDOR_MAX.
	(processor_types): Add BUILTIN_CPU_TYPE_MAX.
	(processor_features): Add FEATURE_3DNOW, FEATURE_3DNOWP,
	FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
	FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
	FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
	FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
	FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
	FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
	FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE, FEATURE_PCONFIG,
	FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
	(__processor_model): Moved to cpuinfo.h.
	(__cpu_model): Removed.
	(__cpu_features2): Likewise.
	(SIZE_OF_CPU_FEATURES): New.
	* common/config/i386/cpuinfo.h: Moved from
	libgcc/config/i386/cpuinfo.c.
	(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
	(__processor_model2): New.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(has_cpu_feature): New function.
	(set_cpu_feature): Likewise.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	Use CHECK___builtin_cpu_is.  Return Intel CPU name.
	(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
	Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
	FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
	FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
	FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
	FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
	FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
	FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE,
	FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT and FEATURE_XSAVES
	(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
	Also update cpu_model2.
	* 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.  Replace F_XXX
	with FEATURE_XXX.  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 AMD CPU name.  Call get_intel_cpu to get
	Intel CPU name.  Use isa_names_table to generate command-line
	options.
	* config/i386/i386-builtins.c: Include
	"common/config/i386/cpuinfo.h" and
	"common/config/i386/i386-isas.h".
	(feature_priority): Moved to common/config/i386/i386-isas.h.
	(processor_features): Removed.
	(processor_model): Removed.
	(_arch_names_table): Use "const int" on model.
	(M_CPU_TYPE_START): New.
	(M_CPU_SUBTYPE_START): Likewise.
	(M_VENDOR): Likewise.
	(M_CPU_TYPE): Likewise.
	(M_CPU_SUBTYPE): Likewise.
	(arch_names_table): Replace M_XXX with M_VENDOR, M_CPU_TYPE and
	M_CPU_SUBTYPE.
	(isa_names_table): Moved to common/config/i386/i386-isas.h.
	(fold_builtin_cpu): Change __cpu_features2 to an array.

gcc/testsuite/

	PR target/95259
	* gcc.target/i386/builtin_target.c: Include <stdlib.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.

libgcc/

	PR target/95259
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Changed to array.
	(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_intel_cpu): Likewise.
	(get_available_features): Likewise.
	(__cpu_indicator_init): Call cpu_indicator_init.
	* config/i386/cpuinfo.h: Moved to
	gcc/common/config/i386/cpuinfo-builtins.h.
---
 .../common/config/i386/cpuinfo-builtins.h     |  70 +-
 gcc/common/config/i386/cpuinfo.h              | 845 ++++++++++++++++++
 gcc/common/config/i386/i386-isas.h            | 201 +++++
 gcc/config/i386/driver-i386.c                 | 680 +++-----------
 gcc/config/i386/i386-builtins.c               | 302 ++-----
 .../gcc.target/i386/builtin_target.c          | 354 +-------
 libgcc/config/i386/cpuinfo.c                  | 464 +---------
 7 files changed, 1325 insertions(+), 1591 deletions(-)
 rename libgcc/config/i386/cpuinfo.h => gcc/common/config/i386/cpuinfo-builtins.h (71%)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 create mode 100644 gcc/common/config/i386/i386-isas.h

diff --git a/libgcc/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo-builtins.h
similarity index 71%
rename from libgcc/config/i386/cpuinfo.h
rename to gcc/common/config/i386/cpuinfo-builtins.h
index 0f97510cde1..7a20dcf9ef8 100644
--- a/libgcc/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo-builtins.h
@@ -30,6 +30,10 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
+  BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
 
@@ -45,13 +49,14 @@ enum processor_types
   INTEL_SILVERMONT,
   INTEL_KNL,
   AMD_BTVER1,
-  AMD_BTVER2,  
+  AMD_BTVER2,
   AMDFAM17H,
   INTEL_KNM,
   INTEL_GOLDMONT,
   INTEL_GOLDMONT_PLUS,
   INTEL_TREMONT,
-  CPU_TYPE_MAX
+  CPU_TYPE_MAX,
+  BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
 };
 
 enum processor_subtypes
@@ -123,14 +128,57 @@ enum processor_features
   FEATURE_AVX512VNNI,
   FEATURE_AVX512BITALG,
   FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_3DNOW,
+  FEATURE_3DNOWP,
+  FEATURE_ADX,
+  FEATURE_ABM,
+  FEATURE_CLDEMOTE,
+  FEATURE_CLFLUSHOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO,
+  FEATURE_CMPXCHG16B,
+  FEATURE_CMPXCHG8B,
+  FEATURE_ENQCMD,
+  FEATURE_F16C,
+  FEATURE_FSGSBASE,
+  FEATURE_FXSAVE,
+  FEATURE_HLE,
+  FEATURE_IBT,
+  FEATURE_LAHF_LM,
+  FEATURE_LM,
+  FEATURE_LWP,
+  FEATURE_LZCNT,
+  FEATURE_MOVBE,
+  FEATURE_MOVDIR64B,
+  FEATURE_MOVDIRI,
+  FEATURE_MWAITX,
+  FEATURE_OSPKE,
+  FEATURE_OSXSAVE,
+  FEATURE_PCONFIG,
+  FEATURE_PKU,
+  FEATURE_PREFETCHWT1,
+  FEATURE_PRFCHW,
+  FEATURE_PTWRITE,
+  FEATURE_RDPID,
+  FEATURE_RDRND,
+  FEATURE_RDSEED,
+  FEATURE_RTM,
+  FEATURE_SERIALIZE,
+  FEATURE_SGX,
+  FEATURE_SHA,
+  FEATURE_SHSTK,
+  FEATURE_TBM,
+  FEATURE_TSXLDTRK,
+  FEATURE_VAES,
+  FEATURE_WAITPKG,
+  FEATURE_WBNOINVD,
+  FEATURE_XSAVE,
+  FEATURE_XSAVEC,
+  FEATURE_XSAVEOPT,
+  FEATURE_XSAVES,
+  CPU_FEATURE_MAX
 };
 
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..13f4b0e51e5
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,845 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "cpuinfo-builtins.h"
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  /* The first 32 features are stored as bitmasks in __cpu_features.
+     The rest of features are stored as bitmasks in a separate array
+     of unsigned int.  */
+  unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+  unsigned int __cpu_family;
+  unsigned int __cpu_model;
+  unsigned int __cpu_max_level;
+  unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      return cpu_model->__cpu_features[0] & (1U << (f & 31));
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+  gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+      {
+	cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+	return;
+      }
+  gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+	     struct __processor_model2 *cpu_model2,
+	     unsigned int *cpu_features2)
+{
+  const char *cpu = NULL;
+  unsigned int family = cpu_model2->__cpu_family;
+  unsigned int model = cpu_model2->__cpu_model;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_AVX2))
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XSAVEOPT))
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_BMI))
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XOP))
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLWB))
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLZERO))
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       struct __processor_model2 *cpu_model2,
+	       unsigned int *cpu_features2,
+	       unsigned int brand_id)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+    return cpu;
+
+  switch (cpu_model2->__cpu_model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_cpu_feature (cpu_model, cpu_features2,
+			   FEATURE_AVX512VNNI))
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one.  */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+			struct __processor_model2 *cpu_model2,
+			unsigned int *cpu_features2,
+			unsigned int ecx, unsigned int edx)
+{
+  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+  unsigned int eax, ebx;
+  unsigned int ext_level;
+
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+#define XSTATE_FP			0x1
+#define XSTATE_SSE			0x2
+#define XSTATE_YMM			0x4
+#define XSTATE_OPMASK			0x20
+#define XSTATE_ZMM			0x40
+#define XSTATE_HI_ZMM			0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      __asm__ (".byte 0x0f, 0x01, 0xd0"
+	       : "=a" (xcrlow), "=d" (xcrhigh)
+	       : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+	{
+	  avx_usable = 1;
+	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+			   == XCR_AVX512F_ENABLED_MASK);
+	}
+    }
+
+#define set_feature(f) \
+  set_cpu_feature (cpu_model, cpu_features2, f)
+
+  if (edx & bit_CMOV)
+    set_feature (FEATURE_CMOV);
+  if (edx & bit_MMX)
+    set_feature (FEATURE_MMX);
+  if (edx & bit_SSE)
+    set_feature (FEATURE_SSE);
+  if (edx & bit_SSE2)
+    set_feature (FEATURE_SSE2);
+  if (edx & bit_CMPXCHG8B)
+    set_feature (FEATURE_CMPXCHG8B);
+  if (edx & bit_FXSAVE)
+    set_feature (FEATURE_FXSAVE);
+
+  if (ecx & bit_POPCNT)
+    set_feature (FEATURE_POPCNT);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_PCLMUL)
+    set_feature (FEATURE_PCLMUL);
+  if (ecx & bit_SSE3)
+    set_feature (FEATURE_SSE3);
+  if (ecx & bit_SSSE3)
+    set_feature (FEATURE_SSSE3);
+  if (ecx & bit_SSE4_1)
+    set_feature (FEATURE_SSE4_1);
+  if (ecx & bit_SSE4_2)
+    set_feature (FEATURE_SSE4_2);
+  if (ecx & bit_OSXSAVE)
+    set_feature (FEATURE_OSXSAVE);
+  if (ecx & bit_CMPXCHG16B)
+    set_feature (FEATURE_CMPXCHG16B);
+  if (ecx & bit_MOVBE)
+    set_feature (FEATURE_MOVBE);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_F16C)
+    set_feature (FEATURE_F16C);
+  if (ecx & bit_RDRND)
+    set_feature (FEATURE_RDRND);
+  if (ecx & bit_XSAVE)
+    set_feature (FEATURE_XSAVE);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+	set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+	set_feature (FEATURE_FMA);
+    }
+
+  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+  if (max_cpuid_level >= 7)
+    {
+      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_BMI)
+	set_feature (FEATURE_BMI);
+      if (ebx & bit_SGX)
+	set_feature (FEATURE_SGX);
+      if (ebx & bit_HLE)
+	set_feature (FEATURE_HLE);
+      if (ebx & bit_RTM)
+	set_feature (FEATURE_RTM);
+      if (avx_usable)
+	{
+	  if (ebx & bit_AVX2)
+	    set_feature (FEATURE_AVX2);
+	  if (ecx & bit_VPCLMULQDQ)
+	    set_feature (FEATURE_VPCLMULQDQ);
+	}
+      if (ebx & bit_BMI2)
+	set_feature (FEATURE_BMI2);
+      if (ebx & bit_FSGSBASE)
+	set_feature (FEATURE_FSGSBASE);
+      if (ebx & bit_RDSEED)
+	set_feature (FEATURE_RDSEED);
+      if (ebx & bit_ADX)
+	set_feature (FEATURE_ADX);
+      if (ebx & bit_SHA)
+	set_feature (FEATURE_SHA);
+      if (ebx & bit_CLFLUSHOPT)
+	set_feature (FEATURE_CLFLUSHOPT);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
+      if (ecx & bit_PREFETCHWT1)
+	set_feature (FEATURE_PREFETCHWT1);
+      if (ecx & bit_OSPKE)
+	set_feature (FEATURE_OSPKE);
+      if (ecx & bit_RDPID)
+	set_feature (FEATURE_RDPID);
+      if (ecx & bit_VAES)
+	set_feature (FEATURE_VAES);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ecx & bit_MOVDIRI)
+	set_feature (FEATURE_MOVDIRI);
+      if (ecx & bit_MOVDIR64B)
+	set_feature (FEATURE_MOVDIR64B);
+      if (ecx & bit_ENQCMD)
+	set_feature (FEATURE_ENQCMD);
+      if (ecx & bit_CLDEMOTE)
+	set_feature (FEATURE_CLDEMOTE);
+      if (ecx & bit_WAITPKG)
+	set_feature (FEATURE_WAITPKG);
+      if (ecx & bit_SHSTK)
+	set_feature (FEATURE_SHSTK);
+      if (edx & bit_SERIALIZE)
+	set_feature (FEATURE_SERIALIZE);
+      if (edx & bit_TSXLDTRK)
+	set_feature (FEATURE_TSXLDTRK);
+      if (edx & bit_PCONFIG)
+	set_feature (FEATURE_PCONFIG);
+      if (edx & bit_IBT)
+	set_feature (FEATURE_IBT);
+      if (avx512_usable)
+	{
+	  if (ebx & bit_AVX512F)
+	    set_feature (FEATURE_AVX512F);
+	  if (ebx & bit_AVX512VL)
+	    set_feature (FEATURE_AVX512VL);
+	  if (ebx & bit_AVX512BW)
+	    set_feature (FEATURE_AVX512BW);
+	  if (ebx & bit_AVX512DQ)
+	    set_feature (FEATURE_AVX512DQ);
+	  if (ebx & bit_AVX512CD)
+	    set_feature (FEATURE_AVX512CD);
+	  if (ebx & bit_AVX512PF)
+	    set_feature (FEATURE_AVX512PF);
+	  if (ebx & bit_AVX512ER)
+	    set_feature (FEATURE_AVX512ER);
+	  if (ebx & bit_AVX512IFMA)
+	    set_feature (FEATURE_AVX512IFMA);
+	  if (ecx & bit_AVX512VBMI)
+	    set_feature (FEATURE_AVX512VBMI);
+	  if (ecx & bit_AVX512VBMI2)
+	    set_feature (FEATURE_AVX512VBMI2);
+	  if (ecx & bit_AVX512VNNI)
+	    set_feature (FEATURE_AVX512VNNI);
+	  if (ecx & bit_AVX512BITALG)
+	    set_feature (FEATURE_AVX512BITALG);
+	  if (ecx & bit_AVX512VPOPCNTDQ)
+	    set_feature (FEATURE_AVX512VPOPCNTDQ);
+	  if (edx & bit_AVX5124VNNIW)
+	    set_feature (FEATURE_AVX5124VNNIW);
+	  if (edx & bit_AVX5124FMAPS)
+	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
+
+	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+	  if (eax & bit_AVX512BF16)
+	    set_feature (FEATURE_AVX512BF16);
+	}
+    }
+
+  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+  if (max_cpuid_level >= 0xd)
+    {
+      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+      if (eax & bit_XSAVEC)
+	set_feature (FEATURE_XSAVEC);
+      if (eax & bit_XSAVES)
+	set_feature (FEATURE_XSAVES);
+    }
+
+  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+  if (max_cpuid_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_PTWRITE)
+	set_feature (FEATURE_PTWRITE);
+    }
+
+  /* Check cpuid level of extended features.  */
+  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+  cpu_model2->__cpu_ext_level = ext_level;
+
+  if (ext_level >= 0x80000001)
+    {
+      __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+      if (ecx & bit_SSE4a)
+	set_feature (FEATURE_SSE4_A);
+      if (ecx & bit_LAHF_LM)
+	set_feature (FEATURE_LAHF_LM);
+      if (ecx & bit_ABM)
+	set_feature (FEATURE_ABM);
+      if (ecx & bit_LWP)
+	set_feature (FEATURE_LWP);
+      if (ecx & bit_TBM)
+	set_feature (FEATURE_TBM);
+      if (ecx & bit_LZCNT)
+	set_feature (FEATURE_LZCNT);
+      if (ecx & bit_PRFCHW)
+	set_feature (FEATURE_PRFCHW);
+      if (ecx & bit_MWAITX)
+	set_feature (FEATURE_MWAITX);
+
+      if (edx & bit_LM)
+	set_feature (FEATURE_LM);
+      if (edx & bit_3DNOWP)
+	set_feature (FEATURE_3DNOWP);
+      if (edx & bit_3DNOW)
+	set_feature (FEATURE_3DNOW);
+
+      if (avx_usable)
+	{
+	  if (ecx & bit_FMA4)
+	    set_feature (FEATURE_FMA4);
+	  if (ecx & bit_XOP)
+	    set_feature (FEATURE_XOP);
+	}
+    }
+
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+      if (ebx & bit_WBNOINVD)
+	set_feature (FEATURE_WBNOINVD);
+    }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+		    struct __processor_model2 *cpu_model2,
+		    unsigned int *cpu_features2)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  int max_level;
+  unsigned int vendor;
+  unsigned int model, family, brand_id;
+  unsigned int extended_model, extended_family;
+
+  /* This function needs to run just once.  */
+  if (cpu_model->__cpu_vendor)
+    return 0;
+
+  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  vendor = ebx;
+  max_level = eax;
+
+  if (max_level < 1)
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  cpu_model2->__cpu_max_level = max_level;
+
+  model = (eax >> 4) & 0x0f;
+  family = (eax >> 8) & 0x0f;
+  brand_id = ebx & 0xff;
+  extended_model = (eax >> 12) & 0xf0;
+  extended_family = (eax >> 20) & 0xff;
+
+  if (vendor == signature_INTEL_ebx)
+    {
+      /* Adjust model and family for Intel CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+      else if (family == 0x06)
+	model += extended_model;
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+      cpu_model->__cpu_vendor = VENDOR_INTEL;
+    }
+  else if (vendor == signature_AMD_ebx)
+    {
+      /* Adjust model and family for AMD CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+      cpu_model->__cpu_vendor = VENDOR_AMD;
+    }
+  else if (vendor == signature_CENTAUR_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+  else if (vendor == signature_CYRIX_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CYRIX;
+  else if (vendor == signature_NSC_ebx)
+    cpu_model->__cpu_vendor = VENDOR_NSC;
+  else
+    cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+  return 0;
+}
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
new file mode 100644
index 00000000000..32faee6c608
--- /dev/null
+++ b/gcc/common/config/i386/i386-isas.h
@@ -0,0 +1,201 @@
+/* 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/>.  */
+
+/* Priority of i386 features, greater value is higher priority.   This is
+   used to decide the order in which function dispatch must happen.  For
+   instance, a version specialized for SSE4.2 should be checked for dispatch
+   before a version for SSE3, as SSE4.2 implies SSE3.  */
+enum feature_priority
+{
+  P_ZERO = 0,
+  P_MMX,
+  P_SSE,
+  P_SSE2,
+  P_SSE3,
+  P_SSSE3,
+  P_PROC_SSSE3,
+  P_SSE4_A,
+  P_PROC_SSE4_A,
+  P_SSE4_1,
+  P_SSE4_2,
+  P_PROC_SSE4_2,
+  P_POPCNT,
+  P_AES,
+  P_PCLMUL,
+  P_AVX,
+  P_PROC_AVX,
+  P_BMI,
+  P_PROC_BMI,
+  P_FMA4,
+  P_XOP,
+  P_PROC_XOP,
+  P_FMA,
+  P_PROC_FMA,
+  P_BMI2,
+  P_AVX2,
+  P_PROC_AVX2,
+  P_AVX512F,
+  P_PROC_AVX512F
+};
+
+/* 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_ZERO, 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_ZERO,
+			"-mavx512vl")
+  ISA_NAMES_TABLE_ENTRY("avx512bw", FEATURE_AVX512BW, P_ZERO,
+			"-mavx512bw")
+  ISA_NAMES_TABLE_ENTRY("avx512dq", FEATURE_AVX512DQ, P_ZERO,
+			"-mavx512dq")
+  ISA_NAMES_TABLE_ENTRY("avx512cd", FEATURE_AVX512CD, P_ZERO,
+			"-mavx512cd")
+  ISA_NAMES_TABLE_ENTRY("avx512er", FEATURE_AVX512ER, P_ZERO,
+			"-mavx512er")
+  ISA_NAMES_TABLE_ENTRY("avx512pf", FEATURE_AVX512PF, P_ZERO,
+			"-mavx512pf")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi", FEATURE_AVX512VBMI, P_ZERO,
+			"-mavx512vbmi")
+  ISA_NAMES_TABLE_ENTRY("avx512ifma", FEATURE_AVX512IFMA, P_ZERO,
+			"-mavx512ifma")
+  ISA_NAMES_TABLE_ENTRY("avx5124vnniw", FEATURE_AVX5124VNNIW, P_ZERO,
+			"-mavx5124vnniw")
+  ISA_NAMES_TABLE_ENTRY("avx5124fmaps", FEATURE_AVX5124FMAPS, P_ZERO,
+			"-mavx5124fmaps")
+  ISA_NAMES_TABLE_ENTRY("avx512vpopcntdq", FEATURE_AVX512VPOPCNTDQ,
+			P_ZERO, "-mavx512vpopcntdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO,
+			"-mavx512vbmi2")
+  ISA_NAMES_TABLE_ENTRY("gfni", FEATURE_GFNI, P_ZERO, "-mgfni")
+  ISA_NAMES_TABLE_ENTRY("vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO,
+			"-mvpclmulqdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vnni", FEATURE_AVX512VNNI, P_ZERO,
+			"-mavx512vnni")
+  ISA_NAMES_TABLE_ENTRY("avx512bitalg", FEATURE_AVX512BITALG, P_ZERO,
+			"-mavx512bitalg")
+  ISA_NAMES_TABLE_ENTRY("avx512bf16", FEATURE_AVX512BF16, P_ZERO,
+			"-mavx512bf16")
+  ISA_NAMES_TABLE_ENTRY("avx512vp2intersect", FEATURE_AVX512VP2INTERSECT,
+			P_ZERO, "-mavx512vp2intersect")
+  ISA_NAMES_TABLE_ENTRY("3dnow", FEATURE_3DNOW, P_ZERO, "-m3dnow")
+  ISA_NAMES_TABLE_ENTRY("3dnowp", FEATURE_3DNOWP, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("adx", FEATURE_ADX, P_ZERO, "-madx")
+  ISA_NAMES_TABLE_ENTRY("abm", FEATURE_ABM, P_ZERO, "-mabm")
+  ISA_NAMES_TABLE_ENTRY("cldemote", FEATURE_CLDEMOTE, P_ZERO,
+			"-mcldemote")
+  ISA_NAMES_TABLE_ENTRY("clflushopt", FEATURE_CLFLUSHOPT, P_ZERO,
+			"-mclflushopt")
+  ISA_NAMES_TABLE_ENTRY("clwb", FEATURE_CLWB, P_ZERO, "-mclwb")
+  ISA_NAMES_TABLE_ENTRY("clzero", FEATURE_CLZERO, P_ZERO, "-mclzero")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg16b", FEATURE_CMPXCHG16B, P_ZERO,
+			"-mcx16")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg8b", FEATURE_CMPXCHG8B, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("enqcmd", FEATURE_ENQCMD, P_ZERO, "-menqcmd")
+  ISA_NAMES_TABLE_ENTRY("f16c", FEATURE_F16C, P_ZERO, "-mf16c")
+  ISA_NAMES_TABLE_ENTRY("fsgsbase", FEATURE_FSGSBASE, P_ZERO,
+			"-mfsgsbase")
+  ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
+  ISA_NAMES_TABLE_ENTRY("hle", FEATURE_HLE, P_ZERO, "-mhle")
+  ISA_NAMES_TABLE_ENTRY("ibt", FEATURE_IBT, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lahf_lm", FEATURE_LAHF_LM, P_ZERO, "-msahf")
+  ISA_NAMES_TABLE_ENTRY("lm", FEATURE_LM, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lwp", FEATURE_LWP, P_ZERO, "-mlwp")
+  ISA_NAMES_TABLE_ENTRY("lzcnt", FEATURE_LZCNT, P_ZERO, "-mlzcnt")
+  ISA_NAMES_TABLE_ENTRY("movbe", FEATURE_MOVBE, P_ZERO, "-mmovbe")
+  ISA_NAMES_TABLE_ENTRY("movdir64b", FEATURE_MOVDIR64B, P_ZERO,
+			"-mmovdir64b")
+  ISA_NAMES_TABLE_ENTRY("movdiri", FEATURE_MOVDIRI, P_ZERO, "-mmovdiri")
+  ISA_NAMES_TABLE_ENTRY("mwaitx", FEATURE_MWAITX, P_ZERO, "-mmwaitx")
+  ISA_NAMES_TABLE_ENTRY("ospke", FEATURE_OSPKE, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("osxsave", FEATURE_OSXSAVE, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("pconfig", FEATURE_PCONFIG, P_ZERO, "-mpconfig")
+  ISA_NAMES_TABLE_ENTRY("pku", FEATURE_PKU, P_ZERO, "-mpku")
+  ISA_NAMES_TABLE_ENTRY("prefetchwt1", FEATURE_PREFETCHWT1, P_ZERO,
+			"-mprefetchwt1")
+  ISA_NAMES_TABLE_ENTRY("prfchw", FEATURE_PRFCHW, P_ZERO, "-mprfchw")
+  ISA_NAMES_TABLE_ENTRY("ptwrite", FEATURE_PTWRITE, P_ZERO, "-mptwrite")
+  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
+  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
+  ISA_NAMES_TABLE_ENTRY("rdseed", FEATURE_RDSEED, P_ZERO, "-mrdseed")
+  ISA_NAMES_TABLE_ENTRY("rtm", FEATURE_RTM, P_ZERO, "-mrtm")
+  ISA_NAMES_TABLE_ENTRY("serialize", FEATURE_SERIALIZE, P_ZERO,
+			"-mserialize")
+  ISA_NAMES_TABLE_ENTRY("sgx", FEATURE_SGX, P_ZERO, "-msgx")
+  ISA_NAMES_TABLE_ENTRY("sha", FEATURE_SHA, P_ZERO, "-msha")
+  ISA_NAMES_TABLE_ENTRY("shstk", FEATURE_SHSTK, P_ZERO, "-mshstk")
+  ISA_NAMES_TABLE_ENTRY("tbm", FEATURE_TBM, P_ZERO, "-mtbm")
+  ISA_NAMES_TABLE_ENTRY("tsxldtrk", FEATURE_TSXLDTRK, P_ZERO,
+			"-mtsxldtrk")
+  ISA_NAMES_TABLE_ENTRY("vaes", FEATURE_VAES, P_ZERO, "-mvaes")
+  ISA_NAMES_TABLE_ENTRY("waitpkg", FEATURE_WAITPKG, P_ZERO, "-mwaitpkg")
+  ISA_NAMES_TABLE_ENTRY("wbnoinvd", FEATURE_WBNOINVD, P_ZERO,
+			"-mwbnoinvd")
+  ISA_NAMES_TABLE_ENTRY("xsave", FEATURE_XSAVE, P_ZERO, "-mxsave")
+  ISA_NAMES_TABLE_ENTRY("xsavec", FEATURE_XSAVEC, P_ZERO, "-mxsavec")
+  ISA_NAMES_TABLE_ENTRY("xsaveopt", FEATURE_XSAVEOPT, P_ZERO,
+			"-mxsaveopt")
+  ISA_NAMES_TABLE_ENTRY("xsaves", FEATURE_XSAVES, P_ZERO, "-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 be3ed0158f2..fbbc957510a 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -90,6 +90,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "dwarf2out.h"
 #include "i386-builtins.h"
+#include "common/config/i386/cpuinfo-builtins.h"
+#include "common/config/i386/i386-isas.h"
 
 #undef BDESC
 #undef BDESC_FIRST
@@ -1835,235 +1837,66 @@ ix86_builtin_reciprocal (tree fndecl)
     }
 }
 
-/* Priority of i386 features, greater value is higher priority.   This is
-   used to decide the order in which function dispatch must happen.  For
-   instance, a version specialized for SSE4.2 should be checked for dispatch
-   before a version for SSE3, as SSE4.2 implies SSE3.  */
-enum feature_priority
-{
-  P_ZERO = 0,
-  P_MMX,
-  P_SSE,
-  P_SSE2,
-  P_SSE3,
-  P_SSSE3,
-  P_PROC_SSSE3,
-  P_SSE4_A,
-  P_PROC_SSE4_A,
-  P_SSE4_1,
-  P_SSE4_2,
-  P_PROC_SSE4_2,
-  P_POPCNT,
-  P_AES,
-  P_PCLMUL,
-  P_AVX,
-  P_PROC_AVX,
-  P_BMI,
-  P_PROC_BMI,
-  P_FMA4,
-  P_XOP,
-  P_PROC_XOP,
-  P_FMA,
-  P_PROC_FMA,
-  P_BMI2,
-  P_AVX2,
-  P_PROC_AVX2,
-  P_AVX512F,
-  P_PROC_AVX512F
-};
-
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512BF16,
-  F_AVX512VP2INTERSECT,
-  F_MAX
-};
-
-/* These are the values for vendor types and cpu types  and subtypes
-   in cpuinfo.c.  Cpu types and subtypes should be subtracted by
-   the corresponding start value.  */
-enum processor_model
-{
-  M_INTEL = 1,
-  M_AMD,
-  M_CPU_TYPE_START,
-  M_INTEL_BONNELL,
-  M_INTEL_CORE2,
-  M_INTEL_COREI7,
-  M_AMDFAM10H,
-  M_AMDFAM15H,
-  M_INTEL_SILVERMONT,
-  M_INTEL_KNL,
-  M_AMD_BTVER1,
-  M_AMD_BTVER2,
-  M_AMDFAM17H,
-  M_INTEL_KNM,
-  M_INTEL_GOLDMONT,
-  M_INTEL_GOLDMONT_PLUS,
-  M_INTEL_TREMONT,
-  M_CPU_SUBTYPE_START,
-  M_INTEL_COREI7_NEHALEM,
-  M_INTEL_COREI7_WESTMERE,
-  M_INTEL_COREI7_SANDYBRIDGE,
-  M_AMDFAM10H_BARCELONA,
-  M_AMDFAM10H_SHANGHAI,
-  M_AMDFAM10H_ISTANBUL,
-  M_AMDFAM15H_BDVER1,
-  M_AMDFAM15H_BDVER2,
-  M_AMDFAM15H_BDVER3,
-  M_AMDFAM15H_BDVER4,
-  M_AMDFAM17H_ZNVER1,
-  M_INTEL_COREI7_IVYBRIDGE,
-  M_INTEL_COREI7_HASWELL,
-  M_INTEL_COREI7_BROADWELL,
-  M_INTEL_COREI7_SKYLAKE,
-  M_INTEL_COREI7_SKYLAKE_AVX512,
-  M_INTEL_COREI7_CANNONLAKE,
-  M_INTEL_COREI7_ICELAKE_CLIENT,
-  M_INTEL_COREI7_ICELAKE_SERVER,
-  M_AMDFAM17H_ZNVER2,
-  M_INTEL_COREI7_CASCADELAKE,
-  M_INTEL_COREI7_TIGERLAKE,
-  M_INTEL_COREI7_COOPERLAKE
-};
-
 struct _arch_names_table
 {
   const char *const name;
-  const enum processor_model model;
+  const int model;
 };
 
-static const _arch_names_table arch_names_table[] =
-{
-  {"amd", M_AMD},
-  {"intel", M_INTEL},
-  {"atom", M_INTEL_BONNELL},
-  {"slm", M_INTEL_SILVERMONT},
-  {"core2", M_INTEL_CORE2},
-  {"corei7", M_INTEL_COREI7},
-  {"nehalem", M_INTEL_COREI7_NEHALEM},
-  {"westmere", M_INTEL_COREI7_WESTMERE},
-  {"sandybridge", M_INTEL_COREI7_SANDYBRIDGE},
-  {"ivybridge", M_INTEL_COREI7_IVYBRIDGE},
-  {"haswell", M_INTEL_COREI7_HASWELL},
-  {"broadwell", M_INTEL_COREI7_BROADWELL},
-  {"skylake", M_INTEL_COREI7_SKYLAKE},
-  {"skylake-avx512", M_INTEL_COREI7_SKYLAKE_AVX512},
-  {"cannonlake", M_INTEL_COREI7_CANNONLAKE},
-  {"icelake-client", M_INTEL_COREI7_ICELAKE_CLIENT},
-  {"icelake-server", M_INTEL_COREI7_ICELAKE_SERVER},
-  {"cascadelake", M_INTEL_COREI7_CASCADELAKE},
-  {"tigerlake", M_INTEL_COREI7_TIGERLAKE},
-  {"cooperlake", M_INTEL_COREI7_COOPERLAKE},
-  {"bonnell", M_INTEL_BONNELL},
-  {"silvermont", M_INTEL_SILVERMONT},
-  {"goldmont", M_INTEL_GOLDMONT},
-  {"goldmont-plus", M_INTEL_GOLDMONT_PLUS},
-  {"tremont", M_INTEL_TREMONT},
-  {"knl", M_INTEL_KNL},
-  {"knm", M_INTEL_KNM},
-  {"amdfam10h", M_AMDFAM10H},
-  {"barcelona", M_AMDFAM10H_BARCELONA},
-  {"shanghai", M_AMDFAM10H_SHANGHAI},
-  {"istanbul", M_AMDFAM10H_ISTANBUL},
-  {"btver1", M_AMD_BTVER1},
-  {"amdfam15h", M_AMDFAM15H},
-  {"bdver1", M_AMDFAM15H_BDVER1},
-  {"bdver2", M_AMDFAM15H_BDVER2},
-  {"bdver3", M_AMDFAM15H_BDVER3},
-  {"bdver4", M_AMDFAM15H_BDVER4},
-  {"btver2", M_AMD_BTVER2},
-  {"amdfam17h", M_AMDFAM17H},
-  {"znver1", M_AMDFAM17H_ZNVER1},
-  {"znver2", M_AMDFAM17H_ZNVER2},
-};
+/* These are the values for vendor types, cpu types and subtypes in
+   cpuinfo.h.  Cpu types and subtypes should be subtracted by the
+   corresponding start value.  */
 
-/* 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;
-};
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+  (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
 
-static const _isa_names_table isa_names_table[] =
+static const _arch_names_table arch_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_ZERO},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_ZERO},
-  {"avx512bw",F_AVX512BW, P_ZERO},
-  {"avx512dq",F_AVX512DQ, P_ZERO},
-  {"avx512cd",F_AVX512CD, P_ZERO},
-  {"avx512er",F_AVX512ER, P_ZERO},
-  {"avx512pf",F_AVX512PF, P_ZERO},
-  {"avx512vbmi",F_AVX512VBMI, P_ZERO},
-  {"avx512ifma",F_AVX512IFMA, P_ZERO},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_ZERO},
-  {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
-  {"gfni",	F_GFNI,	P_ZERO},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
-  {"avx512vnni", F_AVX512VNNI, P_ZERO},
-  {"avx512bitalg", F_AVX512BITALG, P_ZERO},
-  {"avx512bf16", F_AVX512BF16, P_ZERO},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO}
+  {"amd", M_VENDOR (VENDOR_AMD)},
+  {"intel", M_VENDOR (VENDOR_INTEL)},
+  {"atom", M_CPU_TYPE (INTEL_BONNELL)},
+  {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"core2", M_CPU_TYPE (INTEL_CORE2)},
+  {"corei7", M_CPU_TYPE (INTEL_COREI7)},
+  {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
+  {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
+  {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
+  {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
+  {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
+  {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
+  {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
+  {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
+  {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
+  {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
+  {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
+  {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
+  {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
+  {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
+  {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
+  {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
+  {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
+  {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
+  {"knl", M_CPU_TYPE (INTEL_KNL)},
+  {"knm", M_CPU_TYPE (INTEL_KNM)},
+  {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
+  {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
+  {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
+  {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
+  {"btver1", M_CPU_TYPE (AMD_BTVER1)},
+  {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
+  {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
+  {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
+  {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
+  {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
+  {"btver2", M_CPU_TYPE (AMD_BTVER2)},
+  {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
+  {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
+  {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
 };
 
 /* This parses the attribute arguments to target in DECL and determines
@@ -2509,16 +2342,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
 
       if (isa_names_table[i].feature >= 32)
 	{
-	  tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+	  tree index_type
+	    = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+	  tree type = build_array_type (unsigned_type_node, index_type);
+	  tree __cpu_features2_var = make_var_decl (type,
 						    "__cpu_features2");
 
 	  varpool_node::add (__cpu_features2_var);
-	  field_val = (1U << (isa_names_table[i].feature - 32));
-	  /* Return __cpu_features2 & field_val  */
-	  final = build2 (BIT_AND_EXPR, unsigned_type_node,
-			  __cpu_features2_var,
-			  build_int_cstu (unsigned_type_node, field_val));
-	  return build1 (CONVERT_EXPR, integer_type_node, final);
+	  for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+	    if (isa_names_table[i].feature < (32 + 32 + j * 32))
+	      {
+		field_val = (1U << (isa_names_table[i].feature
+				    - (32 + j * 32)));
+		tree index = size_int (j);
+		array_elt = build4 (ARRAY_REF, unsigned_type_node,
+				    __cpu_features2_var,
+				    index, NULL_TREE, NULL_TREE);
+		/* Return __cpu_features2[index] & field_val  */
+		final = build2 (BIT_AND_EXPR, unsigned_type_node,
+				array_elt,
+				build_int_cstu (unsigned_type_node,
+						field_val));
+		return build1 (CONVERT_EXPR, integer_type_node, final);
+	      }
 	}
 
       field = TYPE_FIELDS (__processor_model_type);
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..368c0a54efe 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,348 +7,52 @@
 /* { 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/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;
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index cf5f0884bb4..49c5107546f 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +39,14 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
    size of __cpu_model is part of ABI.  So, new features that don't
    fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
-
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
-/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
-   the max possible level of CPUID insn.  */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
-			int max_cpuid_level)
-{
-  unsigned int eax, ebx;
-  unsigned int ext_level;
-
-  unsigned int features = 0;
-  unsigned int features2 = 0;
-
-  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
-#define XCR_XFEATURE_ENABLED_MASK	0x0
-#define XSTATE_FP			0x1
-#define XSTATE_SSE			0x2
-#define XSTATE_YMM			0x4
-#define XSTATE_OPMASK			0x20
-#define XSTATE_ZMM			0x40
-#define XSTATE_HI_ZMM			0x80
-
-#define XCR_AVX_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
-  /* Check if AVX and AVX512 are usable.  */
-  int avx_usable = 0;
-  int avx512_usable = 0;
-  if ((ecx & bit_OSXSAVE))
-    {
-      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
-         ZMM16-ZMM31 states are supported by OSXSAVE.  */
-      unsigned int xcrlow;
-      unsigned int xcrhigh;
-      asm (".byte 0x0f, 0x01, 0xd0"
-	   : "=a" (xcrlow), "=d" (xcrhigh)
-	   : "c" (XCR_XFEATURE_ENABLED_MASK));
-      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
-	{
-	  avx_usable = 1;
-	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
-			   == XCR_AVX512F_ENABLED_MASK);
-	}
-    }
-
-#define set_feature(f) \
-  do						\
-    {						\
-      if (f < 32)				\
-	features |= (1U << (f & 31));		\
-      else					\
-	features2 |= (1U << ((f - 32) & 31));	\
-    }						\
-  while (0)
-
-  if (edx & bit_CMOV)
-    set_feature (FEATURE_CMOV);
-  if (edx & bit_MMX)
-    set_feature (FEATURE_MMX);
-  if (edx & bit_SSE)
-    set_feature (FEATURE_SSE);
-  if (edx & bit_SSE2)
-    set_feature (FEATURE_SSE2);
-  if (ecx & bit_POPCNT)
-    set_feature (FEATURE_POPCNT);
-  if (ecx & bit_AES)
-    set_feature (FEATURE_AES);
-  if (ecx & bit_PCLMUL)
-    set_feature (FEATURE_PCLMUL);
-  if (ecx & bit_SSE3)
-    set_feature (FEATURE_SSE3);
-  if (ecx & bit_SSSE3)
-    set_feature (FEATURE_SSSE3);
-  if (ecx & bit_SSE4_1)
-    set_feature (FEATURE_SSE4_1);
-  if (ecx & bit_SSE4_2)
-    set_feature (FEATURE_SSE4_2);
-  if (avx_usable)
-    {
-      if (ecx & bit_AVX)
-	set_feature (FEATURE_AVX);
-      if (ecx & bit_FMA)
-	set_feature (FEATURE_FMA);
-    }
-
-  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
-  if (max_cpuid_level >= 7)
-    {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
-      if (ebx & bit_BMI)
-	set_feature (FEATURE_BMI);
-      if (avx_usable)
-	{
-	  if (ebx & bit_AVX2)
-	    set_feature (FEATURE_AVX2);
-	  if (ecx & bit_VPCLMULQDQ)
-	    set_feature (FEATURE_VPCLMULQDQ);
-	}
-      if (ebx & bit_BMI2)
-	set_feature (FEATURE_BMI2);
-      if (ecx & bit_GFNI)
-	set_feature (FEATURE_GFNI);
-      if (avx512_usable)
-	{
-	  if (ebx & bit_AVX512F)
-	    set_feature (FEATURE_AVX512F);
-	  if (ebx & bit_AVX512VL)
-	    set_feature (FEATURE_AVX512VL);
-	  if (ebx & bit_AVX512BW)
-	    set_feature (FEATURE_AVX512BW);
-	  if (ebx & bit_AVX512DQ)
-	    set_feature (FEATURE_AVX512DQ);
-	  if (ebx & bit_AVX512CD)
-	    set_feature (FEATURE_AVX512CD);
-	  if (ebx & bit_AVX512PF)
-	    set_feature (FEATURE_AVX512PF);
-	  if (ebx & bit_AVX512ER)
-	    set_feature (FEATURE_AVX512ER);
-	  if (ebx & bit_AVX512IFMA)
-	    set_feature (FEATURE_AVX512IFMA);
-	  if (ecx & bit_AVX512VBMI)
-	    set_feature (FEATURE_AVX512VBMI);
-	  if (ecx & bit_AVX512VBMI2)
-	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_AVX512VNNI)
-	    set_feature (FEATURE_AVX512VNNI);
-	  if (ecx & bit_AVX512BITALG)
-	    set_feature (FEATURE_AVX512BITALG);
-	  if (ecx & bit_AVX512VPOPCNTDQ)
-	    set_feature (FEATURE_AVX512VPOPCNTDQ);
-	  if (edx & bit_AVX5124VNNIW)
-	    set_feature (FEATURE_AVX5124VNNIW);
-	  if (edx & bit_AVX5124FMAPS)
-	    set_feature (FEATURE_AVX5124FMAPS);
-	  if (edx & bit_AVX512VP2INTERSECT)
-	    set_feature (FEATURE_AVX512VP2INTERSECT);
+   in libgcc.a only, preferably hidden.
 
-	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
-	  if (eax & bit_AVX512BF16)
-	    set_feature (FEATURE_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)
-	set_feature (FEATURE_SSE4_A);
-      if (avx_usable)
-	{
-	  if (ecx & bit_FMA4)
-	    set_feature (FEATURE_FMA4);
-	  if (ecx & bit_XOP)
-	    set_feature (FEATURE_XOP);
-	}
-    }
-    
-  __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
-  __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
-}
+   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+   smaller array, it can only access the first few elements.  */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
    the right values.  This needs to run only once.  This constructor is
@@ -429,85 +57,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
 __cpu_indicator_init (void)
 {
-  unsigned int eax, ebx, ecx, edx;
-
-  int max_level;
-  unsigned int vendor;
-  unsigned int model, family, brand_id;
-  unsigned int extended_model, extended_family;
-
-  /* This function needs to run just once.  */
-  if (__cpu_model.__cpu_vendor)
-    return 0;
-
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  vendor = ebx;
-  max_level = eax;
-
-  if (max_level < 1)
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
-    {
-      /* Adjust model and family for Intel CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_INTEL;
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_AMD;
-    }
-  else
-    __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
-  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
-  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
-  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
-  return 0;
+  struct __processor_model2 cpu_model2;
+  return cpu_indicator_init (&__cpu_model, &cpu_model2,
+			     __cpu_features2);
 }
 
 #if defined SHARED && defined USE_ELF_SYMVER
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-26 11:59                                 ` V5 " H.J. Lu
@ 2020-05-26 13:27                                   ` Martin Liška
  2020-06-09 16:35                                     ` PING^1: " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Martin Liška @ 2020-05-26 13:27 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Uros Bizjak, Jan Hubicka, Jakub Jelinek, Jeffrey Law,
	Richard Biener, gcc-patches

On 5/26/20 1:59 PM, H.J. Lu wrote:
> On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
>>
>> On 5/25/20 7:42 PM, H.J. Lu wrote:
>>> Here is the updated patch.  OK for master?
>>
>> Thank you for the updated patch.
>>
>> I have still few nits:
>>
>> 1) I would make all the:
>>
>>> +  has_sse3 = has_feature (FEATURE_SSE3);
>>
>> a macro. The local variable seems to superfluous.
> 
> Done.

Thanks!

> 
>> 2) can we automatically deduce option name:
>>
>>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
>>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
>>
>> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> 
> The new option field serves 2 purposes:
> 
> 1. Not all features have a corresponding command-line option
> 
> ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> 
>       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
>          if (isa_names_table[i].option)
> 
> 2. Some feature has a different name in the command-line option.
> 
>    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")

I noticed that, one can theoretically use "" for an option that does not
have a flag. And NULL for these which have option equal to "-m" + name.
Anyway, that's a nit.

I support the patch!
Martin

> 
> Here is the updated patch.   OK for master?
> 
> Thanks.
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* PING^1: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-05-26 13:27                                   ` Martin Liška
@ 2020-06-09 16:35                                     ` H.J. Lu
  2020-06-16 17:11                                       ` PING^2: " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-06-09 16:35 UTC (permalink / raw)
  To: Martin Liška
  Cc: Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener, gcc-patches

On Tue, May 26, 2020 at 6:27 AM Martin Liška <mliska@suse.cz> wrote:
>
> On 5/26/20 1:59 PM, H.J. Lu wrote:
> > On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
> >>
> >> On 5/25/20 7:42 PM, H.J. Lu wrote:
> >>> Here is the updated patch.  OK for master?
> >>
> >> Thank you for the updated patch.
> >>
> >> I have still few nits:
> >>
> >> 1) I would make all the:
> >>
> >>> +  has_sse3 = has_feature (FEATURE_SSE3);
> >>
> >> a macro. The local variable seems to superfluous.
> >
> > Done.
>
> Thanks!
>
> >
> >> 2) can we automatically deduce option name:
> >>
> >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> >>
> >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> >
> > The new option field serves 2 purposes:
> >
> > 1. Not all features have a corresponding command-line option
> >
> > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> >
> >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> >          if (isa_names_table[i].option)
> >
> > 2. Some feature has a different name in the command-line option.
> >
> >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
>
> I noticed that, one can theoretically use "" for an option that does not
> have a flag. And NULL for these which have option equal to "-m" + name.
> Anyway, that's a nit.
>
> I support the patch!
> Martin
>
> >
> > Here is the updated patch.   OK for master?
> >
> > Thanks.
> >
>

PING:

https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* PING^2: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-09 16:35                                     ` PING^1: " H.J. Lu
@ 2020-06-16 17:11                                       ` H.J. Lu
  2020-06-20 13:39                                         ` H.J. Lu
  2020-06-24  6:25                                         ` PING^2: V5 " Martin Liška
  0 siblings, 2 replies; 30+ messages in thread
From: H.J. Lu @ 2020-06-16 17:11 UTC (permalink / raw)
  To: Martin Liška
  Cc: Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener, gcc-patches

On Tue, Jun 9, 2020 at 9:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, May 26, 2020 at 6:27 AM Martin Liška <mliska@suse.cz> wrote:
> >
> > On 5/26/20 1:59 PM, H.J. Lu wrote:
> > > On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
> > >>
> > >> On 5/25/20 7:42 PM, H.J. Lu wrote:
> > >>> Here is the updated patch.  OK for master?
> > >>
> > >> Thank you for the updated patch.
> > >>
> > >> I have still few nits:
> > >>
> > >> 1) I would make all the:
> > >>
> > >>> +  has_sse3 = has_feature (FEATURE_SSE3);
> > >>
> > >> a macro. The local variable seems to superfluous.
> > >
> > > Done.
> >
> > Thanks!
> >
> > >
> > >> 2) can we automatically deduce option name:
> > >>
> > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > >>
> > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > >
> > > The new option field serves 2 purposes:
> > >
> > > 1. Not all features have a corresponding command-line option
> > >
> > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > >
> > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > >          if (isa_names_table[i].option)
> > >
> > > 2. Some feature has a different name in the command-line option.
> > >
> > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> >
> > I noticed that, one can theoretically use "" for an option that does not
> > have a flag. And NULL for these which have option equal to "-m" + name.
> > Anyway, that's a nit.
> >
> > I support the patch!
> > Martin
> >
> > >
> > > Here is the updated patch.   OK for master?
> > >
> > > Thanks.
> > >
> >
>
> PING:
>
> https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
>

PING.

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: PING^2: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-16 17:11                                       ` PING^2: " H.J. Lu
@ 2020-06-20 13:39                                         ` H.J. Lu
  2020-06-21 17:18                                           ` Uros Bizjak
  2020-06-24  6:25                                         ` PING^2: V5 " Martin Liška
  1 sibling, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-06-20 13:39 UTC (permalink / raw)
  To: Martin Liška, Uros Bizjak, GCC Patches
  Cc: Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener

On Tue, Jun 16, 2020 at 10:11 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Jun 9, 2020 at 9:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, May 26, 2020 at 6:27 AM Martin Liška <mliska@suse.cz> wrote:
> > >
> > > On 5/26/20 1:59 PM, H.J. Lu wrote:
> > > > On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
> > > >>
> > > >> On 5/25/20 7:42 PM, H.J. Lu wrote:
> > > >>> Here is the updated patch.  OK for master?
> > > >>
> > > >> Thank you for the updated patch.
> > > >>
> > > >> I have still few nits:
> > > >>
> > > >> 1) I would make all the:
> > > >>
> > > >>> +  has_sse3 = has_feature (FEATURE_SSE3);
> > > >>
> > > >> a macro. The local variable seems to superfluous.
> > > >
> > > > Done.
> > >
> > > Thanks!
> > >
> > > >
> > > >> 2) can we automatically deduce option name:
> > > >>
> > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > >>
> > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > >
> > > > The new option field serves 2 purposes:
> > > >
> > > > 1. Not all features have a corresponding command-line option
> > > >
> > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > >
> > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > >          if (isa_names_table[i].option)
> > > >
> > > > 2. Some feature has a different name in the command-line option.
> > > >
> > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > >
> > > I noticed that, one can theoretically use "" for an option that does not
> > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > Anyway, that's a nit.
> > >
> > > I support the patch!
> > > Martin
> > >
> > > >
> > > > Here is the updated patch.   OK for master?
> > > >
> > > > Thanks.
> > > >
> > >
> >
> > PING:
> >
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> >
>
> PING.

Hi,

We have patches like

https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html

queued up because of this prerequisite patch.   Are there any objections
to this patch?

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: PING^2: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-20 13:39                                         ` H.J. Lu
@ 2020-06-21 17:18                                           ` Uros Bizjak
  2020-06-21 17:22                                             ` H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: Uros Bizjak @ 2020-06-21 17:18 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Martin Liška, GCC Patches, Jan Hubicka, Jakub Jelinek,
	Jeffrey Law, Richard Biener

On Sat, Jun 20, 2020 at 3:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> > > > >> 2) can we automatically deduce option name:
> > > > >>
> > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > > >>
> > > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > > >
> > > > > The new option field serves 2 purposes:
> > > > >
> > > > > 1. Not all features have a corresponding command-line option
> > > > >
> > > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > > >
> > > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > > >          if (isa_names_table[i].option)
> > > > >
> > > > > 2. Some feature has a different name in the command-line option.
> > > > >
> > > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > > >
> > > > I noticed that, one can theoretically use "" for an option that does not
> > > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > > Anyway, that's a nit.
> > > >
> > > > I support the patch!
> > > > Martin
> > > >
> > > > >
> > > > > Here is the updated patch.   OK for master?
> > > > >
> > > > > Thanks.
> > > > >
> > > >
> > >
> > > PING:
> > >
> > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > >
> >
> > PING.
>
> Hi,
>
> We have patches like
>
> https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html
>
> queued up because of this prerequisite patch.   Are there any objections
> to this patch?

Yes, there are my objections.

As explained before, I support unifying libgcc and core gcc handling,
but _NOT_ unifying with driver-i386.c. Unifying libgcc and core gcc
handling would have benefit to avoid desynchronisation between the two
(which happened multiple times in the past, resulting in various API
issues). OTOH, unifying with driver-i386.c would result in quite messy
approach, because driver-i386 handles more targets beside relatively
recent 64bit Intel and AMD targets, not to mention heuristics to
determine the most appropriate target when standard detection fails
(e.g. emulators).

Uros.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: PING^2: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-21 17:18                                           ` Uros Bizjak
@ 2020-06-21 17:22                                             ` H.J. Lu
  2020-06-22 23:25                                               ` V6 " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-06-21 17:22 UTC (permalink / raw)
  To: Uros Bizjak
  Cc: Martin Liška, GCC Patches, Jan Hubicka, Jakub Jelinek,
	Jeffrey Law, Richard Biener

On Sun, Jun 21, 2020 at 10:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Sat, Jun 20, 2020 at 3:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> > > > > >> 2) can we automatically deduce option name:
> > > > > >>
> > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > > > >>
> > > > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > > > >
> > > > > > The new option field serves 2 purposes:
> > > > > >
> > > > > > 1. Not all features have a corresponding command-line option
> > > > > >
> > > > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > > > >
> > > > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > > > >          if (isa_names_table[i].option)
> > > > > >
> > > > > > 2. Some feature has a different name in the command-line option.
> > > > > >
> > > > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > > > >
> > > > > I noticed that, one can theoretically use "" for an option that does not
> > > > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > > > Anyway, that's a nit.
> > > > >
> > > > > I support the patch!
> > > > > Martin
> > > > >
> > > > > >
> > > > > > Here is the updated patch.   OK for master?
> > > > > >
> > > > > > Thanks.
> > > > > >
> > > > >
> > > >
> > > > PING:
> > > >
> > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > > >
> > >
> > > PING.
> >
> > Hi,
> >
> > We have patches like
> >
> > https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html
> >
> > queued up because of this prerequisite patch.   Are there any objections
> > to this patch?
>
> Yes, there are my objections.
>
> As explained before, I support unifying libgcc and core gcc handling,
> but _NOT_ unifying with driver-i386.c. Unifying libgcc and core gcc
> handling would have benefit to avoid desynchronisation between the two
> (which happened multiple times in the past, resulting in various API
> issues). OTOH, unifying with driver-i386.c would result in quite messy
> approach, because driver-i386 handles more targets beside relatively
> recent 64bit Intel and AMD targets, not to mention heuristics to
> determine the most appropriate target when standard detection fails
> (e.g. emulators).

Only the duplicated parts of driver-i386.c should be unified.  The only impact
should be removing code duplications.  If it isn't the case, it is a bug in my
implementation.

-- 
H.J.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V6 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-21 17:22                                             ` H.J. Lu
@ 2020-06-22 23:25                                               ` H.J. Lu
  2020-06-24 12:27                                                 ` V7 " H.J. Lu
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-06-22 23:25 UTC (permalink / raw)
  To: Uros Bizjak
  Cc: Martin Liška, GCC Patches, Jan Hubicka, Jakub Jelinek,
	Jeffrey Law, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 3197 bytes --]

On Sun, Jun 21, 2020 at 10:22 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sun, Jun 21, 2020 at 10:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Sat, Jun 20, 2020 at 3:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > > > > > >> 2) can we automatically deduce option name:
> > > > > > >>
> > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > > > > >>
> > > > > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > > > > >
> > > > > > > The new option field serves 2 purposes:
> > > > > > >
> > > > > > > 1. Not all features have a corresponding command-line option
> > > > > > >
> > > > > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > > > > >
> > > > > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > > > > >          if (isa_names_table[i].option)
> > > > > > >
> > > > > > > 2. Some feature has a different name in the command-line option.
> > > > > > >
> > > > > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > > > > >
> > > > > > I noticed that, one can theoretically use "" for an option that does not
> > > > > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > > > > Anyway, that's a nit.
> > > > > >
> > > > > > I support the patch!
> > > > > > Martin
> > > > > >
> > > > > > >
> > > > > > > Here is the updated patch.   OK for master?
> > > > > > >
> > > > > > > Thanks.
> > > > > > >
> > > > > >
> > > > >
> > > > > PING:
> > > > >
> > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > > > >
> > > >
> > > > PING.
> > >
> > > Hi,
> > >
> > > We have patches like
> > >
> > > https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html
> > >
> > > queued up because of this prerequisite patch.   Are there any objections
> > > to this patch?
> >
> > Yes, there are my objections.
> >
> > As explained before, I support unifying libgcc and core gcc handling,
> > but _NOT_ unifying with driver-i386.c. Unifying libgcc and core gcc
> > handling would have benefit to avoid desynchronisation between the two
> > (which happened multiple times in the past, resulting in various API
> > issues). OTOH, unifying with driver-i386.c would result in quite messy
> > approach, because driver-i386 handles more targets beside relatively
> > recent 64bit Intel and AMD targets, not to mention heuristics to
> > determine the most appropriate target when standard detection fails
> > (e.g. emulators).
>
> Only the duplicated parts of driver-i386.c should be unified.  The only impact
> should be removing code duplications.  If it isn't the case, it is a bug in my
> implementation.

Here is the updated patch to remove FEATURE_OSPKE and use bit_OSPKE
for FEATURE_PKU.  It uses the same get_amd_cpu and get_intel_cpu in
libgcc and driver-i386.c:
   a. Detect the processor name for newer Intel and AMD processors.
      Since the older processor names are only supported by driver-i386.c,
      not by libgcc, detection for the older processors remains in
      driver-i386.c.
   b. Detect available ISAs for all Intel and AMD processors.

-- 
H.J.

[-- Attachment #2: 0001-x86-Move-cpuinfo.h-from-libgcc-to-common-config-i386.patch --]
[-- Type: text/x-patch, Size: 107178 bytes --]

From 13c2bedec0a81cebc2cf7b81cabb554f1d618781 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386

There are x86 code duplications:

1. 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.
2. Both x86 backend and libgcc define enum processor_features.  libgcc
sets enum processor_feature and x86 backend checks enum processor_feature.
They are very easy out of sync and it has happened multiple times in the
past.

Move cpuinfo.h from libgcc to common/config/i386 and move isa_names_table
to common/config/i386 so that we can

1. Use the same get_amd_cpu and get_intel_cpu in libgcc and driver-i386.c:
   a. Detect the processor name for newer Intel and AMD processors.
      Since the older processor names are only supported by driver-i386.c,
      not by libgcc, detection for the older processors remains in
      driver-i386.c.
   b. Detect available ISAs for all Intel and AMD processors.
2. Share the same enum processor_features and isa_names_table in x86
backend and libgcc.

This patch contains the following changes:

1. Use the same enum processor_features in libgcc and x86 backend.
2. Add more processor features to enum processor_features.
3. Use the same isa_names_table in i386-builtins.c, driver-i386.c and
gcc.target/i386/builtin_target.c.
4. Use isa_names_table to auto-generate ISA command-line options.
5. Use isa_names_table to auto-generate __builtin_cpu_supports tests.
6. Add M_VENDOR, M_CPU_TYPE and M_CPU_SUBTYPE in i386-builtins.c to
avoid duplication.
7. Use cpu_indicator_init, has_cpu_feature, get_amd_cpu and get_intel_cpu
in driver-i386.c and builtin_target.c.

gcc/

	PR target/95259
	* common/config/i386/cpuinfo-builtins.h: Moved from
	libgcc/config/i386/cpuinfo.h.
	(processor_vendor): Add VENDOR_CENTAUR, VENDOR_CYRIX, VENDOR_NSC
	and BUILTIN_VENDOR_MAX.
	(processor_types): Add BUILTIN_CPU_TYPE_MAX.
	(processor_features): Add FEATURE_3DNOW, FEATURE_3DNOWP,
	FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
	FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
	FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
	FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
	FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
	FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
	FEATURE_MWAITX, FEATURE_OSXSAVE, FEATURE_PCONFIG,
	FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
	(__processor_model): Moved to cpuinfo.h.
	(__cpu_model): Removed.
	(__cpu_features2): Likewise.
	(SIZE_OF_CPU_FEATURES): New.
	* common/config/i386/cpuinfo.h: Moved from
	libgcc/config/i386/cpuinfo.c.
	(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
	(__processor_model2): New.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(has_cpu_feature): New function.
	(set_cpu_feature): Likewise.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	Use CHECK___builtin_cpu_is.  Return Intel CPU name.
	(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
	Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
	FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
	FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
	FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
	FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
	FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
	FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSXSAVE,
	FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT and FEATURE_XSAVES
	(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
	Also update cpu_model2.
	* common/config/i386/i386-common.c (processor_alias_table): Add
	priority to each entry.
	* 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.  Replace F_XXX
	with FEATURE_XXX.  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 AMD CPU name.  Call get_intel_cpu to get
	Intel CPU name.  Use isa_names_table to generate command-line
	options.
	* config/i386/i386-builtins.c: Include
	"common/config/i386/cpuinfo.h" and
	"common/config/i386/i386-isas.h".
	(feature_priority): Moved to common/config/i386/i386-isas.h.
	(processor_features): Removed.
	(processor_model): Removed.
	(_arch_names_table): Use "const int" on model.
	(M_CPU_TYPE_START): New.
	(M_CPU_SUBTYPE_START): Likewise.
	(M_VENDOR): Likewise.
	(M_CPU_TYPE): Likewise.
	(M_CPU_SUBTYPE): Likewise.
	(arch_names_table): Replace M_XXX with M_VENDOR, M_CPU_TYPE and
	M_CPU_SUBTYPE.
	(isa_names_table): Moved to common/config/i386/i386-isas.h.
	(fold_builtin_cpu): Change __cpu_features2 to an array.

gcc/testsuite/

	PR target/95259
	* gcc.target/i386/builtin_target.c: Include <stdlib.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.

libgcc/

	PR target/95259
	* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
	(__cpu_features2): Changed to array.
	(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
	(get_intel_cpu): Likewise.
	(get_available_features): Likewise.
	(__cpu_indicator_init): Call cpu_indicator_init.
	* config/i386/cpuinfo.h: Moved to
	gcc/common/config/i386/cpuinfo-builtins.h.
---
 .../common/config/i386/cpuinfo-builtins.h     |  69 +-
 gcc/common/config/i386/cpuinfo.h              | 846 ++++++++++++++++++
 gcc/common/config/i386/i386-isas.h            | 200 +++++
 gcc/config/i386/driver-i386.c                 | 680 +++-----------
 gcc/config/i386/i386-builtins.c               | 302 ++-----
 .../gcc.target/i386/builtin_target.c          | 354 +-------
 libgcc/config/i386/cpuinfo.c                  | 464 +---------
 7 files changed, 1324 insertions(+), 1591 deletions(-)
 rename libgcc/config/i386/cpuinfo.h => gcc/common/config/i386/cpuinfo-builtins.h (71%)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 create mode 100644 gcc/common/config/i386/i386-isas.h

diff --git a/libgcc/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo-builtins.h
similarity index 71%
rename from libgcc/config/i386/cpuinfo.h
rename to gcc/common/config/i386/cpuinfo-builtins.h
index 0f97510cde1..e87d7f515f8 100644
--- a/libgcc/config/i386/cpuinfo.h
+++ b/gcc/common/config/i386/cpuinfo-builtins.h
@@ -30,6 +30,10 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
+  BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
 
@@ -45,13 +49,14 @@ enum processor_types
   INTEL_SILVERMONT,
   INTEL_KNL,
   AMD_BTVER1,
-  AMD_BTVER2,  
+  AMD_BTVER2,
   AMDFAM17H,
   INTEL_KNM,
   INTEL_GOLDMONT,
   INTEL_GOLDMONT_PLUS,
   INTEL_TREMONT,
-  CPU_TYPE_MAX
+  CPU_TYPE_MAX,
+  BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
 };
 
 enum processor_subtypes
@@ -123,14 +128,56 @@ enum processor_features
   FEATURE_AVX512VNNI,
   FEATURE_AVX512BITALG,
   FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_3DNOW,
+  FEATURE_3DNOWP,
+  FEATURE_ADX,
+  FEATURE_ABM,
+  FEATURE_CLDEMOTE,
+  FEATURE_CLFLUSHOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO,
+  FEATURE_CMPXCHG16B,
+  FEATURE_CMPXCHG8B,
+  FEATURE_ENQCMD,
+  FEATURE_F16C,
+  FEATURE_FSGSBASE,
+  FEATURE_FXSAVE,
+  FEATURE_HLE,
+  FEATURE_IBT,
+  FEATURE_LAHF_LM,
+  FEATURE_LM,
+  FEATURE_LWP,
+  FEATURE_LZCNT,
+  FEATURE_MOVBE,
+  FEATURE_MOVDIR64B,
+  FEATURE_MOVDIRI,
+  FEATURE_MWAITX,
+  FEATURE_OSXSAVE,
+  FEATURE_PCONFIG,
+  FEATURE_PKU,
+  FEATURE_PREFETCHWT1,
+  FEATURE_PRFCHW,
+  FEATURE_PTWRITE,
+  FEATURE_RDPID,
+  FEATURE_RDRND,
+  FEATURE_RDSEED,
+  FEATURE_RTM,
+  FEATURE_SERIALIZE,
+  FEATURE_SGX,
+  FEATURE_SHA,
+  FEATURE_SHSTK,
+  FEATURE_TBM,
+  FEATURE_TSXLDTRK,
+  FEATURE_VAES,
+  FEATURE_WAITPKG,
+  FEATURE_WBNOINVD,
+  FEATURE_XSAVE,
+  FEATURE_XSAVEC,
+  FEATURE_XSAVEOPT,
+  FEATURE_XSAVES,
+  CPU_FEATURE_MAX
 };
 
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..c7300ef1a2b
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,846 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "cpuinfo-builtins.h"
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  /* The first 32 features are stored as bitmasks in __cpu_features.
+     The rest of features are stored as bitmasks in a separate array
+     of unsigned int.  */
+  unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+  unsigned int __cpu_family;
+  unsigned int __cpu_model;
+  unsigned int __cpu_max_level;
+  unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      return cpu_model->__cpu_features[0] & (1U << (f & 31));
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+  gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+      {
+	cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+	return;
+      }
+  gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+	     struct __processor_model2 *cpu_model2,
+	     unsigned int *cpu_features2)
+{
+  const char *cpu = NULL;
+  unsigned int family = cpu_model2->__cpu_family;
+  unsigned int model = cpu_model2->__cpu_model;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_AVX2))
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XSAVEOPT))
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_BMI))
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XOP))
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLWB))
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLZERO))
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       struct __processor_model2 *cpu_model2,
+	       unsigned int *cpu_features2,
+	       unsigned int brand_id)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+    return cpu;
+
+  switch (cpu_model2->__cpu_model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_cpu_feature (cpu_model, cpu_features2,
+			   FEATURE_AVX512VNNI))
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one.  */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+			struct __processor_model2 *cpu_model2,
+			unsigned int *cpu_features2,
+			unsigned int ecx, unsigned int edx)
+{
+  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+  unsigned int eax, ebx;
+  unsigned int ext_level;
+
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+#define XSTATE_FP			0x1
+#define XSTATE_SSE			0x2
+#define XSTATE_YMM			0x4
+#define XSTATE_OPMASK			0x20
+#define XSTATE_ZMM			0x40
+#define XSTATE_HI_ZMM			0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      __asm__ (".byte 0x0f, 0x01, 0xd0"
+	       : "=a" (xcrlow), "=d" (xcrhigh)
+	       : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+	{
+	  avx_usable = 1;
+	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+			   == XCR_AVX512F_ENABLED_MASK);
+	}
+    }
+
+#define set_feature(f) \
+  set_cpu_feature (cpu_model, cpu_features2, f)
+
+  if (edx & bit_CMOV)
+    set_feature (FEATURE_CMOV);
+  if (edx & bit_MMX)
+    set_feature (FEATURE_MMX);
+  if (edx & bit_SSE)
+    set_feature (FEATURE_SSE);
+  if (edx & bit_SSE2)
+    set_feature (FEATURE_SSE2);
+  if (edx & bit_CMPXCHG8B)
+    set_feature (FEATURE_CMPXCHG8B);
+  if (edx & bit_FXSAVE)
+    set_feature (FEATURE_FXSAVE);
+
+  if (ecx & bit_POPCNT)
+    set_feature (FEATURE_POPCNT);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_PCLMUL)
+    set_feature (FEATURE_PCLMUL);
+  if (ecx & bit_SSE3)
+    set_feature (FEATURE_SSE3);
+  if (ecx & bit_SSSE3)
+    set_feature (FEATURE_SSSE3);
+  if (ecx & bit_SSE4_1)
+    set_feature (FEATURE_SSE4_1);
+  if (ecx & bit_SSE4_2)
+    set_feature (FEATURE_SSE4_2);
+  if (ecx & bit_OSXSAVE)
+    set_feature (FEATURE_OSXSAVE);
+  if (ecx & bit_CMPXCHG16B)
+    set_feature (FEATURE_CMPXCHG16B);
+  if (ecx & bit_MOVBE)
+    set_feature (FEATURE_MOVBE);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_F16C)
+    set_feature (FEATURE_F16C);
+  if (ecx & bit_RDRND)
+    set_feature (FEATURE_RDRND);
+  if (ecx & bit_XSAVE)
+    set_feature (FEATURE_XSAVE);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+	set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+	set_feature (FEATURE_FMA);
+    }
+
+  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+  if (max_cpuid_level >= 7)
+    {
+      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_BMI)
+	set_feature (FEATURE_BMI);
+      if (ebx & bit_SGX)
+	set_feature (FEATURE_SGX);
+      if (ebx & bit_HLE)
+	set_feature (FEATURE_HLE);
+      if (ebx & bit_RTM)
+	set_feature (FEATURE_RTM);
+      if (avx_usable)
+	{
+	  if (ebx & bit_AVX2)
+	    set_feature (FEATURE_AVX2);
+	  if (ecx & bit_VPCLMULQDQ)
+	    set_feature (FEATURE_VPCLMULQDQ);
+	}
+      if (ebx & bit_BMI2)
+	set_feature (FEATURE_BMI2);
+      if (ebx & bit_FSGSBASE)
+	set_feature (FEATURE_FSGSBASE);
+      if (ebx & bit_RDSEED)
+	set_feature (FEATURE_RDSEED);
+      if (ebx & bit_ADX)
+	set_feature (FEATURE_ADX);
+      if (ebx & bit_SHA)
+	set_feature (FEATURE_SHA);
+      if (ebx & bit_CLFLUSHOPT)
+	set_feature (FEATURE_CLFLUSHOPT);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
+      if (ecx & bit_PREFETCHWT1)
+	set_feature (FEATURE_PREFETCHWT1);
+      /* NB: bit_OSPKE indicates that OS supports PKU.  */
+      if (ecx & bit_OSPKE)
+	set_feature (FEATURE_PKU);
+      if (ecx & bit_RDPID)
+	set_feature (FEATURE_RDPID);
+      if (ecx & bit_VAES)
+	set_feature (FEATURE_VAES);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ecx & bit_MOVDIRI)
+	set_feature (FEATURE_MOVDIRI);
+      if (ecx & bit_MOVDIR64B)
+	set_feature (FEATURE_MOVDIR64B);
+      if (ecx & bit_ENQCMD)
+	set_feature (FEATURE_ENQCMD);
+      if (ecx & bit_CLDEMOTE)
+	set_feature (FEATURE_CLDEMOTE);
+      if (ecx & bit_WAITPKG)
+	set_feature (FEATURE_WAITPKG);
+      if (ecx & bit_SHSTK)
+	set_feature (FEATURE_SHSTK);
+      if (edx & bit_SERIALIZE)
+	set_feature (FEATURE_SERIALIZE);
+      if (edx & bit_TSXLDTRK)
+	set_feature (FEATURE_TSXLDTRK);
+      if (edx & bit_PCONFIG)
+	set_feature (FEATURE_PCONFIG);
+      if (edx & bit_IBT)
+	set_feature (FEATURE_IBT);
+      if (avx512_usable)
+	{
+	  if (ebx & bit_AVX512F)
+	    set_feature (FEATURE_AVX512F);
+	  if (ebx & bit_AVX512VL)
+	    set_feature (FEATURE_AVX512VL);
+	  if (ebx & bit_AVX512BW)
+	    set_feature (FEATURE_AVX512BW);
+	  if (ebx & bit_AVX512DQ)
+	    set_feature (FEATURE_AVX512DQ);
+	  if (ebx & bit_AVX512CD)
+	    set_feature (FEATURE_AVX512CD);
+	  if (ebx & bit_AVX512PF)
+	    set_feature (FEATURE_AVX512PF);
+	  if (ebx & bit_AVX512ER)
+	    set_feature (FEATURE_AVX512ER);
+	  if (ebx & bit_AVX512IFMA)
+	    set_feature (FEATURE_AVX512IFMA);
+	  if (ecx & bit_AVX512VBMI)
+	    set_feature (FEATURE_AVX512VBMI);
+	  if (ecx & bit_AVX512VBMI2)
+	    set_feature (FEATURE_AVX512VBMI2);
+	  if (ecx & bit_AVX512VNNI)
+	    set_feature (FEATURE_AVX512VNNI);
+	  if (ecx & bit_AVX512BITALG)
+	    set_feature (FEATURE_AVX512BITALG);
+	  if (ecx & bit_AVX512VPOPCNTDQ)
+	    set_feature (FEATURE_AVX512VPOPCNTDQ);
+	  if (edx & bit_AVX5124VNNIW)
+	    set_feature (FEATURE_AVX5124VNNIW);
+	  if (edx & bit_AVX5124FMAPS)
+	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
+
+	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+	  if (eax & bit_AVX512BF16)
+	    set_feature (FEATURE_AVX512BF16);
+	}
+    }
+
+  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+  if (max_cpuid_level >= 0xd)
+    {
+      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+      if (eax & bit_XSAVEC)
+	set_feature (FEATURE_XSAVEC);
+      if (eax & bit_XSAVES)
+	set_feature (FEATURE_XSAVES);
+    }
+
+  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+  if (max_cpuid_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_PTWRITE)
+	set_feature (FEATURE_PTWRITE);
+    }
+
+  /* Check cpuid level of extended features.  */
+  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+  cpu_model2->__cpu_ext_level = ext_level;
+
+  if (ext_level >= 0x80000001)
+    {
+      __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+      if (ecx & bit_SSE4a)
+	set_feature (FEATURE_SSE4_A);
+      if (ecx & bit_LAHF_LM)
+	set_feature (FEATURE_LAHF_LM);
+      if (ecx & bit_ABM)
+	set_feature (FEATURE_ABM);
+      if (ecx & bit_LWP)
+	set_feature (FEATURE_LWP);
+      if (ecx & bit_TBM)
+	set_feature (FEATURE_TBM);
+      if (ecx & bit_LZCNT)
+	set_feature (FEATURE_LZCNT);
+      if (ecx & bit_PRFCHW)
+	set_feature (FEATURE_PRFCHW);
+      if (ecx & bit_MWAITX)
+	set_feature (FEATURE_MWAITX);
+
+      if (edx & bit_LM)
+	set_feature (FEATURE_LM);
+      if (edx & bit_3DNOWP)
+	set_feature (FEATURE_3DNOWP);
+      if (edx & bit_3DNOW)
+	set_feature (FEATURE_3DNOW);
+
+      if (avx_usable)
+	{
+	  if (ecx & bit_FMA4)
+	    set_feature (FEATURE_FMA4);
+	  if (ecx & bit_XOP)
+	    set_feature (FEATURE_XOP);
+	}
+    }
+
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+      if (ebx & bit_WBNOINVD)
+	set_feature (FEATURE_WBNOINVD);
+    }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+		    struct __processor_model2 *cpu_model2,
+		    unsigned int *cpu_features2)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  int max_level;
+  unsigned int vendor;
+  unsigned int model, family, brand_id;
+  unsigned int extended_model, extended_family;
+
+  /* This function needs to run just once.  */
+  if (cpu_model->__cpu_vendor)
+    return 0;
+
+  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  vendor = ebx;
+  max_level = eax;
+
+  if (max_level < 1)
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  cpu_model2->__cpu_max_level = max_level;
+
+  model = (eax >> 4) & 0x0f;
+  family = (eax >> 8) & 0x0f;
+  brand_id = ebx & 0xff;
+  extended_model = (eax >> 12) & 0xf0;
+  extended_family = (eax >> 20) & 0xff;
+
+  if (vendor == signature_INTEL_ebx)
+    {
+      /* Adjust model and family for Intel CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+      else if (family == 0x06)
+	model += extended_model;
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+      cpu_model->__cpu_vendor = VENDOR_INTEL;
+    }
+  else if (vendor == signature_AMD_ebx)
+    {
+      /* Adjust model and family for AMD CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+      cpu_model->__cpu_vendor = VENDOR_AMD;
+    }
+  else if (vendor == signature_CENTAUR_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+  else if (vendor == signature_CYRIX_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CYRIX;
+  else if (vendor == signature_NSC_ebx)
+    cpu_model->__cpu_vendor = VENDOR_NSC;
+  else
+    cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+  return 0;
+}
diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
new file mode 100644
index 00000000000..ac0dd5736dc
--- /dev/null
+++ b/gcc/common/config/i386/i386-isas.h
@@ -0,0 +1,200 @@
+/* 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/>.  */
+
+/* Priority of i386 features, greater value is higher priority.   This is
+   used to decide the order in which function dispatch must happen.  For
+   instance, a version specialized for SSE4.2 should be checked for dispatch
+   before a version for SSE3, as SSE4.2 implies SSE3.  */
+enum feature_priority
+{
+  P_ZERO = 0,
+  P_MMX,
+  P_SSE,
+  P_SSE2,
+  P_SSE3,
+  P_SSSE3,
+  P_PROC_SSSE3,
+  P_SSE4_A,
+  P_PROC_SSE4_A,
+  P_SSE4_1,
+  P_SSE4_2,
+  P_PROC_SSE4_2,
+  P_POPCNT,
+  P_AES,
+  P_PCLMUL,
+  P_AVX,
+  P_PROC_AVX,
+  P_BMI,
+  P_PROC_BMI,
+  P_FMA4,
+  P_XOP,
+  P_PROC_XOP,
+  P_FMA,
+  P_PROC_FMA,
+  P_BMI2,
+  P_AVX2,
+  P_PROC_AVX2,
+  P_AVX512F,
+  P_PROC_AVX512F
+};
+
+/* 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_ZERO, 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_ZERO,
+			"-mavx512vl")
+  ISA_NAMES_TABLE_ENTRY("avx512bw", FEATURE_AVX512BW, P_ZERO,
+			"-mavx512bw")
+  ISA_NAMES_TABLE_ENTRY("avx512dq", FEATURE_AVX512DQ, P_ZERO,
+			"-mavx512dq")
+  ISA_NAMES_TABLE_ENTRY("avx512cd", FEATURE_AVX512CD, P_ZERO,
+			"-mavx512cd")
+  ISA_NAMES_TABLE_ENTRY("avx512er", FEATURE_AVX512ER, P_ZERO,
+			"-mavx512er")
+  ISA_NAMES_TABLE_ENTRY("avx512pf", FEATURE_AVX512PF, P_ZERO,
+			"-mavx512pf")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi", FEATURE_AVX512VBMI, P_ZERO,
+			"-mavx512vbmi")
+  ISA_NAMES_TABLE_ENTRY("avx512ifma", FEATURE_AVX512IFMA, P_ZERO,
+			"-mavx512ifma")
+  ISA_NAMES_TABLE_ENTRY("avx5124vnniw", FEATURE_AVX5124VNNIW, P_ZERO,
+			"-mavx5124vnniw")
+  ISA_NAMES_TABLE_ENTRY("avx5124fmaps", FEATURE_AVX5124FMAPS, P_ZERO,
+			"-mavx5124fmaps")
+  ISA_NAMES_TABLE_ENTRY("avx512vpopcntdq", FEATURE_AVX512VPOPCNTDQ,
+			P_ZERO, "-mavx512vpopcntdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO,
+			"-mavx512vbmi2")
+  ISA_NAMES_TABLE_ENTRY("gfni", FEATURE_GFNI, P_ZERO, "-mgfni")
+  ISA_NAMES_TABLE_ENTRY("vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO,
+			"-mvpclmulqdq")
+  ISA_NAMES_TABLE_ENTRY("avx512vnni", FEATURE_AVX512VNNI, P_ZERO,
+			"-mavx512vnni")
+  ISA_NAMES_TABLE_ENTRY("avx512bitalg", FEATURE_AVX512BITALG, P_ZERO,
+			"-mavx512bitalg")
+  ISA_NAMES_TABLE_ENTRY("avx512bf16", FEATURE_AVX512BF16, P_ZERO,
+			"-mavx512bf16")
+  ISA_NAMES_TABLE_ENTRY("avx512vp2intersect", FEATURE_AVX512VP2INTERSECT,
+			P_ZERO, "-mavx512vp2intersect")
+  ISA_NAMES_TABLE_ENTRY("3dnow", FEATURE_3DNOW, P_ZERO, "-m3dnow")
+  ISA_NAMES_TABLE_ENTRY("3dnowp", FEATURE_3DNOWP, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("adx", FEATURE_ADX, P_ZERO, "-madx")
+  ISA_NAMES_TABLE_ENTRY("abm", FEATURE_ABM, P_ZERO, "-mabm")
+  ISA_NAMES_TABLE_ENTRY("cldemote", FEATURE_CLDEMOTE, P_ZERO,
+			"-mcldemote")
+  ISA_NAMES_TABLE_ENTRY("clflushopt", FEATURE_CLFLUSHOPT, P_ZERO,
+			"-mclflushopt")
+  ISA_NAMES_TABLE_ENTRY("clwb", FEATURE_CLWB, P_ZERO, "-mclwb")
+  ISA_NAMES_TABLE_ENTRY("clzero", FEATURE_CLZERO, P_ZERO, "-mclzero")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg16b", FEATURE_CMPXCHG16B, P_ZERO,
+			"-mcx16")
+  ISA_NAMES_TABLE_ENTRY("cmpxchg8b", FEATURE_CMPXCHG8B, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("enqcmd", FEATURE_ENQCMD, P_ZERO, "-menqcmd")
+  ISA_NAMES_TABLE_ENTRY("f16c", FEATURE_F16C, P_ZERO, "-mf16c")
+  ISA_NAMES_TABLE_ENTRY("fsgsbase", FEATURE_FSGSBASE, P_ZERO,
+			"-mfsgsbase")
+  ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
+  ISA_NAMES_TABLE_ENTRY("hle", FEATURE_HLE, P_ZERO, "-mhle")
+  ISA_NAMES_TABLE_ENTRY("ibt", FEATURE_IBT, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lahf_lm", FEATURE_LAHF_LM, P_ZERO, "-msahf")
+  ISA_NAMES_TABLE_ENTRY("lm", FEATURE_LM, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("lwp", FEATURE_LWP, P_ZERO, "-mlwp")
+  ISA_NAMES_TABLE_ENTRY("lzcnt", FEATURE_LZCNT, P_ZERO, "-mlzcnt")
+  ISA_NAMES_TABLE_ENTRY("movbe", FEATURE_MOVBE, P_ZERO, "-mmovbe")
+  ISA_NAMES_TABLE_ENTRY("movdir64b", FEATURE_MOVDIR64B, P_ZERO,
+			"-mmovdir64b")
+  ISA_NAMES_TABLE_ENTRY("movdiri", FEATURE_MOVDIRI, P_ZERO, "-mmovdiri")
+  ISA_NAMES_TABLE_ENTRY("mwaitx", FEATURE_MWAITX, P_ZERO, "-mmwaitx")
+  ISA_NAMES_TABLE_ENTRY("osxsave", FEATURE_OSXSAVE, P_ZERO, NULL)
+  ISA_NAMES_TABLE_ENTRY("pconfig", FEATURE_PCONFIG, P_ZERO, "-mpconfig")
+  ISA_NAMES_TABLE_ENTRY("pku", FEATURE_PKU, P_ZERO, "-mpku")
+  ISA_NAMES_TABLE_ENTRY("prefetchwt1", FEATURE_PREFETCHWT1, P_ZERO,
+			"-mprefetchwt1")
+  ISA_NAMES_TABLE_ENTRY("prfchw", FEATURE_PRFCHW, P_ZERO, "-mprfchw")
+  ISA_NAMES_TABLE_ENTRY("ptwrite", FEATURE_PTWRITE, P_ZERO, "-mptwrite")
+  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
+  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
+  ISA_NAMES_TABLE_ENTRY("rdseed", FEATURE_RDSEED, P_ZERO, "-mrdseed")
+  ISA_NAMES_TABLE_ENTRY("rtm", FEATURE_RTM, P_ZERO, "-mrtm")
+  ISA_NAMES_TABLE_ENTRY("serialize", FEATURE_SERIALIZE, P_ZERO,
+			"-mserialize")
+  ISA_NAMES_TABLE_ENTRY("sgx", FEATURE_SGX, P_ZERO, "-msgx")
+  ISA_NAMES_TABLE_ENTRY("sha", FEATURE_SHA, P_ZERO, "-msha")
+  ISA_NAMES_TABLE_ENTRY("shstk", FEATURE_SHSTK, P_ZERO, "-mshstk")
+  ISA_NAMES_TABLE_ENTRY("tbm", FEATURE_TBM, P_ZERO, "-mtbm")
+  ISA_NAMES_TABLE_ENTRY("tsxldtrk", FEATURE_TSXLDTRK, P_ZERO,
+			"-mtsxldtrk")
+  ISA_NAMES_TABLE_ENTRY("vaes", FEATURE_VAES, P_ZERO, "-mvaes")
+  ISA_NAMES_TABLE_ENTRY("waitpkg", FEATURE_WAITPKG, P_ZERO, "-mwaitpkg")
+  ISA_NAMES_TABLE_ENTRY("wbnoinvd", FEATURE_WBNOINVD, P_ZERO,
+			"-mwbnoinvd")
+  ISA_NAMES_TABLE_ENTRY("xsave", FEATURE_XSAVE, P_ZERO, "-mxsave")
+  ISA_NAMES_TABLE_ENTRY("xsavec", FEATURE_XSAVEC, P_ZERO, "-mxsavec")
+  ISA_NAMES_TABLE_ENTRY("xsaveopt", FEATURE_XSAVEOPT, P_ZERO,
+			"-mxsaveopt")
+  ISA_NAMES_TABLE_ENTRY("xsaves", FEATURE_XSAVES, P_ZERO, "-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 be3ed0158f2..fbbc957510a 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -90,6 +90,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "dwarf2out.h"
 #include "i386-builtins.h"
+#include "common/config/i386/cpuinfo-builtins.h"
+#include "common/config/i386/i386-isas.h"
 
 #undef BDESC
 #undef BDESC_FIRST
@@ -1835,235 +1837,66 @@ ix86_builtin_reciprocal (tree fndecl)
     }
 }
 
-/* Priority of i386 features, greater value is higher priority.   This is
-   used to decide the order in which function dispatch must happen.  For
-   instance, a version specialized for SSE4.2 should be checked for dispatch
-   before a version for SSE3, as SSE4.2 implies SSE3.  */
-enum feature_priority
-{
-  P_ZERO = 0,
-  P_MMX,
-  P_SSE,
-  P_SSE2,
-  P_SSE3,
-  P_SSSE3,
-  P_PROC_SSSE3,
-  P_SSE4_A,
-  P_PROC_SSE4_A,
-  P_SSE4_1,
-  P_SSE4_2,
-  P_PROC_SSE4_2,
-  P_POPCNT,
-  P_AES,
-  P_PCLMUL,
-  P_AVX,
-  P_PROC_AVX,
-  P_BMI,
-  P_PROC_BMI,
-  P_FMA4,
-  P_XOP,
-  P_PROC_XOP,
-  P_FMA,
-  P_PROC_FMA,
-  P_BMI2,
-  P_AVX2,
-  P_PROC_AVX2,
-  P_AVX512F,
-  P_PROC_AVX512F
-};
-
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512BF16,
-  F_AVX512VP2INTERSECT,
-  F_MAX
-};
-
-/* These are the values for vendor types and cpu types  and subtypes
-   in cpuinfo.c.  Cpu types and subtypes should be subtracted by
-   the corresponding start value.  */
-enum processor_model
-{
-  M_INTEL = 1,
-  M_AMD,
-  M_CPU_TYPE_START,
-  M_INTEL_BONNELL,
-  M_INTEL_CORE2,
-  M_INTEL_COREI7,
-  M_AMDFAM10H,
-  M_AMDFAM15H,
-  M_INTEL_SILVERMONT,
-  M_INTEL_KNL,
-  M_AMD_BTVER1,
-  M_AMD_BTVER2,
-  M_AMDFAM17H,
-  M_INTEL_KNM,
-  M_INTEL_GOLDMONT,
-  M_INTEL_GOLDMONT_PLUS,
-  M_INTEL_TREMONT,
-  M_CPU_SUBTYPE_START,
-  M_INTEL_COREI7_NEHALEM,
-  M_INTEL_COREI7_WESTMERE,
-  M_INTEL_COREI7_SANDYBRIDGE,
-  M_AMDFAM10H_BARCELONA,
-  M_AMDFAM10H_SHANGHAI,
-  M_AMDFAM10H_ISTANBUL,
-  M_AMDFAM15H_BDVER1,
-  M_AMDFAM15H_BDVER2,
-  M_AMDFAM15H_BDVER3,
-  M_AMDFAM15H_BDVER4,
-  M_AMDFAM17H_ZNVER1,
-  M_INTEL_COREI7_IVYBRIDGE,
-  M_INTEL_COREI7_HASWELL,
-  M_INTEL_COREI7_BROADWELL,
-  M_INTEL_COREI7_SKYLAKE,
-  M_INTEL_COREI7_SKYLAKE_AVX512,
-  M_INTEL_COREI7_CANNONLAKE,
-  M_INTEL_COREI7_ICELAKE_CLIENT,
-  M_INTEL_COREI7_ICELAKE_SERVER,
-  M_AMDFAM17H_ZNVER2,
-  M_INTEL_COREI7_CASCADELAKE,
-  M_INTEL_COREI7_TIGERLAKE,
-  M_INTEL_COREI7_COOPERLAKE
-};
-
 struct _arch_names_table
 {
   const char *const name;
-  const enum processor_model model;
+  const int model;
 };
 
-static const _arch_names_table arch_names_table[] =
-{
-  {"amd", M_AMD},
-  {"intel", M_INTEL},
-  {"atom", M_INTEL_BONNELL},
-  {"slm", M_INTEL_SILVERMONT},
-  {"core2", M_INTEL_CORE2},
-  {"corei7", M_INTEL_COREI7},
-  {"nehalem", M_INTEL_COREI7_NEHALEM},
-  {"westmere", M_INTEL_COREI7_WESTMERE},
-  {"sandybridge", M_INTEL_COREI7_SANDYBRIDGE},
-  {"ivybridge", M_INTEL_COREI7_IVYBRIDGE},
-  {"haswell", M_INTEL_COREI7_HASWELL},
-  {"broadwell", M_INTEL_COREI7_BROADWELL},
-  {"skylake", M_INTEL_COREI7_SKYLAKE},
-  {"skylake-avx512", M_INTEL_COREI7_SKYLAKE_AVX512},
-  {"cannonlake", M_INTEL_COREI7_CANNONLAKE},
-  {"icelake-client", M_INTEL_COREI7_ICELAKE_CLIENT},
-  {"icelake-server", M_INTEL_COREI7_ICELAKE_SERVER},
-  {"cascadelake", M_INTEL_COREI7_CASCADELAKE},
-  {"tigerlake", M_INTEL_COREI7_TIGERLAKE},
-  {"cooperlake", M_INTEL_COREI7_COOPERLAKE},
-  {"bonnell", M_INTEL_BONNELL},
-  {"silvermont", M_INTEL_SILVERMONT},
-  {"goldmont", M_INTEL_GOLDMONT},
-  {"goldmont-plus", M_INTEL_GOLDMONT_PLUS},
-  {"tremont", M_INTEL_TREMONT},
-  {"knl", M_INTEL_KNL},
-  {"knm", M_INTEL_KNM},
-  {"amdfam10h", M_AMDFAM10H},
-  {"barcelona", M_AMDFAM10H_BARCELONA},
-  {"shanghai", M_AMDFAM10H_SHANGHAI},
-  {"istanbul", M_AMDFAM10H_ISTANBUL},
-  {"btver1", M_AMD_BTVER1},
-  {"amdfam15h", M_AMDFAM15H},
-  {"bdver1", M_AMDFAM15H_BDVER1},
-  {"bdver2", M_AMDFAM15H_BDVER2},
-  {"bdver3", M_AMDFAM15H_BDVER3},
-  {"bdver4", M_AMDFAM15H_BDVER4},
-  {"btver2", M_AMD_BTVER2},
-  {"amdfam17h", M_AMDFAM17H},
-  {"znver1", M_AMDFAM17H_ZNVER1},
-  {"znver2", M_AMDFAM17H_ZNVER2},
-};
+/* These are the values for vendor types, cpu types and subtypes in
+   cpuinfo.h.  Cpu types and subtypes should be subtracted by the
+   corresponding start value.  */
 
-/* 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;
-};
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+  (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
 
-static const _isa_names_table isa_names_table[] =
+static const _arch_names_table arch_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_ZERO},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_ZERO},
-  {"avx512bw",F_AVX512BW, P_ZERO},
-  {"avx512dq",F_AVX512DQ, P_ZERO},
-  {"avx512cd",F_AVX512CD, P_ZERO},
-  {"avx512er",F_AVX512ER, P_ZERO},
-  {"avx512pf",F_AVX512PF, P_ZERO},
-  {"avx512vbmi",F_AVX512VBMI, P_ZERO},
-  {"avx512ifma",F_AVX512IFMA, P_ZERO},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_ZERO},
-  {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
-  {"gfni",	F_GFNI,	P_ZERO},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
-  {"avx512vnni", F_AVX512VNNI, P_ZERO},
-  {"avx512bitalg", F_AVX512BITALG, P_ZERO},
-  {"avx512bf16", F_AVX512BF16, P_ZERO},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO}
+  {"amd", M_VENDOR (VENDOR_AMD)},
+  {"intel", M_VENDOR (VENDOR_INTEL)},
+  {"atom", M_CPU_TYPE (INTEL_BONNELL)},
+  {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"core2", M_CPU_TYPE (INTEL_CORE2)},
+  {"corei7", M_CPU_TYPE (INTEL_COREI7)},
+  {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
+  {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
+  {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
+  {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
+  {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
+  {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
+  {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
+  {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
+  {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
+  {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
+  {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
+  {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
+  {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
+  {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
+  {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
+  {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
+  {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
+  {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
+  {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
+  {"knl", M_CPU_TYPE (INTEL_KNL)},
+  {"knm", M_CPU_TYPE (INTEL_KNM)},
+  {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
+  {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
+  {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
+  {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
+  {"btver1", M_CPU_TYPE (AMD_BTVER1)},
+  {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
+  {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
+  {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
+  {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
+  {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
+  {"btver2", M_CPU_TYPE (AMD_BTVER2)},
+  {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
+  {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
+  {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
 };
 
 /* This parses the attribute arguments to target in DECL and determines
@@ -2509,16 +2342,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
 
       if (isa_names_table[i].feature >= 32)
 	{
-	  tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+	  tree index_type
+	    = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+	  tree type = build_array_type (unsigned_type_node, index_type);
+	  tree __cpu_features2_var = make_var_decl (type,
 						    "__cpu_features2");
 
 	  varpool_node::add (__cpu_features2_var);
-	  field_val = (1U << (isa_names_table[i].feature - 32));
-	  /* Return __cpu_features2 & field_val  */
-	  final = build2 (BIT_AND_EXPR, unsigned_type_node,
-			  __cpu_features2_var,
-			  build_int_cstu (unsigned_type_node, field_val));
-	  return build1 (CONVERT_EXPR, integer_type_node, final);
+	  for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+	    if (isa_names_table[i].feature < (32 + 32 + j * 32))
+	      {
+		field_val = (1U << (isa_names_table[i].feature
+				    - (32 + j * 32)));
+		tree index = size_int (j);
+		array_elt = build4 (ARRAY_REF, unsigned_type_node,
+				    __cpu_features2_var,
+				    index, NULL_TREE, NULL_TREE);
+		/* Return __cpu_features2[index] & field_val  */
+		final = build2 (BIT_AND_EXPR, unsigned_type_node,
+				array_elt,
+				build_int_cstu (unsigned_type_node,
+						field_val));
+		return build1 (CONVERT_EXPR, integer_type_node, final);
+	      }
 	}
 
       field = TYPE_FIELDS (__processor_model_type);
diff --git a/gcc/testsuite/gcc.target/i386/builtin_target.c b/gcc/testsuite/gcc.target/i386/builtin_target.c
index 7a8b6e805ed..368c0a54efe 100644
--- a/gcc/testsuite/gcc.target/i386/builtin_target.c
+++ b/gcc/testsuite/gcc.target/i386/builtin_target.c
@@ -7,348 +7,52 @@
 /* { 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/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;
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index cf5f0884bb4..49c5107546f 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +39,14 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
    size of __cpu_model is part of ABI.  So, new features that don't
    fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
-
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
-/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
-   the max possible level of CPUID insn.  */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
-			int max_cpuid_level)
-{
-  unsigned int eax, ebx;
-  unsigned int ext_level;
-
-  unsigned int features = 0;
-  unsigned int features2 = 0;
-
-  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
-#define XCR_XFEATURE_ENABLED_MASK	0x0
-#define XSTATE_FP			0x1
-#define XSTATE_SSE			0x2
-#define XSTATE_YMM			0x4
-#define XSTATE_OPMASK			0x20
-#define XSTATE_ZMM			0x40
-#define XSTATE_HI_ZMM			0x80
-
-#define XCR_AVX_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
-  /* Check if AVX and AVX512 are usable.  */
-  int avx_usable = 0;
-  int avx512_usable = 0;
-  if ((ecx & bit_OSXSAVE))
-    {
-      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
-         ZMM16-ZMM31 states are supported by OSXSAVE.  */
-      unsigned int xcrlow;
-      unsigned int xcrhigh;
-      asm (".byte 0x0f, 0x01, 0xd0"
-	   : "=a" (xcrlow), "=d" (xcrhigh)
-	   : "c" (XCR_XFEATURE_ENABLED_MASK));
-      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
-	{
-	  avx_usable = 1;
-	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
-			   == XCR_AVX512F_ENABLED_MASK);
-	}
-    }
-
-#define set_feature(f) \
-  do						\
-    {						\
-      if (f < 32)				\
-	features |= (1U << (f & 31));		\
-      else					\
-	features2 |= (1U << ((f - 32) & 31));	\
-    }						\
-  while (0)
-
-  if (edx & bit_CMOV)
-    set_feature (FEATURE_CMOV);
-  if (edx & bit_MMX)
-    set_feature (FEATURE_MMX);
-  if (edx & bit_SSE)
-    set_feature (FEATURE_SSE);
-  if (edx & bit_SSE2)
-    set_feature (FEATURE_SSE2);
-  if (ecx & bit_POPCNT)
-    set_feature (FEATURE_POPCNT);
-  if (ecx & bit_AES)
-    set_feature (FEATURE_AES);
-  if (ecx & bit_PCLMUL)
-    set_feature (FEATURE_PCLMUL);
-  if (ecx & bit_SSE3)
-    set_feature (FEATURE_SSE3);
-  if (ecx & bit_SSSE3)
-    set_feature (FEATURE_SSSE3);
-  if (ecx & bit_SSE4_1)
-    set_feature (FEATURE_SSE4_1);
-  if (ecx & bit_SSE4_2)
-    set_feature (FEATURE_SSE4_2);
-  if (avx_usable)
-    {
-      if (ecx & bit_AVX)
-	set_feature (FEATURE_AVX);
-      if (ecx & bit_FMA)
-	set_feature (FEATURE_FMA);
-    }
-
-  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
-  if (max_cpuid_level >= 7)
-    {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
-      if (ebx & bit_BMI)
-	set_feature (FEATURE_BMI);
-      if (avx_usable)
-	{
-	  if (ebx & bit_AVX2)
-	    set_feature (FEATURE_AVX2);
-	  if (ecx & bit_VPCLMULQDQ)
-	    set_feature (FEATURE_VPCLMULQDQ);
-	}
-      if (ebx & bit_BMI2)
-	set_feature (FEATURE_BMI2);
-      if (ecx & bit_GFNI)
-	set_feature (FEATURE_GFNI);
-      if (avx512_usable)
-	{
-	  if (ebx & bit_AVX512F)
-	    set_feature (FEATURE_AVX512F);
-	  if (ebx & bit_AVX512VL)
-	    set_feature (FEATURE_AVX512VL);
-	  if (ebx & bit_AVX512BW)
-	    set_feature (FEATURE_AVX512BW);
-	  if (ebx & bit_AVX512DQ)
-	    set_feature (FEATURE_AVX512DQ);
-	  if (ebx & bit_AVX512CD)
-	    set_feature (FEATURE_AVX512CD);
-	  if (ebx & bit_AVX512PF)
-	    set_feature (FEATURE_AVX512PF);
-	  if (ebx & bit_AVX512ER)
-	    set_feature (FEATURE_AVX512ER);
-	  if (ebx & bit_AVX512IFMA)
-	    set_feature (FEATURE_AVX512IFMA);
-	  if (ecx & bit_AVX512VBMI)
-	    set_feature (FEATURE_AVX512VBMI);
-	  if (ecx & bit_AVX512VBMI2)
-	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_AVX512VNNI)
-	    set_feature (FEATURE_AVX512VNNI);
-	  if (ecx & bit_AVX512BITALG)
-	    set_feature (FEATURE_AVX512BITALG);
-	  if (ecx & bit_AVX512VPOPCNTDQ)
-	    set_feature (FEATURE_AVX512VPOPCNTDQ);
-	  if (edx & bit_AVX5124VNNIW)
-	    set_feature (FEATURE_AVX5124VNNIW);
-	  if (edx & bit_AVX5124FMAPS)
-	    set_feature (FEATURE_AVX5124FMAPS);
-	  if (edx & bit_AVX512VP2INTERSECT)
-	    set_feature (FEATURE_AVX512VP2INTERSECT);
+   in libgcc.a only, preferably hidden.
 
-	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
-	  if (eax & bit_AVX512BF16)
-	    set_feature (FEATURE_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)
-	set_feature (FEATURE_SSE4_A);
-      if (avx_usable)
-	{
-	  if (ecx & bit_FMA4)
-	    set_feature (FEATURE_FMA4);
-	  if (ecx & bit_XOP)
-	    set_feature (FEATURE_XOP);
-	}
-    }
-    
-  __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
-  __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
-}
+   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+   smaller array, it can only access the first few elements.  */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
    the right values.  This needs to run only once.  This constructor is
@@ -429,85 +57,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
 __cpu_indicator_init (void)
 {
-  unsigned int eax, ebx, ecx, edx;
-
-  int max_level;
-  unsigned int vendor;
-  unsigned int model, family, brand_id;
-  unsigned int extended_model, extended_family;
-
-  /* This function needs to run just once.  */
-  if (__cpu_model.__cpu_vendor)
-    return 0;
-
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  vendor = ebx;
-  max_level = eax;
-
-  if (max_level < 1)
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
-    {
-      /* Adjust model and family for Intel CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_INTEL;
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_AMD;
-    }
-  else
-    __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
-  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
-  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
-  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
-  return 0;
+  struct __processor_model2 cpu_model2;
+  return cpu_indicator_init (&__cpu_model, &cpu_model2,
+			     __cpu_features2);
 }
 
 #if defined SHARED && defined USE_ELF_SYMVER
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: PING^2: V5 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-16 17:11                                       ` PING^2: " H.J. Lu
  2020-06-20 13:39                                         ` H.J. Lu
@ 2020-06-24  6:25                                         ` Martin Liška
  1 sibling, 0 replies; 30+ messages in thread
From: Martin Liška @ 2020-06-24  6:25 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Jan Hubicka, Jakub Jelinek, Jeffrey Law, Richard Biener, gcc-patches

On 6/16/20 7:11 PM, H.J. Lu wrote:
> On Tue, Jun 9, 2020 at 9:35 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Tue, May 26, 2020 at 6:27 AM Martin Liška <mliska@suse.cz> wrote:
>>>
>>> On 5/26/20 1:59 PM, H.J. Lu wrote:
>>>> On Tue, May 26, 2020 at 2:30 AM Martin Liška <mliska@suse.cz> wrote:
>>>>>
>>>>> On 5/25/20 7:42 PM, H.J. Lu wrote:
>>>>>> Here is the updated patch.  OK for master?
>>>>>
>>>>> Thank you for the updated patch.
>>>>>
>>>>> I have still few nits:
>>>>>
>>>>> 1) I would make all the:
>>>>>
>>>>>> +  has_sse3 = has_feature (FEATURE_SSE3);
>>>>>
>>>>> a macro. The local variable seems to superfluous.
>>>>
>>>> Done.
>>>
>>> Thanks!
>>>
>>>>
>>>>> 2) can we automatically deduce option name:
>>>>>
>>>>>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
>>>>>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
>>>>>
>>>>> I mean "-m" + "rdrnd" == "-mrdrnd" ?
>>>>
>>>> The new option field serves 2 purposes:
>>>>
>>>> 1. Not all features have a corresponding command-line option
>>>>
>>>> ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
>>>>
>>>>        for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
>>>>           if (isa_names_table[i].option)
>>>>
>>>> 2. Some feature has a different name in the command-line option.
>>>>
>>>>     ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
>>>
>>> I noticed that, one can theoretically use "" for an option that does not
>>> have a flag. And NULL for these which have option equal to "-m" + name.
>>> Anyway, that's a nit.
>>>
>>> I support the patch!
>>> Martin
>>>
>>>>
>>>> Here is the updated patch.   OK for master?
>>>>
>>>> Thanks.
>>>>
>>>
>>
>> PING:
>>
>> https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
>>
> 
> PING.
> 

@Honza: Can you please take a look at the patch?

Martin

^ permalink raw reply	[flat|nested] 30+ messages in thread

* V7 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-22 23:25                                               ` V6 " H.J. Lu
@ 2020-06-24 12:27                                                 ` H.J. Lu
  2020-06-24 12:43                                                   ` Uros Bizjak
  0 siblings, 1 reply; 30+ messages in thread
From: H.J. Lu @ 2020-06-24 12:27 UTC (permalink / raw)
  To: Uros Bizjak, Martin Liška, GCC Patches, Jan Hubicka,
	Jakub Jelinek, Jeffrey Law, Richard Biener

On Mon, Jun 22, 2020 at 04:25:46PM -0700, H.J. Lu wrote:
> On Sun, Jun 21, 2020 at 10:22 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sun, Jun 21, 2020 at 10:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > On Sat, Jun 20, 2020 at 3:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > > > > > >> 2) can we automatically deduce option name:
> > > > > > > >>
> > > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > > > > > >>
> > > > > > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > > > > > >
> > > > > > > > The new option field serves 2 purposes:
> > > > > > > >
> > > > > > > > 1. Not all features have a corresponding command-line option
> > > > > > > >
> > > > > > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > > > > > >
> > > > > > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > > > > > >          if (isa_names_table[i].option)
> > > > > > > >
> > > > > > > > 2. Some feature has a different name in the command-line option.
> > > > > > > >
> > > > > > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > > > > > >
> > > > > > > I noticed that, one can theoretically use "" for an option that does not
> > > > > > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > > > > > Anyway, that's a nit.
> > > > > > >
> > > > > > > I support the patch!
> > > > > > > Martin
> > > > > > >
> > > > > > > >
> > > > > > > > Here is the updated patch.   OK for master?
> > > > > > > >
> > > > > > > > Thanks.
> > > > > > > >
> > > > > > >
> > > > > >
> > > > > > PING:
> > > > > >
> > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > > > > >
> > > > >
> > > > > PING.
> > > >
> > > > Hi,
> > > >
> > > > We have patches like
> > > >
> > > > https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html
> > > >
> > > > queued up because of this prerequisite patch.   Are there any objections
> > > > to this patch?
> > >
> > > Yes, there are my objections.
> > >
> > > As explained before, I support unifying libgcc and core gcc handling,
> > > but _NOT_ unifying with driver-i386.c. Unifying libgcc and core gcc
> > > handling would have benefit to avoid desynchronisation between the two
> > > (which happened multiple times in the past, resulting in various API
> > > issues). OTOH, unifying with driver-i386.c would result in quite messy
> > > approach, because driver-i386 handles more targets beside relatively
> > > recent 64bit Intel and AMD targets, not to mention heuristics to
> > > determine the most appropriate target when standard detection fails
> > > (e.g. emulators).
> >
> > Only the duplicated parts of driver-i386.c should be unified.  The only impact
> > should be removing code duplications.  If it isn't the case, it is a bug in my
> > implementation.
> 
> Here is the updated patch to remove FEATURE_OSPKE and use bit_OSPKE
> for FEATURE_PKU.  It uses the same get_amd_cpu and get_intel_cpu in
> libgcc and driver-i386.c:
>    a. Detect the processor name for newer Intel and AMD processors.
>       Since the older processor names are only supported by driver-i386.c,
>       not by libgcc, detection for the older processors remains in
>       driver-i386.c.
>    b. Detect available ISAs for all Intel and AMD processors.
> 

Here is the updated patch for x86 backend and libgcc.  driver-i386.c
is unchanged.

OK for master?

Thannks.

H.J.
---
Both x86 backend and libgcc define enum processor_features.  libgcc sets
enum processor_feature and x86 backend checks enum processor_feature.
They are very easy out of sync and it has happened multiple times in the
past.

1. Move cpuinfo.h from libgcc to common/config/i386 so that we can share
the same enum processor_features in x86 backend and libgcc.
2. Change __cpu_features2 to an array to support more processor features.
3. Add more processor features to enum processor_features.

gcc/

	PR target/95259
	* common/config/i386/cpuinfo.h: New file.
	(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
	(__processor_model2): New.
	(CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
	(has_cpu_feature): New function.
	(set_cpu_feature): Likewise.
	(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	CHECK___builtin_cpu_is.  Return AMD CPU name.
	(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
	Use CHECK___builtin_cpu_is.  Return Intel CPU name.
	(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
	Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
	FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
	FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
	FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
	FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
	FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
	FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSXSAVE,
	FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT and FEATURE_XSAVES
	(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
	Also update cpu_model2.
	* common/config/i386/i386-cpuinfo.h (processor_vendor): Add
	Add VENDOR_CENTAUR, VENDOR_CYRIX and VENDOR_NSC.
	(processor_features): Moved from gcc/config/i386/i386-builtins.c.
	Renamed F_XXX to FEATURE_XXX.  Add FEATURE_3DNOW, FEATURE_3DNOWP,
	FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
	FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
	FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
	FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
	FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
	FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
	FEATURE_MWAITX, FEATURE_OSXSAVE, FEATURE_PCONFIG,
	FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
	FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
	FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
	FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
	FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
	FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
	(SIZE_OF_CPU_FEATURES): New.
	* config/i386/i386-builtins.c (processor_features): Removed.
	(isa_names_table): Replace F_XXX with FEATURE_XXX.
	(fold_builtin_cpu): Change __cpu_features2 to an array.

libgcc/

	PR target/95259
	* config/i386/cpuinfo.c: Don't include "cpuinfo.h".  Include
	"common/config/i386/i386-cpuinfo.h" and
	"common/config/i386/cpuinfo.h".
	(__cpu_features2): Changed to array.
	(get_amd_cpu): Removed.
	(get_intel_cpu): Likewise.
	(get_available_features): Likewise.
	(__cpu_indicator_init): Call cpu_indicator_init.
	* config/i386/cpuinfo.h: Removed.
---
 gcc/common/config/i386/cpuinfo.h      | 844 ++++++++++++++++++++++++++
 gcc/common/config/i386/i386-cpuinfo.h |  98 +++
 gcc/config/i386/i386-builtins.c       | 147 ++---
 libgcc/config/i386/cpuinfo.c          | 465 +-------------
 libgcc/config/i386/cpuinfo.h          | 136 -----
 5 files changed, 1009 insertions(+), 681 deletions(-)
 create mode 100644 gcc/common/config/i386/cpuinfo.h
 delete mode 100644 libgcc/config/i386/cpuinfo.h

diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644
index 00000000000..2d72b3b60fd
--- /dev/null
+++ b/gcc/common/config/i386/cpuinfo.h
@@ -0,0 +1,844 @@
+/* Get CPU type and Features for x86 processors.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
+   Contributed by Sriraman Tallam (tmsriram@google.com)
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  /* The first 32 features are stored as bitmasks in __cpu_features.
+     The rest of features are stored as bitmasks in a separate array
+     of unsigned int.  */
+  unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+  unsigned int __cpu_family;
+  unsigned int __cpu_model;
+  unsigned int __cpu_max_level;
+  unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F.  */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      return cpu_model->__cpu_features[0] & (1U << (f & 31));
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+  gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+		 unsigned int *cpu_features2,
+		 enum processor_features f)
+{
+  unsigned int i;
+  if (f < 32)
+    {
+      /* The first 32 features.  */
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+    if (f < (32 + 32 + i * 32))
+      {
+	cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+	return;
+      }
+  gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name.  Return
+   NULL for unknown AMD CPU.  */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+	     struct __processor_model2 *cpu_model2,
+	     unsigned int *cpu_features2)
+{
+  const char *cpu = NULL;
+  unsigned int family = cpu_model2->__cpu_family;
+  unsigned int model = cpu_model2->__cpu_model;
+
+  switch (family)
+    {
+    case 0x10:
+      /* AMD Family 10h.  */
+      cpu = "amdfam10";
+      cpu_model->__cpu_type = AMDFAM10H;
+      switch (model)
+	{
+	case 0x2:
+	  /* Barcelona.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("barcelona");
+	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+	  break;
+	case 0x4:
+	  /* Shanghai.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("shanghai");
+	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+	  break;
+	case 0x8:
+	  /* Istanbul.  */
+	  CHECK___builtin_cpu_is ("amdfam10h");
+	  CHECK___builtin_cpu_is ("istanbul");
+	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case 0x14:
+      /* AMD Family 14h "btver1". */
+      cpu = "btver1";
+      CHECK___builtin_cpu_is ("btver1");
+      cpu_model->__cpu_type = AMD_BTVER1;
+      break;
+    case 0x15:
+      /* AMD Family 15h "Bulldozer".  */
+      cpu_model->__cpu_type = AMDFAM15H;
+      if (model == 0x2)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0xf)
+	{
+	  /* Bulldozer version 1.  */
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      else if (model <= 0x2f)
+	{
+	  /* Bulldozer version 2 "Piledriver" */
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (model <= 0x4f)
+	{
+	  /* Bulldozer version 3 "Steamroller"  */
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (model <= 0x7f)
+	{
+	  /* Bulldozer version 4 "Excavator"   */
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_AVX2))
+	{
+	  cpu = "bdver4";
+	  CHECK___builtin_cpu_is ("bdver4");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XSAVEOPT))
+	{
+	  cpu = "bdver3";
+	  CHECK___builtin_cpu_is ("bdver3");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_BMI))
+	{
+	  cpu = "bdver2";
+	  CHECK___builtin_cpu_is ("bdver2");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_XOP))
+	{
+	  cpu = "bdver1";
+	  CHECK___builtin_cpu_is ("bdver1");
+	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+	}
+      break;
+    case 0x16:
+      /* AMD Family 16h "btver2" */
+      cpu = "btver2";
+      CHECK___builtin_cpu_is ("btver2");
+      cpu_model->__cpu_type = AMD_BTVER2;
+      break;
+    case 0x17:
+      cpu_model->__cpu_type = AMDFAM17H;
+      if (model <= 0x1f)
+	{
+	  /* AMD family 17h version 1.  */
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      else if (model >= 0x30)
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLWB))
+	{
+	  cpu = "znver2";
+	  CHECK___builtin_cpu_is ("znver2");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+	}
+      else if (has_cpu_feature (cpu_model, cpu_features2,
+				FEATURE_CLZERO))
+	{
+	  cpu = "znver1";
+	  CHECK___builtin_cpu_is ("znver1");
+	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+	}
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name.  Return
+   NULL for unknown Intel CPU.  */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+	       struct __processor_model2 *cpu_model2,
+	       unsigned int *cpu_features2,
+	       unsigned int brand_id)
+{
+  const char *cpu = NULL;
+
+  /* Parse family and model only for brand ID 0 and model 6. */
+  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+    return cpu;
+
+  switch (cpu_model2->__cpu_model)
+    {
+    case 0x1c:
+    case 0x26:
+      /* Bonnell.  */
+      cpu = "bonnell";
+      CHECK___builtin_cpu_is ("atom");
+      cpu_model->__cpu_type = INTEL_BONNELL;
+      break;
+    case 0x37:
+    case 0x4a:
+    case 0x4d:
+    case 0x5d:
+      /* Silvermont.  */
+    case 0x4c:
+    case 0x5a:
+    case 0x75:
+      /* Airmont.  */
+      cpu = "silvermont";
+      CHECK___builtin_cpu_is ("silvermont");
+      cpu_model->__cpu_type = INTEL_SILVERMONT;
+      break;
+    case 0x5c:
+    case 0x5f:
+      /* Goldmont.  */
+      cpu = "goldmont";
+      CHECK___builtin_cpu_is ("goldmont");
+      cpu_model->__cpu_type = INTEL_GOLDMONT;
+      break;
+    case 0x7a:
+      /* Goldmont Plus.  */
+      cpu = "goldmont-plus";
+      CHECK___builtin_cpu_is ("goldmont-plus");
+      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+      break;
+    case 0x86:
+    case 0x96:
+    case 0x9c:
+      /* Tremont.  */
+      cpu = "tremont";
+      CHECK___builtin_cpu_is ("tremont");
+      cpu_model->__cpu_type = INTEL_TREMONT;
+      break;
+    case 0x57:
+      /* Knights Landing.  */
+      cpu = "knl";
+      CHECK___builtin_cpu_is ("knl");
+      cpu_model->__cpu_type = INTEL_KNL;
+      break;
+    case 0x85:
+      /* Knights Mill. */
+      cpu = "knm";
+      CHECK___builtin_cpu_is ("knm");
+      cpu_model->__cpu_type = INTEL_KNM;
+      break;
+    case 0x1a:
+    case 0x1e:
+    case 0x1f:
+    case 0x2e:
+      /* Nehalem.  */
+      cpu = "nehalem";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("nehalem");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+      break;
+    case 0x25:
+    case 0x2c:
+    case 0x2f:
+      /* Westmere.  */
+      cpu = "westmere";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("westmere");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+      break;
+    case 0x2a:
+    case 0x2d:
+      /* Sandy Bridge.  */
+      cpu = "sandybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("sandybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+      break;
+    case 0x3a:
+    case 0x3e:
+      /* Ivy Bridge.  */
+      cpu = "ivybridge";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("ivybridge");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+      break;
+    case 0x3c:
+    case 0x3f:
+    case 0x45:
+    case 0x46:
+      /* Haswell.  */
+      cpu = "haswell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("haswell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+      break;
+    case 0x3d:
+    case 0x47:
+    case 0x4f:
+    case 0x56:
+      /* Broadwell.  */
+      cpu = "broadwell";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("broadwell");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+      break;
+    case 0x4e:
+    case 0x5e:
+      /* Skylake.  */
+    case 0x8e:
+    case 0x9e:
+      /* Kaby Lake.  */
+    case 0xa5:
+    case 0xa6:
+      /* Comet Lake.  */
+      cpu = "skylake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("skylake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+      break;
+    case 0x55:
+      CHECK___builtin_cpu_is ("corei7");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      if (has_cpu_feature (cpu_model, cpu_features2,
+			   FEATURE_AVX512VNNI))
+	{
+	  /* Cascade Lake.  */
+	  cpu = "cascadelake";
+	  CHECK___builtin_cpu_is ("cascadelake");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+	}
+      else
+	{
+	  /* Skylake with AVX-512 support.  */
+	  cpu = "skylake-avx512";
+	  CHECK___builtin_cpu_is ("skylake-avx512");
+	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+	}
+      break;
+    case 0x66:
+      /* Cannon Lake.  */
+      cpu = "cannonlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("cannonlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+      break;
+    case 0x6a:
+    case 0x6c:
+      /* Ice Lake server.  */
+      cpu = "icelake-server";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-server");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+      break;
+    case 0x7e:
+    case 0x7d:
+    case 0x9d:
+       /* Ice Lake client.  */
+      cpu = "icelake-client";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("icelake-client");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+      break;
+    case 0x8c:
+    case 0x8d:
+      /* Tiger Lake.  */
+      cpu = "tigerlake";
+      CHECK___builtin_cpu_is ("corei7");
+      CHECK___builtin_cpu_is ("tigerlake");
+      cpu_model->__cpu_type = INTEL_COREI7;
+      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+      break;
+    case 0x17:
+    case 0x1d:
+      /* Penryn.  */
+    case 0x0f:
+      /* Merom.  */
+      cpu = "core2";
+      CHECK___builtin_cpu_is ("core2");
+      cpu_model->__cpu_type = INTEL_CORE2;
+      break;
+    default:
+      break;
+    }
+
+  return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one.  */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+			struct __processor_model2 *cpu_model2,
+			unsigned int *cpu_features2,
+			unsigned int ecx, unsigned int edx)
+{
+  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+  unsigned int eax, ebx;
+  unsigned int ext_level;
+
+  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
+#define XCR_XFEATURE_ENABLED_MASK	0x0
+#define XSTATE_FP			0x1
+#define XSTATE_SSE			0x2
+#define XSTATE_YMM			0x4
+#define XSTATE_OPMASK			0x20
+#define XSTATE_ZMM			0x40
+#define XSTATE_HI_ZMM			0x80
+
+#define XCR_AVX_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+  /* Check if AVX and AVX512 are usable.  */
+  int avx_usable = 0;
+  int avx512_usable = 0;
+  if ((ecx & bit_OSXSAVE))
+    {
+      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      __asm__ (".byte 0x0f, 0x01, 0xd0"
+	       : "=a" (xcrlow), "=d" (xcrhigh)
+	       : "c" (XCR_XFEATURE_ENABLED_MASK));
+      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+	{
+	  avx_usable = 1;
+	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+			   == XCR_AVX512F_ENABLED_MASK);
+	}
+    }
+
+#define set_feature(f) \
+  set_cpu_feature (cpu_model, cpu_features2, f)
+
+  if (edx & bit_CMOV)
+    set_feature (FEATURE_CMOV);
+  if (edx & bit_MMX)
+    set_feature (FEATURE_MMX);
+  if (edx & bit_SSE)
+    set_feature (FEATURE_SSE);
+  if (edx & bit_SSE2)
+    set_feature (FEATURE_SSE2);
+  if (edx & bit_CMPXCHG8B)
+    set_feature (FEATURE_CMPXCHG8B);
+  if (edx & bit_FXSAVE)
+    set_feature (FEATURE_FXSAVE);
+
+  if (ecx & bit_POPCNT)
+    set_feature (FEATURE_POPCNT);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_PCLMUL)
+    set_feature (FEATURE_PCLMUL);
+  if (ecx & bit_SSE3)
+    set_feature (FEATURE_SSE3);
+  if (ecx & bit_SSSE3)
+    set_feature (FEATURE_SSSE3);
+  if (ecx & bit_SSE4_1)
+    set_feature (FEATURE_SSE4_1);
+  if (ecx & bit_SSE4_2)
+    set_feature (FEATURE_SSE4_2);
+  if (ecx & bit_OSXSAVE)
+    set_feature (FEATURE_OSXSAVE);
+  if (ecx & bit_CMPXCHG16B)
+    set_feature (FEATURE_CMPXCHG16B);
+  if (ecx & bit_MOVBE)
+    set_feature (FEATURE_MOVBE);
+  if (ecx & bit_AES)
+    set_feature (FEATURE_AES);
+  if (ecx & bit_F16C)
+    set_feature (FEATURE_F16C);
+  if (ecx & bit_RDRND)
+    set_feature (FEATURE_RDRND);
+  if (ecx & bit_XSAVE)
+    set_feature (FEATURE_XSAVE);
+  if (avx_usable)
+    {
+      if (ecx & bit_AVX)
+	set_feature (FEATURE_AVX);
+      if (ecx & bit_FMA)
+	set_feature (FEATURE_FMA);
+    }
+
+  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+  if (max_cpuid_level >= 7)
+    {
+      __cpuid_count (7, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_BMI)
+	set_feature (FEATURE_BMI);
+      if (ebx & bit_SGX)
+	set_feature (FEATURE_SGX);
+      if (ebx & bit_HLE)
+	set_feature (FEATURE_HLE);
+      if (ebx & bit_RTM)
+	set_feature (FEATURE_RTM);
+      if (avx_usable)
+	{
+	  if (ebx & bit_AVX2)
+	    set_feature (FEATURE_AVX2);
+	  if (ecx & bit_VPCLMULQDQ)
+	    set_feature (FEATURE_VPCLMULQDQ);
+	}
+      if (ebx & bit_BMI2)
+	set_feature (FEATURE_BMI2);
+      if (ebx & bit_FSGSBASE)
+	set_feature (FEATURE_FSGSBASE);
+      if (ebx & bit_RDSEED)
+	set_feature (FEATURE_RDSEED);
+      if (ebx & bit_ADX)
+	set_feature (FEATURE_ADX);
+      if (ebx & bit_SHA)
+	set_feature (FEATURE_SHA);
+      if (ebx & bit_CLFLUSHOPT)
+	set_feature (FEATURE_CLFLUSHOPT);
+      if (ebx & bit_CLWB)
+	set_feature (FEATURE_CLWB);
+      if (ecx & bit_PREFETCHWT1)
+	set_feature (FEATURE_PREFETCHWT1);
+      /* NB: bit_OSPKE indicates that OS supports PKU.  */
+      if (ecx & bit_OSPKE)
+	set_feature (FEATURE_PKU);
+      if (ecx & bit_RDPID)
+	set_feature (FEATURE_RDPID);
+      if (ecx & bit_VAES)
+	set_feature (FEATURE_VAES);
+      if (ecx & bit_GFNI)
+	set_feature (FEATURE_GFNI);
+      if (ecx & bit_MOVDIRI)
+	set_feature (FEATURE_MOVDIRI);
+      if (ecx & bit_MOVDIR64B)
+	set_feature (FEATURE_MOVDIR64B);
+      if (ecx & bit_ENQCMD)
+	set_feature (FEATURE_ENQCMD);
+      if (ecx & bit_CLDEMOTE)
+	set_feature (FEATURE_CLDEMOTE);
+      if (ecx & bit_WAITPKG)
+	set_feature (FEATURE_WAITPKG);
+      if (ecx & bit_SHSTK)
+	set_feature (FEATURE_SHSTK);
+      if (edx & bit_SERIALIZE)
+	set_feature (FEATURE_SERIALIZE);
+      if (edx & bit_TSXLDTRK)
+	set_feature (FEATURE_TSXLDTRK);
+      if (edx & bit_PCONFIG)
+	set_feature (FEATURE_PCONFIG);
+      if (edx & bit_IBT)
+	set_feature (FEATURE_IBT);
+      if (avx512_usable)
+	{
+	  if (ebx & bit_AVX512F)
+	    set_feature (FEATURE_AVX512F);
+	  if (ebx & bit_AVX512VL)
+	    set_feature (FEATURE_AVX512VL);
+	  if (ebx & bit_AVX512BW)
+	    set_feature (FEATURE_AVX512BW);
+	  if (ebx & bit_AVX512DQ)
+	    set_feature (FEATURE_AVX512DQ);
+	  if (ebx & bit_AVX512CD)
+	    set_feature (FEATURE_AVX512CD);
+	  if (ebx & bit_AVX512PF)
+	    set_feature (FEATURE_AVX512PF);
+	  if (ebx & bit_AVX512ER)
+	    set_feature (FEATURE_AVX512ER);
+	  if (ebx & bit_AVX512IFMA)
+	    set_feature (FEATURE_AVX512IFMA);
+	  if (ecx & bit_AVX512VBMI)
+	    set_feature (FEATURE_AVX512VBMI);
+	  if (ecx & bit_AVX512VBMI2)
+	    set_feature (FEATURE_AVX512VBMI2);
+	  if (ecx & bit_AVX512VNNI)
+	    set_feature (FEATURE_AVX512VNNI);
+	  if (ecx & bit_AVX512BITALG)
+	    set_feature (FEATURE_AVX512BITALG);
+	  if (ecx & bit_AVX512VPOPCNTDQ)
+	    set_feature (FEATURE_AVX512VPOPCNTDQ);
+	  if (edx & bit_AVX5124VNNIW)
+	    set_feature (FEATURE_AVX5124VNNIW);
+	  if (edx & bit_AVX5124FMAPS)
+	    set_feature (FEATURE_AVX5124FMAPS);
+	  if (edx & bit_AVX512VP2INTERSECT)
+	    set_feature (FEATURE_AVX512VP2INTERSECT);
+
+	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+	  if (eax & bit_AVX512BF16)
+	    set_feature (FEATURE_AVX512BF16);
+	}
+    }
+
+  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+  if (max_cpuid_level >= 0xd)
+    {
+      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+      if (eax & bit_XSAVEOPT)
+	set_feature (FEATURE_XSAVEOPT);
+      if (eax & bit_XSAVEC)
+	set_feature (FEATURE_XSAVEC);
+      if (eax & bit_XSAVES)
+	set_feature (FEATURE_XSAVES);
+    }
+
+  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+  if (max_cpuid_level >= 0x14)
+    {
+      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+      if (ebx & bit_PTWRITE)
+	set_feature (FEATURE_PTWRITE);
+    }
+
+  /* Check cpuid level of extended features.  */
+  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+  cpu_model2->__cpu_ext_level = ext_level;
+
+  if (ext_level >= 0x80000001)
+    {
+      __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+      if (ecx & bit_SSE4a)
+	set_feature (FEATURE_SSE4_A);
+      if (ecx & bit_LAHF_LM)
+	set_feature (FEATURE_LAHF_LM);
+      if (ecx & bit_ABM)
+	set_feature (FEATURE_ABM);
+      if (ecx & bit_LWP)
+	set_feature (FEATURE_LWP);
+      if (ecx & bit_TBM)
+	set_feature (FEATURE_TBM);
+      if (ecx & bit_LZCNT)
+	set_feature (FEATURE_LZCNT);
+      if (ecx & bit_PRFCHW)
+	set_feature (FEATURE_PRFCHW);
+      if (ecx & bit_MWAITX)
+	set_feature (FEATURE_MWAITX);
+
+      if (edx & bit_LM)
+	set_feature (FEATURE_LM);
+      if (edx & bit_3DNOWP)
+	set_feature (FEATURE_3DNOWP);
+      if (edx & bit_3DNOW)
+	set_feature (FEATURE_3DNOW);
+
+      if (avx_usable)
+	{
+	  if (ecx & bit_FMA4)
+	    set_feature (FEATURE_FMA4);
+	  if (ecx & bit_XOP)
+	    set_feature (FEATURE_XOP);
+	}
+    }
+
+  if (ext_level >= 0x80000008)
+    {
+      __cpuid (0x80000008, eax, ebx, ecx, edx);
+      if (ebx & bit_CLZERO)
+	set_feature (FEATURE_CLZERO);
+      if (ebx & bit_WBNOINVD)
+	set_feature (FEATURE_WBNOINVD);
+    }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+		    struct __processor_model2 *cpu_model2,
+		    unsigned int *cpu_features2)
+{
+  unsigned int eax, ebx, ecx, edx;
+
+  int max_level;
+  unsigned int vendor;
+  unsigned int model, family, brand_id;
+  unsigned int extended_model, extended_family;
+
+  /* This function needs to run just once.  */
+  if (cpu_model->__cpu_vendor)
+    return 0;
+
+  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  vendor = ebx;
+  max_level = eax;
+
+  if (max_level < 1)
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    {
+      cpu_model->__cpu_vendor = VENDOR_OTHER;
+      return -1;
+    }
+
+  cpu_model2->__cpu_max_level = max_level;
+
+  model = (eax >> 4) & 0x0f;
+  family = (eax >> 8) & 0x0f;
+  brand_id = ebx & 0xff;
+  extended_model = (eax >> 12) & 0xf0;
+  extended_family = (eax >> 20) & 0xff;
+
+  if (vendor == signature_INTEL_ebx)
+    {
+      /* Adjust model and family for Intel CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+      else if (family == 0x06)
+	model += extended_model;
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+      cpu_model->__cpu_vendor = VENDOR_INTEL;
+    }
+  else if (vendor == signature_AMD_ebx)
+    {
+      /* Adjust model and family for AMD CPUS. */
+      if (family == 0x0f)
+	{
+	  family += extended_family;
+	  model += extended_model;
+	}
+
+      cpu_model2->__cpu_family = family;
+      cpu_model2->__cpu_model = model;
+
+      /* Find available features. */
+      get_available_features (cpu_model, cpu_model2, cpu_features2,
+			      ecx, edx);
+      /* Get CPU type.  */
+      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+      cpu_model->__cpu_vendor = VENDOR_AMD;
+    }
+  else if (vendor == signature_CENTAUR_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+  else if (vendor == signature_CYRIX_ebx)
+    cpu_model->__cpu_vendor = VENDOR_CYRIX;
+  else if (vendor == signature_NSC_ebx)
+    cpu_model->__cpu_vendor = VENDOR_NSC;
+  else
+    cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+  return 0;
+}
diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
index e11c68f46dd..96cf0eaea47 100644
--- a/gcc/common/config/i386/i386-cpuinfo.h
+++ b/gcc/common/config/i386/i386-cpuinfo.h
@@ -30,6 +30,9 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
   BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
@@ -122,6 +125,101 @@ enum feature_priority
   P_PROC_DYNAMIC
 };
 
+/* ISA Features supported. New features have to be inserted at the end.  */
+
+enum processor_features
+{
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_SSE4_A,
+  FEATURE_FMA4,
+  FEATURE_XOP,
+  FEATURE_FMA,
+  FEATURE_AVX512F,
+  FEATURE_BMI,
+  FEATURE_BMI2,
+  FEATURE_AES,
+  FEATURE_PCLMUL,
+  FEATURE_AVX512VL,
+  FEATURE_AVX512BW,
+  FEATURE_AVX512DQ,
+  FEATURE_AVX512CD,
+  FEATURE_AVX512ER,
+  FEATURE_AVX512PF,
+  FEATURE_AVX512VBMI,
+  FEATURE_AVX512IFMA,
+  FEATURE_AVX5124VNNIW,
+  FEATURE_AVX5124FMAPS,
+  FEATURE_AVX512VPOPCNTDQ,
+  FEATURE_AVX512VBMI2,
+  FEATURE_GFNI,
+  FEATURE_VPCLMULQDQ,
+  FEATURE_AVX512VNNI,
+  FEATURE_AVX512BITALG,
+  FEATURE_AVX512BF16,
+  FEATURE_AVX512VP2INTERSECT,
+  FEATURE_3DNOW,
+  FEATURE_3DNOWP,
+  FEATURE_ADX,
+  FEATURE_ABM,
+  FEATURE_CLDEMOTE,
+  FEATURE_CLFLUSHOPT,
+  FEATURE_CLWB,
+  FEATURE_CLZERO,
+  FEATURE_CMPXCHG16B,
+  FEATURE_CMPXCHG8B,
+  FEATURE_ENQCMD,
+  FEATURE_F16C,
+  FEATURE_FSGSBASE,
+  FEATURE_FXSAVE,
+  FEATURE_HLE,
+  FEATURE_IBT,
+  FEATURE_LAHF_LM,
+  FEATURE_LM,
+  FEATURE_LWP,
+  FEATURE_LZCNT,
+  FEATURE_MOVBE,
+  FEATURE_MOVDIR64B,
+  FEATURE_MOVDIRI,
+  FEATURE_MWAITX,
+  FEATURE_OSXSAVE,
+  FEATURE_PCONFIG,
+  FEATURE_PKU,
+  FEATURE_PREFETCHWT1,
+  FEATURE_PRFCHW,
+  FEATURE_PTWRITE,
+  FEATURE_RDPID,
+  FEATURE_RDRND,
+  FEATURE_RDSEED,
+  FEATURE_RTM,
+  FEATURE_SERIALIZE,
+  FEATURE_SGX,
+  FEATURE_SHA,
+  FEATURE_SHSTK,
+  FEATURE_TBM,
+  FEATURE_TSXLDTRK,
+  FEATURE_VAES,
+  FEATURE_WAITPKG,
+  FEATURE_WBNOINVD,
+  FEATURE_XSAVE,
+  FEATURE_XSAVEC,
+  FEATURE_XSAVEOPT,
+  FEATURE_XSAVES,
+  CPU_FEATURE_MAX
+};
+
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
+
 /* These are the values for vendor types, cpu types and subtypes.  Cpu
    types and subtypes should be subtracted by the corresponding start
    value.  */
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 6f6a8328ef1..57e709d6c43 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -1835,50 +1835,6 @@ ix86_builtin_reciprocal (tree fndecl)
     }
 }
 
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
-  F_CMOV = 0,
-  F_MMX,
-  F_POPCNT,
-  F_SSE,
-  F_SSE2,
-  F_SSE3,
-  F_SSSE3,
-  F_SSE4_1,
-  F_SSE4_2,
-  F_AVX,
-  F_AVX2,
-  F_SSE4_A,
-  F_FMA4,
-  F_XOP,
-  F_FMA,
-  F_AVX512F,
-  F_BMI,
-  F_BMI2,
-  F_AES,
-  F_PCLMUL,
-  F_AVX512VL,
-  F_AVX512BW,
-  F_AVX512DQ,
-  F_AVX512CD,
-  F_AVX512ER,
-  F_AVX512PF,
-  F_AVX512VBMI,
-  F_AVX512IFMA,
-  F_AVX5124VNNIW,
-  F_AVX5124FMAPS,
-  F_AVX512VPOPCNTDQ,
-  F_AVX512VBMI2,
-  F_GFNI,
-  F_VPCLMULQDQ,
-  F_AVX512VNNI,
-  F_AVX512BITALG,
-  F_AVX512BF16,
-  F_AVX512VP2INTERSECT,
-  F_MAX
-};
-
 /* These are the target attribute strings for which a dispatcher is
    available, from fold_builtin_cpu.  */
 struct _isa_names_table
@@ -1890,44 +1846,44 @@ struct _isa_names_table
 
 static const _isa_names_table isa_names_table[] =
 {
-  {"cmov",    F_CMOV,	P_NONE},
-  {"mmx",     F_MMX,	P_MMX},
-  {"popcnt",  F_POPCNT,	P_POPCNT},
-  {"sse",     F_SSE,	P_SSE},
-  {"sse2",    F_SSE2,	P_SSE2},
-  {"sse3",    F_SSE3,	P_SSE3},
-  {"ssse3",   F_SSSE3,	P_SSSE3},
-  {"sse4a",   F_SSE4_A,	P_SSE4_A},
-  {"sse4.1",  F_SSE4_1,	P_SSE4_1},
-  {"sse4.2",  F_SSE4_2,	P_SSE4_2},
-  {"avx",     F_AVX,	P_AVX},
-  {"fma4",    F_FMA4,	P_FMA4},
-  {"xop",     F_XOP,	P_XOP},
-  {"fma",     F_FMA,	P_FMA},
-  {"avx2",    F_AVX2,	P_AVX2},
-  {"avx512f", F_AVX512F, P_AVX512F},
-  {"bmi",     F_BMI,	P_BMI},
-  {"bmi2",    F_BMI2,	P_BMI2},
-  {"aes",     F_AES,	P_AES},
-  {"pclmul",  F_PCLMUL,	P_PCLMUL},
-  {"avx512vl",F_AVX512VL, P_NONE},
-  {"avx512bw",F_AVX512BW, P_NONE},
-  {"avx512dq",F_AVX512DQ, P_NONE},
-  {"avx512cd",F_AVX512CD, P_NONE},
-  {"avx512er",F_AVX512ER, P_NONE},
-  {"avx512pf",F_AVX512PF, P_NONE},
-  {"avx512vbmi",F_AVX512VBMI, P_NONE},
-  {"avx512ifma",F_AVX512IFMA, P_NONE},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_NONE},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_NONE},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,	P_NONE},
-  {"avx512vbmi2", F_AVX512VBMI2, P_NONE},
-  {"gfni",	F_GFNI,	P_NONE},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_NONE},
-  {"avx512vnni", F_AVX512VNNI, P_NONE},
-  {"avx512bitalg", F_AVX512BITALG, P_NONE},
-  {"avx512bf16", F_AVX512BF16, P_NONE},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_NONE}
+  {"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
@@ -2294,16 +2250,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
 
       if (isa_names_table[i].feature >= 32)
 	{
-	  tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+	  tree index_type
+	    = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+	  tree type = build_array_type (unsigned_type_node, index_type);
+	  tree __cpu_features2_var = make_var_decl (type,
 						    "__cpu_features2");
 
 	  varpool_node::add (__cpu_features2_var);
-	  field_val = (1U << (isa_names_table[i].feature - 32));
-	  /* Return __cpu_features2 & field_val  */
-	  final = build2 (BIT_AND_EXPR, unsigned_type_node,
-			  __cpu_features2_var,
-			  build_int_cstu (unsigned_type_node, field_val));
-	  return build1 (CONVERT_EXPR, integer_type_node, final);
+	  for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+	    if (isa_names_table[i].feature < (32 + 32 + j * 32))
+	      {
+		field_val = (1U << (isa_names_table[i].feature
+				    - (32 + j * 32)));
+		tree index = size_int (j);
+		array_elt = build4 (ARRAY_REF, unsigned_type_node,
+				    __cpu_features2_var,
+				    index, NULL_TREE, NULL_TREE);
+		/* Return __cpu_features2[index] & field_val  */
+		final = build2 (BIT_AND_EXPR, unsigned_type_node,
+				array_elt,
+				build_int_cstu (unsigned_type_node,
+						field_val));
+		return build1 (CONVERT_EXPR, integer_type_node, final);
+	      }
 	}
 
       field = TYPE_FIELDS (__processor_model_type);
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index cf5f0884bb4..7218952f32a 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "cpuid.h"
 #include "tsystem.h"
 #include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/i386-cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +40,14 @@ int __cpu_indicator_init (void)
 
 
 struct __processor_model __cpu_model = { };
-#ifndef SHARED
 /* We want to move away from __cpu_model in libgcc_s.so.1 and the
    size of __cpu_model is part of ABI.  So, new features that don't
    fit into __cpu_model.__cpu_features[0] go into extra variables
-   in libgcc.a only, preferrably hidden.  */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU.  */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
-  switch (family)
-    {
-    /* AMD Family 10h.  */
-    case 0x10:
-      __cpu_model.__cpu_type = AMDFAM10H;
-      switch (model)
-	{
-	case 0x2:
-	  /* Barcelona.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
-	  break;
-	case 0x4:
-	  /* Shanghai.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
-	  break;
-	case 0x8:
-	  /* Istanbul.  */
-	  __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
-	  break;
-	default:
-	  break;
-	}
-      break;
-    /* AMD Family 14h "btver1". */
-    case 0x14:
-      __cpu_model.__cpu_type = AMD_BTVER1;
-      break;
-    /* AMD Family 15h "Bulldozer".  */
-    case 0x15:
-      __cpu_model.__cpu_type = AMDFAM15H;
-
-      if (model == 0x2)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 1.  */
-      else if (model <= 0xf)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
-      /* Bulldozer version 2 "Piledriver" */
-      else if (model <= 0x2f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;      
-      /* Bulldozer version 3 "Steamroller"  */
-      else if (model <= 0x4f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
-      /* Bulldozer version 4 "Excavator"   */
-      else if (model <= 0x7f)
-	__cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
-      break;
-    /* AMD Family 16h "btver2" */
-    case 0x16:
-      __cpu_model.__cpu_type = AMD_BTVER2;
-      break;
-    case 0x17:
-      __cpu_model.__cpu_type = AMDFAM17H;
-      /* AMD family 17h version 1.  */
-      if (model <= 0x1f)
-	__cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
-      if (model >= 0x30)
-	 __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
-      break;
-    default:
-      break;
-    }
-}
-
-/* Get the specific type of Intel CPU.  */
-
-static void
-get_intel_cpu (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:
-	      /* Bonnell.  */
-	      __cpu_model.__cpu_type = INTEL_BONNELL;
-	      break;
-	    case 0x37:
-	    case 0x4a:
-	    case 0x4d:
-	    case 0x5a:
-	    case 0x5d:
-	      /* Silvermont.  */
-	      __cpu_model.__cpu_type = INTEL_SILVERMONT;
-	      break;
-	    case 0x5c:
-	    case 0x5f:
-	      /* Goldmont.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT;
-	      break;
-	    case 0x7a:
-	      /* Goldmont Plus.  */
-	      __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
-	      break;
-	    case 0x57:
-	      /* Knights Landing.  */
-	      __cpu_model.__cpu_type = INTEL_KNL;
-	      break;
-	    case 0x85:
-	      /* Knights Mill. */
-	      __cpu_model.__cpu_type = INTEL_KNM;
-	      break;
-	    case 0x1a:
-	    case 0x1e:
-	    case 0x1f:
-	    case 0x2e:
-	      /* Nehalem.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
-	      break;
-	    case 0x25:
-	    case 0x2c:
-	    case 0x2f:
-	      /* Westmere.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
-	      break;
-	    case 0x2a:
-	    case 0x2d:
-	      /* Sandy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
-	      break;
-	    case 0x3a:
-	    case 0x3e:
-	      /* Ivy Bridge.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
-	      break;
-	    case 0x3c:
-	    case 0x3f:
-	    case 0x45:
-	    case 0x46:
-	      /* Haswell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
-	      break;
-	    case 0x3d:
-	    case 0x47:
-	    case 0x4f:
-	    case 0x56:
-	      /* Broadwell.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
-	      break;
-	    case 0x4e:
-	    case 0x5e:
-	      /* Skylake.  */
-	    case 0x8e:
-	    case 0x9e:
-	      /* Kaby Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
-	      break;
-	    case 0x55:
-	      {
-	        unsigned int eax, ebx, ecx, edx;
-	        __cpu_model.__cpu_type = INTEL_COREI7;
-	        __cpuid_count (7, 0, eax, ebx, ecx, edx);
-	        if (ecx & bit_AVX512VNNI)
-	          /* Cascade Lake.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
-	        else
-	          /* Skylake with AVX-512 support.  */
-	          __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
-	      }
-	      break;
-	    case 0x66:
-	      /* Cannon Lake.  */
-	      __cpu_model.__cpu_type = INTEL_COREI7;
-	      __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
-	      break;
-	    case 0x17:
-	    case 0x1d:
-	      /* Penryn.  */
-	    case 0x0f:
-	      /* Merom.  */
-	      __cpu_model.__cpu_type = INTEL_CORE2;
-	      break;
-	    default:
-	      break;
-	    }
-	  break;
-	default:
-	  /* We have no idea.  */
-	  break;
-	}
-    }
-}	             	
-
-/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
-   the max possible level of CPUID insn.  */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
-			int max_cpuid_level)
-{
-  unsigned int eax, ebx;
-  unsigned int ext_level;
-
-  unsigned int features = 0;
-  unsigned int features2 = 0;
-
-  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
-#define XCR_XFEATURE_ENABLED_MASK	0x0
-#define XSTATE_FP			0x1
-#define XSTATE_SSE			0x2
-#define XSTATE_YMM			0x4
-#define XSTATE_OPMASK			0x20
-#define XSTATE_ZMM			0x40
-#define XSTATE_HI_ZMM			0x80
-
-#define XCR_AVX_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
-  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
-  /* Check if AVX and AVX512 are usable.  */
-  int avx_usable = 0;
-  int avx512_usable = 0;
-  if ((ecx & bit_OSXSAVE))
-    {
-      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
-         ZMM16-ZMM31 states are supported by OSXSAVE.  */
-      unsigned int xcrlow;
-      unsigned int xcrhigh;
-      asm (".byte 0x0f, 0x01, 0xd0"
-	   : "=a" (xcrlow), "=d" (xcrhigh)
-	   : "c" (XCR_XFEATURE_ENABLED_MASK));
-      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
-	{
-	  avx_usable = 1;
-	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
-			   == XCR_AVX512F_ENABLED_MASK);
-	}
-    }
-
-#define set_feature(f) \
-  do						\
-    {						\
-      if (f < 32)				\
-	features |= (1U << (f & 31));		\
-      else					\
-	features2 |= (1U << ((f - 32) & 31));	\
-    }						\
-  while (0)
-
-  if (edx & bit_CMOV)
-    set_feature (FEATURE_CMOV);
-  if (edx & bit_MMX)
-    set_feature (FEATURE_MMX);
-  if (edx & bit_SSE)
-    set_feature (FEATURE_SSE);
-  if (edx & bit_SSE2)
-    set_feature (FEATURE_SSE2);
-  if (ecx & bit_POPCNT)
-    set_feature (FEATURE_POPCNT);
-  if (ecx & bit_AES)
-    set_feature (FEATURE_AES);
-  if (ecx & bit_PCLMUL)
-    set_feature (FEATURE_PCLMUL);
-  if (ecx & bit_SSE3)
-    set_feature (FEATURE_SSE3);
-  if (ecx & bit_SSSE3)
-    set_feature (FEATURE_SSSE3);
-  if (ecx & bit_SSE4_1)
-    set_feature (FEATURE_SSE4_1);
-  if (ecx & bit_SSE4_2)
-    set_feature (FEATURE_SSE4_2);
-  if (avx_usable)
-    {
-      if (ecx & bit_AVX)
-	set_feature (FEATURE_AVX);
-      if (ecx & bit_FMA)
-	set_feature (FEATURE_FMA);
-    }
-
-  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
-  if (max_cpuid_level >= 7)
-    {
-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
-      if (ebx & bit_BMI)
-	set_feature (FEATURE_BMI);
-      if (avx_usable)
-	{
-	  if (ebx & bit_AVX2)
-	    set_feature (FEATURE_AVX2);
-	  if (ecx & bit_VPCLMULQDQ)
-	    set_feature (FEATURE_VPCLMULQDQ);
-	}
-      if (ebx & bit_BMI2)
-	set_feature (FEATURE_BMI2);
-      if (ecx & bit_GFNI)
-	set_feature (FEATURE_GFNI);
-      if (avx512_usable)
-	{
-	  if (ebx & bit_AVX512F)
-	    set_feature (FEATURE_AVX512F);
-	  if (ebx & bit_AVX512VL)
-	    set_feature (FEATURE_AVX512VL);
-	  if (ebx & bit_AVX512BW)
-	    set_feature (FEATURE_AVX512BW);
-	  if (ebx & bit_AVX512DQ)
-	    set_feature (FEATURE_AVX512DQ);
-	  if (ebx & bit_AVX512CD)
-	    set_feature (FEATURE_AVX512CD);
-	  if (ebx & bit_AVX512PF)
-	    set_feature (FEATURE_AVX512PF);
-	  if (ebx & bit_AVX512ER)
-	    set_feature (FEATURE_AVX512ER);
-	  if (ebx & bit_AVX512IFMA)
-	    set_feature (FEATURE_AVX512IFMA);
-	  if (ecx & bit_AVX512VBMI)
-	    set_feature (FEATURE_AVX512VBMI);
-	  if (ecx & bit_AVX512VBMI2)
-	    set_feature (FEATURE_AVX512VBMI2);
-	  if (ecx & bit_AVX512VNNI)
-	    set_feature (FEATURE_AVX512VNNI);
-	  if (ecx & bit_AVX512BITALG)
-	    set_feature (FEATURE_AVX512BITALG);
-	  if (ecx & bit_AVX512VPOPCNTDQ)
-	    set_feature (FEATURE_AVX512VPOPCNTDQ);
-	  if (edx & bit_AVX5124VNNIW)
-	    set_feature (FEATURE_AVX5124VNNIW);
-	  if (edx & bit_AVX5124FMAPS)
-	    set_feature (FEATURE_AVX5124FMAPS);
-	  if (edx & bit_AVX512VP2INTERSECT)
-	    set_feature (FEATURE_AVX512VP2INTERSECT);
+   in libgcc.a only, preferably hidden.
 
-	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
-	  if (eax & bit_AVX512BF16)
-	    set_feature (FEATURE_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)
-	set_feature (FEATURE_SSE4_A);
-      if (avx_usable)
-	{
-	  if (ecx & bit_FMA4)
-	    set_feature (FEATURE_FMA4);
-	  if (ecx & bit_XOP)
-	    set_feature (FEATURE_XOP);
-	}
-    }
-    
-  __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
-  __cpu_features2 = features2;
-#else
-  (void) features2;
-#endif
-}
+   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+   smaller array, it can only access the first few elements.  */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
 
 /* A constructor function that is sets __cpu_model and __cpu_features with
    the right values.  This needs to run only once.  This constructor is
@@ -429,85 +58,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
 int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
 __cpu_indicator_init (void)
 {
-  unsigned int eax, ebx, ecx, edx;
-
-  int max_level;
-  unsigned int vendor;
-  unsigned int model, family, brand_id;
-  unsigned int extended_model, extended_family;
-
-  /* This function needs to run just once.  */
-  if (__cpu_model.__cpu_vendor)
-    return 0;
-
-  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
-  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  vendor = ebx;
-  max_level = eax;
-
-  if (max_level < 1)
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
-    {
-      __cpu_model.__cpu_vendor = VENDOR_OTHER;
-      return -1;
-    }
-
-  model = (eax >> 4) & 0x0f;
-  family = (eax >> 8) & 0x0f;
-  brand_id = ebx & 0xff;
-  extended_model = (eax >> 12) & 0xf0;
-  extended_family = (eax >> 20) & 0xff;
-
-  if (vendor == signature_INTEL_ebx)
-    {
-      /* Adjust model and family for Intel CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-      else if (family == 0x06)
-	model += extended_model;
-
-      /* Get CPU type.  */
-      get_intel_cpu (family, model, brand_id);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_INTEL;
-    }
-  else if (vendor == signature_AMD_ebx)
-    {
-      /* Adjust model and family for AMD CPUS. */
-      if (family == 0x0f)
-	{
-	  family += extended_family;
-	  model += extended_model;
-	}
-
-      /* Get CPU type.  */
-      get_amd_cpu (family, model);
-      /* Find available features. */
-      get_available_features (ecx, edx, max_level);
-      __cpu_model.__cpu_vendor = VENDOR_AMD;
-    }
-  else
-    __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
-  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
-  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
-  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
-  return 0;
+  struct __processor_model2 cpu_model2;
+  return cpu_indicator_init (&__cpu_model, &cpu_model2,
+			     __cpu_features2);
 }
 
 #if defined SHARED && defined USE_ELF_SYMVER
diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
deleted file mode 100644
index 0f97510cde1..00000000000
--- a/libgcc/config/i386/cpuinfo.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Get CPU type and Features for x86 processors.
-   Copyright (C) 2012-2020 Free Software Foundation, Inc.
-   Contributed by Sriraman Tallam (tmsriram@google.com)
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-<http://www.gnu.org/licenses/>.  */
-
-/* Processor Vendor and Models. */
-
-enum processor_vendor
-{
-  VENDOR_INTEL = 1,
-  VENDOR_AMD,
-  VENDOR_OTHER,
-  VENDOR_MAX
-};
-
-/* Any new types or subtypes have to be inserted at the end. */
-
-enum processor_types
-{
-  INTEL_BONNELL = 1,
-  INTEL_CORE2,
-  INTEL_COREI7,
-  AMDFAM10H,
-  AMDFAM15H,
-  INTEL_SILVERMONT,
-  INTEL_KNL,
-  AMD_BTVER1,
-  AMD_BTVER2,  
-  AMDFAM17H,
-  INTEL_KNM,
-  INTEL_GOLDMONT,
-  INTEL_GOLDMONT_PLUS,
-  INTEL_TREMONT,
-  CPU_TYPE_MAX
-};
-
-enum processor_subtypes
-{
-  INTEL_COREI7_NEHALEM = 1,
-  INTEL_COREI7_WESTMERE,
-  INTEL_COREI7_SANDYBRIDGE,
-  AMDFAM10H_BARCELONA,
-  AMDFAM10H_SHANGHAI,
-  AMDFAM10H_ISTANBUL,
-  AMDFAM15H_BDVER1,
-  AMDFAM15H_BDVER2,
-  AMDFAM15H_BDVER3,
-  AMDFAM15H_BDVER4,
-  AMDFAM17H_ZNVER1,
-  INTEL_COREI7_IVYBRIDGE,
-  INTEL_COREI7_HASWELL,
-  INTEL_COREI7_BROADWELL,
-  INTEL_COREI7_SKYLAKE,
-  INTEL_COREI7_SKYLAKE_AVX512,
-  INTEL_COREI7_CANNONLAKE,
-  INTEL_COREI7_ICELAKE_CLIENT,
-  INTEL_COREI7_ICELAKE_SERVER,
-  AMDFAM17H_ZNVER2,
-  INTEL_COREI7_CASCADELAKE,
-  INTEL_COREI7_TIGERLAKE,
-  INTEL_COREI7_COOPERLAKE,
-  CPU_SUBTYPE_MAX
-};
-
-/* ISA Features supported. New features have to be inserted at the end.  */
-
-enum processor_features
-{
-  FEATURE_CMOV = 0,
-  FEATURE_MMX,
-  FEATURE_POPCNT,
-  FEATURE_SSE,
-  FEATURE_SSE2,
-  FEATURE_SSE3,
-  FEATURE_SSSE3,
-  FEATURE_SSE4_1,
-  FEATURE_SSE4_2,
-  FEATURE_AVX,
-  FEATURE_AVX2,
-  FEATURE_SSE4_A,
-  FEATURE_FMA4,
-  FEATURE_XOP,
-  FEATURE_FMA,
-  FEATURE_AVX512F,
-  FEATURE_BMI,
-  FEATURE_BMI2,
-  FEATURE_AES,
-  FEATURE_PCLMUL,
-  FEATURE_AVX512VL,
-  FEATURE_AVX512BW,
-  FEATURE_AVX512DQ,
-  FEATURE_AVX512CD,
-  FEATURE_AVX512ER,
-  FEATURE_AVX512PF,
-  FEATURE_AVX512VBMI,
-  FEATURE_AVX512IFMA,
-  FEATURE_AVX5124VNNIW,
-  FEATURE_AVX5124FMAPS,
-  FEATURE_AVX512VPOPCNTDQ,
-  FEATURE_AVX512VBMI2,
-  FEATURE_GFNI,
-  FEATURE_VPCLMULQDQ,
-  FEATURE_AVX512VNNI,
-  FEATURE_AVX512BITALG,
-  FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
-};
-
-extern struct __processor_model
-{
-  unsigned int __cpu_vendor;
-  unsigned int __cpu_type;
-  unsigned int __cpu_subtype;
-  unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
-- 
2.26.2


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: V7 [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
  2020-06-24 12:27                                                 ` V7 " H.J. Lu
@ 2020-06-24 12:43                                                   ` Uros Bizjak
  0 siblings, 0 replies; 30+ messages in thread
From: Uros Bizjak @ 2020-06-24 12:43 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Martin Liška, GCC Patches, Jan Hubicka, Jakub Jelinek,
	Jeffrey Law, Richard Biener

On Wed, Jun 24, 2020 at 2:27 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Jun 22, 2020 at 04:25:46PM -0700, H.J. Lu wrote:
> > On Sun, Jun 21, 2020 at 10:22 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Sun, Jun 21, 2020 at 10:18 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> > > >
> > > > On Sat, Jun 20, 2020 at 3:40 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > > > > > >> 2) can we automatically deduce option name:
> > > > > > > > >>
> > > > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdpid", FEATURE_RDPID, P_ZERO, "-mrdpid")
> > > > > > > > >>> +  ISA_NAMES_TABLE_ENTRY("rdrnd", FEATURE_RDRND, P_ZERO, "-mrdrnd")
> > > > > > > > >>
> > > > > > > > >> I mean "-m" + "rdrnd" == "-mrdrnd" ?
> > > > > > > > >
> > > > > > > > > The new option field serves 2 purposes:
> > > > > > > > >
> > > > > > > > > 1. Not all features have a corresponding command-line option
> > > > > > > > >
> > > > > > > > > ISA_NAMES_TABLE_ENTRY("cmov", FEATURE_CMOV, P_ZERO, NULL)
> > > > > > > > >
> > > > > > > > >       for (i = 0; i < ARRAY_SIZE (isa_names_table); i++)
> > > > > > > > >          if (isa_names_table[i].option)
> > > > > > > > >
> > > > > > > > > 2. Some feature has a different name in the command-line option.
> > > > > > > > >
> > > > > > > > >    ISA_NAMES_TABLE_ENTRY("fxsave", FEATURE_FXSAVE, P_ZERO, "-mfxsr")
> > > > > > > >
> > > > > > > > I noticed that, one can theoretically use "" for an option that does not
> > > > > > > > have a flag. And NULL for these which have option equal to "-m" + name.
> > > > > > > > Anyway, that's a nit.
> > > > > > > >
> > > > > > > > I support the patch!
> > > > > > > > Martin
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Here is the updated patch.   OK for master?
> > > > > > > > >
> > > > > > > > > Thanks.
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > > PING:
> > > > > > >
> > > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > > > > > >
> > > > > >
> > > > > > PING.
> > > > >
> > > > > Hi,
> > > > >
> > > > > We have patches like
> > > > >
> > > > > https://gcc.gnu.org/pipermail/gcc-bugs/2020-June/705851.html
> > > > >
> > > > > queued up because of this prerequisite patch.   Are there any objections
> > > > > to this patch?
> > > >
> > > > Yes, there are my objections.
> > > >
> > > > As explained before, I support unifying libgcc and core gcc handling,
> > > > but _NOT_ unifying with driver-i386.c. Unifying libgcc and core gcc
> > > > handling would have benefit to avoid desynchronisation between the two
> > > > (which happened multiple times in the past, resulting in various API
> > > > issues). OTOH, unifying with driver-i386.c would result in quite messy
> > > > approach, because driver-i386 handles more targets beside relatively
> > > > recent 64bit Intel and AMD targets, not to mention heuristics to
> > > > determine the most appropriate target when standard detection fails
> > > > (e.g. emulators).
> > >
> > > Only the duplicated parts of driver-i386.c should be unified.  The only impact
> > > should be removing code duplications.  If it isn't the case, it is a bug in my
> > > implementation.
> >
> > Here is the updated patch to remove FEATURE_OSPKE and use bit_OSPKE
> > for FEATURE_PKU.  It uses the same get_amd_cpu and get_intel_cpu in
> > libgcc and driver-i386.c:
> >    a. Detect the processor name for newer Intel and AMD processors.
> >       Since the older processor names are only supported by driver-i386.c,
> >       not by libgcc, detection for the older processors remains in
> >       driver-i386.c.
> >    b. Detect available ISAs for all Intel and AMD processors.
> >
>
> 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.

> OK for master?

Yes, this part looks OK to me.

Thanks,
Uros.

>
> Thannks.
>
> H.J.
> ---
> Both x86 backend and libgcc define enum processor_features.  libgcc sets
> enum processor_feature and x86 backend checks enum processor_feature.
> They are very easy out of sync and it has happened multiple times in the
> past.
>
> 1. Move cpuinfo.h from libgcc to common/config/i386 so that we can share
> the same enum processor_features in x86 backend and libgcc.
> 2. Change __cpu_features2 to an array to support more processor features.
> 3. Add more processor features to enum processor_features.
>
> gcc/
>
>         PR target/95259
>         * common/config/i386/cpuinfo.h: New file.
>         (__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
>         (__processor_model2): New.
>         (CHECK___builtin_cpu_is): New.  Defined as empty if not defined.
>         (has_cpu_feature): New function.
>         (set_cpu_feature): Likewise.
>         (get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
>         CHECK___builtin_cpu_is.  Return AMD CPU name.
>         (get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c.  Use
>         Use CHECK___builtin_cpu_is.  Return Intel CPU name.
>         (get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
>         Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
>         FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
>         FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
>         FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
>         FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
>         FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
>         FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSXSAVE,
>         FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
>         FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
>         FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
>         FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
>         FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
>         FEATURE_XSAVEOPT and FEATURE_XSAVES
>         (cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
>         Also update cpu_model2.
>         * common/config/i386/i386-cpuinfo.h (processor_vendor): Add
>         Add VENDOR_CENTAUR, VENDOR_CYRIX and VENDOR_NSC.
>         (processor_features): Moved from gcc/config/i386/i386-builtins.c.
>         Renamed F_XXX to FEATURE_XXX.  Add FEATURE_3DNOW, FEATURE_3DNOWP,
>         FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
>         FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
>         FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
>         FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
>         FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
>         FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
>         FEATURE_MWAITX, FEATURE_OSXSAVE, FEATURE_PCONFIG,
>         FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
>         FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
>         FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
>         FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
>         FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
>         FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
>         (SIZE_OF_CPU_FEATURES): New.
>         * config/i386/i386-builtins.c (processor_features): Removed.
>         (isa_names_table): Replace F_XXX with FEATURE_XXX.
>         (fold_builtin_cpu): Change __cpu_features2 to an array.
>
> libgcc/
>
>         PR target/95259
>         * config/i386/cpuinfo.c: Don't include "cpuinfo.h".  Include
>         "common/config/i386/i386-cpuinfo.h" and
>         "common/config/i386/cpuinfo.h".
>         (__cpu_features2): Changed to array.
>         (get_amd_cpu): Removed.
>         (get_intel_cpu): Likewise.
>         (get_available_features): Likewise.
>         (__cpu_indicator_init): Call cpu_indicator_init.
>         * config/i386/cpuinfo.h: Removed.
> ---
>  gcc/common/config/i386/cpuinfo.h      | 844 ++++++++++++++++++++++++++
>  gcc/common/config/i386/i386-cpuinfo.h |  98 +++
>  gcc/config/i386/i386-builtins.c       | 147 ++---
>  libgcc/config/i386/cpuinfo.c          | 465 +-------------
>  libgcc/config/i386/cpuinfo.h          | 136 -----
>  5 files changed, 1009 insertions(+), 681 deletions(-)
>  create mode 100644 gcc/common/config/i386/cpuinfo.h
>  delete mode 100644 libgcc/config/i386/cpuinfo.h
>
> diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
> new file mode 100644
> index 00000000000..2d72b3b60fd
> --- /dev/null
> +++ b/gcc/common/config/i386/cpuinfo.h
> @@ -0,0 +1,844 @@
> +/* Get CPU type and Features for x86 processors.
> +   Copyright (C) 2012-2020 Free Software Foundation, Inc.
> +   Contributed by Sriraman Tallam (tmsriram@google.com)
> +
> +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.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +struct __processor_model
> +{
> +  unsigned int __cpu_vendor;
> +  unsigned int __cpu_type;
> +  unsigned int __cpu_subtype;
> +  /* The first 32 features are stored as bitmasks in __cpu_features.
> +     The rest of features are stored as bitmasks in a separate array
> +     of unsigned int.  */
> +  unsigned int __cpu_features[1];
> +};
> +
> +struct __processor_model2
> +{
> +  unsigned int __cpu_family;
> +  unsigned int __cpu_model;
> +  unsigned int __cpu_max_level;
> +  unsigned int __cpu_ext_level;
> +};
> +
> +#ifndef CHECK___builtin_cpu_is
> +# define CHECK___builtin_cpu_is(cpu)
> +#endif
> +
> +/* Return non-zero if the processor has feature F.  */
> +
> +static inline int
> +has_cpu_feature (struct __processor_model *cpu_model,
> +                unsigned int *cpu_features2,
> +                enum processor_features f)
> +{
> +  unsigned int i;
> +  if (f < 32)
> +    {
> +      /* The first 32 features.  */
> +      return cpu_model->__cpu_features[0] & (1U << (f & 31));
> +    }
> +  /* The rest of features.  cpu_features2[i] contains features from
> +     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
> +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> +    if (f < (32 + 32 + i * 32))
> +    return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
> +  gcc_unreachable ();
> +}
> +
> +static inline void
> +set_cpu_feature (struct __processor_model *cpu_model,
> +                unsigned int *cpu_features2,
> +                enum processor_features f)
> +{
> +  unsigned int i;
> +  if (f < 32)
> +    {
> +      /* The first 32 features.  */
> +      cpu_model->__cpu_features[0] |= (1U << (f & 31));
> +      return;
> +    }
> +  /* The rest of features.  cpu_features2[i] contains features from
> +     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
> +  for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
> +    if (f < (32 + 32 + i * 32))
> +      {
> +       cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
> +       return;
> +      }
> +  gcc_unreachable ();
> +}
> +
> +/* Get the specific type of AMD CPU and return AMD CPU name.  Return
> +   NULL for unknown AMD CPU.  */
> +
> +static inline const char *
> +get_amd_cpu (struct __processor_model *cpu_model,
> +            struct __processor_model2 *cpu_model2,
> +            unsigned int *cpu_features2)
> +{
> +  const char *cpu = NULL;
> +  unsigned int family = cpu_model2->__cpu_family;
> +  unsigned int model = cpu_model2->__cpu_model;
> +
> +  switch (family)
> +    {
> +    case 0x10:
> +      /* AMD Family 10h.  */
> +      cpu = "amdfam10";
> +      cpu_model->__cpu_type = AMDFAM10H;
> +      switch (model)
> +       {
> +       case 0x2:
> +         /* Barcelona.  */
> +         CHECK___builtin_cpu_is ("amdfam10h");
> +         CHECK___builtin_cpu_is ("barcelona");
> +         cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
> +         break;
> +       case 0x4:
> +         /* Shanghai.  */
> +         CHECK___builtin_cpu_is ("amdfam10h");
> +         CHECK___builtin_cpu_is ("shanghai");
> +         cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
> +         break;
> +       case 0x8:
> +         /* Istanbul.  */
> +         CHECK___builtin_cpu_is ("amdfam10h");
> +         CHECK___builtin_cpu_is ("istanbul");
> +         cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
> +         break;
> +       default:
> +         break;
> +       }
> +      break;
> +    case 0x14:
> +      /* AMD Family 14h "btver1". */
> +      cpu = "btver1";
> +      CHECK___builtin_cpu_is ("btver1");
> +      cpu_model->__cpu_type = AMD_BTVER1;
> +      break;
> +    case 0x15:
> +      /* AMD Family 15h "Bulldozer".  */
> +      cpu_model->__cpu_type = AMDFAM15H;
> +      if (model == 0x2)
> +       {
> +         /* Bulldozer version 2 "Piledriver" */
> +         cpu = "bdver2";
> +         CHECK___builtin_cpu_is ("bdver2");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
> +       }
> +      else if (model <= 0xf)
> +       {
> +         /* Bulldozer version 1.  */
> +         cpu = "bdver1";
> +         CHECK___builtin_cpu_is ("bdver1");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
> +       }
> +      else if (model <= 0x2f)
> +       {
> +         /* Bulldozer version 2 "Piledriver" */
> +         cpu = "bdver2";
> +         CHECK___builtin_cpu_is ("bdver2");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
> +       }
> +      else if (model <= 0x4f)
> +       {
> +         /* Bulldozer version 3 "Steamroller"  */
> +         cpu = "bdver3";
> +         CHECK___builtin_cpu_is ("bdver3");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
> +       }
> +      else if (model <= 0x7f)
> +       {
> +         /* Bulldozer version 4 "Excavator"   */
> +         cpu = "bdver4";
> +         CHECK___builtin_cpu_is ("bdver4");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_AVX2))
> +       {
> +         cpu = "bdver4";
> +         CHECK___builtin_cpu_is ("bdver4");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_XSAVEOPT))
> +       {
> +         cpu = "bdver3";
> +         CHECK___builtin_cpu_is ("bdver3");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_BMI))
> +       {
> +         cpu = "bdver2";
> +         CHECK___builtin_cpu_is ("bdver2");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_XOP))
> +       {
> +         cpu = "bdver1";
> +         CHECK___builtin_cpu_is ("bdver1");
> +         cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
> +       }
> +      break;
> +    case 0x16:
> +      /* AMD Family 16h "btver2" */
> +      cpu = "btver2";
> +      CHECK___builtin_cpu_is ("btver2");
> +      cpu_model->__cpu_type = AMD_BTVER2;
> +      break;
> +    case 0x17:
> +      cpu_model->__cpu_type = AMDFAM17H;
> +      if (model <= 0x1f)
> +       {
> +         /* AMD family 17h version 1.  */
> +         cpu = "znver1";
> +         CHECK___builtin_cpu_is ("znver1");
> +         cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
> +       }
> +      else if (model >= 0x30)
> +       {
> +         cpu = "znver2";
> +         CHECK___builtin_cpu_is ("znver2");
> +         cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_CLWB))
> +       {
> +         cpu = "znver2";
> +         CHECK___builtin_cpu_is ("znver2");
> +         cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
> +       }
> +      else if (has_cpu_feature (cpu_model, cpu_features2,
> +                               FEATURE_CLZERO))
> +       {
> +         cpu = "znver1";
> +         CHECK___builtin_cpu_is ("znver1");
> +         cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
> +       }
> +      break;
> +    default:
> +      break;
> +    }
> +
> +  return cpu;
> +}
> +
> +/* Get the specific type of Intel CPU and return Intel CPU name.  Return
> +   NULL for unknown Intel CPU.  */
> +
> +static inline const char *
> +get_intel_cpu (struct __processor_model *cpu_model,
> +              struct __processor_model2 *cpu_model2,
> +              unsigned int *cpu_features2,
> +              unsigned int brand_id)
> +{
> +  const char *cpu = NULL;
> +
> +  /* Parse family and model only for brand ID 0 and model 6. */
> +  if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
> +    return cpu;
> +
> +  switch (cpu_model2->__cpu_model)
> +    {
> +    case 0x1c:
> +    case 0x26:
> +      /* Bonnell.  */
> +      cpu = "bonnell";
> +      CHECK___builtin_cpu_is ("atom");
> +      cpu_model->__cpu_type = INTEL_BONNELL;
> +      break;
> +    case 0x37:
> +    case 0x4a:
> +    case 0x4d:
> +    case 0x5d:
> +      /* Silvermont.  */
> +    case 0x4c:
> +    case 0x5a:
> +    case 0x75:
> +      /* Airmont.  */
> +      cpu = "silvermont";
> +      CHECK___builtin_cpu_is ("silvermont");
> +      cpu_model->__cpu_type = INTEL_SILVERMONT;
> +      break;
> +    case 0x5c:
> +    case 0x5f:
> +      /* Goldmont.  */
> +      cpu = "goldmont";
> +      CHECK___builtin_cpu_is ("goldmont");
> +      cpu_model->__cpu_type = INTEL_GOLDMONT;
> +      break;
> +    case 0x7a:
> +      /* Goldmont Plus.  */
> +      cpu = "goldmont-plus";
> +      CHECK___builtin_cpu_is ("goldmont-plus");
> +      cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
> +      break;
> +    case 0x86:
> +    case 0x96:
> +    case 0x9c:
> +      /* Tremont.  */
> +      cpu = "tremont";
> +      CHECK___builtin_cpu_is ("tremont");
> +      cpu_model->__cpu_type = INTEL_TREMONT;
> +      break;
> +    case 0x57:
> +      /* Knights Landing.  */
> +      cpu = "knl";
> +      CHECK___builtin_cpu_is ("knl");
> +      cpu_model->__cpu_type = INTEL_KNL;
> +      break;
> +    case 0x85:
> +      /* Knights Mill. */
> +      cpu = "knm";
> +      CHECK___builtin_cpu_is ("knm");
> +      cpu_model->__cpu_type = INTEL_KNM;
> +      break;
> +    case 0x1a:
> +    case 0x1e:
> +    case 0x1f:
> +    case 0x2e:
> +      /* Nehalem.  */
> +      cpu = "nehalem";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("nehalem");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
> +      break;
> +    case 0x25:
> +    case 0x2c:
> +    case 0x2f:
> +      /* Westmere.  */
> +      cpu = "westmere";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("westmere");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
> +      break;
> +    case 0x2a:
> +    case 0x2d:
> +      /* Sandy Bridge.  */
> +      cpu = "sandybridge";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("sandybridge");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
> +      break;
> +    case 0x3a:
> +    case 0x3e:
> +      /* Ivy Bridge.  */
> +      cpu = "ivybridge";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("ivybridge");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
> +      break;
> +    case 0x3c:
> +    case 0x3f:
> +    case 0x45:
> +    case 0x46:
> +      /* Haswell.  */
> +      cpu = "haswell";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("haswell");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
> +      break;
> +    case 0x3d:
> +    case 0x47:
> +    case 0x4f:
> +    case 0x56:
> +      /* Broadwell.  */
> +      cpu = "broadwell";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("broadwell");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
> +      break;
> +    case 0x4e:
> +    case 0x5e:
> +      /* Skylake.  */
> +    case 0x8e:
> +    case 0x9e:
> +      /* Kaby Lake.  */
> +    case 0xa5:
> +    case 0xa6:
> +      /* Comet Lake.  */
> +      cpu = "skylake";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("skylake");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
> +      break;
> +    case 0x55:
> +      CHECK___builtin_cpu_is ("corei7");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      if (has_cpu_feature (cpu_model, cpu_features2,
> +                          FEATURE_AVX512VNNI))
> +       {
> +         /* Cascade Lake.  */
> +         cpu = "cascadelake";
> +         CHECK___builtin_cpu_is ("cascadelake");
> +         cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
> +       }
> +      else
> +       {
> +         /* Skylake with AVX-512 support.  */
> +         cpu = "skylake-avx512";
> +         CHECK___builtin_cpu_is ("skylake-avx512");
> +         cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
> +       }
> +      break;
> +    case 0x66:
> +      /* Cannon Lake.  */
> +      cpu = "cannonlake";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("cannonlake");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
> +      break;
> +    case 0x6a:
> +    case 0x6c:
> +      /* Ice Lake server.  */
> +      cpu = "icelake-server";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("icelake-server");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
> +      break;
> +    case 0x7e:
> +    case 0x7d:
> +    case 0x9d:
> +       /* Ice Lake client.  */
> +      cpu = "icelake-client";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("icelake-client");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
> +      break;
> +    case 0x8c:
> +    case 0x8d:
> +      /* Tiger Lake.  */
> +      cpu = "tigerlake";
> +      CHECK___builtin_cpu_is ("corei7");
> +      CHECK___builtin_cpu_is ("tigerlake");
> +      cpu_model->__cpu_type = INTEL_COREI7;
> +      cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
> +      break;
> +    case 0x17:
> +    case 0x1d:
> +      /* Penryn.  */
> +    case 0x0f:
> +      /* Merom.  */
> +      cpu = "core2";
> +      CHECK___builtin_cpu_is ("core2");
> +      cpu_model->__cpu_type = INTEL_CORE2;
> +      break;
> +    default:
> +      break;
> +    }
> +
> +  return cpu;
> +}
> +
> +/* ECX and EDX are output of CPUID at level one.  */
> +static inline void
> +get_available_features (struct __processor_model *cpu_model,
> +                       struct __processor_model2 *cpu_model2,
> +                       unsigned int *cpu_features2,
> +                       unsigned int ecx, unsigned int edx)
> +{
> +  unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
> +  unsigned int eax, ebx;
> +  unsigned int ext_level;
> +
> +  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
> +#define XCR_XFEATURE_ENABLED_MASK      0x0
> +#define XSTATE_FP                      0x1
> +#define XSTATE_SSE                     0x2
> +#define XSTATE_YMM                     0x4
> +#define XSTATE_OPMASK                  0x20
> +#define XSTATE_ZMM                     0x40
> +#define XSTATE_HI_ZMM                  0x80
> +
> +#define XCR_AVX_ENABLED_MASK \
> +  (XSTATE_SSE | XSTATE_YMM)
> +#define XCR_AVX512F_ENABLED_MASK \
> +  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
> +
> +  /* Check if AVX and AVX512 are usable.  */
> +  int avx_usable = 0;
> +  int avx512_usable = 0;
> +  if ((ecx & bit_OSXSAVE))
> +    {
> +      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
> +        ZMM16-ZMM31 states are supported by OSXSAVE.  */
> +      unsigned int xcrlow;
> +      unsigned int xcrhigh;
> +      __asm__ (".byte 0x0f, 0x01, 0xd0"
> +              : "=a" (xcrlow), "=d" (xcrhigh)
> +              : "c" (XCR_XFEATURE_ENABLED_MASK));
> +      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
> +       {
> +         avx_usable = 1;
> +         avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
> +                          == XCR_AVX512F_ENABLED_MASK);
> +       }
> +    }
> +
> +#define set_feature(f) \
> +  set_cpu_feature (cpu_model, cpu_features2, f)
> +
> +  if (edx & bit_CMOV)
> +    set_feature (FEATURE_CMOV);
> +  if (edx & bit_MMX)
> +    set_feature (FEATURE_MMX);
> +  if (edx & bit_SSE)
> +    set_feature (FEATURE_SSE);
> +  if (edx & bit_SSE2)
> +    set_feature (FEATURE_SSE2);
> +  if (edx & bit_CMPXCHG8B)
> +    set_feature (FEATURE_CMPXCHG8B);
> +  if (edx & bit_FXSAVE)
> +    set_feature (FEATURE_FXSAVE);
> +
> +  if (ecx & bit_POPCNT)
> +    set_feature (FEATURE_POPCNT);
> +  if (ecx & bit_AES)
> +    set_feature (FEATURE_AES);
> +  if (ecx & bit_PCLMUL)
> +    set_feature (FEATURE_PCLMUL);
> +  if (ecx & bit_SSE3)
> +    set_feature (FEATURE_SSE3);
> +  if (ecx & bit_SSSE3)
> +    set_feature (FEATURE_SSSE3);
> +  if (ecx & bit_SSE4_1)
> +    set_feature (FEATURE_SSE4_1);
> +  if (ecx & bit_SSE4_2)
> +    set_feature (FEATURE_SSE4_2);
> +  if (ecx & bit_OSXSAVE)
> +    set_feature (FEATURE_OSXSAVE);
> +  if (ecx & bit_CMPXCHG16B)
> +    set_feature (FEATURE_CMPXCHG16B);
> +  if (ecx & bit_MOVBE)
> +    set_feature (FEATURE_MOVBE);
> +  if (ecx & bit_AES)
> +    set_feature (FEATURE_AES);
> +  if (ecx & bit_F16C)
> +    set_feature (FEATURE_F16C);
> +  if (ecx & bit_RDRND)
> +    set_feature (FEATURE_RDRND);
> +  if (ecx & bit_XSAVE)
> +    set_feature (FEATURE_XSAVE);
> +  if (avx_usable)
> +    {
> +      if (ecx & bit_AVX)
> +       set_feature (FEATURE_AVX);
> +      if (ecx & bit_FMA)
> +       set_feature (FEATURE_FMA);
> +    }
> +
> +  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
> +  if (max_cpuid_level >= 7)
> +    {
> +      __cpuid_count (7, 0, eax, ebx, ecx, edx);
> +      if (ebx & bit_BMI)
> +       set_feature (FEATURE_BMI);
> +      if (ebx & bit_SGX)
> +       set_feature (FEATURE_SGX);
> +      if (ebx & bit_HLE)
> +       set_feature (FEATURE_HLE);
> +      if (ebx & bit_RTM)
> +       set_feature (FEATURE_RTM);
> +      if (avx_usable)
> +       {
> +         if (ebx & bit_AVX2)
> +           set_feature (FEATURE_AVX2);
> +         if (ecx & bit_VPCLMULQDQ)
> +           set_feature (FEATURE_VPCLMULQDQ);
> +       }
> +      if (ebx & bit_BMI2)
> +       set_feature (FEATURE_BMI2);
> +      if (ebx & bit_FSGSBASE)
> +       set_feature (FEATURE_FSGSBASE);
> +      if (ebx & bit_RDSEED)
> +       set_feature (FEATURE_RDSEED);
> +      if (ebx & bit_ADX)
> +       set_feature (FEATURE_ADX);
> +      if (ebx & bit_SHA)
> +       set_feature (FEATURE_SHA);
> +      if (ebx & bit_CLFLUSHOPT)
> +       set_feature (FEATURE_CLFLUSHOPT);
> +      if (ebx & bit_CLWB)
> +       set_feature (FEATURE_CLWB);
> +      if (ecx & bit_PREFETCHWT1)
> +       set_feature (FEATURE_PREFETCHWT1);
> +      /* NB: bit_OSPKE indicates that OS supports PKU.  */
> +      if (ecx & bit_OSPKE)
> +       set_feature (FEATURE_PKU);
> +      if (ecx & bit_RDPID)
> +       set_feature (FEATURE_RDPID);
> +      if (ecx & bit_VAES)
> +       set_feature (FEATURE_VAES);
> +      if (ecx & bit_GFNI)
> +       set_feature (FEATURE_GFNI);
> +      if (ecx & bit_MOVDIRI)
> +       set_feature (FEATURE_MOVDIRI);
> +      if (ecx & bit_MOVDIR64B)
> +       set_feature (FEATURE_MOVDIR64B);
> +      if (ecx & bit_ENQCMD)
> +       set_feature (FEATURE_ENQCMD);
> +      if (ecx & bit_CLDEMOTE)
> +       set_feature (FEATURE_CLDEMOTE);
> +      if (ecx & bit_WAITPKG)
> +       set_feature (FEATURE_WAITPKG);
> +      if (ecx & bit_SHSTK)
> +       set_feature (FEATURE_SHSTK);
> +      if (edx & bit_SERIALIZE)
> +       set_feature (FEATURE_SERIALIZE);
> +      if (edx & bit_TSXLDTRK)
> +       set_feature (FEATURE_TSXLDTRK);
> +      if (edx & bit_PCONFIG)
> +       set_feature (FEATURE_PCONFIG);
> +      if (edx & bit_IBT)
> +       set_feature (FEATURE_IBT);
> +      if (avx512_usable)
> +       {
> +         if (ebx & bit_AVX512F)
> +           set_feature (FEATURE_AVX512F);
> +         if (ebx & bit_AVX512VL)
> +           set_feature (FEATURE_AVX512VL);
> +         if (ebx & bit_AVX512BW)
> +           set_feature (FEATURE_AVX512BW);
> +         if (ebx & bit_AVX512DQ)
> +           set_feature (FEATURE_AVX512DQ);
> +         if (ebx & bit_AVX512CD)
> +           set_feature (FEATURE_AVX512CD);
> +         if (ebx & bit_AVX512PF)
> +           set_feature (FEATURE_AVX512PF);
> +         if (ebx & bit_AVX512ER)
> +           set_feature (FEATURE_AVX512ER);
> +         if (ebx & bit_AVX512IFMA)
> +           set_feature (FEATURE_AVX512IFMA);
> +         if (ecx & bit_AVX512VBMI)
> +           set_feature (FEATURE_AVX512VBMI);
> +         if (ecx & bit_AVX512VBMI2)
> +           set_feature (FEATURE_AVX512VBMI2);
> +         if (ecx & bit_AVX512VNNI)
> +           set_feature (FEATURE_AVX512VNNI);
> +         if (ecx & bit_AVX512BITALG)
> +           set_feature (FEATURE_AVX512BITALG);
> +         if (ecx & bit_AVX512VPOPCNTDQ)
> +           set_feature (FEATURE_AVX512VPOPCNTDQ);
> +         if (edx & bit_AVX5124VNNIW)
> +           set_feature (FEATURE_AVX5124VNNIW);
> +         if (edx & bit_AVX5124FMAPS)
> +           set_feature (FEATURE_AVX5124FMAPS);
> +         if (edx & bit_AVX512VP2INTERSECT)
> +           set_feature (FEATURE_AVX512VP2INTERSECT);
> +
> +         __cpuid_count (7, 1, eax, ebx, ecx, edx);
> +         if (eax & bit_AVX512BF16)
> +           set_feature (FEATURE_AVX512BF16);
> +       }
> +    }
> +
> +  /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
> +  if (max_cpuid_level >= 0xd)
> +    {
> +      __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
> +      if (eax & bit_XSAVEOPT)
> +       set_feature (FEATURE_XSAVEOPT);
> +      if (eax & bit_XSAVEC)
> +       set_feature (FEATURE_XSAVEC);
> +      if (eax & bit_XSAVES)
> +       set_feature (FEATURE_XSAVES);
> +    }
> +
> +  /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
> +  if (max_cpuid_level >= 0x14)
> +    {
> +      __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
> +      if (ebx & bit_PTWRITE)
> +       set_feature (FEATURE_PTWRITE);
> +    }
> +
> +  /* Check cpuid level of extended features.  */
> +  __cpuid (0x80000000, ext_level, ebx, ecx, edx);
> +
> +  cpu_model2->__cpu_ext_level = ext_level;
> +
> +  if (ext_level >= 0x80000001)
> +    {
> +      __cpuid (0x80000001, eax, ebx, ecx, edx);
> +
> +      if (ecx & bit_SSE4a)
> +       set_feature (FEATURE_SSE4_A);
> +      if (ecx & bit_LAHF_LM)
> +       set_feature (FEATURE_LAHF_LM);
> +      if (ecx & bit_ABM)
> +       set_feature (FEATURE_ABM);
> +      if (ecx & bit_LWP)
> +       set_feature (FEATURE_LWP);
> +      if (ecx & bit_TBM)
> +       set_feature (FEATURE_TBM);
> +      if (ecx & bit_LZCNT)
> +       set_feature (FEATURE_LZCNT);
> +      if (ecx & bit_PRFCHW)
> +       set_feature (FEATURE_PRFCHW);
> +      if (ecx & bit_MWAITX)
> +       set_feature (FEATURE_MWAITX);
> +
> +      if (edx & bit_LM)
> +       set_feature (FEATURE_LM);
> +      if (edx & bit_3DNOWP)
> +       set_feature (FEATURE_3DNOWP);
> +      if (edx & bit_3DNOW)
> +       set_feature (FEATURE_3DNOW);
> +
> +      if (avx_usable)
> +       {
> +         if (ecx & bit_FMA4)
> +           set_feature (FEATURE_FMA4);
> +         if (ecx & bit_XOP)
> +           set_feature (FEATURE_XOP);
> +       }
> +    }
> +
> +  if (ext_level >= 0x80000008)
> +    {
> +      __cpuid (0x80000008, eax, ebx, ecx, edx);
> +      if (ebx & bit_CLZERO)
> +       set_feature (FEATURE_CLZERO);
> +      if (ebx & bit_WBNOINVD)
> +       set_feature (FEATURE_WBNOINVD);
> +    }
> +
> +#undef set_feature
> +}
> +
> +static inline int
> +cpu_indicator_init (struct __processor_model *cpu_model,
> +                   struct __processor_model2 *cpu_model2,
> +                   unsigned int *cpu_features2)
> +{
> +  unsigned int eax, ebx, ecx, edx;
> +
> +  int max_level;
> +  unsigned int vendor;
> +  unsigned int model, family, brand_id;
> +  unsigned int extended_model, extended_family;
> +
> +  /* This function needs to run just once.  */
> +  if (cpu_model->__cpu_vendor)
> +    return 0;
> +
> +  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
> +  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
> +    {
> +      cpu_model->__cpu_vendor = VENDOR_OTHER;
> +      return -1;
> +    }
> +
> +  vendor = ebx;
> +  max_level = eax;
> +
> +  if (max_level < 1)
> +    {
> +      cpu_model->__cpu_vendor = VENDOR_OTHER;
> +      return -1;
> +    }
> +
> +  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
> +    {
> +      cpu_model->__cpu_vendor = VENDOR_OTHER;
> +      return -1;
> +    }
> +
> +  cpu_model2->__cpu_max_level = max_level;
> +
> +  model = (eax >> 4) & 0x0f;
> +  family = (eax >> 8) & 0x0f;
> +  brand_id = ebx & 0xff;
> +  extended_model = (eax >> 12) & 0xf0;
> +  extended_family = (eax >> 20) & 0xff;
> +
> +  if (vendor == signature_INTEL_ebx)
> +    {
> +      /* Adjust model and family for Intel CPUS. */
> +      if (family == 0x0f)
> +       {
> +         family += extended_family;
> +         model += extended_model;
> +       }
> +      else if (family == 0x06)
> +       model += extended_model;
> +
> +      cpu_model2->__cpu_family = family;
> +      cpu_model2->__cpu_model = model;
> +
> +      /* Find available features. */
> +      get_available_features (cpu_model, cpu_model2, cpu_features2,
> +                             ecx, edx);
> +      /* Get CPU type.  */
> +      get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
> +      cpu_model->__cpu_vendor = VENDOR_INTEL;
> +    }
> +  else if (vendor == signature_AMD_ebx)
> +    {
> +      /* Adjust model and family for AMD CPUS. */
> +      if (family == 0x0f)
> +       {
> +         family += extended_family;
> +         model += extended_model;
> +       }
> +
> +      cpu_model2->__cpu_family = family;
> +      cpu_model2->__cpu_model = model;
> +
> +      /* Find available features. */
> +      get_available_features (cpu_model, cpu_model2, cpu_features2,
> +                             ecx, edx);
> +      /* Get CPU type.  */
> +      get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
> +      cpu_model->__cpu_vendor = VENDOR_AMD;
> +    }
> +  else if (vendor == signature_CENTAUR_ebx)
> +    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
> +  else if (vendor == signature_CYRIX_ebx)
> +    cpu_model->__cpu_vendor = VENDOR_CYRIX;
> +  else if (vendor == signature_NSC_ebx)
> +    cpu_model->__cpu_vendor = VENDOR_NSC;
> +  else
> +    cpu_model->__cpu_vendor = VENDOR_OTHER;
> +
> +  gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
> +  gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
> +  gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
> +
> +  return 0;
> +}
> diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
> index e11c68f46dd..96cf0eaea47 100644
> --- a/gcc/common/config/i386/i386-cpuinfo.h
> +++ b/gcc/common/config/i386/i386-cpuinfo.h
> @@ -30,6 +30,9 @@ enum processor_vendor
>    VENDOR_INTEL = 1,
>    VENDOR_AMD,
>    VENDOR_OTHER,
> +  VENDOR_CENTAUR,
> +  VENDOR_CYRIX,
> +  VENDOR_NSC,
>    BUILTIN_VENDOR_MAX = VENDOR_OTHER,
>    VENDOR_MAX
>  };
> @@ -122,6 +125,101 @@ enum feature_priority
>    P_PROC_DYNAMIC
>  };
>
> +/* ISA Features supported. New features have to be inserted at the end.  */
> +
> +enum processor_features
> +{
> +  FEATURE_CMOV = 0,
> +  FEATURE_MMX,
> +  FEATURE_POPCNT,
> +  FEATURE_SSE,
> +  FEATURE_SSE2,
> +  FEATURE_SSE3,
> +  FEATURE_SSSE3,
> +  FEATURE_SSE4_1,
> +  FEATURE_SSE4_2,
> +  FEATURE_AVX,
> +  FEATURE_AVX2,
> +  FEATURE_SSE4_A,
> +  FEATURE_FMA4,
> +  FEATURE_XOP,
> +  FEATURE_FMA,
> +  FEATURE_AVX512F,
> +  FEATURE_BMI,
> +  FEATURE_BMI2,
> +  FEATURE_AES,
> +  FEATURE_PCLMUL,
> +  FEATURE_AVX512VL,
> +  FEATURE_AVX512BW,
> +  FEATURE_AVX512DQ,
> +  FEATURE_AVX512CD,
> +  FEATURE_AVX512ER,
> +  FEATURE_AVX512PF,
> +  FEATURE_AVX512VBMI,
> +  FEATURE_AVX512IFMA,
> +  FEATURE_AVX5124VNNIW,
> +  FEATURE_AVX5124FMAPS,
> +  FEATURE_AVX512VPOPCNTDQ,
> +  FEATURE_AVX512VBMI2,
> +  FEATURE_GFNI,
> +  FEATURE_VPCLMULQDQ,
> +  FEATURE_AVX512VNNI,
> +  FEATURE_AVX512BITALG,
> +  FEATURE_AVX512BF16,
> +  FEATURE_AVX512VP2INTERSECT,
> +  FEATURE_3DNOW,
> +  FEATURE_3DNOWP,
> +  FEATURE_ADX,
> +  FEATURE_ABM,
> +  FEATURE_CLDEMOTE,
> +  FEATURE_CLFLUSHOPT,
> +  FEATURE_CLWB,
> +  FEATURE_CLZERO,
> +  FEATURE_CMPXCHG16B,
> +  FEATURE_CMPXCHG8B,
> +  FEATURE_ENQCMD,
> +  FEATURE_F16C,
> +  FEATURE_FSGSBASE,
> +  FEATURE_FXSAVE,
> +  FEATURE_HLE,
> +  FEATURE_IBT,
> +  FEATURE_LAHF_LM,
> +  FEATURE_LM,
> +  FEATURE_LWP,
> +  FEATURE_LZCNT,
> +  FEATURE_MOVBE,
> +  FEATURE_MOVDIR64B,
> +  FEATURE_MOVDIRI,
> +  FEATURE_MWAITX,
> +  FEATURE_OSXSAVE,
> +  FEATURE_PCONFIG,
> +  FEATURE_PKU,
> +  FEATURE_PREFETCHWT1,
> +  FEATURE_PRFCHW,
> +  FEATURE_PTWRITE,
> +  FEATURE_RDPID,
> +  FEATURE_RDRND,
> +  FEATURE_RDSEED,
> +  FEATURE_RTM,
> +  FEATURE_SERIALIZE,
> +  FEATURE_SGX,
> +  FEATURE_SHA,
> +  FEATURE_SHSTK,
> +  FEATURE_TBM,
> +  FEATURE_TSXLDTRK,
> +  FEATURE_VAES,
> +  FEATURE_WAITPKG,
> +  FEATURE_WBNOINVD,
> +  FEATURE_XSAVE,
> +  FEATURE_XSAVEC,
> +  FEATURE_XSAVEOPT,
> +  FEATURE_XSAVES,
> +  CPU_FEATURE_MAX
> +};
> +
> +/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
> +#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
> +
>  /* These are the values for vendor types, cpu types and subtypes.  Cpu
>     types and subtypes should be subtracted by the corresponding start
>     value.  */
> diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
> index 6f6a8328ef1..57e709d6c43 100644
> --- a/gcc/config/i386/i386-builtins.c
> +++ b/gcc/config/i386/i386-builtins.c
> @@ -1835,50 +1835,6 @@ ix86_builtin_reciprocal (tree fndecl)
>      }
>  }
>
> -/* This is the order of bit-fields in __processor_features in cpuinfo.c */
> -enum processor_features
> -{
> -  F_CMOV = 0,
> -  F_MMX,
> -  F_POPCNT,
> -  F_SSE,
> -  F_SSE2,
> -  F_SSE3,
> -  F_SSSE3,
> -  F_SSE4_1,
> -  F_SSE4_2,
> -  F_AVX,
> -  F_AVX2,
> -  F_SSE4_A,
> -  F_FMA4,
> -  F_XOP,
> -  F_FMA,
> -  F_AVX512F,
> -  F_BMI,
> -  F_BMI2,
> -  F_AES,
> -  F_PCLMUL,
> -  F_AVX512VL,
> -  F_AVX512BW,
> -  F_AVX512DQ,
> -  F_AVX512CD,
> -  F_AVX512ER,
> -  F_AVX512PF,
> -  F_AVX512VBMI,
> -  F_AVX512IFMA,
> -  F_AVX5124VNNIW,
> -  F_AVX5124FMAPS,
> -  F_AVX512VPOPCNTDQ,
> -  F_AVX512VBMI2,
> -  F_GFNI,
> -  F_VPCLMULQDQ,
> -  F_AVX512VNNI,
> -  F_AVX512BITALG,
> -  F_AVX512BF16,
> -  F_AVX512VP2INTERSECT,
> -  F_MAX
> -};
> -
>  /* These are the target attribute strings for which a dispatcher is
>     available, from fold_builtin_cpu.  */
>  struct _isa_names_table
> @@ -1890,44 +1846,44 @@ struct _isa_names_table
>
>  static const _isa_names_table isa_names_table[] =
>  {
> -  {"cmov",    F_CMOV,  P_NONE},
> -  {"mmx",     F_MMX,   P_MMX},
> -  {"popcnt",  F_POPCNT,        P_POPCNT},
> -  {"sse",     F_SSE,   P_SSE},
> -  {"sse2",    F_SSE2,  P_SSE2},
> -  {"sse3",    F_SSE3,  P_SSE3},
> -  {"ssse3",   F_SSSE3, P_SSSE3},
> -  {"sse4a",   F_SSE4_A,        P_SSE4_A},
> -  {"sse4.1",  F_SSE4_1,        P_SSE4_1},
> -  {"sse4.2",  F_SSE4_2,        P_SSE4_2},
> -  {"avx",     F_AVX,   P_AVX},
> -  {"fma4",    F_FMA4,  P_FMA4},
> -  {"xop",     F_XOP,   P_XOP},
> -  {"fma",     F_FMA,   P_FMA},
> -  {"avx2",    F_AVX2,  P_AVX2},
> -  {"avx512f", F_AVX512F, P_AVX512F},
> -  {"bmi",     F_BMI,   P_BMI},
> -  {"bmi2",    F_BMI2,  P_BMI2},
> -  {"aes",     F_AES,   P_AES},
> -  {"pclmul",  F_PCLMUL,        P_PCLMUL},
> -  {"avx512vl",F_AVX512VL, P_NONE},
> -  {"avx512bw",F_AVX512BW, P_NONE},
> -  {"avx512dq",F_AVX512DQ, P_NONE},
> -  {"avx512cd",F_AVX512CD, P_NONE},
> -  {"avx512er",F_AVX512ER, P_NONE},
> -  {"avx512pf",F_AVX512PF, P_NONE},
> -  {"avx512vbmi",F_AVX512VBMI, P_NONE},
> -  {"avx512ifma",F_AVX512IFMA, P_NONE},
> -  {"avx5124vnniw",F_AVX5124VNNIW, P_NONE},
> -  {"avx5124fmaps",F_AVX5124FMAPS, P_NONE},
> -  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,        P_NONE},
> -  {"avx512vbmi2", F_AVX512VBMI2, P_NONE},
> -  {"gfni",     F_GFNI, P_NONE},
> -  {"vpclmulqdq", F_VPCLMULQDQ, P_NONE},
> -  {"avx512vnni", F_AVX512VNNI, P_NONE},
> -  {"avx512bitalg", F_AVX512BITALG, P_NONE},
> -  {"avx512bf16", F_AVX512BF16, P_NONE},
> -  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_NONE}
> +  {"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
> @@ -2294,16 +2250,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
>
>        if (isa_names_table[i].feature >= 32)
>         {
> -         tree __cpu_features2_var = make_var_decl (unsigned_type_node,
> +         tree index_type
> +           = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
> +         tree type = build_array_type (unsigned_type_node, index_type);
> +         tree __cpu_features2_var = make_var_decl (type,
>                                                     "__cpu_features2");
>
>           varpool_node::add (__cpu_features2_var);
> -         field_val = (1U << (isa_names_table[i].feature - 32));
> -         /* Return __cpu_features2 & field_val  */
> -         final = build2 (BIT_AND_EXPR, unsigned_type_node,
> -                         __cpu_features2_var,
> -                         build_int_cstu (unsigned_type_node, field_val));
> -         return build1 (CONVERT_EXPR, integer_type_node, final);
> +         for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
> +           if (isa_names_table[i].feature < (32 + 32 + j * 32))
> +             {
> +               field_val = (1U << (isa_names_table[i].feature
> +                                   - (32 + j * 32)));
> +               tree index = size_int (j);
> +               array_elt = build4 (ARRAY_REF, unsigned_type_node,
> +                                   __cpu_features2_var,
> +                                   index, NULL_TREE, NULL_TREE);
> +               /* Return __cpu_features2[index] & field_val  */
> +               final = build2 (BIT_AND_EXPR, unsigned_type_node,
> +                               array_elt,
> +                               build_int_cstu (unsigned_type_node,
> +                                               field_val));
> +               return build1 (CONVERT_EXPR, integer_type_node, final);
> +             }
>         }
>
>        field = TYPE_FIELDS (__processor_model_type);
> diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
> index cf5f0884bb4..7218952f32a 100644
> --- a/libgcc/config/i386/cpuinfo.c
> +++ b/libgcc/config/i386/cpuinfo.c
> @@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  #include "cpuid.h"
>  #include "tsystem.h"
>  #include "auto-target.h"
> -#include "cpuinfo.h"
> +#include "common/config/i386/i386-cpuinfo.h"
> +#include "common/config/i386/cpuinfo.h"
>
>  #ifdef HAVE_INIT_PRIORITY
>  #define CONSTRUCTOR_PRIORITY (101)
> @@ -39,386 +40,14 @@ int __cpu_indicator_init (void)
>
>
>  struct __processor_model __cpu_model = { };
> -#ifndef SHARED
>  /* We want to move away from __cpu_model in libgcc_s.so.1 and the
>     size of __cpu_model is part of ABI.  So, new features that don't
>     fit into __cpu_model.__cpu_features[0] go into extra variables
> -   in libgcc.a only, preferrably hidden.  */
> -unsigned int __cpu_features2;
> -#endif
> -
> -
> -/* Get the specific type of AMD CPU.  */
> -
> -static void
> -get_amd_cpu (unsigned int family, unsigned int model)
> -{
> -  switch (family)
> -    {
> -    /* AMD Family 10h.  */
> -    case 0x10:
> -      __cpu_model.__cpu_type = AMDFAM10H;
> -      switch (model)
> -       {
> -       case 0x2:
> -         /* Barcelona.  */
> -         __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
> -         break;
> -       case 0x4:
> -         /* Shanghai.  */
> -         __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
> -         break;
> -       case 0x8:
> -         /* Istanbul.  */
> -         __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
> -         break;
> -       default:
> -         break;
> -       }
> -      break;
> -    /* AMD Family 14h "btver1". */
> -    case 0x14:
> -      __cpu_model.__cpu_type = AMD_BTVER1;
> -      break;
> -    /* AMD Family 15h "Bulldozer".  */
> -    case 0x15:
> -      __cpu_model.__cpu_type = AMDFAM15H;
> -
> -      if (model == 0x2)
> -       __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
> -      /* Bulldozer version 1.  */
> -      else if (model <= 0xf)
> -       __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
> -      /* Bulldozer version 2 "Piledriver" */
> -      else if (model <= 0x2f)
> -       __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
> -      /* Bulldozer version 3 "Steamroller"  */
> -      else if (model <= 0x4f)
> -       __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
> -      /* Bulldozer version 4 "Excavator"   */
> -      else if (model <= 0x7f)
> -       __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
> -      break;
> -    /* AMD Family 16h "btver2" */
> -    case 0x16:
> -      __cpu_model.__cpu_type = AMD_BTVER2;
> -      break;
> -    case 0x17:
> -      __cpu_model.__cpu_type = AMDFAM17H;
> -      /* AMD family 17h version 1.  */
> -      if (model <= 0x1f)
> -       __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
> -      if (model >= 0x30)
> -        __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
> -      break;
> -    default:
> -      break;
> -    }
> -}
> -
> -/* Get the specific type of Intel CPU.  */
> -
> -static void
> -get_intel_cpu (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:
> -             /* Bonnell.  */
> -             __cpu_model.__cpu_type = INTEL_BONNELL;
> -             break;
> -           case 0x37:
> -           case 0x4a:
> -           case 0x4d:
> -           case 0x5a:
> -           case 0x5d:
> -             /* Silvermont.  */
> -             __cpu_model.__cpu_type = INTEL_SILVERMONT;
> -             break;
> -           case 0x5c:
> -           case 0x5f:
> -             /* Goldmont.  */
> -             __cpu_model.__cpu_type = INTEL_GOLDMONT;
> -             break;
> -           case 0x7a:
> -             /* Goldmont Plus.  */
> -             __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
> -             break;
> -           case 0x57:
> -             /* Knights Landing.  */
> -             __cpu_model.__cpu_type = INTEL_KNL;
> -             break;
> -           case 0x85:
> -             /* Knights Mill. */
> -             __cpu_model.__cpu_type = INTEL_KNM;
> -             break;
> -           case 0x1a:
> -           case 0x1e:
> -           case 0x1f:
> -           case 0x2e:
> -             /* Nehalem.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
> -             break;
> -           case 0x25:
> -           case 0x2c:
> -           case 0x2f:
> -             /* Westmere.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
> -             break;
> -           case 0x2a:
> -           case 0x2d:
> -             /* Sandy Bridge.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
> -             break;
> -           case 0x3a:
> -           case 0x3e:
> -             /* Ivy Bridge.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
> -             break;
> -           case 0x3c:
> -           case 0x3f:
> -           case 0x45:
> -           case 0x46:
> -             /* Haswell.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
> -             break;
> -           case 0x3d:
> -           case 0x47:
> -           case 0x4f:
> -           case 0x56:
> -             /* Broadwell.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
> -             break;
> -           case 0x4e:
> -           case 0x5e:
> -             /* Skylake.  */
> -           case 0x8e:
> -           case 0x9e:
> -             /* Kaby Lake.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
> -             break;
> -           case 0x55:
> -             {
> -               unsigned int eax, ebx, ecx, edx;
> -               __cpu_model.__cpu_type = INTEL_COREI7;
> -               __cpuid_count (7, 0, eax, ebx, ecx, edx);
> -               if (ecx & bit_AVX512VNNI)
> -                 /* Cascade Lake.  */
> -                 __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
> -               else
> -                 /* Skylake with AVX-512 support.  */
> -                 __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
> -             }
> -             break;
> -           case 0x66:
> -             /* Cannon Lake.  */
> -             __cpu_model.__cpu_type = INTEL_COREI7;
> -             __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
> -             break;
> -           case 0x17:
> -           case 0x1d:
> -             /* Penryn.  */
> -           case 0x0f:
> -             /* Merom.  */
> -             __cpu_model.__cpu_type = INTEL_CORE2;
> -             break;
> -           default:
> -             break;
> -           }
> -         break;
> -       default:
> -         /* We have no idea.  */
> -         break;
> -       }
> -    }
> -}
> -
> -/* ECX and EDX are output of CPUID at level one.  MAX_CPUID_LEVEL is
> -   the max possible level of CPUID insn.  */
> -static void
> -get_available_features (unsigned int ecx, unsigned int edx,
> -                       int max_cpuid_level)
> -{
> -  unsigned int eax, ebx;
> -  unsigned int ext_level;
> -
> -  unsigned int features = 0;
> -  unsigned int features2 = 0;
> -
> -  /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
> -#define XCR_XFEATURE_ENABLED_MASK      0x0
> -#define XSTATE_FP                      0x1
> -#define XSTATE_SSE                     0x2
> -#define XSTATE_YMM                     0x4
> -#define XSTATE_OPMASK                  0x20
> -#define XSTATE_ZMM                     0x40
> -#define XSTATE_HI_ZMM                  0x80
> -
> -#define XCR_AVX_ENABLED_MASK \
> -  (XSTATE_SSE | XSTATE_YMM)
> -#define XCR_AVX512F_ENABLED_MASK \
> -  (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
> -
> -  /* Check if AVX and AVX512 are usable.  */
> -  int avx_usable = 0;
> -  int avx512_usable = 0;
> -  if ((ecx & bit_OSXSAVE))
> -    {
> -      /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
> -         ZMM16-ZMM31 states are supported by OSXSAVE.  */
> -      unsigned int xcrlow;
> -      unsigned int xcrhigh;
> -      asm (".byte 0x0f, 0x01, 0xd0"
> -          : "=a" (xcrlow), "=d" (xcrhigh)
> -          : "c" (XCR_XFEATURE_ENABLED_MASK));
> -      if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
> -       {
> -         avx_usable = 1;
> -         avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
> -                          == XCR_AVX512F_ENABLED_MASK);
> -       }
> -    }
> -
> -#define set_feature(f) \
> -  do                                           \
> -    {                                          \
> -      if (f < 32)                              \
> -       features |= (1U << (f & 31));           \
> -      else                                     \
> -       features2 |= (1U << ((f - 32) & 31));   \
> -    }                                          \
> -  while (0)
> -
> -  if (edx & bit_CMOV)
> -    set_feature (FEATURE_CMOV);
> -  if (edx & bit_MMX)
> -    set_feature (FEATURE_MMX);
> -  if (edx & bit_SSE)
> -    set_feature (FEATURE_SSE);
> -  if (edx & bit_SSE2)
> -    set_feature (FEATURE_SSE2);
> -  if (ecx & bit_POPCNT)
> -    set_feature (FEATURE_POPCNT);
> -  if (ecx & bit_AES)
> -    set_feature (FEATURE_AES);
> -  if (ecx & bit_PCLMUL)
> -    set_feature (FEATURE_PCLMUL);
> -  if (ecx & bit_SSE3)
> -    set_feature (FEATURE_SSE3);
> -  if (ecx & bit_SSSE3)
> -    set_feature (FEATURE_SSSE3);
> -  if (ecx & bit_SSE4_1)
> -    set_feature (FEATURE_SSE4_1);
> -  if (ecx & bit_SSE4_2)
> -    set_feature (FEATURE_SSE4_2);
> -  if (avx_usable)
> -    {
> -      if (ecx & bit_AVX)
> -       set_feature (FEATURE_AVX);
> -      if (ecx & bit_FMA)
> -       set_feature (FEATURE_FMA);
> -    }
> -
> -  /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
> -  if (max_cpuid_level >= 7)
> -    {
> -      __cpuid_count (7, 0, eax, ebx, ecx, edx);
> -      if (ebx & bit_BMI)
> -       set_feature (FEATURE_BMI);
> -      if (avx_usable)
> -       {
> -         if (ebx & bit_AVX2)
> -           set_feature (FEATURE_AVX2);
> -         if (ecx & bit_VPCLMULQDQ)
> -           set_feature (FEATURE_VPCLMULQDQ);
> -       }
> -      if (ebx & bit_BMI2)
> -       set_feature (FEATURE_BMI2);
> -      if (ecx & bit_GFNI)
> -       set_feature (FEATURE_GFNI);
> -      if (avx512_usable)
> -       {
> -         if (ebx & bit_AVX512F)
> -           set_feature (FEATURE_AVX512F);
> -         if (ebx & bit_AVX512VL)
> -           set_feature (FEATURE_AVX512VL);
> -         if (ebx & bit_AVX512BW)
> -           set_feature (FEATURE_AVX512BW);
> -         if (ebx & bit_AVX512DQ)
> -           set_feature (FEATURE_AVX512DQ);
> -         if (ebx & bit_AVX512CD)
> -           set_feature (FEATURE_AVX512CD);
> -         if (ebx & bit_AVX512PF)
> -           set_feature (FEATURE_AVX512PF);
> -         if (ebx & bit_AVX512ER)
> -           set_feature (FEATURE_AVX512ER);
> -         if (ebx & bit_AVX512IFMA)
> -           set_feature (FEATURE_AVX512IFMA);
> -         if (ecx & bit_AVX512VBMI)
> -           set_feature (FEATURE_AVX512VBMI);
> -         if (ecx & bit_AVX512VBMI2)
> -           set_feature (FEATURE_AVX512VBMI2);
> -         if (ecx & bit_AVX512VNNI)
> -           set_feature (FEATURE_AVX512VNNI);
> -         if (ecx & bit_AVX512BITALG)
> -           set_feature (FEATURE_AVX512BITALG);
> -         if (ecx & bit_AVX512VPOPCNTDQ)
> -           set_feature (FEATURE_AVX512VPOPCNTDQ);
> -         if (edx & bit_AVX5124VNNIW)
> -           set_feature (FEATURE_AVX5124VNNIW);
> -         if (edx & bit_AVX5124FMAPS)
> -           set_feature (FEATURE_AVX5124FMAPS);
> -         if (edx & bit_AVX512VP2INTERSECT)
> -           set_feature (FEATURE_AVX512VP2INTERSECT);
> +   in libgcc.a only, preferably hidden.
>
> -         __cpuid_count (7, 1, eax, ebx, ecx, edx);
> -         if (eax & bit_AVX512BF16)
> -           set_feature (FEATURE_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)
> -       set_feature (FEATURE_SSE4_A);
> -      if (avx_usable)
> -       {
> -         if (ecx & bit_FMA4)
> -           set_feature (FEATURE_FMA4);
> -         if (ecx & bit_XOP)
> -           set_feature (FEATURE_XOP);
> -       }
> -    }
> -
> -  __cpu_model.__cpu_features[0] = features;
> -#ifndef SHARED
> -  __cpu_features2 = features2;
> -#else
> -  (void) features2;
> -#endif
> -}
> +   NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
> +   smaller array, it can only access the first few elements.  */
> +unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
>
>  /* A constructor function that is sets __cpu_model and __cpu_features with
>     the right values.  This needs to run only once.  This constructor is
> @@ -429,85 +58,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
>  int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
>  __cpu_indicator_init (void)
>  {
> -  unsigned int eax, ebx, ecx, edx;
> -
> -  int max_level;
> -  unsigned int vendor;
> -  unsigned int model, family, brand_id;
> -  unsigned int extended_model, extended_family;
> -
> -  /* This function needs to run just once.  */
> -  if (__cpu_model.__cpu_vendor)
> -    return 0;
> -
> -  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
> -  if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
> -    {
> -      __cpu_model.__cpu_vendor = VENDOR_OTHER;
> -      return -1;
> -    }
> -
> -  vendor = ebx;
> -  max_level = eax;
> -
> -  if (max_level < 1)
> -    {
> -      __cpu_model.__cpu_vendor = VENDOR_OTHER;
> -      return -1;
> -    }
> -
> -  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
> -    {
> -      __cpu_model.__cpu_vendor = VENDOR_OTHER;
> -      return -1;
> -    }
> -
> -  model = (eax >> 4) & 0x0f;
> -  family = (eax >> 8) & 0x0f;
> -  brand_id = ebx & 0xff;
> -  extended_model = (eax >> 12) & 0xf0;
> -  extended_family = (eax >> 20) & 0xff;
> -
> -  if (vendor == signature_INTEL_ebx)
> -    {
> -      /* Adjust model and family for Intel CPUS. */
> -      if (family == 0x0f)
> -       {
> -         family += extended_family;
> -         model += extended_model;
> -       }
> -      else if (family == 0x06)
> -       model += extended_model;
> -
> -      /* Get CPU type.  */
> -      get_intel_cpu (family, model, brand_id);
> -      /* Find available features. */
> -      get_available_features (ecx, edx, max_level);
> -      __cpu_model.__cpu_vendor = VENDOR_INTEL;
> -    }
> -  else if (vendor == signature_AMD_ebx)
> -    {
> -      /* Adjust model and family for AMD CPUS. */
> -      if (family == 0x0f)
> -       {
> -         family += extended_family;
> -         model += extended_model;
> -       }
> -
> -      /* Get CPU type.  */
> -      get_amd_cpu (family, model);
> -      /* Find available features. */
> -      get_available_features (ecx, edx, max_level);
> -      __cpu_model.__cpu_vendor = VENDOR_AMD;
> -    }
> -  else
> -    __cpu_model.__cpu_vendor = VENDOR_OTHER;
> -
> -  gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
> -  gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
> -  gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
> -
> -  return 0;
> +  struct __processor_model2 cpu_model2;
> +  return cpu_indicator_init (&__cpu_model, &cpu_model2,
> +                            __cpu_features2);
>  }
>
>  #if defined SHARED && defined USE_ELF_SYMVER
> diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
> deleted file mode 100644
> index 0f97510cde1..00000000000
> --- a/libgcc/config/i386/cpuinfo.h
> +++ /dev/null
> @@ -1,136 +0,0 @@
> -/* Get CPU type and Features for x86 processors.
> -   Copyright (C) 2012-2020 Free Software Foundation, Inc.
> -   Contributed by Sriraman Tallam (tmsriram@google.com)
> -
> -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.
> -
> -Under Section 7 of GPL version 3, you are granted additional
> -permissions described in the GCC Runtime Library Exception, version
> -3.1, as published by the Free Software Foundation.
> -
> -You should have received a copy of the GNU General Public License and
> -a copy of the GCC Runtime Library Exception along with this program;
> -see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> -<http://www.gnu.org/licenses/>.  */
> -
> -/* Processor Vendor and Models. */
> -
> -enum processor_vendor
> -{
> -  VENDOR_INTEL = 1,
> -  VENDOR_AMD,
> -  VENDOR_OTHER,
> -  VENDOR_MAX
> -};
> -
> -/* Any new types or subtypes have to be inserted at the end. */
> -
> -enum processor_types
> -{
> -  INTEL_BONNELL = 1,
> -  INTEL_CORE2,
> -  INTEL_COREI7,
> -  AMDFAM10H,
> -  AMDFAM15H,
> -  INTEL_SILVERMONT,
> -  INTEL_KNL,
> -  AMD_BTVER1,
> -  AMD_BTVER2,
> -  AMDFAM17H,
> -  INTEL_KNM,
> -  INTEL_GOLDMONT,
> -  INTEL_GOLDMONT_PLUS,
> -  INTEL_TREMONT,
> -  CPU_TYPE_MAX
> -};
> -
> -enum processor_subtypes
> -{
> -  INTEL_COREI7_NEHALEM = 1,
> -  INTEL_COREI7_WESTMERE,
> -  INTEL_COREI7_SANDYBRIDGE,
> -  AMDFAM10H_BARCELONA,
> -  AMDFAM10H_SHANGHAI,
> -  AMDFAM10H_ISTANBUL,
> -  AMDFAM15H_BDVER1,
> -  AMDFAM15H_BDVER2,
> -  AMDFAM15H_BDVER3,
> -  AMDFAM15H_BDVER4,
> -  AMDFAM17H_ZNVER1,
> -  INTEL_COREI7_IVYBRIDGE,
> -  INTEL_COREI7_HASWELL,
> -  INTEL_COREI7_BROADWELL,
> -  INTEL_COREI7_SKYLAKE,
> -  INTEL_COREI7_SKYLAKE_AVX512,
> -  INTEL_COREI7_CANNONLAKE,
> -  INTEL_COREI7_ICELAKE_CLIENT,
> -  INTEL_COREI7_ICELAKE_SERVER,
> -  AMDFAM17H_ZNVER2,
> -  INTEL_COREI7_CASCADELAKE,
> -  INTEL_COREI7_TIGERLAKE,
> -  INTEL_COREI7_COOPERLAKE,
> -  CPU_SUBTYPE_MAX
> -};
> -
> -/* ISA Features supported. New features have to be inserted at the end.  */
> -
> -enum processor_features
> -{
> -  FEATURE_CMOV = 0,
> -  FEATURE_MMX,
> -  FEATURE_POPCNT,
> -  FEATURE_SSE,
> -  FEATURE_SSE2,
> -  FEATURE_SSE3,
> -  FEATURE_SSSE3,
> -  FEATURE_SSE4_1,
> -  FEATURE_SSE4_2,
> -  FEATURE_AVX,
> -  FEATURE_AVX2,
> -  FEATURE_SSE4_A,
> -  FEATURE_FMA4,
> -  FEATURE_XOP,
> -  FEATURE_FMA,
> -  FEATURE_AVX512F,
> -  FEATURE_BMI,
> -  FEATURE_BMI2,
> -  FEATURE_AES,
> -  FEATURE_PCLMUL,
> -  FEATURE_AVX512VL,
> -  FEATURE_AVX512BW,
> -  FEATURE_AVX512DQ,
> -  FEATURE_AVX512CD,
> -  FEATURE_AVX512ER,
> -  FEATURE_AVX512PF,
> -  FEATURE_AVX512VBMI,
> -  FEATURE_AVX512IFMA,
> -  FEATURE_AVX5124VNNIW,
> -  FEATURE_AVX5124FMAPS,
> -  FEATURE_AVX512VPOPCNTDQ,
> -  FEATURE_AVX512VBMI2,
> -  FEATURE_GFNI,
> -  FEATURE_VPCLMULQDQ,
> -  FEATURE_AVX512VNNI,
> -  FEATURE_AVX512BITALG,
> -  FEATURE_AVX512BF16,
> -  FEATURE_AVX512VP2INTERSECT
> -};
> -
> -extern struct __processor_model
> -{
> -  unsigned int __cpu_vendor;
> -  unsigned int __cpu_type;
> -  unsigned int __cpu_subtype;
> -  unsigned int __cpu_features[1];
> -} __cpu_model;
> -extern unsigned int __cpu_features2;
> --
> 2.26.2
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2020-06-24 12:43 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-18 11:58 [PATCH] x86: Update Intel processor detection H.J. Lu
2020-05-18 12:18 ` Uros Bizjak
2020-05-18 12:34   ` H.J. Lu
2020-05-18 12:43     ` Uros Bizjak
2020-05-18 12:57       ` H.J. Lu
2020-05-19  2:16         ` [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386 H.J. Lu
2020-05-19  5:56           ` Uros Bizjak
2020-05-19 19:57             ` V2 " H.J. Lu
2020-05-19 21:06               ` Uros Bizjak
2020-05-19 21:39                 ` H.J. Lu
2020-05-20  6:10                   ` Uros Bizjak
2020-05-20 11:21                     ` H.J. Lu
2020-05-21 17:37                       ` H.J. Lu
2020-05-22 14:51                         ` V3 " H.J. Lu
2020-05-25  9:52                           ` Martin Liška
2020-05-25 17:42                             ` V4 " H.J. Lu
2020-05-26  9:30                               ` Martin Liška
2020-05-26 11:59                                 ` V5 " H.J. Lu
2020-05-26 13:27                                   ` Martin Liška
2020-06-09 16:35                                     ` PING^1: " H.J. Lu
2020-06-16 17:11                                       ` PING^2: " H.J. Lu
2020-06-20 13:39                                         ` H.J. Lu
2020-06-21 17:18                                           ` Uros Bizjak
2020-06-21 17:22                                             ` H.J. Lu
2020-06-22 23:25                                               ` V6 " H.J. Lu
2020-06-24 12:27                                                 ` V7 " H.J. Lu
2020-06-24 12:43                                                   ` Uros Bizjak
2020-06-24  6:25                                         ` PING^2: V5 " Martin Liška
2020-05-20  1:30                 ` V2 " H.J. Lu
2020-05-19  9:17           ` Thomas Koenig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).