[llvm] [SPIR-V] Look up printf format string type in the correct function (PR #201523)

Tim Besard via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 01:40:43 PDT 2026


https://github.com/maleadt updated https://github.com/llvm/llvm-project/pull/201523

>From fbe15146316fbefba3d82b12e33d00741454ee25 Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Thu, 4 Jun 2026 09:44:02 +0200
Subject: [PATCH] [SPIR-V] Look up printf format string type in the correct
 function

addPrintfRequirements() resolved the SPIR-V type of the format string
operand via getSPIRVTypeForVReg() without passing the instruction's
parent MachineFunction, so the lookup defaulted to the registry's CurMF:
whichever function happened to be processed last. Virtual register
numbers are only unique within a function, so in multi-function modules
the check could inspect an unrelated function's type. A colliding vreg
with a non-UniformConstant pointer type triggered a spurious fatal
"SPV_EXT_relaxed_printf_string_address_space is required" error even
when the format string was in the constant address space; conversely,
the extension requirement could be silently skipped when the colliding
vreg had no recorded type.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply at anthropic.com>
---
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp |  3 +-
 .../multi-function-printf.ll                  | 44 +++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/multi-function-printf.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 49d9dc95603ca..8294aa4b45ea2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1478,7 +1478,8 @@ void addPrintfRequirements(const MachineInstr &MI,
                            SPIRV::RequirementHandler &Reqs,
                            const SPIRVSubtarget &ST) {
   SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
-  SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(MI.getOperand(4).getReg());
+  SPIRVTypeInst PtrType =
+      GR->getSPIRVTypeForVReg(MI.getOperand(4).getReg(), MI.getMF());
   if (PtrType) {
     MachineOperand ASOp = PtrType->getOperand(1);
     if (ASOp.isImm()) {
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/multi-function-printf.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/multi-function-printf.ll
new file mode 100644
index 0000000000000..dfabcc47f07ae
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/multi-function-printf.ll
@@ -0,0 +1,44 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; The format string is in the constant address space, so no extension is
+; required. The pointer type of the format string used to be looked up in
+; whichever function was processed last instead of the calling function,
+; spuriously requiring the extension when an unrelated function's colliding
+; virtual register had a non-UniformConstant pointer type. The loads in @last
+; only exist to populate its vreg-to-type map with non-UniformConstant types
+; at the vreg numbers that collide with the format string's vreg in @kern.
+
+; CHECK-NOT: OpExtension "SPV_EXT_relaxed_printf_string_address_space"
+; CHECK: OpExtInstImport "OpenCL.std"
+
+ at .str = private unnamed_addr addrspace(2) constant [6 x i8] c"hello\00", align 1
+
+declare i32 @printf(ptr addrspace(2), ...)
+
+define spir_kernel void @kern() {
+entry:
+  %r = call i32 (ptr addrspace(2), ...) @printf(ptr addrspace(2) @.str)
+  ret void
+}
+
+define void @last(ptr addrspace(3) %p) {
+entry:
+  %g1 = getelementptr inbounds i32, ptr addrspace(3) %p, i64 1
+  %v1 = load i32, ptr addrspace(3) %g1, align 4
+  %g2 = getelementptr inbounds i32, ptr addrspace(3) %p, i64 2
+  %v2 = load i32, ptr addrspace(3) %g2, align 4
+  %g3 = getelementptr inbounds i32, ptr addrspace(3) %p, i64 3
+  %v3 = load i32, ptr addrspace(3) %g3, align 4
+  %g4 = getelementptr inbounds i32, ptr addrspace(3) %p, i64 4
+  %v4 = load i32, ptr addrspace(3) %g4, align 4
+  %g5 = getelementptr inbounds i32, ptr addrspace(3) %p, i64 5
+  %v5 = load i32, ptr addrspace(3) %g5, align 4
+  %s1 = add i32 %v1, %v2
+  %s2 = add i32 %s1, %v3
+  %s3 = add i32 %s2, %v4
+  %s4 = add i32 %s3, %v5
+  store i32 %s4, ptr addrspace(3) %p, align 4
+  ret void
+}



More information about the llvm-commits mailing list