On Thu, May 21, 2020 at 10:37 AM H.J. Lu <hjl.to...@gmail.com> wrote: > > On Wed, May 20, 2020 at 4:21 AM H.J. Lu <hjl.to...@gmail.com> wrote: > > > > On Tue, May 19, 2020 at 11:10 PM Uros Bizjak <ubiz...@gmail.com> wrote: > > > > > > On Tue, May 19, 2020 at 11:40 PM H.J. Lu <hjl.to...@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.
From 74bf612b8f33937cc33dcea46baabf2bf56eb9ee Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@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 (tmsri...@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