On Mon, Nov 25, 2024 at 11:26:39PM +0000, Richard Sandiford wrote: > 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; > }
There are some hypothetical cases in which your suggested approach wouldn't be able to avoid the new feature flag, whereas my more targetted approach here would. I'm struggling to think of a realistic example though, as I can only think of one core in which any of these features have been backported to an earlier architecture version. The closest bad examples I can find are: - Using -mcpu=a64fx+nosve: This would canonicalise to armv8.2-a+f16+fcma with either approach. If jscvt didn't exist, however, then my approach would instead give armv8.3-a+nopauth+norcpc. - Running on an unrecognised future cpu with an unfortunate combination of features could also be an example, but that's probably unrealistic. I also feel that this is a work-around that we should be applying in moderation only when we know it would actually help with compatibility issues. However, if you'd still prefer to use a bigger table-driven hammer, then I can change the patch to do that. > > + > > +/* 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.) This seems like a reasonable improvement, though I do see the "seems like feature creep" remark. > 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} > > } } */