I'm going to commit this soon, but I'd appreciate if anybody could have
a quick look and let me know if anything is obviously broken or doing
things the hard way, or something. Thanks!

Andrew

------------------

Almost all device-specific settings are now centralised into gcn-devices.def
for the compiler, mkoffload, and libgomp.  No longer will we have to touch 10
files in multiple places just to add another device without any exotic
features.  (New ISAs and devices with incompatible metadata will continue to
need a bit more.)

In order to remove the device-specific conditionals in the code a new value
HSACO_ATTR_UNSUPPORTED has been added, indicating that the assembler will
reject any setting of that option.

This incorporates some of Tobias's patch from March 2024.

Co-Authored-By: Tobias Burnus <tbur...@baylibre.com>

gcc/ChangeLog:

        * config.gcc (amdgcn): Add gcn-device-macros.h to tm_file.
        Add gcn-tables.opt to extra_options.
        * config/gcn/gcn-hsa.h (NO_XNACK): Delete.
        (NO_SRAM_ECC): Delete.
        (SRAMOPT): Move definition to generated file gcn-device-macros.h.
        (XNACKOPT): Likewise.
        (ASM_SPEC): Redefine using generated values from gcn-device-macros.h.
        * config/gcn/gcn-opts.h
        (enum processor_type): Generate from gcn-devices.def.
        (TARGET_VEGA10): Delete.
        (TARGET_VEGA20): Delete.
        (TARGET_GFX908): Delete.
        (TARGET_GFX90a): Delete.
        (TARGET_GFX90c): Delete.
        (TARGET_GFX1030): Delete.
        (TARGET_GFX1036): Delete.
        (TARGET_GFX1100): Delete.
        (TARGET_GFX1103): Delete.
        (TARGET_XNACK): Redefine to allow for HSACO_ATTR_UNSUPPORTED.
        (enum hsaco_attr_type): Add HSACO_ATTR_UNSUPPORTED.
        (TARGET_TGSPLIT): New define.
        * config/gcn/gcn.cc (gcn_devices): New constant table.
        (gcn_option_override): Rework to use gcn_devices table.
        (gcn_omp_device_kind_arch_isa): Likewise.
        (output_file_start): Likewise.
        (gcn_hsa_declare_function_name): Rework using TARGET_* macros.
        * config/gcn/gcn.h (gcn_devices): Declare struct and table.
        (TARGET_CPU_CPP_BUILTINS): Rework using gcn_devices.
        * config/gcn/gcn.opt: Move enum data to generated file gcn-tables.opt.
        Use new names for the default values.
        * config/gcn/mkoffload.cc (EF_AMDGPU_MACH_AMDGCN_GFX900): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX906): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX908): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX90a): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX90c): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX1030): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX1036): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX1100): Delete.
        (EF_AMDGPU_MACH_AMDGCN_GFX1103): Delete.
        (enum elf_arch_code): Define using gcn-devices.def.
        (get_arch): Rework using gcn-devices.def.
        (main): Rework using gcn-devices.def
        * config/gcn/t-gcn-hsa (gcn-tables.opt): Generate file.
        (gcn-device-macros.h): Generate file.
        * config/gcn/t-omp-device: Generate isa list from gcn-devices.def.
        * config/gcn/gcn-devices.def: New file.
        * config/gcn/gcn-tables.opt: New file.
        * config/gcn/gcn-tables.opt.urls: New file.
        * config/gcn/gen-gcn-device-macros.awk: New file.
        * config/gcn/gen-opt-tables.awk: New file.

libgomp/ChangeLog:

        * plugin/plugin-gcn.c (EF_AMDGPU_MACH): Generate from gcn-devices.def.
        (gcn_gfx803_s): Delete.
        (gcn_gfx900_s): Delete.
        (gcn_gfx906_s): Delete.
        (gcn_gfx908_s): Delete.
        (gcn_gfx90a_s): Delete.
        (gcn_gfx90c_s): Delete.
        (gcn_gfx1030_s): Delete.
        (gcn_gfx1036_s): Delete.
        (gcn_gfx1100_s): Delete.
        (gcn_gfx1103_s): Delete.
        (gcn_isa_name_len): Delete.
        (isa_hsa_name): Rename ...
        (isa_name): ... to this, and rework using gcn-devices.def.
        (isa_gcc_name): Delete.
        (isa_code): Rework using gcn-devices.def.
        (max_isa_vgprs): Rework using gcn-devices.def.
        (isa_matches_agent): Update isa_name usage.
        (GOMP_OFFLOAD_init_device): Improve diagnostic using the name.
---
 gcc/config.gcc                           |   3 +-
 gcc/config/gcn/gcn-devices.def           | 143 +++++++++++++++++++++++
 gcc/config/gcn/gcn-hsa.h                 |  23 +---
 gcc/config/gcn/gcn-opts.h                |  31 ++---
 gcc/config/gcn/gcn-tables.opt            |  52 +++++++++
 gcc/config/gcn/gcn-tables.opt.urls       |   2 +
 gcc/config/gcn/gcn.cc                    | 132 +++++----------------
 gcc/config/gcn/gcn.h                     |  37 +++---
 gcc/config/gcn/gcn.opt                   |  37 +-----
 gcc/config/gcn/gen-gcn-device-macros.awk | 110 +++++++++++++++++
 gcc/config/gcn/gen-opt-tables.awk        |  55 +++++++++
 gcc/config/gcn/mkoffload.cc              | 114 +++++++-----------
 gcc/config/gcn/t-gcn-hsa                 |   7 ++
 gcc/config/gcn/t-omp-device              |   4 +-
 libgomp/plugin/plugin-gcn.c              | 142 +++++-----------------
 15 files changed, 507 insertions(+), 385 deletions(-)
 create mode 100644 gcc/config/gcn/gcn-devices.def
 create mode 100644 gcc/config/gcn/gcn-tables.opt
 create mode 100644 gcc/config/gcn/gcn-tables.opt.urls
 create mode 100644 gcc/config/gcn/gen-gcn-device-macros.awk
 create mode 100644 gcc/config/gcn/gen-opt-tables.awk

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 71ac3badafd..fd848228722 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1806,11 +1806,12 @@ ft32-*-elf)
        tmake_file="${tmake_file} ft32/t-ft32"
        ;;
 amdgcn-*-amdhsa)
-       tm_file="elfos.h gcn/gcn-hsa.h gcn/gcn.h newlib-stdint.h"
+       tm_file="elfos.h gcn/gcn-hsa.h gcn/gcn.h newlib-stdint.h 
./gcn-device-macros.h"
        tmake_file="gcn/t-gcn-hsa"
        native_system_header_dir=/include
        extra_modes=gcn/gcn-modes.def
        extra_objs="${extra_objs} gcn-tree.o"
+       extra_options="${extra_options} gcn/gcn-tables.opt"
        case "$host" in
        x86_64*-*-linux-gnu )
                if test "$ac_cv_search_dlopen" != no; then
diff --git a/gcc/config/gcn/gcn-devices.def b/gcc/config/gcn/gcn-devices.def
new file mode 100644
index 00000000000..f2dbe18b6ae
--- /dev/null
+++ b/gcc/config/gcn/gcn-devices.def
@@ -0,0 +1,143 @@
+/* Copyright (C) 2024 Free Software Foundation, Inc.
+
+   This file is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at your option)
+   any later version.
+
+   This file is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* GCN Device Configurations.
+
+   This file contains all the device-specific information needed for both
+   GCC and Libgomp.  Please respect the formatting and field comments as
+   this file is read by Awk scripts in addition to the C++ preprocessor.
+
+   To add a new device:
+    1. Add a new GCN_DEVICE instance below.
+    2. Add the name to the list in config.gcc.
+    3. Allow gcn-tables.opt to regenerate.
+    4. Implement target-specific metadata and new features using
+       PROCESSOR_<NAME> (or a new ISA feature flag).
+    5. Consider adding to the set of device-specific tests in the libgomp
+       testsuite.
+
+    New ISA variants are defined in gcn-opts.h.  Please use the feature macros
+    in any conditionals, rather than depending on specific devices or ISAs
+    directly.
+
+    GCN_DEVICE field descriptions:
+      0  "name"  (text, external)
+        Lower case device name used in -march=name, diagnostics,
+       assembler directives, etc.
+      1  "NAME"  (text, external)
+        Upper case device name used in macros.
+      2  "ELF"   (hex integer, external)
+        Magic number used assigned to this device for use in elf_flags.
+      3  "ISA"   (enum gcn_isa, internal)
+        ISA variant for instruction selection, etc.
+      4  "XNACK default"   (enum hsaco_attr_type, internal)
+        Default value for the -mattr=[-+]xnack setting.  May need to correspond
+       to the assembler expectations for this device.
+      5  "SRAM_ECC default"   (enum hsaco_attr_type, internal)
+        Default value for the -mattr=[-+]sram-ecc setting.  Only really used
+       to ensure that the binary is in a known state mkoffload can match.
+      6  "WAVE64 mode"    (enum hsaco_attr_type, internal)
+        Set "on" for devices where this needs to be configured, "unsupported"
+       otherwise (meaning no special treatment needed).  GCC does not support
+       wave32 mode.
+      7  "CU mode"    (enum hsaco_attr_type, internal)
+        Set "on" for devices that have this feature, "unsupported" otherwise
+       (meaning that CU mode is not optional on the device).  GCC does not
+       support CU mode off.
+      8  "Max ISA VGPRs"   (integer, internal)
+        Define how many registers there are in the VGPR register file, for the
+       purposes of calculating maximum occupancy.  Some devices have AVGPRs
+       in the same register file, some have more registers than are
+       addressable from a single kernel.  Used by libgomp's plugin-gcn.c.
+
+    Fields marked "external", above, have values defined elsewhere (HSA, ROCM,
+    LLVM, ELF, etc.) and must have matching definitions here.  Fields marked
+    "internal" are defined and used only in GCC (although some may have
+    user-visible effects) and may be refactored as needed.  */
+
+GCN_DEVICE(gfx900, GFX900, 0x2c, ISA_GCN5,
+          /* XNACK default */ HSACO_ATTR_OFF,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_UNSUPPORTED,
+          /* CU mode */ HSACO_ATTR_UNSUPPORTED,
+           /* Max ISA VGPRs */ 256
+          )
+
+GCN_DEVICE(gfx906, GFX906, 0x2f, ISA_GCN5,
+          /* XNACK default */ HSACO_ATTR_OFF,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_UNSUPPORTED,
+          /* CU mode */ HSACO_ATTR_UNSUPPORTED,
+           /* Max ISA VGPRs */ 256
+          )
+
+GCN_DEVICE(gfx908, GFX908, 0x30, ISA_CDNA1,
+          /* XNACK default */ HSACO_ATTR_OFF,
+          /* SRAM_ECC default */ HSACO_ATTR_ANY,
+          /* WAVE64 mode */ HSACO_ATTR_UNSUPPORTED,
+          /* CU mode */ HSACO_ATTR_UNSUPPORTED,
+           /* Max ISA VGPRs */ 256
+          )
+
+GCN_DEVICE(gfx90a, GFX90A, 0x3f, ISA_CDNA2,
+          /* XNACK default */ HSACO_ATTR_ANY,
+          /* SRAM_ECC default */ HSACO_ATTR_ANY,
+          /* WAVE64 mode */ HSACO_ATTR_UNSUPPORTED,
+          /* CU mode */ HSACO_ATTR_UNSUPPORTED,
+           /* Max ISA VGPRs */ 512
+          )
+
+GCN_DEVICE(gfx90c, GFX90C, 0x32, ISA_GCN5,
+          /* XNACK default */ HSACO_ATTR_ANY,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_UNSUPPORTED,
+          /* CU mode */ HSACO_ATTR_UNSUPPORTED,
+           /* Max ISA VGPRs */ 256
+          )
+
+GCN_DEVICE(gfx1030, GFX1030, 0x36, ISA_RDNA2,
+          /* XNACK default */ HSACO_ATTR_UNSUPPORTED,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_ON,
+          /* CU mode */ HSACO_ATTR_ON,
+           /* Max ISA VGPRs */ 512 /* 512 SIMD32 = 256 wavefrontsize64.  */
+          )
+
+GCN_DEVICE(gfx1036, GFX1036, 0x45, ISA_RDNA2,
+          /* XNACK default */ HSACO_ATTR_UNSUPPORTED,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_ON,
+          /* CU mode */ HSACO_ATTR_ON,
+           /* Max ISA VGPRs */ 512 /* 512 SIMD32 = 256 wavefrontsize64.  */
+          )
+
+GCN_DEVICE(gfx1100, GFX1100, 0x41, ISA_RDNA3,
+          /* XNACK default */ HSACO_ATTR_UNSUPPORTED,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_ON,
+          /* CU mode */ HSACO_ATTR_ON,
+           /* Max ISA VGPRs */ 1536 /* 1536 SIMD32 = 768 wavefrontsize64.  */
+          )
+
+GCN_DEVICE(gfx1103, GFX1103, 0x44, ISA_RDNA3,
+          /* XNACK default */ HSACO_ATTR_UNSUPPORTED,
+          /* SRAM_ECC default */ HSACO_ATTR_UNSUPPORTED,
+          /* WAVE64 mode */ HSACO_ATTR_ON,
+          /* CU mode */ HSACO_ATTR_ON,
+           /* Max ISA VGPRs */ 1536
+          )
+
+#undef GCN_DEVICE
diff --git a/gcc/config/gcn/gcn-hsa.h b/gcc/config/gcn/gcn-hsa.h
index 7a1bfad49ca..7665e4f3158 100644
--- a/gcc/config/gcn/gcn-hsa.h
+++ b/gcc/config/gcn/gcn-hsa.h
@@ -82,29 +82,16 @@ extern unsigned int gcn_local_sym_hash (const char *name);
    GCC supports LLVM >= 13.0.1 and only LLVM >= 14 supports version 5.  */
 #define ABI_VERSION_SPEC "--amdhsa-code-object-version=4"
 
-/* Note that the XNACK and SRAM-ECC settings must match those in mkoffload.cc
-   as the latter creates new ELF object file when debugging is enabled and
-   the ELF flags (e_flags) of that generated file must be identical to those
-   generated by the compiler.  */
-
-#define NO_XNACK 
"march=gfx1030:;march=gfx1036:;march=gfx1100:;march=gfx1103:;" \
-    /* These match the defaults set in gcn.cc.  */ \
-    
"!mxnack*|mxnack=default:%{march=gfx900|march=gfx906|march=gfx908:-mattr=-xnack};"
-#define NO_SRAM_ECC "!march=*:;march=gfx900:;march=gfx906:;march=gfx90c:;"
-
-/* In HSACOv4 no attribute setting means the binary supports "any" hardware
-   configuration.  The name of the attribute also changed.  */
-#define SRAMOPT "msram-ecc=on:-mattr=+sramecc;msram-ecc=off:-mattr=-sramecc"
-#define XNACKOPT "mxnack=on:-mattr=+xnack;mxnack=off:-mattr=-xnack"
+#include "gcn-device-macros.h"
 
 /* Use LLVM assembler and linker options.  */
 #define ASM_SPEC  "-triple=amdgcn--amdhsa "  \
                  "%{march=*:-mcpu=%*} " \
                  ABI_VERSION_SPEC " " \
-                 "%{" NO_XNACK XNACKOPT "} " \
-                 "%{" NO_SRAM_ECC SRAMOPT "} " \
-                 
"%{march=gfx1030|march=gfx1036|march=gfx1100|march=gfx1103:-mattr=+wavefrontsize64}
 " \
-                 
"%{march=gfx1030|march=gfx1036|march=gfx1100|march=gfx1103:-mattr=+cumode} " \
+                 XNACKOPT \
+                 SRAMOPT \
+                 WAVE64OPT \
+                 CUMODEOPT \
                  "-filetype=obj"
 #define LINK_SPEC "--pie --export-dynamic"
 #define LIB_SPEC  "-lc"
diff --git a/gcc/config/gcn/gcn-opts.h b/gcc/config/gcn/gcn-opts.h
index 76f50ab9364..0026becdedc 100644
--- a/gcc/config/gcn/gcn-opts.h
+++ b/gcc/config/gcn/gcn-opts.h
@@ -17,30 +17,15 @@
 #ifndef GCN_OPTS_H
 #define GCN_OPTS_H
 
-/* Which processor to generate code or schedule for.  */
+/* Create constants for PROCESSOR_GFX???.  */
 enum processor_type
 {
-  PROCESSOR_VEGA10,  // gfx900
-  PROCESSOR_VEGA20,  // gfx906
-  PROCESSOR_GFX908,
-  PROCESSOR_GFX90a,
-  PROCESSOR_GFX90c,
-  PROCESSOR_GFX1030,
-  PROCESSOR_GFX1036,
-  PROCESSOR_GFX1100,
-  PROCESSOR_GFX1103
+#define GCN_DEVICE(name, NAME, ...) \
+  PROCESSOR_ ## NAME,
+#include "gcn-devices.def"
+  PROCESSOR_COUNT
 };
 
-#define TARGET_VEGA10 (gcn_arch == PROCESSOR_VEGA10)
-#define TARGET_VEGA20 (gcn_arch == PROCESSOR_VEGA20)
-#define TARGET_GFX908 (gcn_arch == PROCESSOR_GFX908)
-#define TARGET_GFX90a (gcn_arch == PROCESSOR_GFX90a)
-#define TARGET_GFX90c (gcn_arch == PROCESSOR_GFX90c)
-#define TARGET_GFX1030 (gcn_arch == PROCESSOR_GFX1030)
-#define TARGET_GFX1036 (gcn_arch == PROCESSOR_GFX1036)
-#define TARGET_GFX1100 (gcn_arch == PROCESSOR_GFX1100)
-#define TARGET_GFX1103 (gcn_arch == PROCESSOR_GFX1103)
-
 /* Set in gcn_option_override.  */
 extern enum gcn_isa {
   ISA_UNKNOWN,
@@ -63,10 +48,12 @@ extern enum gcn_isa {
 
 #define TARGET_PACKED_WORK_ITEMS (TARGET_CDNA2_PLUS || TARGET_RDNA3)
 
-#define TARGET_XNACK (flag_xnack != HSACO_ATTR_OFF)
+#define TARGET_XNACK (flag_xnack == HSACO_ATTR_ON \
+                     || flag_xnack == HSACO_ATTR_ANY)
 
 enum hsaco_attr_type
 {
+  HSACO_ATTR_UNSUPPORTED,
   HSACO_ATTR_OFF,
   HSACO_ATTR_ON,
   HSACO_ATTR_ANY,
@@ -106,5 +93,7 @@ enum hsaco_attr_type
 /* Different devices uses different cache control instructions.  */
 #define TARGET_WBINVL1_CACHE (!TARGET_RDNA2_PLUS)
 #define TARGET_GLn_CACHE TARGET_RDNA2_PLUS
+/* Some devices have TGSPLIT, which needs at least metadata.  */
+#define TARGET_TGSPLIT TARGET_CDNA2_PLUS
 
 #endif
diff --git a/gcc/config/gcn/gcn-tables.opt b/gcc/config/gcn/gcn-tables.opt
new file mode 100644
index 00000000000..140316f7250
--- /dev/null
+++ b/gcc/config/gcn/gcn-tables.opt
@@ -0,0 +1,52 @@
+; -*- buffer-read-only: t -*-
+; Generated automatically by gen-opt-tables.awk from gcn-devices.def.
+; Do not edit.
+
+; Copyright (C) 2024 Free Software Foundation, Inc.
+
+; This file is part of GCC.
+
+; GCC is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as
+; published by the Free Software Foundation; either version 3,
+; or (at your option) any later version.
+
+; GCC is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+
+; You should have received a copy of the GNU General Public
+; License along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+Enum
+Name(gpu_type) Type(enum processor_type)
+GCN GPU type to use:
+
+EnumValue
+Enum(gpu_type) String(gfx900) Value(PROCESSOR_GFX900)
+
+EnumValue
+Enum(gpu_type) String(gfx906) Value(PROCESSOR_GFX906)
+
+EnumValue
+Enum(gpu_type) String(gfx908) Value(PROCESSOR_GFX908)
+
+EnumValue
+Enum(gpu_type) String(gfx90a) Value(PROCESSOR_GFX90A)
+
+EnumValue
+Enum(gpu_type) String(gfx90c) Value(PROCESSOR_GFX90C)
+
+EnumValue
+Enum(gpu_type) String(gfx1030) Value(PROCESSOR_GFX1030)
+
+EnumValue
+Enum(gpu_type) String(gfx1036) Value(PROCESSOR_GFX1036)
+
+EnumValue
+Enum(gpu_type) String(gfx1100) Value(PROCESSOR_GFX1100)
+
+EnumValue
+Enum(gpu_type) String(gfx1103) Value(PROCESSOR_GFX1103)
diff --git a/gcc/config/gcn/gcn-tables.opt.urls 
b/gcc/config/gcn/gcn-tables.opt.urls
new file mode 100644
index 00000000000..b13ed90ebef
--- /dev/null
+++ b/gcc/config/gcn/gcn-tables.opt.urls
@@ -0,0 +1,2 @@
+; Autogenerated by regenerate-opt-urls.py from gcc/config/gcn/gcn-tables.opt 
and generated HTML
+
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index db48a6776b1..3dc6acfa950 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -98,6 +98,14 @@ static hash_map<tree, int> lds_allocs;
 #define MAX_NORMAL_VGPR_COUNT  24
 #define MAX_NORMAL_AVGPR_COUNT 24
 
+/* Import all the data from gcn-devices.def.
+   The PROCESSOR_GFXnnn should be indices for this table.  */
+const struct gcn_device_def gcn_devices[] = {
+#define GCN_DEVICE(name, NAME, ELF, ISA, XNACK, SRAMECC, WAVE64, CU, VGPRS) \
+    {PROCESSOR_ ## NAME, #name, #NAME, ISA, XNACK, SRAMECC, WAVE64, CU, VGPRS},
+#include "gcn-devices.def"
+};
+
 /* }}}  */
 /* {{{ Initialization and options.  */
 
@@ -133,17 +141,8 @@ gcn_option_override (void)
   if (!flag_pic)
     flag_pic = flag_pie;
 
-  gcn_isa = (gcn_arch == PROCESSOR_VEGA10 ? ISA_GCN5
-      : gcn_arch == PROCESSOR_VEGA20 ? ISA_GCN5
-      : gcn_arch == PROCESSOR_GFX908 ? ISA_CDNA1
-      : gcn_arch == PROCESSOR_GFX90a ? ISA_CDNA2
-      : gcn_arch == PROCESSOR_GFX90c ? ISA_GCN5
-      : gcn_arch == PROCESSOR_GFX1030 ? ISA_RDNA2
-      : gcn_arch == PROCESSOR_GFX1036 ? ISA_RDNA2
-      : gcn_arch == PROCESSOR_GFX1100 ? ISA_RDNA3
-      : gcn_arch == PROCESSOR_GFX1103 ? ISA_RDNA3
-      : ISA_UNKNOWN);
-  gcc_assert (gcn_isa != ISA_UNKNOWN);
+  gcc_assert (gcn_arch >= 0 && gcn_arch < PROCESSOR_COUNT);
+  gcn_isa = gcn_devices[gcn_arch].isa;
 
   /* Reserve 1Kb (somewhat arbitrarily) of LDS space for reduction results and
      worker broadcasts.  */
@@ -164,20 +163,13 @@ gcn_option_override (void)
     }
 
   /* gfx1030 and gfx1100 do not support XNACK.  */
-  if (gcn_arch == PROCESSOR_GFX1030
-      || gcn_arch == PROCESSOR_GFX1036
-      || gcn_arch == PROCESSOR_GFX1100
-      || gcn_arch == PROCESSOR_GFX1103)
+  if (gcn_devices[gcn_arch].xnack_default == HSACO_ATTR_UNSUPPORTED)
     {
       if (flag_xnack == HSACO_ATTR_ON)
        error ("%<-mxnack=on%> is incompatible with %<-march=%s%>",
-              (gcn_arch == PROCESSOR_GFX1030 ? "gfx1030"
-               : gcn_arch == PROCESSOR_GFX1036 ? "gfx1036"
-               : gcn_arch == PROCESSOR_GFX1100 ? "gfx1100"
-               : gcn_arch == PROCESSOR_GFX1103 ? "gfx1103"
-               : NULL));
-      /* Allow HSACO_ATTR_ANY silently because that's the default.  */
-      flag_xnack = HSACO_ATTR_OFF;
+              gcn_devices[gcn_arch].name);
+      /* Allow HSACO_ATTR_ANY silently.  */
+      flag_xnack = HSACO_ATTR_UNSUPPORTED;
     }
 
   /* There's no need for XNACK on devices without USM, and there are register
@@ -185,23 +177,10 @@ gcn_option_override (void)
      available.
      FIXME: can the regalloc mean the default can be really "any"?  */
   if (flag_xnack == HSACO_ATTR_DEFAULT)
-    switch (gcn_arch)
-      {
-      case PROCESSOR_VEGA10:
-      case PROCESSOR_VEGA20:
-      case PROCESSOR_GFX908:
-       flag_xnack = HSACO_ATTR_OFF;
-       break;
-      case PROCESSOR_GFX90a:
-      case PROCESSOR_GFX90c:
-       flag_xnack = HSACO_ATTR_ANY;
-       break;
-      default:
-       gcc_unreachable ();
-      }
+    flag_xnack = gcn_devices[gcn_arch].xnack_default;
 
   if (flag_sram_ecc == HSACO_ATTR_DEFAULT)
-    flag_sram_ecc = HSACO_ATTR_ANY;
+    flag_sram_ecc = gcn_devices[gcn_arch].sramecc_default;
 }
 
 /* }}}  */
@@ -3030,25 +3009,7 @@ gcn_omp_device_kind_arch_isa (enum 
omp_device_kind_arch_isa trait,
     case omp_device_arch:
       return strcmp (name, "amdgcn") == 0 || strcmp (name, "gcn") == 0;
     case omp_device_isa:
-      if (strcmp (name, "gfx900") == 0)
-       return gcn_arch == PROCESSOR_VEGA10;
-      if (strcmp (name, "gfx906") == 0)
-       return gcn_arch == PROCESSOR_VEGA20;
-      if (strcmp (name, "gfx908") == 0)
-       return gcn_arch == PROCESSOR_GFX908;
-      if (strcmp (name, "gfx90a") == 0)
-       return gcn_arch == PROCESSOR_GFX90a;
-      if (strcmp (name, "gfx90c") == 0)
-       return gcn_arch == PROCESSOR_GFX90c;
-      if (strcmp (name, "gfx1030") == 0)
-       return gcn_arch == PROCESSOR_GFX1030;
-      if (strcmp (name, "gfx1036") == 0)
-       return gcn_arch == PROCESSOR_GFX1036;
-      if (strcmp (name, "gfx1100") == 0)
-       return gcn_arch == PROCESSOR_GFX1100;
-      if (strcmp (name, "gfx1103") == 0)
-       return gcn_arch == PROCESSOR_GFX1103;
-      return 0;
+      return strcmp (name, gcn_devices[gcn_arch].name) == 0;
     default:
       gcc_unreachable ();
     }
@@ -6545,54 +6506,11 @@ output_file_start (void)
      configuration.  */
   const char *xnack = (flag_xnack == HSACO_ATTR_ON ? ":xnack+"
                       : flag_xnack == HSACO_ATTR_OFF ? ":xnack-"
-                      : "");
+                      : "" /* Unsupported or "any".  */);
   const char *sram_ecc = (flag_sram_ecc == HSACO_ATTR_ON ? ":sramecc+"
                          : flag_sram_ecc == HSACO_ATTR_OFF ? ":sramecc-"
-                         : "");
-
-  const char *cpu;
-  switch (gcn_arch)
-    {
-    case PROCESSOR_VEGA10:
-      cpu = "gfx900";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_VEGA20:
-      cpu = "gfx906";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_GFX908:
-      cpu = "gfx908";
-      break;
-    case PROCESSOR_GFX90a:
-      cpu = "gfx90a";
-      break;
-    case PROCESSOR_GFX90c:
-      cpu = "gfx90c";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_GFX1030:
-      cpu = "gfx1030";
-      xnack = "";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_GFX1036:
-      cpu = "gfx1036";
-      xnack = "";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_GFX1100:
-      cpu = "gfx1100";
-      xnack = "";
-      sram_ecc = "";
-      break;
-    case PROCESSOR_GFX1103:
-      cpu = "gfx1103";
-      xnack = "";
-      sram_ecc = "";
-      break;
-    default: gcc_unreachable ();
-    }
+                         : "" /* Unsupported or "any".  */);
+  const char *cpu = gcn_devices[gcn_arch].name;
 
   fprintf(asm_out_file, "\t.amdgcn_target \"amdgcn-unknown-amdhsa--%s%s%s\"\n",
          cpu, sram_ecc, xnack);
@@ -6739,11 +6657,13 @@ gcn_hsa_declare_function_name (FILE *file, const char 
*name,
   if (!TARGET_ARCHITECTED_FLAT_SCRATCH)
     fprintf (file,
           "\t  .amdhsa_reserve_flat_scratch\t0\n");
-  if (gcn_arch == PROCESSOR_GFX90a)
+  if (TARGET_AVGPR_COMBINED)
     fprintf (file,
-            "\t  .amdhsa_accum_offset\t%i\n"
-            "\t  .amdhsa_tg_split\t0\n",
+            "\t  .amdhsa_accum_offset\t%i\n",
             vgpr); /* The AGPRs come after the VGPRs.  */
+  if (TARGET_TGSPLIT)
+    fprintf (file,
+            "\t  .amdhsa_tg_split\t0\n");
   fputs ("\t.end_amdhsa_kernel\n", file);
 
 #if 1
@@ -6774,7 +6694,7 @@ gcn_hsa_declare_function_name (FILE *file, const char 
*name,
           (TARGET_WAVE64_COMPAT
            ? " ; wavefrontsize64 counts double on SIMD32"
            : ""));
-  if (gcn_arch == PROCESSOR_GFX90a || gcn_arch == PROCESSOR_GFX908)
+  if (TARGET_AVGPRS)
     fprintf (file, "            .agpr_count: %i\n", avgpr);
   fputs ("        .end_amdgpu_metadata\n", file);
 #endif
diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
index faefe68cdfa..ff508406ff1 100644
--- a/gcc/config/gcn/gcn.h
+++ b/gcc/config/gcn/gcn.h
@@ -16,6 +16,20 @@
 
 #include "config/gcn/gcn-opts.h"
 
+extern const struct gcn_device_def {
+  enum processor_type id;
+  const char *name;
+  const char *NAME;
+  enum gcn_isa isa;
+
+  /* Features.  */
+  enum hsaco_attr_type xnack_default;
+  enum hsaco_attr_type sramecc_default;
+  enum hsaco_attr_type wave64_default;
+  enum hsaco_attr_type cumode_default;
+  int max_isa_vgprs;
+} gcn_devices[];
+
 #define TARGET_CPU_CPP_BUILTINS()                                              
\
   do                                                                           
\
     {                                                                          
\
@@ -32,26 +46,9 @@
        builtin_define ("__RDNA3__");                                          \
       else                                                                     
\
        gcc_unreachable ();                                                    \
-      if (TARGET_VEGA10)                                                       
\
-       builtin_define ("__gfx900__");                                         \
-      else if (TARGET_VEGA20)                                                  
\
-       builtin_define ("__gfx906__");                                         \
-      else if (TARGET_GFX908)                                                  
\
-       builtin_define ("__gfx908__");                                         \
-      else if (TARGET_GFX90a)                                                  
\
-       builtin_define ("__gfx90a__");                                         \
-      else if (TARGET_GFX90c)                                                  
\
-       builtin_define ("__gfx90c__");                                         \
-      else if (TARGET_GFX1030)                                                 
\
-       builtin_define ("__gfx1030__");                                        \
-      else if (TARGET_GFX1036)                                                 
\
-       builtin_define ("__gfx1036__");                                        \
-      else if (TARGET_GFX1100)                                                 
\
-       builtin_define ("__gfx1100__");                                        \
-      else if (TARGET_GFX1103)                                                 
\
-       builtin_define ("__gfx1103__");                                        \
-      else                                                                     
\
-       gcc_unreachable ();                                                    \
+      char *name = (char *)xmalloc (sizeof (gcn_devices[gcn_arch].name) + 5);  
\
+      sprintf (name, "__%s__", gcn_devices[gcn_arch].name);                    
\
+      builtin_define (name);                                                   
\
   } while (0)
 
 #define ASSEMBLER_DIALECT (TARGET_RDNA2_PLUS ? 1 : 0)
diff --git a/gcc/config/gcn/gcn.opt b/gcc/config/gcn/gcn.opt
index 69ecca8a500..57e344e8f2f 100644
--- a/gcc/config/gcn/gcn.opt
+++ b/gcc/config/gcn/gcn.opt
@@ -21,43 +21,12 @@
 HeaderInclude
 config/gcn/gcn-opts.h
 
-Enum
-Name(gpu_type) Type(enum processor_type)
-GCN GPU type to use:
-
-EnumValue
-Enum(gpu_type) String(gfx900) Value(PROCESSOR_VEGA10)
-
-EnumValue
-Enum(gpu_type) String(gfx906) Value(PROCESSOR_VEGA20)
-
-EnumValue
-Enum(gpu_type) String(gfx908) Value(PROCESSOR_GFX908)
-
-EnumValue
-Enum(gpu_type) String(gfx90a) Value(PROCESSOR_GFX90a)
-
-EnumValue
-Enum(gpu_type) String(gfx90c) Value(PROCESSOR_GFX90c)
-
-EnumValue
-Enum(gpu_type) String(gfx1030) Value(PROCESSOR_GFX1030)
-
-EnumValue
-Enum(gpu_type) String(gfx1036) Value(PROCESSOR_GFX1036)
-
-EnumValue
-Enum(gpu_type) String(gfx1100) Value(PROCESSOR_GFX1100)
-
-EnumValue
-Enum(gpu_type) String(gfx1103) Value(PROCESSOR_GFX1103)
-
 march=
-Target RejectNegative Negative(march=) Joined ToLower Enum(gpu_type) 
Var(gcn_arch) Init(PROCESSOR_VEGA10)
+Target RejectNegative Negative(march=) Joined ToLower Enum(gpu_type) 
Var(gcn_arch) Init(PROCESSOR_GFX900)
 Specify the name of the target GPU.
 
 mtune=
-Target RejectNegative Negative(mtune=) Joined ToLower Enum(gpu_type) 
Var(gcn_tune) Init(PROCESSOR_VEGA10)
+Target RejectNegative Negative(mtune=) Joined ToLower Enum(gpu_type) 
Var(gcn_tune) Init(PROCESSOR_GFX900)
 Specify the name of the target GPU.
 
 m32
@@ -114,7 +83,7 @@ Target RejectNegative Joined ToLower Enum(hsaco_attr_type) 
Var(flag_xnack) Init(
 Compile for devices requiring XNACK enabled. Default \"any\" if USM is 
supported.
 
 msram-ecc=
-Target RejectNegative Joined ToLower Enum(hsaco_attr_type) Var(flag_sram_ecc) 
Init(HSACO_ATTR_ANY)
+Target RejectNegative Joined ToLower Enum(hsaco_attr_type) Var(flag_sram_ecc) 
Init(HSACO_ATTR_DEFAULT)
 Compile for devices with the SRAM ECC feature enabled, or not. Default \"any\".
 
 -param=gcn-preferred-vectorization-factor=
diff --git a/gcc/config/gcn/gen-gcn-device-macros.awk 
b/gcc/config/gcn/gen-gcn-device-macros.awk
new file mode 100644
index 00000000000..6352fa5fa3e
--- /dev/null
+++ b/gcc/config/gcn/gen-gcn-device-macros.awk
@@ -0,0 +1,110 @@
+# Generate $objdir/gcn-device-macros.h from gcn-devices.def
+#
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+BEGIN {
+  FS= "[(,] *"
+
+  print "/* Generated by gen-gcn-device-macros.awk from gcn-devices.def."
+  print "   Do not edit.  */"
+
+  list=""
+}
+
+/^GCN_DEVICE\(/ {
+  gfx=$2
+  list=(list " OPT_" gfx)
+
+  print ""
+  next
+}
+
+/XNACK default.*HSACO_ATTR_UNSUPPORTED/ {
+  printf "\n#define XNACK_%s \"march=%s:;\"", gfx, gfx
+  next
+}
+
+/XNACK default.*HSACO_ATTR_OFF/ {
+  printf "\n#define XNACK_%s 
\"march=%s:%{!mxnack*|mxnack=default|mxnack=off:-mattr=-xnack;mxnack=on:-mattr=+xnack};\"",
 gfx, gfx
+  next
+}
+
+/XNACK default.*HSACO_ATTR_ANY/ {
+  printf "\n#define XNACK_%s 
\"march=%s:%{mxnack=off:-mattr=-xnack;mxnack=on:-mattr=+xnack};\"", gfx, gfx
+  next
+}
+
+/XNACK default.*HSACO/ {
+  print FILENAME ":" NR ": error: unhandled HSACO default at line 
(gen-gcn-device-macros.awk)" > "/dev/stderr"
+  exit 1
+}
+
+/SRAM_ECC default.*HSACO_ATTR_UNSUPPORTED/ {
+  printf "\n#define SRAM_%s \"march=%s:;\"", gfx, gfx
+  next
+}
+
+/SRAM_ECC default.*HSACO_ATTR_ANY/ {
+  printf "\n#define SRAM_%s 
\"march=%s:%{msram-ecc=on:-mattr=+sramecc;msram-ecc=off:-mattr=-sramecc};\"", 
gfx, gfx
+  next
+}
+
+/SRAM_ECC default.*HSACO/ {
+  print FILENAME ":" NR ": error: unhandled HSACO default at line 
(gen-gcn-device-macros.awk)" > "/dev/stderr"
+  exit 1
+}
+
+/WAVE64 mode.*HSACO_ATTR_UNSUPPORTED/ {
+  printf "\n#define WAVE64_%s \"march=%s:;\"", gfx, gfx
+  next
+}
+
+/WAVE64 mode.*HSACO_ATTR_ON/ {
+  printf "\n#define WAVE64_%s \"march=%s:-mattr=+wavefrontsize64;\"", gfx, gfx
+  next
+}
+
+/WAVE64 mode.*HSACO/ {
+  print FILENAME ":" NR ": error: unhandled HSACO default at line 
(gen-gcn-device-macros.awk)" > "/dev/stderr"
+  exit 1
+}
+
+/CU mode.*HSACO_ATTR_UNSUPPORTED/ {
+  printf "\n#define CU_%s \"march=%s:;\"", gfx, gfx
+  next
+}
+
+/CU mode.*HSACO_ATTR_ON/ {
+  printf "\n#define CU_%s \"march=%s:-mattr=+cumode;\"", gfx, gfx
+  next
+}
+
+/CU mode.*HSACO/ {
+  print FILENAME ":" NR ": error: unhandled HSACO default at line 
(gen-gcn-device-macros.awk)" > "/dev/stderr"
+  exit 1
+}
+
+END {
+  print ""
+  print ""
+  printf "#define XNACKOPT \"%%{\"%s \":%%eexpected march\\n} \"\n", gensub 
(/OPT/, "XNACK", "g", list)
+  printf "#define SRAMOPT \"%%{\"%s \":%%eexpected march\\n} \"\n", gensub 
(/OPT/, "SRAM", "g", list)
+  printf "#define WAVE64OPT \"%%{\"%s \":%%eexpected march\\n} \"\n", gensub 
(/OPT/, "WAVE64", "g", list)
+  printf "#define CUMODEOPT \"%%{\"%s \":%%eexpected march\\n} \"\n", gensub 
(/OPT/, "CU", "g", list)
+}
diff --git a/gcc/config/gcn/gen-opt-tables.awk 
b/gcc/config/gcn/gen-opt-tables.awk
new file mode 100644
index 00000000000..9fbe4cfe81f
--- /dev/null
+++ b/gcc/config/gcn/gen-opt-tables.awk
@@ -0,0 +1,55 @@
+# Generate gcn-tables.opt from gcn-devices.def
+#
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+BEGIN {
+  FS= "[(,] *"
+
+  print "; -*- buffer-read-only: t -*-"
+  print "; Generated automatically by gen-opt-tables.awk from gcn-devices.def."
+  print "; Do not edit."
+  print ""
+  print "; Copyright (C) 2024 Free Software Foundation, Inc."
+  print ""
+  print "; This file is part of GCC."
+  print ""
+  print "; GCC is free software; you can redistribute it and/or modify"
+  print "; it under the terms of the GNU General Public License as"
+  print "; published by the Free Software Foundation; either version 3,"
+  print "; or (at your option) any later version."
+  print ""
+  print "; GCC is distributed in the hope that it will be useful,"
+  print "; but WITHOUT ANY WARRANTY; without even the implied warranty of"
+  print "; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
+  print "; GNU General Public License for more details."
+  print ""
+  print "; You should have received a copy of the GNU General Public"
+  print "; License along with GCC; see the file COPYING3.  If not see"
+  print "; <http://www.gnu.org/licenses/>."
+  print ""
+  print "Enum"
+  print "Name(gpu_type) Type(enum processor_type)"
+  print "GCN GPU type to use:"
+}
+
+/^GCN_DEVICE\(/ {
+  print ""
+  print "EnumValue"
+  print "Enum(gpu_type) String(" $2 ") Value(PROCESSOR_" $3 ")"
+}
diff --git a/gcc/config/gcn/mkoffload.cc b/gcc/config/gcn/mkoffload.cc
index 1a524ced653..cebb9e506fb 100644
--- a/gcc/config/gcn/mkoffload.cc
+++ b/gcc/config/gcn/mkoffload.cc
@@ -49,24 +49,13 @@
 #undef  ELFABIVERSION_AMDGPU_HSA_V4
 #define ELFABIVERSION_AMDGPU_HSA_V4 2
 
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX900
-#define EF_AMDGPU_MACH_AMDGCN_GFX900 0x2c
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX906
-#define EF_AMDGPU_MACH_AMDGCN_GFX906 0x2f
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX908
-#define EF_AMDGPU_MACH_AMDGCN_GFX908 0x30
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX90a
-#define EF_AMDGPU_MACH_AMDGCN_GFX90a 0x3f
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX90c
-#define EF_AMDGPU_MACH_AMDGCN_GFX90c 0x32
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX1030
-#define EF_AMDGPU_MACH_AMDGCN_GFX1030 0x36
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX1036
-#define EF_AMDGPU_MACH_AMDGCN_GFX1036 0x45
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX1100
-#define EF_AMDGPU_MACH_AMDGCN_GFX1100 0x41
-#undef  EF_AMDGPU_MACH_AMDGCN_GFX1103
-#define EF_AMDGPU_MACH_AMDGCN_GFX1103 0x44
+/* Extract the EF_AMDGPU_MACH_AMDGCN_GFXnnn from the def file.  */
+enum elf_arch_code {
+#define GCN_DEVICE(name, NAME, ELF_ARCH, ...) \
+  EF_AMDGPU_MACH_AMDGCN_ ## NAME = ELF_ARCH,
+#include "gcn-devices.def"
+#undef GCN_DEVICE
+};
 
 #define EF_AMDGPU_FEATURE_XNACK_V4     0x300  /* Mask.  */
 #define EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 0x000
@@ -797,25 +786,15 @@ compile_native (const char *infile, const char *outfile, 
const char *compiler,
 static int
 get_arch (const char *str, const char *with_arch_str)
 {
-  if (strcmp (str, "gfx900") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX900;
-  else if (strcmp (str, "gfx906") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX906;
-  else if (strcmp (str, "gfx908") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX908;
-  else if (strcmp (str, "gfx90a") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX90a;
-  else if (strcmp (str, "gfx90c") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX90c;
-  else if (strcmp (str, "gfx1030") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX1030;
-  else if (strcmp (str, "gfx1036") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX1036;
-  else if (strcmp (str, "gfx1100") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX1100;
-  else if (strcmp (str, "gfx1103") == 0)
-    return EF_AMDGPU_MACH_AMDGCN_GFX1103;
-
+  /* Use the def file to map the name to the elf_arch_code.  */
+  if (!str) ;
+#define GCN_DEVICE(name, NAME, ELF, ...) \
+  else if (strcmp (str, #name) == 0) \
+    return ELF;
+#include "gcn-devices.def"
+#undef GCN_DEVICE
+
+  /* else */
   error ("unrecognized argument in option %<-march=%s%>", str);
 
   /* The suggestions are based on the configured multilib support; the compiler
@@ -1023,41 +1002,36 @@ main (int argc, char **argv)
       gcc_unreachable ();
     }
 
-  /* This must match gcn-hsa.h's settings for NO_XNACK, NO_SRAM_ECC
-     and ASM_SPEC.  */
+  /* Set the default ELF flags for XNACK.  */
   switch (elf_arch)
     {
-    case EF_AMDGPU_MACH_AMDGCN_GFX1030:
-    case EF_AMDGPU_MACH_AMDGCN_GFX1036:
-    case EF_AMDGPU_MACH_AMDGCN_GFX1100:
-    case EF_AMDGPU_MACH_AMDGCN_GFX1103:
-      SET_XNACK_UNSET (elf_flags);
-      SET_SRAM_ECC_UNSET (elf_flags);
-      break;
-    case EF_AMDGPU_MACH_AMDGCN_GFX900:
-      SET_XNACK_OFF (elf_flags);
-      SET_SRAM_ECC_UNSET (elf_flags);
-      break;
-    case EF_AMDGPU_MACH_AMDGCN_GFX906:
-      SET_XNACK_OFF (elf_flags);
-      SET_SRAM_ECC_ANY (elf_flags);
-      break;
-    case EF_AMDGPU_MACH_AMDGCN_GFX908:
-      SET_XNACK_OFF (elf_flags);
-      if (TEST_SRAM_ECC_UNSET (elf_flags))
-       SET_SRAM_ECC_ANY (elf_flags);
-      break;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90a:
-      if (TEST_XNACK_UNSET (elf_flags))
-       SET_XNACK_ANY (elf_flags);
-      if (TEST_SRAM_ECC_UNSET (elf_flags))
-       SET_SRAM_ECC_ANY (elf_flags);
-      break;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90c:
-      if (TEST_XNACK_UNSET (elf_flags))
-       SET_XNACK_ANY (elf_flags);
-      SET_SRAM_ECC_UNSET (elf_flags);
-      break;
+#define GCN_DEVICE(name, NAME, ELF, ISA, XNACK, SRAM, ...) \
+    case ELF: XNACK; break;
+#define HSACO_ATTR_UNSUPPORTED SET_XNACK_UNSET (elf_flags)
+#define HSACO_ATTR_OFF SET_XNACK_OFF (elf_flags)
+#define HSACO_ATTR_ANY \
+      if (TEST_XNACK_UNSET (elf_flags)) SET_XNACK_ANY (elf_flags)
+#include "gcn-devices.def"
+#undef HSACO_ATTR_UNSUPPORTED
+#undef HSACO_ATTR_OFF
+#undef HSACO_ATTR_ANY
+    default:
+      fatal_error (input_location, "unhandled architecture");
+    }
+
+  /* Set the default ELF flags for SRAM_ECC.  */
+  switch (elf_arch)
+    {
+#define GCN_DEVICE(name, NAME, ELF, ISA, XNACK, SRAM, ...) \
+    case ELF: SRAM; break;
+#define HSACO_ATTR_UNSUPPORTED SET_SRAM_ECC_UNSET (elf_flags)
+#define HSACO_ATTR_OFF SET_SRAM_ECC_OFF (elf_flags)
+#define HSACO_ATTR_ANY \
+      if (TEST_SRAM_ECC_UNSET (elf_flags)) SET_SRAM_ECC_ANY (elf_flags)
+#include "gcn-devices.def"
+#undef HSACO_ATTR_UNSUPPORTED
+#undef HSACO_ATTR_OFF
+#undef HSACO_ATTR_ANY
     default:
       fatal_error (input_location, "unhandled architecture");
     }
diff --git a/gcc/config/gcn/t-gcn-hsa b/gcc/config/gcn/t-gcn-hsa
index 5fc34a18bd1..5de32ae4792 100644
--- a/gcc/config/gcn/t-gcn-hsa
+++ b/gcc/config/gcn/t-gcn-hsa
@@ -49,3 +49,10 @@ gcn-tree.o: $(srcdir)/config/gcn/gcn-tree.cc
        $(COMPILE) $<
        $(POSTCOMPILE)
 ALL_HOST_OBJS += gcn-tree.o
+
+$(srcdir)/config/gcn/gcn-tables.opt: $(srcdir)/config/gcn/gcn-devices.def 
$(srcdir)/config/gcn/gen-opt-tables.awk
+       $(AWK) -f $(srcdir)/config/gcn/gen-opt-tables.awk $< > $@
+
+gcn-device-macros.h: $(srcdir)/config/gcn/gcn-devices.def 
$(srcdir)/config/gcn/gen-gcn-device-macros.awk
+       $(AWK) -f $(srcdir)/config/gcn/gen-gcn-device-macros.awk $< > $@
+generated_files += gcn-device-macros.h
diff --git a/gcc/config/gcn/t-omp-device b/gcc/config/gcn/t-omp-device
index 233da0fcf6f..cae6bd316e0 100644
--- a/gcc/config/gcn/t-omp-device
+++ b/gcc/config/gcn/t-omp-device
@@ -1,4 +1,4 @@
-omp-device-properties-gcn: $(srcdir)/config/gcn/gcn.cc
+omp-device-properties-gcn: $(srcdir)/config/gcn/gcn-devices.def
        echo kind: gpu > $@
        echo arch: amdgcn gcn >> $@
-       echo isa: gfx900 gfx906 gfx908 gfx90a gfx90c gfx1030 gfx1036 gfx1100 
gfx1103 >> $@
+       echo isa: `grep -o -P '(?<=GCN_DEVICE\()gfx[0-9a-f]+(?=,)' $<` >> $@
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index 1bd90dc381e..592a7b6daba 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -379,22 +379,15 @@ struct gcn_image_desc
   const unsigned global_variable_count;
 };
 
-/* This enum mirrors the corresponding LLVM enum's values for all ISAs that we
-   support.
-   See https://llvm.org/docs/AMDGPUUsage.html#amdgpu-ef-amdgpu-mach-table */
+/* Enum values corresponding to the the ELF architecture codes.
+   Only 'special' values are actually referenced in this file, but having them
+   all may aid debugging.  */
 
 typedef enum {
   EF_AMDGPU_MACH_UNSUPPORTED = -1,
-  EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a,
-  EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
-  EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f,
-  EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030,
-  EF_AMDGPU_MACH_AMDGCN_GFX90a = 0x03f,
-  EF_AMDGPU_MACH_AMDGCN_GFX90c = 0x032,
-  EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
-  EF_AMDGPU_MACH_AMDGCN_GFX1036 = 0x045,
-  EF_AMDGPU_MACH_AMDGCN_GFX1100 = 0x041,
-  EF_AMDGPU_MACH_AMDGCN_GFX1103 = 0x044
+#define GCN_DEVICE(name, NAME, ELF, ...) \
+  EF_AMDGPU_MACH_AMDGCN_ ## NAME = ELF,
+#include "../../gcc/config/gcn/gcn-devices.def"
 } EF_AMDGPU_MACH;
 
 const static int EF_AMDGPU_MACH_MASK = 0x000000ff;
@@ -1675,98 +1668,28 @@ elf_gcn_isa_field (Elf64_Ehdr *image)
   return image->e_flags & EF_AMDGPU_MACH_MASK;
 }
 
-const static char *gcn_gfx803_s = "gfx803";
-const static char *gcn_gfx900_s = "gfx900";
-const static char *gcn_gfx906_s = "gfx906";
-const static char *gcn_gfx908_s = "gfx908";
-const static char *gcn_gfx90a_s = "gfx90a";
-const static char *gcn_gfx90c_s = "gfx90c";
-const static char *gcn_gfx1030_s = "gfx1030";
-const static char *gcn_gfx1036_s = "gfx1036";
-const static char *gcn_gfx1100_s = "gfx1100";
-const static char *gcn_gfx1103_s = "gfx1103";
-const static int gcn_isa_name_len = 7;
-
 /* Returns the name that the HSA runtime uses for the ISA or NULL if we do not
    support the ISA. */
 
 static const char*
-isa_hsa_name (int isa) {
+isa_name (int isa) {
   switch(isa)
     {
-    case EF_AMDGPU_MACH_AMDGCN_GFX803:
-      return gcn_gfx803_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX900:
-      return gcn_gfx900_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX906:
-      return gcn_gfx906_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX908:
-      return gcn_gfx908_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90a:
-      return gcn_gfx90a_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90c:
-      return gcn_gfx90c_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX1030:
-      return gcn_gfx1030_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX1036:
-      return gcn_gfx1036_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX1100:
-      return gcn_gfx1100_s;
-    case EF_AMDGPU_MACH_AMDGCN_GFX1103:
-      return gcn_gfx1103_s;
+#define GCN_DEVICE(name, NAME, ELF, ...) \
+    case ELF: return #name;
+#include "../../gcc/config/gcn/gcn-devices.def"
     }
   return NULL;
 }
 
-/* Returns the user-facing name that GCC uses to identify the architecture 
(e.g.
-   with -march) or NULL if we do not support the ISA.
-   Keep in sync with /gcc/config/gcn/gcn.{c,opt}.  */
-
-static const char*
-isa_gcc_name (int isa) {
-  switch(isa)
-    {
-    case EF_AMDGPU_MACH_AMDGCN_GFX803:
-      return "fiji";
-    default:
-      return isa_hsa_name (isa);
-    }
-}
-
 /* Returns the code which is used in the GCN object code to identify the ISA 
with
    the given name (as used by the HSA runtime).  */
 
 static gcn_isa
 isa_code(const char *isa) {
-  if (!strncmp (isa, gcn_gfx803_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX803;
-
-  if (!strncmp (isa, gcn_gfx900_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX900;
-
-  if (!strncmp (isa, gcn_gfx906_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX906;
-
-  if (!strncmp (isa, gcn_gfx908_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX908;
-
-  if (!strncmp (isa, gcn_gfx90a_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX90a;
-
-  if (!strncmp (isa, gcn_gfx90c_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX90c;
-
-  if (!strncmp (isa, gcn_gfx1030_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX1030;
-
-  if (!strncmp (isa, gcn_gfx1036_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX1036;
-
-  if (!strncmp (isa, gcn_gfx1100_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX1100;
-
-  if (!strncmp (isa, gcn_gfx1103_s, gcn_isa_name_len))
-    return EF_AMDGPU_MACH_AMDGCN_GFX1103;
+#define GCN_DEVICE(name, NAME, ELF, ...) \
+  if (!strcmp (isa, #name)) return ELF;
+#include "../../gcc/config/gcn/gcn-devices.def"
 
   return EF_AMDGPU_MACH_UNSUPPORTED;
 }
@@ -1778,23 +1701,13 @@ max_isa_vgprs (int isa)
 {
   switch (isa)
     {
-    case EF_AMDGPU_MACH_AMDGCN_GFX803:
-    case EF_AMDGPU_MACH_AMDGCN_GFX900:
-    case EF_AMDGPU_MACH_AMDGCN_GFX906:
-    case EF_AMDGPU_MACH_AMDGCN_GFX908:
-      return 256;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90a:
-      return 512;
-    case EF_AMDGPU_MACH_AMDGCN_GFX90c:
-      return 256;
-    case EF_AMDGPU_MACH_AMDGCN_GFX1030:
-    case EF_AMDGPU_MACH_AMDGCN_GFX1036:
-      return 512;  /* 512 SIMD32 = 256 wavefrontsize64.  */
-    case EF_AMDGPU_MACH_AMDGCN_GFX1100:
-    case EF_AMDGPU_MACH_AMDGCN_GFX1103:
-      return 1536; /* 1536 SIMD32 = 768 wavefrontsize64.  */
-    }
-  GOMP_PLUGIN_fatal ("unhandled ISA in max_isa_vgprs");
+#define GCN_DEVICE(name, NAME, ELF, ISA, XNACK, SRAM, WAVE64, CU, \
+                  MAX_ISA_VGPRS, ...) \
+    case ELF: return MAX_ISA_VGPRS;
+#include "../../gcc/config/gcn/gcn-devices.def"
+    default:
+      GOMP_PLUGIN_fatal ("unhandled ISA in max_isa_vgprs");
+    }
 }
 
 /* }}}  */
@@ -2492,7 +2405,7 @@ static bool
 isa_matches_agent (struct agent_info *agent, Elf64_Ehdr *image)
 {
   int isa_field = elf_gcn_isa_field (image);
-  const char* isa_s = isa_hsa_name (isa_field);
+  const char* isa_s = isa_name (isa_field);
   if (!isa_s)
     {
       hsa_error ("Unsupported ISA in GCN code object.", HSA_STATUS_ERROR);
@@ -2502,15 +2415,13 @@ isa_matches_agent (struct agent_info *agent, Elf64_Ehdr 
*image)
   if (isa_field != agent->device_isa)
     {
       char msg[120];
-      const char *agent_isa_s = isa_hsa_name (agent->device_isa);
-      const char *agent_isa_gcc_s = isa_gcc_name (agent->device_isa);
+      const char *agent_isa_s = isa_name (agent->device_isa);
       assert (agent_isa_s);
-      assert (agent_isa_gcc_s);
 
       snprintf (msg, sizeof msg,
                "GCN code object ISA '%s' does not match GPU ISA '%s'.\n"
                "Try to recompile with '-foffload-options=-march=%s'.\n",
-               isa_s, agent_isa_s, agent_isa_gcc_s);
+               isa_s, agent_isa_s, agent_isa_s);
 
       hsa_error (msg, HSA_STATUS_ERROR);
       return false;
@@ -3461,7 +3372,12 @@ GOMP_OFFLOAD_init_device (int n)
 
   agent->device_isa = isa_code (agent->name);
   if (agent->device_isa == EF_AMDGPU_MACH_UNSUPPORTED)
-    return hsa_error ("Unknown GCN agent architecture", HSA_STATUS_ERROR);
+    {
+      char msg[33 + 64 + 1];
+      snprintf (msg, sizeof msg,
+               "Unknown GCN agent architecture '%s'", agent->name);
+      return hsa_error (msg, HSA_STATUS_ERROR);
+    }
 
   status = hsa_fns.hsa_agent_get_info_fn (agent->id, 
HSA_AGENT_INFO_VENDOR_NAME,
                                          &agent->vendor_name);
-- 
2.46.0

Reply via email to