diff mbox series

[committed] amdgcn: Support LLVM 13 assembler syntax

Message ID 037ac5ad-ead7-753d-638d-44d98759c71c@codesourcery.com
State New
Headers show
Series [committed] amdgcn: Support LLVM 13 assembler syntax | expand

Commit Message

Andrew Stubbs Oct. 7, 2021, 10:40 a.m. UTC
I've committed this patch to allow GCC to adapt to the different 
variants of the LLVM amdgcn assembler. Unfortunately they keep making 
changes without maintaining backwards compatibility.

GCC should now work with LLVM 9, LLVM 12, and LLVM 13 in terms of CLI 
usage, however only LLVM 9 is well tested (I'm aware of at least one bug 
in each of LLVM 12 and 13 that affects GCC-generated binaries).

This patch should make no observable change in behaviour on LLVM 9, and 
add nothing new on LLVM 13 (besides actually working).

Andrew Stubbs
amdgcn: Support LLVM 13 assembler syntax

The LLVM devs have changed the assembler architecture attribute names on both
CLI and in the ".amdgcn_target" directive, and changed the attribute syntax
inside the directive, without keeping any backwards compatibility. :-(

This patch improves our configure tests to detect what dialect to use, what
attributes are valid, and adjusts the specs to match.

gcc/ChangeLog:

	* config.in: Regenerate.
	* config/gcn/gcn-hsa.h (X_FIJI): New macro.
	(X_900): New macro.
	(X_906): New macro.
	(X_908): New macro.
	(A_FIJI): Rename to ...
	(S_FIJI): ... this.
	(A_900): Rename to ...
	(S_900): ... this.
	(A_906): Rename to ...
	(S_906): ... this.
	(A_908): Rename to ...
	(S_908): ... this.
	(SRAMOPT): New macro.
	(ASM_SPEC): Adjust xnack option usage.
	* config/gcn/gcn.c (output_file_start): Adjust amdgcn_target usage.
	* configure: Regenerate.
	* configure.ac: Detect LLVM assembler dialect.
diff mbox series

Patch

diff --git a/gcc/config.in b/gcc/config.in
index 61cafe4f6c0f..b5bec3971dc2 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1463,30 +1463,66 @@ 
 #endif
 
 
-/* Define if your assembler allows -mattr=+sram-ecc for fiji. */
+/* Define if your assembler expects amdgcn_target gfx908+xnack syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V3_SYNTAX
+#endif
+
+
+/* Define if your assembler expects amdgcn_target gfx908:xnack+ syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V4_SYNTAX
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for fiji. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GCN_SRAM_ECC_FIJI
 #endif
 
 
-/* Define if your assembler allows -mattr=+sram-ecc for gfx900. */
+/* Define if your assembler allows -mattr=+sramecc for gfx900. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GCN_SRAM_ECC_GFX900
 #endif
 
 
-/* Define if your assembler allows -mattr=+sram-ecc for gfx906. */
+/* Define if your assembler allows -mattr=+sramecc for gfx906. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GCN_SRAM_ECC_GFX906
 #endif
 
 
-/* Define if your assembler allows -mattr=+sram-ecc for gfx908. */
+/* Define if your assembler allows -mattr=+sramecc for gfx908. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GCN_SRAM_ECC_GFX908
 #endif
 
 
+/* Define if your assembler allows -mattr=+xnack for fiji. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_FIJI
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx900. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX900
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx906. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX906
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx908. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX908
+#endif
+
+
 /* Define to 1 if you have the `getchar_unlocked' function. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GETCHAR_UNLOCKED
diff --git a/gcc/config/gcn/gcn-hsa.h b/gcc/config/gcn/gcn-hsa.h
index fc99c8db7520..60fd40a10b71 100644
--- a/gcc/config/gcn/gcn-hsa.h
+++ b/gcc/config/gcn/gcn-hsa.h
@@ -75,25 +75,64 @@  extern unsigned int gcn_local_sym_hash (const char *name);
    supported for gcn.  */
 #define GOMP_SELF_SPECS ""
 
+#ifdef HAVE_GCN_XNACK_FIJI
+#define X_FIJI
+#else
+#define X_FIJI "!march=*:;march=fiji:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX900
+#define X_900
+#else
+#define X_900 "march=gfx900:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX906
+#define X_906
+#else
+#define X_906 "march=gfx906:;"
+#endif
+#ifdef HAVE_GCN_XNACK_GFX908
+#define X_908
+#else
+#define X_908 "march=gfx908:;"
+#endif
+
 #ifdef HAVE_GCN_SRAM_ECC_FIJI
-#define A_FIJI
+#define S_FIJI
 #else
-#define A_FIJI "!march=*:;march=fiji:;"
+#define S_FIJI "!march=*:;march=fiji:;"
 #endif
 #ifdef HAVE_GCN_SRAM_ECC_GFX900
-#define A_900
+#define S_900
 #else
-#define A_900 "march=gfx900:;"
+#define S_900 "march=gfx900:;"
 #endif
 #ifdef HAVE_GCN_SRAM_ECC_GFX906
-#define A_906
+#define S_906
 #else
-#define A_906 "march=gfx906:;"
+#define S_906 "march=gfx906:;"
 #endif
 #ifdef HAVE_GCN_SRAM_ECC_GFX908
-#define A_908
+#define S_908
+#else
+#define S_908 "march=gfx908:;"
+#endif
+
+#ifdef HAVE_GCN_ASM_V3_SYNTAX
+#define SRAMOPT "sram-ecc"
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+#define SRAMOPT "sramecc"
+#endif
+#if !defined(SRAMOPT) && !defined(IN_LIBGCC2)
+#error "No assembler syntax configured"
+#endif
+
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+/* FIJI cards don't seem to support drivers new enough to allow HSACOv4.  */
+#define HSACO3_SELECT_OPT \
+    "%{!march=*|march=fiji:--amdhsa-code-object-version=3} "
 #else
-#define A_908 "march=gfx908:;"
+#define HSACO3_SELECT_OPT
 #endif
 
 /* These targets can't have SRAM-ECC, even if a broken assembler allows it.  */
@@ -103,10 +142,12 @@  extern unsigned int gcn_local_sym_hash (const char *name);
 /* Use LLVM assembler and linker options.  */
 #define ASM_SPEC  "-triple=amdgcn--amdhsa "  \
 		  "%:last_arg(%{march=*:-mcpu=%*}) " \
-		  "-mattr=%{mxnack:+xnack;:-xnack} " \
+		  HSACO3_SELECT_OPT \
+		  "-mattr=%{" X_FIJI X_900 X_906 X_908 \
+			    "mxnack:+xnack;:-xnack} " \
 		  /* FIXME: support "any" when we move to HSACOv4.  */ \
-		  "-mattr=%{" A_FIJI A_900 A_906 A_908 \
-			    "!msram-ecc=off:+sram-ecc;:-sram-ecc} " \
+		  "-mattr=%{" S_FIJI S_900 S_906 S_908 \
+			    "!msram-ecc=off:+" SRAMOPT ";:-" SRAMOPT "} " \
 		  "-filetype=obj"
 #define LINK_SPEC "--pie --export-dynamic"
 #define LIB_SPEC  "-lc"
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 2a3fc96c1ee0..8517168ff0ad 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -5217,42 +5217,72 @@  static void
 output_file_start (void)
 {
   const char *cpu;
-  bool use_sram = flag_sram_ecc;
+  bool use_xnack_attr = true;
+  bool use_sram_attr = true;
   switch (gcn_arch)
     {
     case PROCESSOR_FIJI:
       cpu = "gfx803";
+#ifndef HAVE_GCN_XNACK_FIJI
+      use_xnack_attr = false;
+#endif
 #ifndef HAVE_GCN_SRAM_ECC_FIJI
-      use_sram = false;
+      use_sram_attr = false;
 #endif
       break;
     case PROCESSOR_VEGA10:
       cpu = "gfx900";
+#ifndef HAVE_GCN_XNACK_GFX900
+      use_xnack_attr = false;
+#endif
 #ifndef HAVE_GCN_SRAM_ECC_GFX900
-      use_sram = false;
+      use_sram_attr = false;
 #endif
       break;
     case PROCESSOR_VEGA20:
       cpu = "gfx906";
+#ifndef HAVE_GCN_XNACK_GFX906
+      use_xnack_attr = false;
+#endif
 #ifndef HAVE_GCN_SRAM_ECC_GFX906
-      use_sram = false;
+      use_sram_attr = false;
 #endif
       break;
     case PROCESSOR_GFX908:
       cpu = "gfx908";
+#ifndef HAVE_GCN_XNACK_GFX908
+      use_xnack_attr = false;
+#endif
 #ifndef HAVE_GCN_SRAM_ECC_GFX908
-      use_sram = false;
+      use_sram_attr = false;
 #endif
       break;
     default: gcc_unreachable ();
     }
 
+#if HAVE_GCN_ASM_V3_SYNTAX
   const char *xnack = (flag_xnack ? "+xnack" : "");
+  const char *sram_ecc = (flag_sram_ecc ? "+sram-ecc" : "");
+#endif
+#if HAVE_GCN_ASM_V4_SYNTAX
+  const char *xnack = (flag_xnack ? ":xnack+" : ":xnack-");
   /* FIXME: support "any" when we move to HSACOv4.  */
-  const char *sram_ecc = (use_sram ? "+sram-ecc" : "");
+  const char *sram_ecc = (flag_sram_ecc ? ":sramecc+" : ":sramecc-");
+#endif
+  if (!use_xnack_attr)
+    xnack = "";
+  if (!use_sram_attr)
+    sram_ecc = "";
 
   fprintf(asm_out_file, "\t.amdgcn_target \"amdgcn-unknown-amdhsa--%s%s%s\"\n",
-	  cpu, xnack, sram_ecc);
+	  cpu,
+#if HAVE_GCN_ASM_V3_SYNTAX
+	  xnack, sram_ecc
+#endif
+#ifdef HAVE_GCN_ASM_V4_SYNTAX
+	  sram_ecc, xnack
+#endif
+	  );
 }
 
 /* Implement ASM_DECLARE_FUNCTION_NAME via gcn-hsa.h.
diff --git a/gcc/configure b/gcc/configure
index d93961912fb8..5ea5a1b71430 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28757,22 +28757,241 @@  esac
 
 case "$target" in
   amdgcn-* | gcn-*)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for fiji" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for fiji... " >&6; }
+    # Test the LLVM assembler syntax dialect; they have made a number of
+    # changes between LLVM 12 & 13 without any backward compatibility.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v2/3 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v2/3 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v3_syntax+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_asm_v3_syntax=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_gcn_asm_v3_syntax=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_asm_v3_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v3_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V3_SYNTAX 1" >>confdefs.h
+
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v4 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v4 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v4_syntax+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_asm_v4_syntax=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_gcn_asm_v4_syntax=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_asm_v4_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v4_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V4_SYNTAX 1" >>confdefs.h
+
+fi
+
+
+    # Some attribute names changed in the move to v4 ...
+    if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+	sramopt="+sram-ecc"
+	sramattr="+sram-ecc"
+	xnackattr="+xnack"
+    elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+	sramopt="+sramecc"
+	sramattr=":sramecc+"
+	xnackattr=":xnack+"
+    else
+	as_fn_error $? "Unrecognised assembler version" "$LINENO" 5
+    fi
+
+    # Test whether the LLVM assembler accepts -mattr=+xnack without any
+    # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+    # LLVM 12+ throws a warning for GPUs without support.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for fiji... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_fiji+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_xnack_ecc_fiji=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_xnack_ecc_fiji=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_fiji" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_fiji" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_fiji = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_FIJI 1" >>confdefs.h
+
+fi
+
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx900... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx900+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_xnack_ecc_gfx900=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_xnack_ecc_gfx900=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx900" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx900" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx900 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX900 1" >>confdefs.h
+
+fi
+
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx906... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx906+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_xnack_ecc_gfx906=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_xnack_ecc_gfx906=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx906" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx906" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx906 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX906 1" >>confdefs.h
+
+fi
+
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx908... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx908+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_gcn_xnack_ecc_gfx908=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_xnack_ecc_gfx908=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_xnack_ecc_gfx908" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx908" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx908 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX908 1" >>confdefs.h
+
+fi
+
+    rm -f conftest.err
+
+    # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+    # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+    # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+    # for GPUs without support.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for fiji... " >&6; }
 if ${gcc_cv_as_gcn_sram_ecc_fiji+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   gcc_cv_as_gcn_sram_ecc_fiji=no
   if test x$gcc_cv_as != x; then
-    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"' > conftest.s
-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; }
     then
-	gcc_cv_as_gcn_sram_ecc_fiji=yes
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_sram_ecc_fiji=yes
     else
       echo "configure: failed program was" >&5
       cat conftest.s >&5
@@ -28788,22 +29007,24 @@  $as_echo "#define HAVE_GCN_SRAM_ECC_FIJI 1" >>confdefs.h
 
 fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx900" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx900... " >&6; }
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx900... " >&6; }
 if ${gcc_cv_as_gcn_sram_ecc_gfx900+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   gcc_cv_as_gcn_sram_ecc_gfx900=no
   if test x$gcc_cv_as != x; then
-    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"' > conftest.s
-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; }
     then
-	gcc_cv_as_gcn_sram_ecc_gfx900=yes
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_sram_ecc_gfx900=yes
     else
       echo "configure: failed program was" >&5
       cat conftest.s >&5
@@ -28819,22 +29040,24 @@  $as_echo "#define HAVE_GCN_SRAM_ECC_GFX900 1" >>confdefs.h
 
 fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx906" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx906... " >&6; }
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx906... " >&6; }
 if ${gcc_cv_as_gcn_sram_ecc_gfx906+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   gcc_cv_as_gcn_sram_ecc_gfx906=no
   if test x$gcc_cv_as != x; then
-    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"' > conftest.s
-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; }
     then
-	gcc_cv_as_gcn_sram_ecc_gfx906=yes
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_sram_ecc_gfx906=yes
     else
       echo "configure: failed program was" >&5
       cat conftest.s >&5
@@ -28850,22 +29073,24 @@  $as_echo "#define HAVE_GCN_SRAM_ECC_GFX906 1" >>confdefs.h
 
 fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+sram-ecc for gfx908" >&5
-$as_echo_n "checking assembler for assembler accepts -mattr=+sram-ecc for gfx908... " >&6; }
+    rm -f conftest.err
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx908... " >&6; }
 if ${gcc_cv_as_gcn_sram_ecc_gfx908+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   gcc_cv_as_gcn_sram_ecc_gfx908=no
   if test x$gcc_cv_as != x; then
-    $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"' > conftest.s
-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc -o conftest.o conftest.s >&5'
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err -o conftest.o conftest.s >&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; }
     then
-	gcc_cv_as_gcn_sram_ecc_gfx908=yes
+	grep "." conftest.err >&5 \
+       || gcc_cv_as_gcn_sram_ecc_gfx908=yes
     else
       echo "configure: failed program was" >&5
       cat conftest.s >&5
@@ -28881,6 +29106,7 @@  $as_echo "#define HAVE_GCN_SRAM_ECC_GFX908 1" >>confdefs.h
 
 fi
 
+    rm -f conftest.err
     ;;
   arm*)
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler for arm accepts context-specific architecture extensions" >&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index b49cb2288b20..344b2f586e8e 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5332,30 +5332,106 @@  esac
 
 case "$target" in
   amdgcn-* | gcn-*)
-    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for fiji],
+    # Test the LLVM assembler syntax dialect; they have made a number of
+    # changes between LLVM 12 & 13 without any backward compatibility.
+    gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v2/3 syntax],
+      gcc_cv_as_gcn_asm_v3_syntax,
+      [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack],
+      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"],,
+      [AC_DEFINE(HAVE_GCN_ASM_V3_SYNTAX, 1,
+       [Define if your assembler expects amdgcn_target gfx908+xnack syntax.])])
+    gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v4 syntax],
+      gcc_cv_as_gcn_asm_v4_syntax,
+      [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack],
+      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"],,
+      [AC_DEFINE(HAVE_GCN_ASM_V4_SYNTAX, 1,
+       [Define if your assembler expects amdgcn_target gfx908:xnack+ syntax.])])
+
+    # Some attribute names changed in the move to v4 ...
+    if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+	sramopt="+sram-ecc"
+	sramattr="+sram-ecc"
+	xnackattr="+xnack"
+    elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+	sramopt="+sramecc"
+	sramattr=":sramecc+"
+	xnackattr=":xnack+"
+    else
+	AC_MSG_ERROR([Unrecognised assembler version])
+    fi
+
+    # Test whether the LLVM assembler accepts -mattr=+xnack without any
+    # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+    # LLVM 12+ throws a warning for GPUs without support.
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for fiji],
+      gcc_cv_as_gcn_xnack_ecc_fiji,
+      [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_xnack_ecc_fiji=yes],
+      [AC_DEFINE(HAVE_GCN_XNACK_FIJI, 1,
+       [Define if your assembler allows -mattr=+xnack for fiji.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx900],
+      gcc_cv_as_gcn_xnack_ecc_gfx900,
+      [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_xnack_ecc_gfx900=yes],
+      [AC_DEFINE(HAVE_GCN_XNACK_GFX900, 1,
+       [Define if your assembler allows -mattr=+xnack for gfx900.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx906],
+      gcc_cv_as_gcn_xnack_ecc_gfx906,
+      [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_xnack_ecc_gfx906=yes],
+      [AC_DEFINE(HAVE_GCN_XNACK_GFX906, 1,
+       [Define if your assembler allows -mattr=+xnack for gfx906.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx908],
+      gcc_cv_as_gcn_xnack_ecc_gfx908,
+      [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_xnack_ecc_gfx908=yes],
+      [AC_DEFINE(HAVE_GCN_XNACK_GFX908, 1,
+       [Define if your assembler allows -mattr=+xnack for gfx908.])])
+    rm -f conftest.err
+
+    # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+    # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+    # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+    # for GPUs without support.
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for fiji],
       gcc_cv_as_gcn_sram_ecc_fiji,
-      [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=-xnack -mattr=+sram-ecc],
-      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx803+sram-ecc"],,
+      [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_sram_ecc_fiji=yes],
       [AC_DEFINE(HAVE_GCN_SRAM_ECC_FIJI, 1,
-       [Define if your assembler allows -mattr=+sram-ecc for fiji.])])
-    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx900],
+       [Define if your assembler allows -mattr=+sramecc for fiji.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx900],
       gcc_cv_as_gcn_sram_ecc_gfx900,
-      [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=-xnack -mattr=+sram-ecc],
-      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx900+sram-ecc"],,
+      [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_sram_ecc_gfx900=yes],
       [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX900, 1,
-       [Define if your assembler allows -mattr=+sram-ecc for gfx900.])])
-    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx906],
+       [Define if your assembler allows -mattr=+sramecc for gfx900.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx906],
       gcc_cv_as_gcn_sram_ecc_gfx906,
-      [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=-xnack -mattr=+sram-ecc],
-      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+sram-ecc"],,
+      [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_sram_ecc_gfx906=yes],
       [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX906, 1,
-       [Define if your assembler allows -mattr=+sram-ecc for gfx906.])])
-    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+sram-ecc for gfx908],
+       [Define if your assembler allows -mattr=+sramecc for gfx906.])])
+    rm -f conftest.err
+    gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx908],
       gcc_cv_as_gcn_sram_ecc_gfx908,
-      [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=-xnack -mattr=+sram-ecc],
-      [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908+sram-ecc"],,
+      [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err], [],
+      [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+       || gcc_cv_as_gcn_sram_ecc_gfx908=yes],
       [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX908, 1,
-       [Define if your assembler allows -mattr=+sram-ecc for gfx908.])])
+       [Define if your assembler allows -mattr=+sramecc for gfx908.])])
+    rm -f conftest.err
     ;;
   arm*)
     gcc_GAS_CHECK_FEATURE([assembler for arm accepts context-specific architecture extensions],