[GCN,11] Backport GCN with LLVM-MC 13 linker fixes to GCC 11

Message ID 48979236-ccd7-37a8-9900-d699eb834ff4@codesourcery.com
State Committed
Headers
Series [GCN,11] Backport GCN with LLVM-MC 13 linker fixes to GCC 11 |

Commit Message

Tobias Burnus Oct. 16, 2021, 8:41 p.m. UTC
  This patch is mostly motivated by distribution needs in general
and Debian/Ubuntu needs in particular – but I think it makes
sense for all GCC 11 users.

GCC's AMD GCN support uses LLVM's assembler and linker mc/lld
and thus requires compatibility with LLVM. On mainline, support
for LLVM 13 was added – and I like to see a backport to GCC 11.

In particular, I would like to "git cherry-pick -x' the following patches:

cfa1f8226f2 gcc/configure.ac: fix register issue for global_load assembler functions
aad32a00b7d amdgcn: Add -mxnack and -msram-ecc [PR 100208]
5c127c4cac3 amdgcn: Mark s_mulk_i32 as clobbering SCC
  (Outside of this series as it only picks a bug fix)
6ca03ca35a5 amdgcn: Support LLVM 13 assembler syntax
  (-> see remark below)
205dafb6ede amdgcn: Implement -msram-ecc=any
81c362c7c2b amdgcn: Fix assembler version incompatibility
f3d64372d77 amdgcn: fix up offload debug linking with LLVM 13

OK for GCC 11?

[I have build GCC x86-64 with amdgcn offloading enabled both
with LLVM 9 and with LLVM 13; libgomp passes fine with LLVM 9
but with the LLVM 13 build, I see an ICE in lld for some testcases,
which I have not debugged – but GCC itself builds and several
libgomp testcases do pass.]

Tobias

PS: I attached
* the full "git log --stat" for all those patches for references
* as the 4th one, "Support LLVM 13 assembler syntax", does not
   cleanly apply, I attached the full patch.

The reason that the latter does not apply is that mainline changed:
"configure: remove version argument from gcc_GAS_CHECK_FEATURE"
in https://gcc.gnu.org/g:e0b6d0b39c69372e4a66f44d218e0244bb549d83
which was fixed for GCN a bit later in commit
"configure: Adjust several assembler checks to remove an unused parm."
https://gcc.gnu.org/g:e5d9873fcb6f90d03b7534af53de39ec65d0cdc5

The only change is "," to ",," in configure.ac; 'configure' itself
was already fine.
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
commit 24a65327ed97e5d3bab565977051c3421a8ff763
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Wed Oct 13 11:53:42 2021 +0100

    amdgcn: fix up offload debug linking with LLVM 13
    
    Between LLVM 9 and LLVM 13 the attribute works differently in several ways,
    and this needs to be allowed for in GCC and mkoffload independently.
    
    This patch fixes up mkoffload when debug info is enabled, which is made more
    complicated because the configure tests checks whether the attribute option
    is accepted silently, but does not check if the assembler actually sets the
    ELF flags for that attribute, and mkoffload needs to mimick that behaviour
    exactly. The patch therefore removes some of the conditionals.
    
    gcc/ChangeLog:
    
            * config/gcn/gcn-hsa.h (S_FIJI): Set unconditionally.
            (S_900): Likewise.
            (S_906): Likewise.
            * config/gcn/gcn.c: Hard code SRAM ECC settings for old architectures.
            * config/gcn/mkoffload.c (ELFABIVERSION_AMDGPU_HSA): Rename to ...
            (ELFABIVERSION_AMDGPU_HSA_V3): ... this.
            (ELFABIVERSION_AMDGPU_HSA_V4): New.
            (SET_SRAM_ECC_UNSUPPORTED): New.
            (copy_early_debug_info): Create elf flags to match the other objects.
            (main): Just let the attribute flags pass through.
    
    (cherry picked from commit f3d64372d777d7d6068df8167b6751c289963e85)

 gcc/config/gcn/gcn-hsa.h   | 13 +------------
 gcc/config/gcn/gcn.c       |  6 ------
 gcc/config/gcn/mkoffload.c | 36 +++++++++++++++++++++++++-----------
 3 files changed, 26 insertions(+), 29 deletions(-)

commit b935972b7153b07000f852b7b1f7d10226928bff
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Thu Sep 30 17:50:33 2021 +0100

    amdgcn: Fix assembler version incompatibility
    
    This is another case of the global_load instruction format changing in LLVM
    (because they fixed a bug).  The configure test is already in place to detect
    what is needed.
    
    gcc/ChangeLog:
    
            * config/gcn/gcn-valu.md (gather<mode>_insn_2offsets<exec>): Apply
            HAVE_GCN_ASM_GLOBAL_LOAD_FIXED.
            (scatter<mode>_insn_2offsets<exec_scatter>): Likewise.
    
    (cherry picked from commit 81c362c7c2bccd72d798bf7ea6c74d4b1cc3931f)

 gcc/config/gcn/gcn-valu.md | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

commit 560abb74a462a3eb6f1320cac711c23e26d0f210
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Tue Sep 28 16:26:09 2021 +0100

    amdgcn: Implement -msram-ecc=any
    
    The option was already there, but just an alias for -msram-ecc=on.  Now that
    LLVM13 supports HSACOv4 and the new ELF flags I can implement the option
    properly.
    
    The "any" option is the default in order to ensure that library files work
    whichever way the user wants, which means we won't need multilibs to support
    the different SRAM ECC hardware configurations.
    
    gcc/ChangeLog:
    
            * config/gcn/gcn-hsa.h (SRAMOPT): Include the whole option string.
            Adjust for new -msram-ecc=any behaviour.
            (ASM_SPEC): Adjust -mxnack and -msram-ecc usage.
            * config/gcn/gcn.c (output_file_start): Implement -msram-ecc=any.
            * config/gcn/mkoffload.c (EF_AMDGPU_XNACK): Rename to ...
            (EF_AMDGPU_XNACK_V3): ... this.
            (EF_AMDGPU_SRAM_ECC): Rename to ...
            (EF_AMDGPU_SRAM_ECC_V3): ... this.
            (EF_AMDGPU_FEATURE_XNACK_V4): New.
            (EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4): New.
            (EF_AMDGPU_FEATURE_XNACK_ANY_V4): New.
            (EF_AMDGPU_FEATURE_XNACK_OFF_V4): New.
            (EF_AMDGPU_FEATURE_XNACK_ON_V4): New.
            (EF_AMDGPU_FEATURE_SRAMECC_V4): New.
            (EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4): New.
            (EF_AMDGPU_FEATURE_SRAMECC_ANY_V4): New.
            (EF_AMDGPU_FEATURE_SRAMECC_OFF_V4): New.
            (EF_AMDGPU_FEATURE_SRAMECC_ON_V4): New.
            (SET_XNACK_ON): New.
            (SET_XNACK_OFF): New.
            (TEST_XNACK): New.
            (SET_SRAM_ECC_ON): New.
            (SET_SRAM_ECC_ANY): New.
            (SET_SRAM_ECC_OFF): New.
            (TEST_SRAM_ECC_ANY): New.
            (TEST_SRAM_ECC_ON): New.
            (main): Implement HSACOv4 and -msram-ecc=any.
    
    (cherry picked from commit 205dafb6edeca08419f4a5976be79bf7c86fd9a1)

 gcc/config/gcn/gcn-hsa.h   |  14 +++---
 gcc/config/gcn/gcn.c       |   8 +++-
 gcc/config/gcn/mkoffload.c | 112 +++++++++++++++++++++++++++++++++------------
 3 files changed, 96 insertions(+), 38 deletions(-)

commit 9128d74d0f41668aa16ec4d0a430aa5d0f1b0b18
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Sat Oct 16 18:41:39 2021 +0200

    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.
    
    (cherry picked from commit 6ca03ca35a58ebf9792aa8a08adf00b6fd3e0015)

 gcc/config.in            |  44 +++++++-
 gcc/config/gcn/gcn-hsa.h |  63 +++++++++--
 gcc/config/gcn/gcn.c     |  44 ++++++--
 gcc/configure            | 266 +++++++++++++++++++++++++++++++++++++++++++----
 gcc/configure.ac         | 108 ++++++++++++++++---
 5 files changed, 467 insertions(+), 58 deletions(-)

commit 4a73a0b76afc77fb09af1d634617fe3191016f05
Author: Julian Brown <julian@codesourcery.com>
Date:   Mon Jun 28 06:58:52 2021 -0700

    amdgcn: Mark s_mulk_i32 as clobbering SCC
    
    The s_mulk_i32 instruction sets the SCC status register according to
    whether the multiplication overflows, but that is not currently modelled
    in the GCN backend.  AFAIK this is a latent bug and hasn't been noticed
    "in the wild", but it should be fixed.
    
    2021-06-29  Julian Brown  <julian@codesourcery.com>
    
    gcc/
            * config/gcn/gcn.md (mulsi3): Make s_mulk_i32 variant clobber SCC.
    
    (cherry picked from commit 5c127c4cac308429cba483a2ac4e175c2ab26165)

 gcc/config/gcn/gcn.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

commit ad727b093c5ca7891919f79a535e6c2754b55479
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Tue Jul 27 15:40:21 2021 +0100

    amdgcn: Fix attributes for LLVM-12 [PR 100208]
    
    This should work for a wider range of LLVM 12 variants now.
    More work required for LLVM 13 though.
    
    gcc/ChangeLog:
    
            PR target/100208
            * config.in: Regenerate.
            * config/gcn/gcn-hsa.h (A_FIJI): New define.
            (A_900): New define.
            (A_906): New define.
            (A_908): New define.
            (ASM_SPEC): Use A_FIJI, A_900, A_906 and A_908.
            * config/gcn/gcn.c (output_file_start): Adjust attributes according
            to the assembler capabilities.
            * config/gcn/mkoffload.c (main): Likewise.
            * configure: Regenerate.
            * configure.ac: Add tests for LLVM assembler attribute features.

 gcc/config.in              |  24 +++++++++
 gcc/config/gcn/gcn-hsa.h   |  25 ++++++++-
 gcc/config/gcn/gcn.c       |  31 +++++++++--
 gcc/config/gcn/mkoffload.c |   3 ++
 gcc/configure              | 129 +++++++++++++++++++++++++++++++++++++++++++++
 gcc/configure.ac           |  29 ++++++++++
 6 files changed, 235 insertions(+), 6 deletions(-)

commit a1a5f5b5f3f37afb5b80bba372eec2dfad617b1d
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Thu Jul 8 15:47:53 2021 +0100

    amdgcn: Add -mxnack and -msram-ecc [PR 100208]
    
    gcc/ChangeLog:
    
            PR target/100208
            * config/gcn/gcn-hsa.h (DRIVER_SELF_SPECS): New.
            (ASM_SPEC): Set -mattr for xnack and sram-ecc.
            * config/gcn/gcn-opts.h (enum sram_ecc_type): New.
            * config/gcn/gcn-valu.md: Add a warning comment.
            * config/gcn/gcn.c (gcn_option_override): Add "sorry" for -mxnack.
            (output_file_start): Add xnack and sram-ecc state to ".amdgcn_target".
            * config/gcn/gcn.md: Add a warning comment.
            * config/gcn/gcn.opt: Add -mxnack and -msram-ecc.
            * config/gcn/mkoffload.c (EF_AMDGPU_MACH_AMDGCN_GFX908): Remove
            SRAM-ECC flag.
            (EF_AMDGPU_XNACK): New.
            (EF_AMDGPU_SRAM_ECC): New.
            (elf_flags): New.
            (copy_early_debug_info): Use elf_flags.
            (main): Handle -mxnack and -msram-ecc options.
            * doc/invoke.texi: Document -mxnack and -msram-ecc.
    
    gcc/testsuite/ChangeLog:
    
            PR target/100208
            * gcc.target/gcn/sram-ecc-1.c: New test.
            * gcc.target/gcn/sram-ecc-2.c: New test.
            * gcc.target/gcn/sram-ecc-3.c: New test.
            * gcc.target/gcn/sram-ecc-4.c: New test.
            * gcc.target/gcn/sram-ecc-5.c: New test.
            * gcc.target/gcn/sram-ecc-6.c: New test.
            * gcc.target/gcn/sram-ecc-7.c: New test.
            * gcc.target/gcn/sram-ecc-8.c: New test.
    
    (cherry picked from commit aad32a00b7d2b64ae158b2b167768a9ae3e20f6e)

 gcc/config/gcn/gcn-hsa.h                  |  6 ++++
 gcc/config/gcn/gcn-opts.h                 |  7 ++++
 gcc/config/gcn/gcn-valu.md                |  2 ++
 gcc/config/gcn/gcn.c                      | 13 +++++--
 gcc/config/gcn/gcn.md                     |  1 +
 gcc/config/gcn/gcn.opt                    | 21 +++++++++++
 gcc/config/gcn/mkoffload.c                | 58 +++++++++++++++++++++++++++++--
 gcc/doc/invoke.texi                       | 17 +++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-1.c | 17 +++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-2.c | 17 +++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-3.c | 21 +++++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-4.c | 21 +++++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-5.c | 17 +++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-6.c | 17 +++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-7.c | 21 +++++++++++
 gcc/testsuite/gcc.target/gcn/sram-ecc-8.c | 21 +++++++++++
 16 files changed, 273 insertions(+), 4 deletions(-)

commit c6fab480c0ae59c1b9bbac8d1d04a20fff902028
Author: Marcel Vollweiler <marcel@codesourcery.com>
Date:   Fri Jun 18 04:50:36 2021 -0700

    gcc/configure.ac: fix register issue for global_load assembler functions
    
    gcc/ChangeLog:
    
            * config.in: Regenerate.
            * config/gcn/gcn.c (print_operand_address): Fix for global_load assembler
            functions.
            * configure: Regenerate.
            * configure.ac: Fix for global_load assembler functions.
    
    (cherry picked from commit cfa1f8226f275447015e2cb3fb0d876133e6509b)

 gcc/config.in        |  6 ++++++
 gcc/config/gcn/gcn.c | 17 +++++++++++++----
 gcc/configure        | 27 +++++++++++++++++++++++++++
 gcc/configure.ac     | 22 ++++++++++++++++++++++
 4 files changed, 68 insertions(+), 4 deletions(-)
  

Comments

Andrew Stubbs Oct. 18, 2021, 8:54 a.m. UTC | #1
This is fine by me.

As I said in my email on the 15th, LLVM 13 is still not considered safe 
to use. The ICE you encountered is a real problem that will affect real 
users.

I expect to work on a solution for that soon.

Andrew

On 16/10/2021 21:41, Tobias Burnus wrote:
> This patch is mostly motivated by distribution needs in general
> and Debian/Ubuntu needs in particular – but I think it makes
> sense for all GCC 11 users.
> 
> GCC's AMD GCN support uses LLVM's assembler and linker mc/lld
> and thus requires compatibility with LLVM. On mainline, support
> for LLVM 13 was added – and I like to see a backport to GCC 11.
> 
> In particular, I would like to "git cherry-pick -x' the following patches:
> 
> cfa1f8226f2 gcc/configure.ac: fix register issue for global_load 
> assembler functions
> aad32a00b7d amdgcn: Add -mxnack and -msram-ecc [PR 100208]
> 5c127c4cac3 amdgcn: Mark s_mulk_i32 as clobbering SCC
>   (Outside of this series as it only picks a bug fix)
> 6ca03ca35a5 amdgcn: Support LLVM 13 assembler syntax
>   (-> see remark below)
> 205dafb6ede amdgcn: Implement -msram-ecc=any
> 81c362c7c2b amdgcn: Fix assembler version incompatibility
> f3d64372d77 amdgcn: fix up offload debug linking with LLVM 13
> 
> OK for GCC 11?
> 
> [I have build GCC x86-64 with amdgcn offloading enabled both
> with LLVM 9 and with LLVM 13; libgomp passes fine with LLVM 9
> but with the LLVM 13 build, I see an ICE in lld for some testcases,
> which I have not debugged – but GCC itself builds and several
> libgomp testcases do pass.]
> 
> Tobias
> 
> PS: I attached
> * the full "git log --stat" for all those patches for references
> * as the 4th one, "Support LLVM 13 assembler syntax", does not
>    cleanly apply, I attached the full patch.
> 
> The reason that the latter does not apply is that mainline changed:
> "configure: remove version argument from gcc_GAS_CHECK_FEATURE"
> in https://gcc.gnu.org/g:e0b6d0b39c69372e4a66f44d218e0244bb549d83
> which was fixed for GCN a bit later in commit
> "configure: Adjust several assembler checks to remove an unused parm."
> https://gcc.gnu.org/g:e5d9873fcb6f90d03b7534af53de39ec65d0cdc5
> 
> The only change is "," to ",," in configure.ac; 'configure' itself
> was already fine.
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 
> 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: 
> Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; 
> Registergericht München, HRB 106955
  

Patch

From 9128d74d0f41668aa16ec4d0a430aa5d0f1b0b18 Mon Sep 17 00:00:00 2001
From: Andrew Stubbs <ams@codesourcery.com>
Date: Sat, 16 Oct 2021 18:41:39 +0200
Subject: [PATCH 5/8] 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.

(cherry picked from commit 6ca03ca35a58ebf9792aa8a08adf00b6fd3e0015)
---
 gcc/config.in            |  44 ++++++-
 gcc/config/gcn/gcn-hsa.h |  63 ++++++++--
 gcc/config/gcn/gcn.c     |  44 +++++--
 gcc/configure            | 266 ++++++++++++++++++++++++++++++++++++---
 gcc/configure.ac         | 108 +++++++++++++---
 5 files changed, 467 insertions(+), 58 deletions(-)

diff --git a/gcc/config.in b/gcc/config.in
index 963f02f68db..2de5a463315 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1444,30 +1444,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 fc99c8db752..60fd40a10b7 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 87fa5064d38..10c1d8a1771 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -5034,42 +5034,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 aa9a5af2aaa..bf44b01e3fb 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28920,22 +28920,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
@@ -28951,22 +29170,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
@@ -28982,22 +29203,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
@@ -29013,22 +29236,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
@@ -29044,6 +29269,7 @@  $as_echo "#define HAVE_GCN_SRAM_ECC_GFX908 1" >>confdefs.h
 
 fi
 
+    rm -f conftest.err
     ;;
 esac
 
diff --git a/gcc/configure.ac b/gcc/configure.ac
index dcc62ba4c11..1d3d1cfed34 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5372,30 +5372,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
     ;;
 esac
 
-- 
2.25.1