[PATCH] i386: support micro-levels in target{, _clone} attrs [PR101696]

H.J. Lu hjl.tools@gmail.com
Thu Aug 12 14:25:10 GMT 2021


On Thu, Aug 12, 2021 at 7:12 AM Martin Liška <mliska@suse.cz> 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 <hjl.tools@gmail.com>
> ---
>   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 <assert.h>
> +
> +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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-x86-Update-__builtin_cpu_supports-for-x86-64-x86-64-.patch
Type: text/x-patch
Size: 5568 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-patches/attachments/20210812/5717d333/attachment-0001.bin>


More information about the Gcc-patches mailing list