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} } } 
*/

Reply via email to