On Thu, Aug 12, 2021 at 7:12 AM Martin Liška wrote: > > Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > I modified the H.J. patch draft. Please send out the v2 patch with the enclosed patch. I added some tests. > @H.J. Can you please verify the newly added 'feature_priority'? > I will take a look at the v2 patch. > As mentioned in the PR, we do miss supports target micro-architectures > in target and target_clone attribute. While the levels > x86-64 x86-64-v2 x86-64-v3 x86-64-v4 are supported values by -march > option, they are actually only aliases for k8 CPU. That said, they are more > closer to __builtin_cpu_supports function and we decided to implement > it there. > > PR target/101696 > > gcc/ChangeLog: > > * common/config/i386/cpuinfo.h (cpu_indicator_init): Add support > for x86-64 micro levels for __builtin_cpu_supports. > * common/config/i386/i386-cpuinfo.h (enum feature_priority): > Add priorities for the micro-arch levels. > (enum processor_features): Add new features. > * common/config/i386/i386-isas.h: Add micro-arch features. > * config/i386/i386-builtins.c (get_builtin_code_for_version): > Support the micro-arch levels by callsing > __builtin_cpu_supports. > * doc/extend.texi: Document that the levels are support by > __builtin_cpu_supports. > > gcc/testsuite/ChangeLog: > > * g++.target/i386/mv30.C: New test. > * gcc.target/i386/mvc16.c: New test. > > Co-Authored-By: H.J. Lu > --- > gcc/common/config/i386/cpuinfo.h | 38 ++++++++++++++++++++ > gcc/common/config/i386/i386-cpuinfo.h | 8 +++++ > gcc/common/config/i386/i386-isas.h | 4 +++ > gcc/config/i386/i386-builtins.c | 22 ++++++++++-- > gcc/doc/extend.texi | 12 +++++++ > gcc/testsuite/g++.target/i386/mv30.C | 50 +++++++++++++++++++++++++++ > gcc/testsuite/gcc.target/i386/mvc16.c | 15 ++++++++ > 7 files changed, 146 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/g++.target/i386/mv30.C > create mode 100644 gcc/testsuite/gcc.target/i386/mvc16.c > > diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h > index 458f41de776..f3b60920c81 100644 > --- a/gcc/common/config/i386/cpuinfo.h > +++ b/gcc/common/config/i386/cpuinfo.h > @@ -931,6 +931,44 @@ cpu_indicator_init (struct __processor_model *cpu_model, > else > cpu_model->__cpu_vendor = VENDOR_OTHER; > > + if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2)) > + { > + set_cpu_feature (cpu_model, cpu_features2, > + FEATURE_X86_64_BASELINE); > + if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2)) > + { > + set_cpu_feature (cpu_model, cpu_features2, > + FEATURE_X86_64_V2); > + if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C) > + && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA) > + && has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_LZCNT) > + && has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_MOVBE)) > + { > + set_cpu_feature (cpu_model, cpu_features2, > + FEATURE_X86_64_V3); > + if (has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_AVX512BW) > + && has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_AVX512CD) > + && has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_AVX512DQ) > + && has_cpu_feature (cpu_model, cpu_features2, > + FEATURE_AVX512VL)) > + set_cpu_feature (cpu_model, cpu_features2, > + FEATURE_X86_64_V4); > + } > + } > + } > + > 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); > diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h > index e68dd656046..1b1846d59b8 100644 > --- a/gcc/common/config/i386/i386-cpuinfo.h > +++ b/gcc/common/config/i386/i386-cpuinfo.h > @@ -102,6 +102,7 @@ enum feature_priority > P_MMX, > P_SSE, > P_SSE2, > + P_X86_64_BASELINE, > P_SSE3, > P_SSSE3, > P_PROC_SSSE3, > @@ -111,6 +112,7 @@ enum feature_priority > P_SSE4_2, > P_PROC_SSE4_2, > P_POPCNT, > + P_X86_64_V2, > P_AES, > P_PCLMUL, > P_AVX, > @@ -125,8 +127,10 @@ enum feature_priority > P_BMI2, > P_AVX2, > P_PROC_AVX2, > + P_X86_64_V3, > P_AVX512F, > P_PROC_AVX512F, > + P_X86_64_V4, > P_PROC_DYNAMIC > }; > > @@ -228,6 +232,10 @@ enum processor_features > FEATURE_AESKLE, > FEATURE_WIDEKL, > FEATURE_AVXVNNI, > + FEATURE_X86_64_BASELINE, > + FEATURE_X86_64_V2, > + FEATURE_X86_64_V3, > + FEATURE_X86_64_V4, > CPU_FEATURE_MAX > }; > > diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h > index 898c18f3dda..cd9523b8fbc 100644 > --- a/gcc/common/config/i386/i386-isas.h > +++ b/gcc/common/config/i386/i386-isas.h > @@ -169,4 +169,8 @@ ISA_NAMES_TABLE_START > ISA_NAMES_TABLE_ENTRY("aeskle", FEATURE_AESKLE, P_NONE, NULL) > ISA_NAMES_TABLE_ENTRY("widekl", FEATURE_WIDEKL, P_NONE, "-mwidekl") > ISA_NAMES_TABLE_ENTRY("avxvnni", FEATURE_AVXVNNI, P_NONE, "-mavxvnni") > + ISA_NAMES_TABLE_ENTRY("x86-64", FEATURE_X86_64_BASELINE, P_NONE, NULL) > + ISA_NAMES_TABLE_ENTRY("x86-64-v2", FEATURE_X86_64_V2, P_NONE, NULL) > + ISA_NAMES_TABLE_ENTRY("x86-64-v3", FEATURE_X86_64_V3, P_NONE, NULL) > + ISA_NAMES_TABLE_ENTRY("x86-64-v4", FEATURE_X86_64_V4, P_NONE, NULL) > ISA_NAMES_TABLE_END > diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c > index 204e2903126..492873bb076 100644 > --- a/gcc/config/i386/i386-builtins.c > +++ b/gcc/config/i386/i386-builtins.c > @@ -1904,8 +1904,24 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) > return 0; > new_target = TREE_TARGET_OPTION (target_node); > gcc_assert (new_target); > - > - if (new_target->arch_specified && new_target->arch > 0) > + enum ix86_builtins builtin_fn = IX86_BUILTIN_CPU_IS; > + > + /* Special case x86-64 micro-level architectures. */ > + const char *arch_name = attrs_str + strlen ("arch="); > + if (startswith (arch_name, "x86-64")) > + { > + arg_str = arch_name; > + builtin_fn = IX86_BUILTIN_CPU_SUPPORTS; > + if (strcmp (arch_name, "x86-64") == 0) > + priority = P_X86_64_BASELINE; > + else if (strcmp (arch_name, "x86-64-v2") == 0) > + priority = P_X86_64_V2; > + else if (strcmp (arch_name, "x86-64-v3") == 0) > + priority = P_X86_64_V3; > + else if (strcmp (arch_name, "x86-64-v4") == 0) > + priority = P_X86_64_V4; > + } > + else if (new_target->arch_specified && new_target->arch > 0) > for (i = 0; i < pta_size; i++) > if (processor_alias_table[i].processor == new_target->arch) > { > @@ -1975,7 +1991,7 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) > > if (predicate_list) > { > - predicate_decl = ix86_builtins [(int) IX86_BUILTIN_CPU_IS]; > + predicate_decl = ix86_builtins [(int) builtin_fn]; > /* For a C string literal the length includes the trailing NULL. */ > predicate_arg = build_string_literal (strlen (arg_str) + 1, arg_str); > predicate_chain = tree_cons (predicate_decl, predicate_arg, > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 49df8e6dc38..d2c695f8dab 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -21644,6 +21644,18 @@ AMD Family 19h CPU. > > @item znver3 > AMD Family 19h Zen version 3. > + > +@item x86-64 > +Baseline x86-64 microarchitecture level (as defined in x86-64 psABI). > + > +@item x86-64-v2 > +x86-64-v2 microarchitecture level. > + > +@item x86-64-v3 > +x86-64-v3 microarchitecture level. > + > +@item x86-64-v4 > +x86-64-v4 microarchitecture level. > @end table > > Here is an example: > diff --git a/gcc/testsuite/g++.target/i386/mv30.C b/gcc/testsuite/g++.target/i386/mv30.C > new file mode 100644 > index 00000000000..b4947f0b481 > --- /dev/null > +++ b/gcc/testsuite/g++.target/i386/mv30.C > @@ -0,0 +1,50 @@ > +// PR target/101696 > +// Test that dispatching can choose the right multiversion > +// for x86-64 microarchitecture levels. > + > +// { dg-do run } > +// { dg-require-ifunc "" } > +// { dg-options "-O2" } > + > +#include > + > +int __attribute__ ((target("default"))) > +foo () > +{ > + return 0; > +} > + > +int __attribute__ ((target("arch=x86-64"))) foo () { > + return 1; > +} > + > +int __attribute__ ((target("arch=x86-64-v2"))) foo () { > + return 2; > +} > + > +int __attribute__ ((target("arch=x86-64-v3"))) foo () { > + return 3; > +} > + > +int __attribute__ ((target("arch=x86-64-v4"))) foo () { > + return 4; > +} > + > + > +int main () > +{ > + int val = foo (); > + > + if (__builtin_cpu_supports ("x86-64-v4")) > + assert (val == 4); > + else if (__builtin_cpu_supports ("x86-64-v3")) > + assert (val == 3); > + else if (__builtin_cpu_supports ("x86-64-v2")) > + assert (val == 2); > + else if (__builtin_cpu_supports ("x86-64")) > + assert (val == 1); > + else > + assert (val == 0); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mvc16.c b/gcc/testsuite/gcc.target/i386/mvc16.c > new file mode 100644 > index 00000000000..def6581f7e7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mvc16.c > @@ -0,0 +1,15 @@ > +/* { dg-do run } */ > +/* { dg-require-ifunc "" } */ > + > +__attribute__((target_clones("arch=x86-64", "arch=x86-64-v2", "arch=x86-64-v3", "arch=x86-64-v4", "default"))) > +int > +foo () > +{ > + return 0; > +} > + > +int > +main () > +{ > + return foo (); > +} > -- > 2.32.0 > -- H.J.