i386: support micro-levels in target{,_clone} attrs [PR101696]
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. * gcc.target/i386/builtin_target.c (CHECK___builtin_cpu_supports): New. Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
parent
03312cbd54
commit
8ea292591e
@ -46,6 +46,10 @@ struct __processor_model2
|
||||
# define CHECK___builtin_cpu_is(cpu)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK___builtin_cpu_supports
|
||||
# define CHECK___builtin_cpu_supports(isa)
|
||||
#endif
|
||||
|
||||
/* Return non-zero if the processor has feature F. */
|
||||
|
||||
static inline int
|
||||
@ -933,6 +937,50 @@ 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))
|
||||
{
|
||||
CHECK___builtin_cpu_supports ("x86-64");
|
||||
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))
|
||||
{
|
||||
CHECK___builtin_cpu_supports ("x86-64-v2");
|
||||
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))
|
||||
{
|
||||
CHECK___builtin_cpu_supports ("x86-64-v3");
|
||||
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))
|
||||
{
|
||||
CHECK___builtin_cpu_supports ("x86-64-v4");
|
||||
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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
@ -229,6 +233,10 @@ enum processor_features
|
||||
FEATURE_WIDEKL,
|
||||
FEATURE_AVXVNNI,
|
||||
FEATURE_AVX512FP16,
|
||||
FEATURE_X86_64_BASELINE,
|
||||
FEATURE_X86_64_V2,
|
||||
FEATURE_X86_64_V3,
|
||||
FEATURE_X86_64_V4,
|
||||
CPU_FEATURE_MAX
|
||||
};
|
||||
|
||||
|
@ -170,4 +170,9 @@ ISA_NAMES_TABLE_START
|
||||
ISA_NAMES_TABLE_ENTRY("widekl", FEATURE_WIDEKL, P_NONE, "-mwidekl")
|
||||
ISA_NAMES_TABLE_ENTRY("avxvnni", FEATURE_AVXVNNI, P_NONE, "-mavxvnni")
|
||||
ISA_NAMES_TABLE_ENTRY("avx512fp16", FEATURE_AVX512FP16, P_NONE, "-mavx512fp16")
|
||||
ISA_NAMES_TABLE_ENTRY("x86-64", FEATURE_X86_64_BASELINE, P_X86_64_BASELINE,
|
||||
NULL)
|
||||
ISA_NAMES_TABLE_ENTRY("x86-64-v2", FEATURE_X86_64_V2, P_X86_64_V2, NULL)
|
||||
ISA_NAMES_TABLE_ENTRY("x86-64-v3", FEATURE_X86_64_V3, P_X86_64_V3, NULL)
|
||||
ISA_NAMES_TABLE_ENTRY("x86-64-v4", FEATURE_X86_64_V4, P_X86_64_V4, NULL)
|
||||
ISA_NAMES_TABLE_END
|
||||
|
@ -1927,8 +1927,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)
|
||||
{
|
||||
@ -1998,7 +2014,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,
|
||||
|
@ -21743,6 +21743,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:
|
||||
|
50
gcc/testsuite/g++.target/i386/mv30.C
Normal file
50
gcc/testsuite/g++.target/i386/mv30.C
Normal file
@ -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;
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
#include <stdlib.h>
|
||||
#include "cpuid.h"
|
||||
#define CHECK___builtin_cpu_is(cpu) assert (__builtin_cpu_is (cpu))
|
||||
#define CHECK___builtin_cpu_supports(isa) \
|
||||
assert (__builtin_cpu_supports (isa))
|
||||
#define gcc_assert(a) assert (a)
|
||||
#define gcc_unreachable() abort ()
|
||||
#define inline
|
||||
|
15
gcc/testsuite/gcc.target/i386/mvc16.c
Normal file
15
gcc/testsuite/gcc.target/i386/mvc16.c
Normal file
@ -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 ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user