[llvm] [SPIR-V] Emit UniformId decoration as OpDecorateId with a Scope id operand (PR #207958)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 02:54:03 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/207958

>From fa293b2e7f7427ece6f1f99c6d84720469dd498f Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Tue, 7 Jul 2026 12:20:02 +0200
Subject: [PATCH 1/3] [SPIR-V] Emit UniformId decoration as OpDecorateId with a
 Scope id operand

Per spec, UniformId operand is a Scope `<id>`, not a literal

Previously it was printed via `printSymbolicOperand<ScopeOperand>`, which asserts on a real id operand, and never emitted correctly
---
 .../SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp   |  2 +-
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp          | 24 ++++++++++++++++---
 .../hlsl-intrinsics/vk-ext-builtin-input.ll   | 11 +++++++++
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index b7dcd10bac809..44192b963d3a1 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -398,7 +398,7 @@ void SPIRVInstPrinter::printOpDecorate(const MCInst *MI, raw_ostream &O) {
       printSymbolicOperand<OperandCategory::BuiltInOperand>(MI, NumFixedOps, O);
       break;
     case Decoration::UniformId:
-      printSymbolicOperand<OperandCategory::ScopeOperand>(MI, NumFixedOps, O);
+      printOperand(MI, NumFixedOps, O);
       break;
     case Decoration::FuncParamAttr:
       printSymbolicOperand<OperandCategory::FunctionParameterAttributeOperand>(
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index cb4ecee69c2f3..9afb7cbeb24a6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -318,9 +318,27 @@ void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder,
             static_cast<uint32_t>(SPIRV::Decoration::FPFastMathMode)) {
       continue; // Ignored.
     }
-    auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
-                   .addUse(Reg)
-                   .addImm(static_cast<uint32_t>(DecorationId->getZExtValue()));
+    uint32_t Dec = static_cast<uint32_t>(DecorationId->getZExtValue());
+    if (Dec == static_cast<uint32_t>(SPIRV::Decoration::UniformId)) {
+      ConstantInt *ScopeV =
+          OpMD->getNumOperands() > 1
+              ? mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(1))
+              : nullptr;
+      if (!ScopeV || !isUInt<32>(ScopeV->getZExtValue()))
+        report_fatal_error("Expect Scope <id> operand of the UniformId "
+                           "decoration");
+      SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
+      SPIRVTypeInst SpvTypeInt32 =
+          GR->getOrCreateSPIRVIntegerType(32, MIRBuilder);
+      Register ScopeReg = GR->buildConstantInt(
+          ScopeV->getZExtValue(), MIRBuilder, SpvTypeInt32, /*EmitIR=*/false);
+      MIRBuilder.buildInstr(SPIRV::OpDecorateId)
+          .addUse(Reg)
+          .addImm(Dec)
+          .addUse(ScopeReg);
+      continue;
+    }
+    auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate).addUse(Reg).addImm(Dec);
     for (unsigned OpI = 1, OpE = OpMD->getNumOperands(); OpI != OpE; ++OpI) {
       if (ConstantInt *OpV =
               mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(OpI)))
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/vk-ext-builtin-input.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/vk-ext-builtin-input.ll
index a551bf8078ad4..9c5300fdb080e 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/vk-ext-builtin-input.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/vk-ext-builtin-input.ll
@@ -3,6 +3,7 @@
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %}
 
 ; CHECK-DAG:        OpDecorate %[[#WorkgroupId:]] BuiltIn WorkgroupId
+; CHECK-DAG:        OpDecorateId %[[#UniformVar:]] UniformId %[[#Scope:]]
 
 ; CHECK-DAG:             %[[#uint:]] = OpTypeInt 32 0
 ; CHECK-DAG:           %[[#uint_0:]] = OpConstant %[[#uint]] 0
@@ -10,7 +11,9 @@
 ; CHECK-DAG:   %[[#ptr_Input_uint:]] = OpTypePointer Input %[[#uint]]
 ; CHECK-DAG: %[[#ptr_Input_v3uint:]] = OpTypePointer Input %[[#v3uint]]
 ; CHECK-DAG:      %[[#WorkgroupId:]] = OpVariable %[[#ptr_Input_v3uint]] Input
+; CHECK-DAG:            %[[#Scope]] = OpConstant %[[#uint]] 2
 @var = external local_unnamed_addr addrspace(7) externally_initialized constant <3 x i32>, align 16, !spirv.Decorations !0
+ at uvar = external local_unnamed_addr addrspace(7) externally_initialized constant i32, !spirv.Decorations !2
 
 define i32 @foo() {
 entry:
@@ -21,5 +24,13 @@ entry:
   ret i32 %0
 }
 
+define i32 @bar() {
+entry:
+  %0 = load i32, ptr addrspace(7) @uvar
+  ret i32 %0
+}
+
 !0 = !{!1}
 !1 = !{i32 11, i32 26}
+!2 = !{!3}
+!3 = !{i32 27, i32 2} ; 27 is UniformId decoration, 2 is Workgroup scope

>From 4eea9a15dcc7e6bf9b12ac7e739ec75abe20d5fc Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 9 Jul 2026 17:46:55 +0200
Subject: [PATCH 2/3] check == 2

---
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 9afb7cbeb24a6..ef80fe146b415 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -321,7 +321,7 @@ void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder,
     uint32_t Dec = static_cast<uint32_t>(DecorationId->getZExtValue());
     if (Dec == static_cast<uint32_t>(SPIRV::Decoration::UniformId)) {
       ConstantInt *ScopeV =
-          OpMD->getNumOperands() > 1
+          OpMD->getNumOperands() == 2
               ? mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(1))
               : nullptr;
       if (!ScopeV || !isUInt<32>(ScopeV->getZExtValue()))

>From 5dae596b67ea7f4db3bb03e7e51ec74debbb6863 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 13 Jul 2026 11:53:53 +0200
Subject: [PATCH 3/3] use assert

---
 llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index ef80fe146b415..feb4fd0ab902d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -324,9 +324,8 @@ void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder,
           OpMD->getNumOperands() == 2
               ? mdconst::dyn_extract<ConstantInt>(OpMD->getOperand(1))
               : nullptr;
-      if (!ScopeV || !isUInt<32>(ScopeV->getZExtValue()))
-        report_fatal_error("Expect Scope <id> operand of the UniformId "
-                           "decoration");
+      assert(ScopeV && isUInt<32>(ScopeV->getZExtValue()) &&
+             "Expect Scope <id> operand of the UniformId decoration");
       SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
       SPIRVTypeInst SpvTypeInt32 =
           GR->getOrCreateSPIRVIntegerType(32, MIRBuilder);



More information about the llvm-commits mailing list