These new flags (+fcma, +jscvt, +rcpc2, +jscvt, +frintts, +wfxt and +xs) were only recently added to the assembler. To improve compatibility with older assemblers, we try to avoid passing these new flags to the assembler if we can express the targetted architecture without them. We do so by using an almost-equivalent architecture string with a higher architecture version.
This should never reduce the set of instructions accepted by the assembler. It will make it more lenient in two cases: 1. Many system registers are currently gated behind architecture versions instead of specific feature flags. Increasing the base architecture version may cause more system register accesses to be accepted. 2. FEAT_XS doesn't have an HWCAP bit or cpuinfo entry. We still want to avoid passing +wfxt or +noxs to the assembler if possible, so we'll instruct the assembler to accept FEAT_XS instructions as well whenever the rest of the new features are enabled. gcc/ChangeLog: * common/config/aarch64/aarch64-common.cc (aarch64_get_arch_string_for_assembler): New. (aarch64_rewrite_march): New. (aarch64_rewrite_selected_cpu): Call new function. * config/aarch64/aarch64-elf.h (ASM_SPEC): Remove identity mapping. * config/aarch64/aarch64-protos.h (aarch64_get_arch_string_for_assembler): New. * config/aarch64/aarch64.cc (aarch64_declare_function_name): Call new function. (aarch64_start_file): Ditto. * config/aarch64/aarch64.h * config/aarch64/aarch64.h (EXTRA_SPEC_FUNCTIONS): Use new macro name. (MCPU_TO_MARCH_SPEC): Rename to... (MARCH_REWRITE_SPEC): ...this, and add new spec rule. (aarch64_rewrite_march): New declaration. (MCPU_TO_MARCH_SPEC_FUNCTIONS): Rename to... (MARCH_REWRITE_SPEC_FUNCTIONS): ...this, and add new function. (ASM_CPU_SPEC): Use new macro name. gcc/testsuite/ChangeLog: * gcc.target/aarch64/cpunative/native_cpu_21.c: Update check. * gcc.target/aarch64/cpunative/native_cpu_22.c: Update check. * gcc.target/aarch64/cpunative/info_27: New test. * gcc.target/aarch64/cpunative/info_28: New test. * gcc.target/aarch64/cpunative/info_29: New test. * gcc.target/aarch64/cpunative/native_cpu_27.c: New test. * gcc.target/aarch64/cpunative/native_cpu_28.c: New test. * gcc.target/aarch64/cpunative/native_cpu_29.c: New test. diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc index 2bfc597e333b6018970a9ee6e370a66b6d0960ef..717b3238be16f39a6fd1b4143662eb540ccf292d 100644 --- a/gcc/common/config/aarch64/aarch64-common.cc +++ b/gcc/common/config/aarch64/aarch64-common.cc @@ -371,6 +371,119 @@ aarch64_get_extension_string_for_isa_flags return outstr; } +/* Generate an arch string to be passed to the assembler. + + Several flags were added retrospectively for features that were previously + enabled only by specifying an architecture version. We want to avoid + passing these flags to the assembler if possible, to improve compatibility + with older assemblers. */ + +std::string +aarch64_get_arch_string_for_assembler (aarch64_arch arch, + aarch64_feature_flags flags) +{ + if (!(flags & AARCH64_FL_FCMA) || !(flags & AARCH64_FL_JSCVT)) + goto done; + + if (arch == AARCH64_ARCH_V8A + || arch == AARCH64_ARCH_V8_1A + || arch == AARCH64_ARCH_V8_2A) + arch = AARCH64_ARCH_V8_3A; + + if (!(flags & AARCH64_FL_RCPC2)) + goto done; + + if (arch == AARCH64_ARCH_V8_3A) + arch = AARCH64_ARCH_V8_4A; + + if (!(flags & AARCH64_FL_FRINTTS) || !(flags & AARCH64_FL_FLAGM2)) + goto done; + + if (arch == AARCH64_ARCH_V8_4A) + arch = AARCH64_ARCH_V8_5A; + + if (!(flags & AARCH64_FL_WFXT)) + goto done; + + if (arch == AARCH64_ARCH_V8_5A || arch == AARCH64_ARCH_V8_6A) + { + arch = AARCH64_ARCH_V8_7A; + /* We don't support native detection for FEAT_XS, so we'll assume it's + present if the rest of these features are also present. If we don't + do this, then we would end up passing +noxs to the assembler. */ + flags |= AARCH64_FL_XS; + } +done: + + const struct arch_to_arch_name* a_to_an; + for (a_to_an = all_architectures; + a_to_an->arch != aarch64_no_arch; + a_to_an++) + { + if (a_to_an->arch == arch) + break; + } + + std::string outstr = a_to_an->arch_name + + aarch64_get_extension_string_for_isa_flags (flags, a_to_an->flags); + + return outstr; +} + +/* Called by the driver to rewrite a name passed to the -march + argument in preparation to be passed to the assembler. The + names passed from the commend line will be in ARGV, we want + to use the right-most argument, which should be in + ARGV[ARGC - 1]. ARGC should always be greater than 0. */ + +const char * +aarch64_rewrite_march (int argc, const char **argv) +{ + gcc_assert (argc); + const char *name = argv[argc - 1]; + std::string original_string (name); + std::string extension_str; + std::string base_name; + size_t extension_pos = original_string.find_first_of ('+'); + + /* Strip and save the extension string. */ + if (extension_pos != std::string::npos) + { + base_name = original_string.substr (0, extension_pos); + extension_str = original_string.substr (extension_pos, + std::string::npos); + } + else + { + /* No extensions. */ + base_name = original_string; + } + + const struct arch_to_arch_name* a_to_an; + for (a_to_an = all_architectures; + a_to_an->arch != aarch64_no_arch; + a_to_an++) + { + if (a_to_an->arch_name == base_name) + break; + } + + /* We couldn't find that architecture name. */ + if (a_to_an->arch == aarch64_no_arch) + fatal_error (input_location, "unknown value %qs for %<-march%>", name); + + aarch64_feature_flags flags = a_to_an->flags; + aarch64_parse_extension (extension_str.c_str (), &flags, NULL); + + std::string outstr = aarch64_get_arch_string_for_assembler (a_to_an->arch, + flags); + + /* We are going to memory leak here, nobody elsewhere + in the callchain is going to clean up after us. The alternative is + to allocate a static buffer, and assert that it is big enough for our + modified string, which seems much worse! */ + return xstrdup (outstr.c_str ()); +} /* Attempt to rewrite NAME, which has been passed on the command line as a -mcpu option to an equivalent -march value. If we can do so, return the new string, otherwise return an error. */ @@ -414,7 +527,7 @@ aarch64_rewrite_selected_cpu (const char *name) break; } - /* We couldn't find that proceesor name, or the processor name we + /* We couldn't find that processor name, or the processor name we found does not map to an architecture we understand. */ if (p_to_a->arch == aarch64_no_arch || a_to_an->arch == aarch64_no_arch) @@ -423,9 +536,8 @@ aarch64_rewrite_selected_cpu (const char *name) aarch64_feature_flags extensions = p_to_a->flags; aarch64_parse_extension (extension_str.c_str (), &extensions, NULL); - std::string outstr = a_to_an->arch_name - + aarch64_get_extension_string_for_isa_flags (extensions, - a_to_an->flags); + std::string outstr = aarch64_get_arch_string_for_assembler (a_to_an->arch, + extensions); /* We are going to memory leak here, nobody elsewhere in the callchain is going to clean up after us. The alternative is diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h index b6fb7936789fed7fc07d61c6e10301f0c451ac5c..1e210ce3b8beacb0ded7b482694df10368b9a50b 100644 --- a/gcc/config/aarch64/aarch64-elf.h +++ b/gcc/config/aarch64/aarch64-elf.h @@ -136,7 +136,6 @@ #define ASM_SPEC "\ %{mbig-endian:-EB} \ %{mlittle-endian:-EL} \ -%{march=*:-march=%*} \ %(asm_cpu_spec)" \ ASM_MABI_SPEC #endif diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 6ab41a21c75dbdb6bba7875408bc1aa6959c9033..6cf09b41e88cb4d029e4d38f722a4247b9f84328 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -1165,6 +1165,8 @@ enum aarch_parse_opt_result aarch64_parse_extension (const char *, void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates); std::string aarch64_get_extension_string_for_isa_flags (aarch64_feature_flags, aarch64_feature_flags); +std::string aarch64_get_arch_string_for_assembler (aarch64_arch, + aarch64_feature_flags); rtl_opt_pass *make_pass_aarch64_early_ra (gcc::context *); rtl_opt_pass *make_pass_fma_steering (gcc::context *); diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index e50bd43f3908916903fe724ec39ae137bc68dfad..9287329a76392034725080ae79060dcd16cfd753 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -1417,7 +1417,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define HAVE_LOCAL_CPU_DETECT # define EXTRA_SPEC_FUNCTIONS \ { "local_cpu_detect", host_detect_local_cpu }, \ - MCPU_TO_MARCH_SPEC_FUNCTIONS + MARCH_REWRITE_SPEC_FUNCTIONS /* Rewrite -m{arch,cpu,tune}=native based on the host system information. When rewriting -march=native convert it into an -mcpu option if no other @@ -1434,7 +1434,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); { "tune", "%{!mcpu=*:%{!mtune=*:%{!march=native:-mtune=%(VALUE)}}}" }, #else # define MCPU_MTUNE_NATIVE_SPECS "" -# define EXTRA_SPEC_FUNCTIONS MCPU_TO_MARCH_SPEC_FUNCTIONS +# define EXTRA_SPEC_FUNCTIONS MARCH_REWRITE_SPEC_FUNCTIONS # define CONFIG_TUNE_SPEC \ {"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}"}, #endif @@ -1449,15 +1449,18 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \ CONFIG_TUNE_SPEC -#define MCPU_TO_MARCH_SPEC \ - " %{mcpu=*:-march=%:rewrite_mcpu(%{mcpu=*:%*})}" +#define MARCH_REWRITE_SPEC \ + " %{mcpu=*:-march=%:rewrite_mcpu(%{mcpu=*:%*})}" \ + " %{march=*:-march=%:rewrite_march(%{march=*:%*})}" extern const char *aarch64_rewrite_mcpu (int argc, const char **argv); -#define MCPU_TO_MARCH_SPEC_FUNCTIONS \ - { "rewrite_mcpu", aarch64_rewrite_mcpu }, +extern const char *aarch64_rewrite_march (int argc, const char **argv); +#define MARCH_REWRITE_SPEC_FUNCTIONS \ + { "rewrite_mcpu", aarch64_rewrite_mcpu }, \ + { "rewrite_march", aarch64_rewrite_march }, #define ASM_CPU_SPEC \ - MCPU_TO_MARCH_SPEC + MARCH_REWRITE_SPEC #define EXTRA_SPECS \ { "asm_cpu_spec", ASM_CPU_SPEC } diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 81885d442ed3e7008aacc937c1a9305b7824bc7c..f32b90c188228fe980e247b4448ee3c1f3e7ddfc 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -24846,16 +24846,12 @@ aarch64_declare_function_name (FILE *stream, const char* name, targ_options = TREE_TARGET_OPTION (target_option_current_node); gcc_assert (targ_options); - const struct processor *this_arch - = aarch64_get_arch (targ_options->x_selected_arch); - auto isa_flags = aarch64_get_asm_isa_flags (targ_options); - std::string extension - = aarch64_get_extension_string_for_isa_flags (isa_flags, - this_arch->flags); + aarch64_arch arch = targ_options->x_selected_arch; + std::string to_print + = aarch64_get_arch_string_for_assembler (arch, isa_flags); /* Only update the assembler .arch string if it is distinct from the last such string we printed. */ - std::string to_print = this_arch->name + extension; if (to_print != aarch64_last_printed_arch_string) { asm_fprintf (asm_out_file, "\t.arch %s\n", to_print.c_str ()); @@ -24977,19 +24973,16 @@ aarch64_start_file (void) struct cl_target_option *default_options = TREE_TARGET_OPTION (target_option_default_node); - const struct processor *default_arch - = aarch64_get_arch (default_options->x_selected_arch); + aarch64_arch default_arch = default_options->x_selected_arch; auto default_isa_flags = aarch64_get_asm_isa_flags (default_options); - std::string extension - = aarch64_get_extension_string_for_isa_flags (default_isa_flags, - default_arch->flags); - - aarch64_last_printed_arch_string = default_arch->name + extension; - aarch64_last_printed_tune_string = ""; - asm_fprintf (asm_out_file, "\t.arch %s\n", - aarch64_last_printed_arch_string.c_str ()); - - default_file_start (); + std::string arch_string + = aarch64_get_arch_string_for_assembler (default_arch, default_isa_flags); + aarch64_last_printed_arch_string = arch_string; + aarch64_last_printed_tune_string = ""; + asm_fprintf (asm_out_file, "\t.arch %s\n", + arch_string.c_str ()); + + default_file_start (); } /* Emit load exclusive. */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_27 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_27 new file mode 100644 index 0000000000000000000000000000000000000000..1ca9354579f0b7fdd77e31857d744476529cd301 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_27 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 100.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs sb dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh bti paca pacg +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xd08 +CPU revision : 2 diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_28 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_28 new file mode 100644 index 0000000000000000000000000000000000000000..0c216abbb9e4d5c0273eaeb1824dc16e66b09c6c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_28 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 100.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat flagm ssbs sb dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh bti paca pacg +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xd08 +CPU revision : 2 diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_29 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_29 new file mode 100644 index 0000000000000000000000000000000000000000..308c06710902507fcf274aa61e2244937d4e227b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_29 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 100.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs sb dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh bti paca pacg wfxt +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xd08 +CPU revision : 2 diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_21.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_21.c index 904cdf452263961442f3ecc31cd1b6563130f9c7..e56b9164024c7535d6b10f451b7bc0796e7bd161 100644 --- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_21.c +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_21.c @@ -7,7 +7,7 @@ int main() return 0; } -/* { dg-final { scan-assembler {\.arch armv8-a\+flagm2\+lse\+dotprod\+rdma\+crc\+fp16fml\+jscvt\+rcpc2\+frintts\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+sb\+ssbs\n} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.5-a\+crc\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+nopredres\+nopauth\n} } } */ /* Check that an Armv8-A core doesn't fall apart on extensions without midr values. */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_22.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_22.c index feb959b11b0e383a5e1f3214d55f80f56d2605d4..db3df27a22ea9275ca303e911061f2c35d3ba722 100644 --- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_22.c +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_22.c @@ -7,7 +7,7 @@ int main() return 0; } -/* { dg-final { scan-assembler {\.arch armv8-a\+flagm2\+lse\+dotprod\+rdma\+crc\+fp16fml\+jscvt\+rcpc2\+frintts\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+sb\+ssbs\+pauth\n} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.5-a\+crc\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+nopredres\n} } } */ /* Check that an Armv8-A core doesn't fall apart on extensions without midr values and that it enables optional features. */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_27.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_27.c new file mode 100644 index 0000000000000000000000000000000000000000..43df6a50706df8855d2e960e508778542d81e643 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_27.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { { aarch64*-*-linux*} && native } } } */ +/* { dg-set-compiler-env-var GCC_CPUINFO "$srcdir/gcc.target/aarch64/cpunative/info_27" } */ +/* { dg-additional-options "-mcpu=native" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler {\.arch armv8-a\+flagm2\+lse\+dotprod\+rdma\+crc\+fp16fml\+rcpc2\+frintts\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+sb\+ssbs\+pauth\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_28.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_28.c new file mode 100644 index 0000000000000000000000000000000000000000..0e0e56f539433ea02c5c71c8c0bae5ddb256e962 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_28.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { { aarch64*-*-linux*} && native } } } */ +/* { dg-set-compiler-env-var GCC_CPUINFO "$srcdir/gcc.target/aarch64/cpunative/info_28" } */ +/* { dg-additional-options "-mcpu=native" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler {\.arch armv8\.3-a\+flagm2\+dotprod\+crc\+fp16fml\+frintts\+i8mm\+bf16\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+sb\+ssbs\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_29.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_29.c new file mode 100644 index 0000000000000000000000000000000000000000..9b07161b77d75cfec19aea01fcf2eb5ece91853a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_29.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { { aarch64*-*-linux*} && native } } } */ +/* { dg-set-compiler-env-var GCC_CPUINFO "$srcdir/gcc.target/aarch64/cpunative/info_29" } */ +/* { dg-additional-options "-mcpu=native" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler {\.arch armv8\.7-a\+crc\+sve2-aes\+sve2-bitperm\+sve2-sha3\+sve2-sm4\+nopredres\n} } } */