[llvm] 5fcab35 - [AMDGPU] Add assembler check for GFX1250 unclaused vmem workaround (#209517)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 02:39:24 PDT 2026


Author: Jay Foad
Date: 2026-07-17T10:39:20+01:00
New Revision: 5fcab35be3b450256e3b02a735900071c0b74a54

URL: https://github.com/llvm/llvm-project/commit/5fcab35be3b450256e3b02a735900071c0b74a54
DIFF: https://github.com/llvm/llvm-project/commit/5fcab35be3b450256e3b02a735900071c0b74a54.diff

LOG: [AMDGPU] Add assembler check for GFX1250 unclaused vmem workaround (#209517)

Warn if an entrypoint does not start with the standard workaround
sequence.

Added: 
    llvm/test/MC/AMDGPU/amdhsa-kernel-prologue.s

Modified: 
    llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
    llvm/test/MC/AMDGPU/hsa-gfx1250-v4.s
    llvm/test/MC/AMDGPU/hsa-gfx1251-v4.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 300a254662857..7ead3d6f2b263 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -1412,6 +1412,21 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
   /// update the target ID first.
   bool TargetDirectiveEmitted = false;
 
+  /// State for checking that every kernel named in a .amdhsa_kernel directive
+  /// begins with the required prologue instruction sequence. Because the
+  /// directive may appear either before or after the kernel's label (it is
+  /// normally emitted after the function body, in .rodata), validation is
+  /// deferred to onEndOfFile(). We record an order-independent timeline of
+  /// parsed labels and emitted instruction opcodes, plus the set of symbols
+  /// named by .amdhsa_kernel directives, and match them up at end of file.
+  SmallVector<unsigned> OpcodeStream;
+  SmallVector<std::tuple<const MCSymbol *, SMLoc, unsigned>>
+      OpcodeStreamSymbols;
+  SmallPtrSet<const MCSymbol *, 8> AMDHSAKernelSymbols;
+
+  /// Verify recorded kernel prologues.
+  void checkKernelPrologues();
+
 private:
   void createConstantSymbol(StringRef Id, int64_t Val);
 
@@ -1710,6 +1725,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
                                uint64_t &ErrorInfo,
                                bool MatchingInlineAsm) override;
   bool ParseDirective(AsmToken DirectiveID) override;
+  void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override;
   void onEndOfFile() override;
   ParseStatus parseOperand(OperandVector &Operands, StringRef Mnemonic,
                            OperandMode Mode = OperandMode_Default);
@@ -5936,6 +5952,8 @@ bool AMDGPUAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     }
     emitTargetDirective();
     Out.emitInstruction(Inst, getSTI());
+    // Record for kernel prologue checking.
+    OpcodeStream.push_back(Inst.getOpcode());
     return false;
   }
 
@@ -6142,6 +6160,10 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
   if (getParser().parseIdentifier(KernelName))
     return true;
 
+  // Remember the kernel name so its prologue can be checked at end of file.
+  // The matching label may have been parsed already or may follow later.
+  AMDHSAKernelSymbols.insert(getContext().getOrCreateSymbol(KernelName));
+
   AMDGPU::MCKernelDescriptor KD =
       AMDGPU::MCKernelDescriptor::getDefaultAmdhsaKernelDescriptor(
           &getSTI(), getContext());
@@ -7070,8 +7092,35 @@ bool AMDGPUAsmParser::ParseDirectiveAMDGPUInfo() {
   return false;
 }
 
+void AMDGPUAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
+  // Record every parsed label in the timeline so that, at end of file, the
+  // instructions following a kernel's label can be located regardless of
+  // whether the .amdhsa_kernel directive came before or after the label.
+  OpcodeStreamSymbols.emplace_back(Symbol, IDLoc, OpcodeStream.size());
+}
+
+void AMDGPUAsmParser::checkKernelPrologues() {
+  if (getFeatureBits()[AMDGPU::FeatureRequiresInitialUnclausedVmem]) {
+    static const unsigned Required[] = {GLOBAL_WB_gfx12, V_NOP_e32_gfx12};
+    for (auto [Sym, Loc, Offset] : OpcodeStreamSymbols) {
+      if (!AMDHSAKernelSymbols.contains(Sym))
+        continue;
+      ArrayRef<unsigned> Prologue = ArrayRef(OpcodeStream).drop_front(Offset);
+      if (Prologue.take_front(std::size(Required)) != ArrayRef(Required)) {
+        Warning(Loc, "kernel '" + Sym->getName() +
+                         "' does not begin with the required prologue "
+                         "sequence: GLOBAL_WB followed by V_NOP");
+      }
+    }
+  }
+  OpcodeStream.clear();
+  OpcodeStreamSymbols.clear();
+  AMDHSAKernelSymbols.clear();
+}
+
 void AMDGPUAsmParser::onEndOfFile() {
   emitTargetDirective();
+  checkKernelPrologues();
   if (InfoData)
     getTargetStreamer().emitAMDGPUInfo(*InfoData);
 }

diff  --git a/llvm/test/MC/AMDGPU/amdhsa-kernel-prologue.s b/llvm/test/MC/AMDGPU/amdhsa-kernel-prologue.s
new file mode 100644
index 0000000000000..824eef3611c1a
--- /dev/null
+++ b/llvm/test/MC/AMDGPU/amdhsa-kernel-prologue.s
@@ -0,0 +1,28 @@
+// RUN: llvm-mc -triple=amdgcn-amd-amdhsa -mcpu=gfx1250 %s -filetype=null 2>&1 | FileCheck %s -implicit-check-not=warning: -check-prefix=GFX1250
+
+// GFX1250: :[[@LINE+1]]:1: warning: kernel 'test_wrong_before' does not begin with the required prologue sequence: GLOBAL_WB followed by V_NOP
+test_wrong_before:
+  s_nop 1
+
+.amdhsa_kernel test_wrong_before
+  .amdhsa_next_free_sgpr 0
+  .amdhsa_next_free_vgpr 0
+.end_amdhsa_kernel
+
+.amdhsa_kernel test_wrong_after
+  .amdhsa_next_free_sgpr 0
+  .amdhsa_next_free_vgpr 0
+.end_amdhsa_kernel
+
+// GFX1250: :[[@LINE+1]]:1: warning: kernel 'test_wrong_after' does not begin with the required prologue sequence: GLOBAL_WB followed by V_NOP
+test_wrong_after:
+  s_nop 2
+
+.amdhsa_kernel test_correct
+  .amdhsa_next_free_sgpr 0
+  .amdhsa_next_free_vgpr 0
+.end_amdhsa_kernel
+
+test_correct:
+  global_wb
+  v_nop

diff  --git a/llvm/test/MC/AMDGPU/hsa-gfx1250-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx1250-v4.s
index 294f46cbde48f..bb877ede1f4c1 100644
--- a/llvm/test/MC/AMDGPU/hsa-gfx1250-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-gfx1250-v4.s
@@ -70,31 +70,43 @@
 .p2align 8
 .type minimal, at function
 minimal:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type complete, at function
 complete:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type special_sgpr, at function
 special_sgpr:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type disabled_user_sgpr, at function
 disabled_user_sgpr:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type max_lds_size, at function
 max_lds_size:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type max_vgprs, at function
 max_vgprs:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .rodata

diff  --git a/llvm/test/MC/AMDGPU/hsa-gfx1251-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx1251-v4.s
index 8e1e34651be6c..201d374f0ec28 100644
--- a/llvm/test/MC/AMDGPU/hsa-gfx1251-v4.s
+++ b/llvm/test/MC/AMDGPU/hsa-gfx1251-v4.s
@@ -70,31 +70,43 @@
 .p2align 8
 .type minimal, at function
 minimal:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type complete, at function
 complete:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type special_sgpr, at function
 special_sgpr:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type disabled_user_sgpr, at function
 disabled_user_sgpr:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type max_lds_size, at function
 max_lds_size:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .p2align 8
 .type max_vgprs, at function
 max_vgprs:
+  global_wb scope:SCOPE_CU
+  v_nop
   s_endpgm
 
 .rodata


        


More information about the llvm-commits mailing list