Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
I modified the H.J. patch draft.
@H.J. Can you please verify the newly added 'feature_priority'?
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.to...@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