[llvm] AMDGPU: Respect target assembler directives over command line (PR #207812)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 7 01:15:54 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/207812

>From a53e0b7105b6d867344d80f705c973977d6d5f92 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 16 Jun 2026 10:14:49 +0200
Subject: [PATCH 1/3] AMDGPU: Respect target assembler directives over command
 line

Mutate the global subtarget, using essentially the same code that ARM uses.
The main difference is we need to mutate the actual CPU name in addition
to just flipping the feature bits, so this needs a new setter in
MCSubtargetInfo. Liberalize the triple check so that after #206480,
old assembly files to not break on new assembler invocations.

For some reason we have 2 different assembler directives that indicate the
target, .amdgcn_target for amdhsa and .amd_amdgpu_isa for amdpal. Previously,
we would take the target from the command line and then error if the directive
did not exactly match. In order to move away from depending on the xnack and
sramecc subtarget features, start treating the directives as a change of target,
similar to ARM's .cpu and .arch directives.

Both .amdgcn_target and .amd_amdgpu_isa encode full triples, but unlike
.amdgcn_target, the PAL directive does not include xnack or sramecc. Ideally
we would introduce new independent directives for these.

Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>
---
 llvm/include/llvm/MC/MCSubtargetInfo.h        |  4 ++
 .../llvm/TargetParser/AMDGPUTargetParser.h    |  6 ++
 .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp      | 72 +++++++++++++++++--
 llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h |  7 ++
 .../AMDGPU/amdgcn-target-directive-conflict.s | 33 +++++++++
 .../amdgcn-target-directive-triple-env.s      |  4 +-
 llvm/test/MC/AMDGPU/hsa-diag-v4.s             | 10 +--
 llvm/test/MC/AMDGPU/hsa-exp.s                 |  2 +-
 llvm/test/MC/AMDGPU/hsa-gfx12-v4.s            |  2 +-
 llvm/test/MC/AMDGPU/hsa-gfx13-v4.s            |  2 +-
 llvm/test/MC/AMDGPU/hsa-tg-split.s            |  2 +-
 llvm/test/MC/AMDGPU/hsa-v4.s                  |  2 +-
 .../MC/AMDGPU/hsa-v5-uses-dynamic-stack.s     |  2 +-
 llvm/test/MC/AMDGPU/isa-version-hsa.s         |  6 +-
 llvm/test/MC/AMDGPU/isa-version-pal.s         |  6 +-
 llvm/test/MC/AMDGPU/isa-version-unk.s         |  6 +-
 16 files changed, 137 insertions(+), 29 deletions(-)
 create mode 100644 llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s

diff --git a/llvm/include/llvm/MC/MCSubtargetInfo.h b/llvm/include/llvm/MC/MCSubtargetInfo.h
index 2d1053b2113c0..1dc1696399951 100644
--- a/llvm/include/llvm/MC/MCSubtargetInfo.h
+++ b/llvm/include/llvm/MC/MCSubtargetInfo.h
@@ -157,6 +157,10 @@ class LLVM_ABI MCSubtargetInfo {
     FeatureBits = FeatureBits_;
   }
 
+  /// Update the CPU string. This is needed when assembly directives
+  /// change the target CPU.
+  void setCPU(StringRef C) { CPU = C.str(); }
+
   StringRef getFeatureString() const { return FeatureString; }
 
   bool hasFeature(unsigned Feature) const {
diff --git a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
index ba447dd346d80..60d25e2f89dfb 100644
--- a/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
+++ b/llvm/include/llvm/TargetParser/AMDGPUTargetParser.h
@@ -47,6 +47,12 @@ struct IsaVersion {
   unsigned Major;
   unsigned Minor;
   unsigned Stepping;
+
+  bool operator==(const IsaVersion &Other) const {
+    return Major == Other.Major && Minor == Other.Minor &&
+           Stepping == Other.Stepping;
+  }
+  bool operator!=(const IsaVersion &Other) const { return !(*this == Other); }
 };
 
 // This isn't comprehensive for now, just things that are needed from the
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 0f70d3ab40892..f328300eb78e2 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -1405,6 +1405,13 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
 
   std::optional<AMDGPU::InfoSectionData> InfoData;
 
+  /// Whether the leading .amdgcn_target directive has been emitted to the
+  /// output streamer yet. The emission is deferred until the first piece of
+  /// content (instruction or kernel descriptor) so that any leading
+  /// .amdgcn_target/.amd_amdgpu_isa directive in the source has had a chance to
+  /// update the target ID first.
+  bool TargetDirectiveEmitted = false;
+
 private:
   void createConstantSymbol(StringRef Id, int64_t Val);
 
@@ -1952,6 +1959,10 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
 
 public:
   void onBeginOfFile() override;
+  /// Emit the deferred leading .amdgcn_target directive if it has not been
+  /// emitted yet. Called before emitting the first instruction or kernel
+  /// descriptor.
+  void emitTargetDirective();
   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
 
   ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK);
@@ -5920,6 +5931,7 @@ bool AMDGPUAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     if (!validateInstruction(Inst, IDLoc, Operands)) {
       return true;
     }
+    emitTargetDirective();
     Out.emitInstruction(Inst, getSTI());
     return false;
   }
@@ -5989,14 +6001,48 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
   const std::optional<AMDGPU::TargetID> &CurrentTargetID =
       getTargetStreamer().getTargetID();
 
-  if (*CurrentTargetID != ParsedTargetID) {
+  Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
+  const Triple &STITriple = getSTI().getTargetTriple();
+  if (!DirectiveTriple.isCompatibleWith(STITriple)) {
     return getParser().Error(
-        TargetStart, Twine(".amdgcn_target directive's target id ") +
-                         Twine(ParsedTargetID.toString()) +
-                         Twine(" does not match the specified target id ") +
+        TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
+                         " is incompatible with " +
                          Twine(CurrentTargetID->toString()));
   }
 
+  // Error if the ISA version doesn't match
+  AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(
+      AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind()));
+  AMDGPU::IsaVersion CurrentISA = AMDGPU::getIsaVersion(getSTI().getCPU());
+  if (DirectiveISA != CurrentISA) {
+    return getParser().Error(
+        TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
+                         " does not match the specified target id " +
+                         Twine(CurrentTargetID->toString()));
+  }
+
+  // Warn if sramecc or xnack mismatch. These do not change the encoding.
+  if (AMDGPU::IsaInfo::targetIDSettingsConflict(
+          ParsedTargetID.getXnackSetting(),
+          CurrentTargetID->getXnackSetting())) {
+    Warning(TargetStart,
+            ".amdgcn_target directive has conflicting xnack settings");
+  }
+  if (AMDGPU::IsaInfo::targetIDSettingsConflict(
+          ParsedTargetID.getSramEccSetting(),
+          CurrentTargetID->getSramEccSetting())) {
+    Warning(TargetStart,
+            ".amdgcn_target directive has conflicting sramecc settings");
+  }
+
+  // Update the target streamer's TargetID with settings from the directive.
+  // We don't update the MCSubtargetInfo because we've already validated
+  // that the directive matches the command-line CPU.
+  getTargetStreamer().getTargetID()->setXnackSetting(
+      ParsedTargetID.getXnackSetting());
+  getTargetStreamer().getTargetID()->setSramEccSetting(
+      ParsedTargetID.getSramEccSetting());
+
   return false;
 }
 
@@ -6587,6 +6633,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
     }
   }
 
+  emitTargetDirective();
   getTargetStreamer().EmitAmdhsaKernelDescriptor(getSTI(), KernelName, KD,
                                                  NextFreeVGPR, NextFreeSGPR,
                                                  ReserveVCC, ReserveFlatScr);
@@ -6599,6 +6646,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() {
     return true;
 
   getTargetStreamer().EmitDirectiveAMDHSACodeObjectVersion(Version);
+  emitTargetDirective();
   return false;
 }
 
@@ -6703,9 +6751,8 @@ bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
 
   if (*CurrentTargetID != ParsedTargetID) {
     return Error(getParser().getTok().getLoc(),
-                 Twine(".amd_amdgpu_isa directive's target id ") +
-                     Twine(ParsedTargetID.toString()) +
-                     Twine(" does not match the specified target id ") +
+                 ".amd_amdgpu_isa " + Twine(ParsedTargetID.toString()) +
+                     " does not match the specified target id " +
                      Twine(CurrentTargetID->toString()));
   }
 
@@ -6977,6 +7024,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGPUInfo() {
 }
 
 void AMDGPUAsmParser::onEndOfFile() {
+  emitTargetDirective();
   if (InfoData)
     getTargetStreamer().emitAMDGPUInfo(*InfoData);
 }
@@ -9427,6 +9475,16 @@ void AMDGPUAsmParser::onBeginOfFile() {
   if (!getTargetStreamer().getTargetID())
     getTargetStreamer().initializeTargetID(getSTI(),
                                            getSTI().getFeatureString());
+}
+
+void AMDGPUAsmParser::emitTargetDirective() {
+  if (TargetDirectiveEmitted)
+    return;
+  TargetDirectiveEmitted = true;
+
+  if (!getParser().getStreamer().getTargetStreamer() ||
+      getSTI().getTargetTriple().getArch() == Triple::r600)
+    return;
 
   if (isHsaAbi(getSTI()))
     getTargetStreamer().EmitDirectiveAMDGCNTarget();
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index 716d6b54a4d20..a13c3c5ba6283 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -163,6 +163,13 @@ enum {
   TRAP_NUM_SGPRS = 16
 };
 
+/// Returns true if \p Lhs and \p Rhs are incompatible (both specific but
+/// different).
+inline bool targetIDSettingsConflict(TargetIDSetting Lhs, TargetIDSetting Rhs) {
+  return Lhs != TargetIDSetting::Any && Rhs != TargetIDSetting::Any &&
+         Lhs != Rhs;
+}
+
 /// \returns Instruction cache line size in bytes for given subtarget \p STI.
 unsigned getInstCacheLineSize(const MCSubtargetInfo &STI);
 
diff --git a/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s b/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s
new file mode 100644
index 0000000000000..b44b8f791a91d
--- /dev/null
+++ b/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s
@@ -0,0 +1,33 @@
+// RUN: split-file %s %t
+
+// Test that .amdgcn_target emits separate warnings for conflicting xnack and
+// sramecc settings between the directive and the command line.
+
+// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx908 -mattr=+xnack,+sramecc %t/xnack.s 2>&1 | FileCheck --check-prefix=XNACK --implicit-check-not=warning %s
+// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx908 -mattr=+xnack,+sramecc %t/sramecc.s 2>&1 | FileCheck --check-prefix=SRAMECC --implicit-check-not=warning %s
+// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx908 -mattr=+xnack,+sramecc %t/both.s 2>&1 | FileCheck --check-prefix=BOTH --implicit-check-not=warning %s
+
+// When the directive specifies modes but the command line leaves them
+// unspecified (Any), there is no conflict and no warning is emitted.
+// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx908 %t/both.s 2>&1 | FileCheck --check-prefix=NOCONFLICT --implicit-check-not=warning %s
+
+// The object emission path honors the directive's xnack/sramecc settings in the
+// e_flags even when the command line does not specify them.
+// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx908 -filetype=obj %t/both.s -o %t/both.o
+// RUN: llvm-readobj --file-headers %t/both.o | FileCheck --check-prefix=OBJ %s
+
+//--- xnack.s
+// XNACK: warning: .amdgcn_target directive has conflicting xnack settings
+.amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx908:sramecc+:xnack-"
+
+//--- sramecc.s
+// SRAMECC: warning: .amdgcn_target directive has conflicting sramecc settings
+.amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx908:sramecc-:xnack+"
+
+//--- both.s
+// BOTH: warning: .amdgcn_target directive has conflicting xnack settings
+// BOTH: warning: .amdgcn_target directive has conflicting sramecc settings
+// NOCONFLICT: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx908:sramecc-:xnack-"
+// OBJ: EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 (0x800)
+// OBJ: EF_AMDGPU_FEATURE_XNACK_OFF_V4 (0x200)
+.amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx908:sramecc-:xnack-"
diff --git a/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s b/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
index 13f9a500d5c2f..92758e4deaee7 100644
--- a/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
+++ b/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
@@ -8,10 +8,10 @@
 
 //--- amdhsa-llvm.s
 // AMDHSA-LLVM: .amdgcn_target "amdgcn-amd-amdhsa-llvm-gfx802"
-// AMDHSA-ERR: {{.*}}:16: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-llvm-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx802
+// AMDHSA-ERR: error: .amdgcn_target amdgcn-amd-amdhsa-llvm-gfx802 is incompatible with amdgcn-amd-amdhsa-unknown-gfx802
 .amdgcn_target "amdgcn-amd-amdhsa-llvm-gfx802"
 
 //--- amdpal-llvm.s
 // AMDPAL-LLVM: .amd_amdgpu_isa "amdgcn-amd-amdpal-llvm-gfx802"
-// AMDPAL-ERR: {{.*}}:17: error: .amd_amdgpu_isa directive's target id amdgcn-amd-amdpal-llvm-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx802
+// AMDPAL-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-llvm-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx802
 .amd_amdgpu_isa "amdgcn-amd-amdpal-llvm-gfx802"
diff --git a/llvm/test/MC/AMDGPU/hsa-diag-v4.s b/llvm/test/MC/AMDGPU/hsa-diag-v4.s
index c4bf7c3e169a4..018a1e61d3c07 100644
--- a/llvm/test/MC/AMDGPU/hsa-diag-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-diag-v4.s
@@ -11,11 +11,11 @@
 
 // GCN-LABEL: warning: test_target
 // GFX8-NOT: error:
-// GFX10: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1010:xnack+
-// GFX11: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1100
-// GFX12: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-[[MCPU]]
-// GFX1170: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1170
-// NONAMDHSA: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-unknown-unknown-gfx810
+// GFX10: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1010:xnack+
+// GFX11: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1100
+// GFX12: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-[[MCPU]]
+// GFX1170: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1170
+// NONAMDHSA: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ is incompatible with amdgcn-amd-unknown-unknown-gfx810
 .warning "test_target"
 .amdgcn_target "amdgcn-amd-amdhsa--gfx810:xnack+"
 
diff --git a/llvm/test/MC/AMDGPU/hsa-exp.s b/llvm/test/MC/AMDGPU/hsa-exp.s
index 035b55f8f98bd..b3974e63f15f0 100644
--- a/llvm/test/MC/AMDGPU/hsa-exp.s
+++ b/llvm/test/MC/AMDGPU/hsa-exp.s
@@ -14,10 +14,10 @@
 // ELF: }
 
 .amdgcn_target "amdgcn-unknown-amdhsa--gfx700"
-// ASM: .amdgcn_target "amdgcn-unknown-amdhsa-unknown-gfx700"
 
 .amdhsa_code_object_version 4
 // ASM: .amdhsa_code_object_version 4
+// ASM: .amdgcn_target "amdgcn-unknown-amdhsa-unknown-gfx700"
 
 .set my_is_ptr64, 1
 
diff --git a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s
index 664db2b8359fd..03de0db3ee079 100644
--- a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s
@@ -49,10 +49,10 @@
 .text
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx1200"
-// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx1200"
 
 .amdhsa_code_object_version 4
 // ASM: .amdhsa_code_object_version 4
+// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx1200"
 
 .p2align 8
 .type minimal, at function
diff --git a/llvm/test/MC/AMDGPU/hsa-gfx13-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx13-v4.s
index b700cec253fb2..82107d912ae95 100644
--- a/llvm/test/MC/AMDGPU/hsa-gfx13-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-gfx13-v4.s
@@ -49,10 +49,10 @@
 .text
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx1310"
-// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx1310"
 
 .amdhsa_code_object_version 4
 // ASM: .amdhsa_code_object_version 4
+// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx1310"
 
 .p2align 8
 .type minimal, at function
diff --git a/llvm/test/MC/AMDGPU/hsa-tg-split.s b/llvm/test/MC/AMDGPU/hsa-tg-split.s
index bbe72cc7e73e4..3a167b9208cad 100644
--- a/llvm/test/MC/AMDGPU/hsa-tg-split.s
+++ b/llvm/test/MC/AMDGPU/hsa-tg-split.s
@@ -9,10 +9,10 @@
 // OBJDUMP-NEXT: 0030 0000ac00 80000000 00000000 00000000
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx90a:xnack+"
-// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx90a:xnack+"
 
 .amdhsa_code_object_version 4
 // ASM: .amdhsa_code_object_version 4
+// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx90a:xnack+"
 
 .p2align 8
 .type minimal, at function
diff --git a/llvm/test/MC/AMDGPU/hsa-v4.s b/llvm/test/MC/AMDGPU/hsa-v4.s
index 07e648e3a9982..3d2056bedbab3 100644
--- a/llvm/test/MC/AMDGPU/hsa-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-v4.s
@@ -47,10 +47,10 @@
 // OBJDUMP-NEXT: 00f0 0000ac00 80000000 00000000 00000000
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx904:xnack+"
-// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx904:xnack+"
 
 .amdhsa_code_object_version 4
 // ASM: .amdhsa_code_object_version 4
+// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx904:xnack+"
 
 .p2align 8
 .type minimal, at function
diff --git a/llvm/test/MC/AMDGPU/hsa-v5-uses-dynamic-stack.s b/llvm/test/MC/AMDGPU/hsa-v5-uses-dynamic-stack.s
index 5ee020c0fd132..3ab4385cd80ad 100644
--- a/llvm/test/MC/AMDGPU/hsa-v5-uses-dynamic-stack.s
+++ b/llvm/test/MC/AMDGPU/hsa-v5-uses-dynamic-stack.s
@@ -52,10 +52,10 @@
 // OBJDUMP-NEXT: 00f0 0000ac00 80000000 00000000 00000000
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx904:xnack+"
-// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx904:xnack+"
 
 .amdhsa_code_object_version 5
 // ASM: .amdhsa_code_object_version 5
+// ASM: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx904:xnack+"
 
 .p2align 8
 .type minimal, at function
diff --git a/llvm/test/MC/AMDGPU/isa-version-hsa.s b/llvm/test/MC/AMDGPU/isa-version-hsa.s
index ac7c0e8e46cd5..3aa9ff7b4d2d5 100644
--- a/llvm/test/MC/AMDGPU/isa-version-hsa.s
+++ b/llvm/test/MC/AMDGPU/isa-version-hsa.s
@@ -9,6 +9,6 @@
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx802"
 // OSABI-HSA: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx802"
-// OSABI-HSA-ERR: :[[@LINE-2]]:16: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx803
-// OSABI-PAL-ERR: :[[@LINE-3]]:16: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx802
-// OSABI-UNK-ERR: :[[@LINE-4]]:16: error: .amdgcn_target directive's target id amdgcn-amd-amdhsa-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx802
+// OSABI-HSA-ERR: :[[@LINE-2]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx803
+// OSABI-PAL-ERR: :[[@LINE-3]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 is incompatible with amdgcn-amd-amdpal-unknown-gfx802
+// OSABI-UNK-ERR: :[[@LINE-4]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 is incompatible with amdgcn-amd-unknown-unknown-gfx802
diff --git a/llvm/test/MC/AMDGPU/isa-version-pal.s b/llvm/test/MC/AMDGPU/isa-version-pal.s
index 9c99b3b5936df..d095d73d2f80e 100644
--- a/llvm/test/MC/AMDGPU/isa-version-pal.s
+++ b/llvm/test/MC/AMDGPU/isa-version-pal.s
@@ -7,8 +7,8 @@
 // RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=gfx803 %s -filetype=null 2>&1 | FileCheck --check-prefix=OSABI-PAL-ERR %s
 
 // OSABI-PAL: .amd_amdgpu_isa "amdgcn-amd-amdpal-unknown-gfx802"
-// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive's target id amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx802
-// OSABI-HSA-ERR: error: .amdgcn_target directive's target id amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx802
-// OSABI-PAL-ERR: error: .amd_amdgpu_isa directive's target id amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx803
+// OSABI-UNK-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx802
+// OSABI-HSA-ERR: error: .amdgcn_target amdgcn-amd-amdpal-unknown-gfx802 is incompatible with amdgcn-amd-amdhsa-unknown-gfx802
+// OSABI-PAL-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx803
 .amd_amdgpu_isa "amdgcn-amd-amdpal--gfx802"
 .amdgcn_target "amdgcn-amd-amdpal--gfx802"
diff --git a/llvm/test/MC/AMDGPU/isa-version-unk.s b/llvm/test/MC/AMDGPU/isa-version-unk.s
index 855dae8a0aa35..e6bbca784efae 100644
--- a/llvm/test/MC/AMDGPU/isa-version-unk.s
+++ b/llvm/test/MC/AMDGPU/isa-version-unk.s
@@ -7,8 +7,8 @@
 // RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=iceland %s -filetype=null 2>&1 | FileCheck --check-prefix=OSABI-PAL-ERR %s
 
 // OSABI-UNK: .amd_amdgpu_isa "amdgcn-amd-unknown-unknown-gfx802"
-// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive's target id amdgcn-amd-unknown-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx803
-// OSABI-HSA-ERR: error: .amdgcn_target directive's target id amdgcn-amd-unknown-unknown-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx802
-// OSABI-PAL-ERR: error: .amdgcn_target directive's target id amdgcn-amd-unknown-unknown-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx802
+// OSABI-UNK-ERR: error: .amd_amdgpu_isa amdgcn-amd-unknown-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx803
+// OSABI-HSA-ERR: error: .amdgcn_target amdgcn-amd-unknown-unknown-gfx802 is incompatible with amdgcn-amd-amdhsa-unknown-gfx802
+// OSABI-PAL-ERR: error: .amdgcn_target amdgcn-amd-unknown-unknown-gfx802 is incompatible with amdgcn-amd-amdpal-unknown-gfx802
 .amd_amdgpu_isa "amdgcn-amd-unknown--gfx802"
 .amdgcn_target "amdgcn-amd-unknown--gfx802"

>From 5eb401e9ff2361273b45ebe9b7bccaf2c83d5c7d Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 7 Jul 2026 09:27:54 +0200
Subject: [PATCH 2/3] Clarify .amdgcn_target processor mismatch diagnostic

---
 .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp      | 33 ++++++++++++++-----
 .../amdgcn-target-directive-triple-env.s      |  2 +-
 llvm/test/MC/AMDGPU/hsa-diag-v4.s             |  8 ++---
 llvm/test/MC/AMDGPU/isa-version-hsa.s         |  2 +-
 llvm/test/MC/AMDGPU/isa-version-pal.s         |  4 +--
 llvm/test/MC/AMDGPU/isa-version-unk.s         |  2 +-
 6 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index f328300eb78e2..b933acf63006d 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -6011,14 +6011,16 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
   }
 
   // Error if the ISA version doesn't match
-  AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(
-      AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind()));
+  StringRef DirectiveProcessor =
+      AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
+  AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
   AMDGPU::IsaVersion CurrentISA = AMDGPU::getIsaVersion(getSTI().getCPU());
   if (DirectiveISA != CurrentISA) {
-    return getParser().Error(
-        TargetStart, ".amdgcn_target " + Twine(ParsedTargetID.toString()) +
-                         " does not match the specified target id " +
-                         Twine(CurrentTargetID->toString()));
+    return getParser().Error(TargetStart,
+                             ".amdgcn_target directive processor " +
+                                 Twine(DirectiveProcessor) +
+                                 " does not match the specified processor " +
+                                 Twine(getSTI().getCPU()));
   }
 
   // Warn if sramecc or xnack mismatch. These do not change the encoding.
@@ -6749,13 +6751,28 @@ bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
   const std::optional<AMDGPU::TargetID> &CurrentTargetID =
       getTargetStreamer().getTargetID();
 
-  if (*CurrentTargetID != ParsedTargetID) {
+  Triple DirectiveTriple(ParsedTargetID.getTargetTripleString());
+  const Triple &STITriple = getSTI().getTargetTriple();
+  if (!DirectiveTriple.isCompatibleWith(STITriple)) {
     return Error(getParser().getTok().getLoc(),
                  ".amd_amdgpu_isa " + Twine(ParsedTargetID.toString()) +
-                     " does not match the specified target id " +
+                     " is incompatible with " +
                      Twine(CurrentTargetID->toString()));
   }
 
+  // Error if the ISA version doesn't match
+  StringRef DirectiveProcessor =
+      AMDGPU::getArchNameAMDGCN(ParsedTargetID.getGPUKind());
+  AMDGPU::IsaVersion DirectiveISA = AMDGPU::getIsaVersion(DirectiveProcessor);
+  AMDGPU::IsaVersion CurrentISA = AMDGPU::getIsaVersion(getSTI().getCPU());
+  if (DirectiveISA != CurrentISA) {
+    return Error(getParser().getTok().getLoc(),
+                 ".amd_amdgpu_isa directive processor " +
+                     Twine(DirectiveProcessor) +
+                     " does not match the specified processor " +
+                     Twine(getSTI().getCPU()));
+  }
+
   getTargetStreamer().EmitISAVersion();
   Lex();
 
diff --git a/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s b/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
index 92758e4deaee7..3e739258addc9 100644
--- a/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
+++ b/llvm/test/MC/AMDGPU/amdgcn-target-directive-triple-env.s
@@ -13,5 +13,5 @@
 
 //--- amdpal-llvm.s
 // AMDPAL-LLVM: .amd_amdgpu_isa "amdgcn-amd-amdpal-llvm-gfx802"
-// AMDPAL-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-llvm-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx802
+// AMDPAL-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-llvm-gfx802 is incompatible with amdgcn-amd-amdpal-unknown-gfx802
 .amd_amdgpu_isa "amdgcn-amd-amdpal-llvm-gfx802"
diff --git a/llvm/test/MC/AMDGPU/hsa-diag-v4.s b/llvm/test/MC/AMDGPU/hsa-diag-v4.s
index 018a1e61d3c07..708efb722e59b 100644
--- a/llvm/test/MC/AMDGPU/hsa-diag-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-diag-v4.s
@@ -11,10 +11,10 @@
 
 // GCN-LABEL: warning: test_target
 // GFX8-NOT: error:
-// GFX10: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1010:xnack+
-// GFX11: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1100
-// GFX12: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-[[MCPU]]
-// GFX1170: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx1170
+// GFX10: error: .amdgcn_target directive processor gfx810 does not match the specified processor gfx1010
+// GFX11: error: .amdgcn_target directive processor gfx810 does not match the specified processor gfx1100
+// GFX12: error: .amdgcn_target directive processor gfx810 does not match the specified processor [[MCPU]]
+// GFX1170: error: .amdgcn_target directive processor gfx810 does not match the specified processor gfx1170
 // NONAMDHSA: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx810:xnack+ is incompatible with amdgcn-amd-unknown-unknown-gfx810
 .warning "test_target"
 .amdgcn_target "amdgcn-amd-amdhsa--gfx810:xnack+"
diff --git a/llvm/test/MC/AMDGPU/isa-version-hsa.s b/llvm/test/MC/AMDGPU/isa-version-hsa.s
index 3aa9ff7b4d2d5..8b90bbc5fade7 100644
--- a/llvm/test/MC/AMDGPU/isa-version-hsa.s
+++ b/llvm/test/MC/AMDGPU/isa-version-hsa.s
@@ -9,6 +9,6 @@
 
 .amdgcn_target "amdgcn-amd-amdhsa--gfx802"
 // OSABI-HSA: .amdgcn_target "amdgcn-amd-amdhsa-unknown-gfx802"
-// OSABI-HSA-ERR: :[[@LINE-2]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 does not match the specified target id amdgcn-amd-amdhsa-unknown-gfx803
+// OSABI-HSA-ERR: :[[@LINE-2]]:16: error: .amdgcn_target directive processor gfx802 does not match the specified processor gfx803
 // OSABI-PAL-ERR: :[[@LINE-3]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 is incompatible with amdgcn-amd-amdpal-unknown-gfx802
 // OSABI-UNK-ERR: :[[@LINE-4]]:16: error: .amdgcn_target amdgcn-amd-amdhsa-unknown-gfx802 is incompatible with amdgcn-amd-unknown-unknown-gfx802
diff --git a/llvm/test/MC/AMDGPU/isa-version-pal.s b/llvm/test/MC/AMDGPU/isa-version-pal.s
index d095d73d2f80e..ff6ec718f1284 100644
--- a/llvm/test/MC/AMDGPU/isa-version-pal.s
+++ b/llvm/test/MC/AMDGPU/isa-version-pal.s
@@ -7,8 +7,8 @@
 // RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=gfx803 %s -filetype=null 2>&1 | FileCheck --check-prefix=OSABI-PAL-ERR %s
 
 // OSABI-PAL: .amd_amdgpu_isa "amdgcn-amd-amdpal-unknown-gfx802"
-// OSABI-UNK-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx802
+// OSABI-UNK-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-unknown-gfx802 is incompatible with amdgcn-amd-unknown-unknown-gfx802
 // OSABI-HSA-ERR: error: .amdgcn_target amdgcn-amd-amdpal-unknown-gfx802 is incompatible with amdgcn-amd-amdhsa-unknown-gfx802
-// OSABI-PAL-ERR: error: .amd_amdgpu_isa amdgcn-amd-amdpal-unknown-gfx802 does not match the specified target id amdgcn-amd-amdpal-unknown-gfx803
+// OSABI-PAL-ERR: error: .amd_amdgpu_isa directive processor gfx802 does not match the specified processor gfx803
 .amd_amdgpu_isa "amdgcn-amd-amdpal--gfx802"
 .amdgcn_target "amdgcn-amd-amdpal--gfx802"
diff --git a/llvm/test/MC/AMDGPU/isa-version-unk.s b/llvm/test/MC/AMDGPU/isa-version-unk.s
index e6bbca784efae..42f65ac774fbd 100644
--- a/llvm/test/MC/AMDGPU/isa-version-unk.s
+++ b/llvm/test/MC/AMDGPU/isa-version-unk.s
@@ -7,7 +7,7 @@
 // RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=iceland %s -filetype=null 2>&1 | FileCheck --check-prefix=OSABI-PAL-ERR %s
 
 // OSABI-UNK: .amd_amdgpu_isa "amdgcn-amd-unknown-unknown-gfx802"
-// OSABI-UNK-ERR: error: .amd_amdgpu_isa amdgcn-amd-unknown-unknown-gfx802 does not match the specified target id amdgcn-amd-unknown-unknown-gfx803
+// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive processor gfx802 does not match the specified processor gfx803
 // OSABI-HSA-ERR: error: .amdgcn_target amdgcn-amd-unknown-unknown-gfx802 is incompatible with amdgcn-amd-amdhsa-unknown-gfx802
 // OSABI-PAL-ERR: error: .amdgcn_target amdgcn-amd-unknown-unknown-gfx802 is incompatible with amdgcn-amd-amdpal-unknown-gfx802
 .amd_amdgpu_isa "amdgcn-amd-unknown--gfx802"

>From e0bfa19bbaf7116c6939539c94b44298dc715f8c Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 7 Jul 2026 09:49:00 +0200
Subject: [PATCH 3/3] Drop setCPU change

---
 llvm/include/llvm/MC/MCSubtargetInfo.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSubtargetInfo.h b/llvm/include/llvm/MC/MCSubtargetInfo.h
index 1dc1696399951..2d1053b2113c0 100644
--- a/llvm/include/llvm/MC/MCSubtargetInfo.h
+++ b/llvm/include/llvm/MC/MCSubtargetInfo.h
@@ -157,10 +157,6 @@ class LLVM_ABI MCSubtargetInfo {
     FeatureBits = FeatureBits_;
   }
 
-  /// Update the CPU string. This is needed when assembly directives
-  /// change the target CPU.
-  void setCPU(StringRef C) { CPU = C.str(); }
-
   StringRef getFeatureString() const { return FeatureString; }
 
   bool hasFeature(unsigned Feature) const {



More information about the llvm-commits mailing list