[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