[llvm-branch-commits] [llvm] [AMDGPU] Validate barrier ID in S_BARRIER_SIGNAL_ISFIRST (PR #220101)

Stanislav Mekhanoshin via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 2 12:54:13 PDT 2026


https://github.com/rampitec updated https://github.com/llvm/llvm-project/pull/220101

>From 7ce724db552099e3047bf6e874acc81191089bcc Mon Sep 17 00:00:00 2001
From: Stanislav Mekhanoshin <Stanislav.Mekhanoshin at amd.com>
Date: Mon, 31 Aug 2026 14:54:06 -0700
Subject: [PATCH] [AMDGPU] Validate barrier ID in S_BARRIER_SIGNAL_ISFIRST

Value user_cluster_barrier_id is not supported.
---
 .../Target/AMDGPU/AMDGPULowerIntrinsics.cpp   |  8 ++++
 .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp      | 23 +++++++++++
 ....barrier.signal.isfirst.invalid_barrier.ll |  9 +++++
 .../lower-intrinsics-cluster-barrier.ll       | 39 ++-----------------
 llvm/test/MC/AMDGPU/gfx12_err.s               |  3 ++
 llvm/test/MC/AMDGPU/gfx13_err.s               |  5 +++
 6 files changed, 51 insertions(+), 36 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.barrier.signal.isfirst.invalid_barrier.ll
 create mode 100644 llvm/test/MC/AMDGPU/gfx13_err.s

diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
index 1fe9b1dc88a23..194461605ba87 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
@@ -14,6 +14,7 @@
 #include "AMDGPU.h"
 #include "AMDGPUTargetMachine.h"
 #include "GCNSubtarget.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/IntrinsicsAMDGPU.h"
@@ -164,6 +165,13 @@ bool AMDGPULowerIntrinsicsImpl::visitBarrier(IntrinsicInst &I) {
         (BarrierID >= AMDGPU::Barrier::NAMED_BARRIER_FIRST &&
          BarrierID <= AMDGPU::Barrier::NAMED_BARRIER_LAST))
       IsWorkgroupScope = true;
+    else if (I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst &&
+             BarrierID == AMDGPU::Barrier::CLUSTER)
+      I.getContext().diagnose(
+          DiagnosticInfoUnsupported(*I.getFunction(),
+                                    "s_barrier_signal_isfirst does not support "
+                                    "user_cluster_barrier_id (-3)",
+                                    I.getDebugLoc()));
   } else {
     assert(I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier);
     IsWorkgroupScope = true;
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 0eab7c7be254b..93ad92237fe0e 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -1865,6 +1865,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
   bool validateLdsDirect(const MCInst &Inst, const OperandVector &Operands);
   bool validateWMMA(const MCInst &Inst, const OperandVector &Operands);
   bool validateMonitorSleep(const MCInst &Inst, const OperandVector &Operands);
+  bool validateClusterBarrierIsFirst(const MCInst &Inst,
+                                     const OperandVector &Operands);
   unsigned getConstantBusLimit(unsigned Opcode) const;
   bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
   bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
@@ -5603,6 +5605,24 @@ bool AMDGPUAsmParser::validateMonitorSleep(const MCInst &Inst,
   return true;
 }
 
+bool AMDGPUAsmParser::validateClusterBarrierIsFirst(
+    const MCInst &Inst, const OperandVector &Operands) {
+  unsigned Opc = Inst.getOpcode();
+  if (Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx12 &&
+      Opc != AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM_gfx13)
+    return true;
+
+  int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
+  int BarrierID = Inst.getOperand(Src0Idx).getImm();
+  if (BarrierID != AMDGPU::Barrier::CLUSTER)
+    return true;
+
+  Error(
+      getOperandLoc(Operands, Src0Idx),
+      "s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)");
+  return false;
+}
+
 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, SMLoc IDLoc,
                                           const OperandVector &Operands) {
   if (!validateLdsDirect(Inst, Operands))
@@ -5737,6 +5757,9 @@ bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, SMLoc IDLoc,
   if (!validateMonitorSleep(Inst, Operands)) {
     return false;
   }
+  if (!validateClusterBarrierIsFirst(Inst, Operands)) {
+    return false;
+  }
 
   return true;
 }
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.barrier.signal.isfirst.invalid_barrier.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.barrier.signal.isfirst.invalid_barrier.ll
new file mode 100644
index 0000000000000..1257bcbe8c3dd
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.barrier.signal.isfirst.invalid_barrier.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -mtriple=amdgpu12.50 -filetype=null < %s 2>&1 | FileCheck -check-prefix=ERR %s
+
+; ERR: error: <unknown>:0:0: in function invalid_barrier_id i1 (): s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)
+
+define i1 @invalid_barrier_id() {
+  %r = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -3)
+  ret i1 %r
+}
+
diff --git a/llvm/test/CodeGen/AMDGPU/lower-intrinsics-cluster-barrier.ll b/llvm/test/CodeGen/AMDGPU/lower-intrinsics-cluster-barrier.ll
index 2f1eb6a63f519..4db05e14e8c34 100644
--- a/llvm/test/CodeGen/AMDGPU/lower-intrinsics-cluster-barrier.ll
+++ b/llvm/test/CodeGen/AMDGPU/lower-intrinsics-cluster-barrier.ll
@@ -5,39 +5,6 @@
 
 declare void @foo(i1)
 
-; Verify that the explicit use of a split cluster barrier isn't optimized away.
-define amdgpu_kernel void @split_barriers() "amdgpu-flat-work-group-size"="32,32" {
-; NOOPT-LABEL: define amdgpu_kernel void @split_barriers(
-; NOOPT-SAME: ) #[[ATTR0:[0-9]+]] {
-; NOOPT-NEXT:    call void @llvm.amdgcn.s.barrier.signal(i32 -3)
-; NOOPT-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -3)
-; NOOPT-NEXT:    [[ISFIRST:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -3)
-; NOOPT-NEXT:    call void @foo(i1 [[ISFIRST]])
-; NOOPT-NEXT:    ret void
-;
-; OPT-WAVE32-LABEL: define amdgpu_kernel void @split_barriers(
-; OPT-WAVE32-SAME: ) #[[ATTR1:[0-9]+]] {
-; OPT-WAVE32-NEXT:    call void @llvm.amdgcn.s.barrier.signal(i32 -3)
-; OPT-WAVE32-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -3)
-; OPT-WAVE32-NEXT:    [[ISFIRST:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -3)
-; OPT-WAVE32-NEXT:    call void @foo(i1 [[ISFIRST]])
-; OPT-WAVE32-NEXT:    ret void
-;
-; OPT-WAVE64-LABEL: define amdgpu_kernel void @split_barriers(
-; OPT-WAVE64-SAME: ) #[[ATTR1:[0-9]+]] {
-; OPT-WAVE64-NEXT:    call void @llvm.amdgcn.s.barrier.signal(i32 -3)
-; OPT-WAVE64-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -3)
-; OPT-WAVE64-NEXT:    [[ISFIRST:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -3)
-; OPT-WAVE64-NEXT:    call void @foo(i1 [[ISFIRST]])
-; OPT-WAVE64-NEXT:    ret void
-;
-  call void @llvm.amdgcn.s.barrier.signal(i32 -3)
-  call void @llvm.amdgcn.s.barrier.wait(i16 -3)
-  %isfirst = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -3)
-  call void @foo(i1 %isfirst)
-  ret void
-}
-
 define amdgpu_kernel void @s_cluster_barrier() {
 ; NOOPT-LABEL: define amdgpu_kernel void @s_cluster_barrier() {
 ; NOOPT-NEXT:    [[TMP1:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -1)
@@ -80,7 +47,7 @@ define amdgpu_kernel void @s_cluster_barrier() {
 
 define amdgpu_kernel void @s_cluster_barrier_wg32() "amdgpu-flat-work-group-size"="32,32" {
 ; NOOPT-LABEL: define amdgpu_kernel void @s_cluster_barrier_wg32(
-; NOOPT-SAME: ) #[[ATTR0]] {
+; NOOPT-SAME: ) #[[ATTR0:[0-9]+]] {
 ; NOOPT-NEXT:    [[TMP1:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 -1)
 ; NOOPT-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -1)
 ; NOOPT-NEXT:    br i1 [[TMP1]], label %[[BB2:.*]], label %[[BB3:.*]]
@@ -92,14 +59,14 @@ define amdgpu_kernel void @s_cluster_barrier_wg32() "amdgpu-flat-work-group-size
 ; NOOPT-NEXT:    ret void
 ;
 ; OPT-WAVE32-LABEL: define amdgpu_kernel void @s_cluster_barrier_wg32(
-; OPT-WAVE32-SAME: ) #[[ATTR1]] {
+; OPT-WAVE32-SAME: ) #[[ATTR1:[0-9]+]] {
 ; OPT-WAVE32-NEXT:    call void @llvm.amdgcn.wave.barrier()
 ; OPT-WAVE32-NEXT:    call void @llvm.amdgcn.s.barrier.signal(i32 -3)
 ; OPT-WAVE32-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -3)
 ; OPT-WAVE32-NEXT:    ret void
 ;
 ; OPT-WAVE64-LABEL: define amdgpu_kernel void @s_cluster_barrier_wg32(
-; OPT-WAVE64-SAME: ) #[[ATTR1]] {
+; OPT-WAVE64-SAME: ) #[[ATTR1:[0-9]+]] {
 ; OPT-WAVE64-NEXT:    call void @llvm.amdgcn.wave.barrier()
 ; OPT-WAVE64-NEXT:    call void @llvm.amdgcn.s.barrier.signal(i32 -3)
 ; OPT-WAVE64-NEXT:    call void @llvm.amdgcn.s.barrier.wait(i16 -3)
diff --git a/llvm/test/MC/AMDGPU/gfx12_err.s b/llvm/test/MC/AMDGPU/gfx12_err.s
index 500fe0bf0d8d9..b4b08dbf677d1 100644
--- a/llvm/test/MC/AMDGPU/gfx12_err.s
+++ b/llvm/test/MC/AMDGPU/gfx12_err.s
@@ -683,3 +683,6 @@ s_wait_event { dont_wait_export_ready: 1 }
 
 s_wait_event { dont_wait_export_ready: 0 }
 // GFX12-ERR: :[[@LINE-1]]:16: error: unknown field
+
+s_barrier_signal_isfirst -3
+// GFX12-ERR: :[[@LINE-1]]:26: error: s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)
diff --git a/llvm/test/MC/AMDGPU/gfx13_err.s b/llvm/test/MC/AMDGPU/gfx13_err.s
new file mode 100644
index 0000000000000..5062f996a1584
--- /dev/null
+++ b/llvm/test/MC/AMDGPU/gfx13_err.s
@@ -0,0 +1,5 @@
+// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 6
+// RUN: not llvm-mc -triple=amdgpu13.10 -filetype=null %s 2>&1 | FileCheck --check-prefixes=GFX12-ERR --implicit-check-not=error: -strict-whitespace %s
+
+s_barrier_signal_isfirst -3
+// GFX12-ERR: :[[@LINE-1]]:26: error: s_barrier_signal_isfirst does not support user_cluster_barrier_id (-3)



More information about the llvm-branch-commits mailing list