Sorry for the slow review. Andrew Carlotti <andrew.carlo...@arm.com> writes: > 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; > +}
I was hoping we could do this in a table-driven way. Experimenting a bit locally (but only lightly tested), the following seems to work: aarch64.h: /* The set of all architecture flags. */ constexpr auto AARCH64_FL_ARCHES ATTRIBUTE_UNUSED = aarch64_feature_flags (0) #define AARCH64_ARCH(A, B, ARCH_IDENT, D, E) \ | feature_deps::ARCH_IDENT ().flag #include "config/aarch64/aarch64-arches.def" ; aarch64-common.cc: ... const struct arch_to_arch_name *best = nullptr; for (auto *a_to_an = all_architectures; a_to_an->arch != aarch64_no_arch; a_to_an++) { /* Require the architecture to have all architecture flags in FLAGS. */ if ((~a_to_an->flags & flags & AARCH64_FL_ARCHES) != 0) continue; /* Skip architectures that add no new mandatory features. */ if (best && (a_to_an->flags & ~best->flags & ~AARCH64_FL_ARCHES) == 0) continue; /* Require FLAGS to include all mandatory extensions. */ if ((a_to_an->flags & ~flags & ~AARCH64_FL_ARCHES) != 0) continue; best = a_to_an; } > + > +/* 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 ()); > +} This is going to seem like feature creep, sorry, but: rather than duplicate the architecture parsing, could we instead move the march and mcpu processing from aarch64.cc to here? Specifically: - aarch64_parse_arch - aarch64_parse_cpu - aarch64_validate_mcpu - aarch64_validate_march - aarch64_print_hint_for_* This would mean making "struct processor" public, and so giving it an aarch64_ name (or putting it in a namespace). We'd also need to remove the tuning information and use a separate table for that. Still, I think it would be more robust than having two pieces of code doing the same parsing. It should also give a better UI, since the driver parsing would give the same hints as the compiler proper. (Only tested to the point of moving the code and linking the driver.) Thanks, Richard > /* 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} } > } */