[llvm] [SPIRV] Add support for the extension SPV_EXT_relaxed_printf_string_address_space (PR #160245)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 25 22:43:38 PDT 2025


https://github.com/EbinJose2002 updated https://github.com/llvm/llvm-project/pull/160245

>From ebe2ad53070c1147437b2c68a4f67832068a5c5d Mon Sep 17 00:00:00 2001
From: EbinJose2002 <ebin.jose at multicorewareinc.com>
Date: Tue, 8 Jul 2025 17:57:43 +0530
Subject: [PATCH 1/2] A workaround for the extension relaxed_printf for SPIRV

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       | 28 +++++-
 llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp    |  5 +-
 .../builtin_printf.ll                         |  9 ++
 .../non-constant-printf.ll                    | 97 +++++++++++++++++++
 4 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 2abd9d36f7606..caa8bde905876 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1132,7 +1132,33 @@ static bool generateExtInst(const SPIRV::IncomingCall *Call,
   const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
   uint32_t Number =
       SPIRV::lookupExtendedBuiltin(Builtin->Name, Builtin->Set)->Number;
-
+  if (Builtin->Name == "printf") {
+    const SPIRVType *PtrType = GR->getSPIRVTypeForVReg(Call->Arguments[0]);
+    if (PtrType) {
+      MachineOperand ASOp = PtrType->getOperand(1);
+      if (ASOp.isImm()) {
+        unsigned AddrSpace = ASOp.getImm();
+        if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
+          MachineFunction &MF = MIRBuilder.getMF();
+          const auto *ST =
+              static_cast<const SPIRVSubtarget *>(&MF.getSubtarget());
+          if (!ST->canUseExtension(
+                  SPIRV::Extension::
+                      SPV_EXT_relaxed_printf_string_address_space)) {
+            report_fatal_error(
+                "Either SPV_EXT_relaxed_printf_string_address_space extension "
+                "should be allowed to translate this module, because this LLVM "
+                "module contains the printf function with format string, whose "
+                "address space is not equal to 2 (constant).",
+                false);
+          }
+          MIRBuilder.buildInstr(SPIRV::OpExtension)
+              .addImm(SPIRV::Extension::
+                          SPV_EXT_relaxed_printf_string_address_space);
+        }
+      }
+    }
+  }
   // Build extended instruction.
   auto MIB =
       MIRBuilder.buildInstr(SPIRV::OpExtInst)
diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
index e7da5504b2d58..a75888c260334 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
@@ -147,7 +147,10 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
         {"SPV_KHR_float_controls2",
          SPIRV::Extension::Extension::SPV_KHR_float_controls2},
         {"SPV_INTEL_tensor_float32_conversion",
-         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}};
+         SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion},
+        {"SPV_EXT_relaxed_printf_string_address_space",
+         SPIRV::Extension::Extension::
+             SPV_EXT_relaxed_printf_string_address_space}};
 
 bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
                                   StringRef ArgValue,
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
new file mode 100644
index 0000000000000..c7c6cc05c13f4
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
@@ -0,0 +1,9 @@
+ at .str = external addrspace(1) constant [21 x i8]
+
+define spir_kernel void @_ZTSZZ4mainENKUlRN4sycl3_V17handlerEE_clES2_EUlvE_() {
+entry:
+  %call.i = tail call spir_func i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) addrspacecast (ptr addrspace(1) @.str to ptr addrspace(4)), ptr addrspace(4) null, ptr addrspace(4) null, i32 0, i32 0, i32 0, ptr addrspace(4) null)
+  ret void
+}
+
+declare spir_func i32 @printf(ptr addrspace(4), ...)
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll
new file mode 100644
index 0000000000000..9901d9fdd8798
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll
@@ -0,0 +1,97 @@
+; RUN: llvm-as %s -o %t.bc
+; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT
+
+; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space
+; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
+
+; RUN: llvm-spirv -to-binary %t.spt -o %t.spv
+; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
+; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
+; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
+
+; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension:
+; CHECK-WO-EXT: SPV_EXT_relaxed_printf_string_address_space extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant).
+
+; CHECK-SPIRV: Extension "SPV_EXT_relaxed_printf_string_address_space"
+; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std"
+; CHECK-SPIRV-DAG: TypeInt [[#TypeInt32Id:]] 32 0
+; CHECK-SPIRV-DAG: TypeInt [[#TypeInt8Id:]] 8 0
+; CHECK-SPIRV-DAG: TypeInt [[#TypeInt64Id:]] 64 0
+; CHECK-SPIRV: TypeArray [[#TypeArrayId:]] [[#TypeInt8Id]] [[#]]
+; CHECK-SPIRV: TypePointer [[#ConstantStorClassGlobalPtrTy:]] 0 [[#TypeArrayId]]
+; CHECK-SPIRV: TypePointer [[#WGStorClassGlobalPtrTy:]] 5 [[#TypeArrayId]]
+; CHECK-SPIRV: TypePointer [[#CrossWFStorClassGlobalPtrTy:]] 4 [[#TypeArrayId]]
+; CHECK-SPIRV: TypePointer [[#GenericStorClassGlobalPtrTy:]] 8 [[#TypeArrayId]]
+; CHECK-SPIRV: TypePointer [[#FunctionStorClassPtrTy:]] 7 [[#TypeInt8Id]]
+; CHECK-SPIRV: TypePointer [[#WGStorClassPtrTy:]] 5 [[#TypeInt8Id]]
+; CHECK-SPIRV: TypePointer [[#CrossWFStorClassPtrTy:]] 4 [[#TypeInt8Id]]
+; CHECK-SPIRV: TypePointer [[#GenericStorClassPtrTy:]] 8 [[#TypeInt8Id]]
+; CHECK-SPIRV: ConstantComposite [[#TypeArrayId]] [[#ConstantCompositeId:]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]]
+; CHECK-SPIRV: Variable [[#ConstantStorClassGlobalPtrTy]] [[#]] 0 [[#ConstantCompositeId:]]
+; CHECK-SPIRV: Variable [[#WGStorClassGlobalPtrTy]] [[#]] 5 [[#ConstantCompositeId:]]
+; CHECK-SPIRV: Variable [[#CrossWFStorClassGlobalPtrTy]] [[#]] 4 [[#ConstantCompositeId:]]
+; CHECK-SPIRV: Variable [[#GenericStorClassGlobalPtrTy]] [[#]] 8 [[#ConstantCompositeId:]]
+; CHECK-SPIRV: InBoundsPtrAccessChain [[#FunctionStorClassPtrTy]] [[#GEP1:]]
+; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP1]]
+; CHECK-SPIRV: InBoundsPtrAccessChain [[#WGStorClassPtrTy]] [[#GEP2:]]
+; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP2]]
+; CHECK-SPIRV: InBoundsPtrAccessChain [[#CrossWFStorClassPtrTy:]] [[#GEP3:]]
+; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP3]]
+; CHECK-SPIRV: InBoundsPtrAccessChain [[#GenericStorClassPtrTy:]] [[#GEP4:]]
+; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP4]]
+
+; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr {{.*}}
+; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) {{.*}}
+; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) {{.*}}
+; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(ptr addrspace(4) {{.*}}
+
+; ModuleID = 'non-constant-printf'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
+target triple = "spir-unknown-unknown"
+
+ at 0 = internal unnamed_addr addrspace(2) constant [6 x i8] c"Test\0A\00", align 1
+ at 1 = internal unnamed_addr addrspace(1) constant [6 x i8] c"Test\0A\00", align 1
+ at 2 = internal unnamed_addr addrspace(3) constant [6 x i8] c"Test\0A\00", align 1
+
+; Function Attrs: nounwind
+define spir_kernel void @test() #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !3 !kernel_arg_type !3 !kernel_arg_type_qual !3 !kernel_arg_base_type !3 {
+  %tmp1 = alloca [6 x i8], align 1
+  call void @llvm.memcpy.p0.p2.i64(ptr align 1 %tmp1, ptr addrspace(2) align 1 @0, i64 6, i1 false)
+  %1 = getelementptr inbounds [6 x i8], ptr %tmp1, i32 0, i32 0
+  %2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr %1) #0
+  %3 = getelementptr inbounds [6 x i8], ptr addrspace(1) @1, i32 0, i32 0
+  %4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) %3) #0
+  %5 = getelementptr inbounds [6 x i8], ptr addrspace(3) @2, i32 0, i32 0
+  %6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) %5) #0
+  ret void
+}
+
+; Function Attrs: nounwind
+declare spir_func i32 @_Z18__spirv_ocl_printfPc(ptr) #0
+
+; Function Attrs: nounwind
+declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1)) #0
+
+; Function Attrs: nounwind
+declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3)) #0
+
+
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0.p2.i64(ptr captures(none), ptr addrspace(2) captures(none) readonly, i64, i1) #0
+
+attributes #0 = { nounwind }
+
+!spirv.MemoryModel = !{!0}
+!opencl.enable.FP_CONTRACT = !{}
+!spirv.Source = !{!1}
+!opencl.spir.version = !{!2}
+!opencl.ocl.version = !{!2}
+!opencl.used.extensions = !{!3}
+!opencl.used.optional.core.features = !{!3}
+!spirv.Generator = !{!4}
+
+!0 = !{i32 1, i32 2}
+!1 = !{i32 3, i32 200000}
+!2 = !{i32 2, i32 0}
+!3 = !{}
+!4 = !{i16 7, i16 0}

>From b91611f47cd27d8333447757be3a86f73bf6cbac Mon Sep 17 00:00:00 2001
From: EbinJose2002 <ebin.jose at multicorewareinc.com>
Date: Fri, 25 Jul 2025 12:48:49 +0530
Subject: [PATCH 2/2] Added the check inside moduleanalysis.

---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       |  28 +----
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp |  31 +++++
 .../builtin_printf.ll                         |  25 +++-
 .../non-constant-printf.ll                    | 119 ++++++------------
 4 files changed, 87 insertions(+), 116 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index caa8bde905876..2abd9d36f7606 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1132,33 +1132,7 @@ static bool generateExtInst(const SPIRV::IncomingCall *Call,
   const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
   uint32_t Number =
       SPIRV::lookupExtendedBuiltin(Builtin->Name, Builtin->Set)->Number;
-  if (Builtin->Name == "printf") {
-    const SPIRVType *PtrType = GR->getSPIRVTypeForVReg(Call->Arguments[0]);
-    if (PtrType) {
-      MachineOperand ASOp = PtrType->getOperand(1);
-      if (ASOp.isImm()) {
-        unsigned AddrSpace = ASOp.getImm();
-        if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
-          MachineFunction &MF = MIRBuilder.getMF();
-          const auto *ST =
-              static_cast<const SPIRVSubtarget *>(&MF.getSubtarget());
-          if (!ST->canUseExtension(
-                  SPIRV::Extension::
-                      SPV_EXT_relaxed_printf_string_address_space)) {
-            report_fatal_error(
-                "Either SPV_EXT_relaxed_printf_string_address_space extension "
-                "should be allowed to translate this module, because this LLVM "
-                "module contains the printf function with format string, whose "
-                "address space is not equal to 2 (constant).",
-                false);
-          }
-          MIRBuilder.buildInstr(SPIRV::OpExtension)
-              .addImm(SPIRV::Extension::
-                          SPV_EXT_relaxed_printf_string_address_space);
-        }
-      }
-    }
-  }
+
   // Build extended instruction.
   auto MIB =
       MIRBuilder.buildInstr(SPIRV::OpExtInst)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index b7e371d190866..ab831c1884fba 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1222,6 +1222,31 @@ static void AddDotProductRequirements(const MachineInstr &MI,
   }
 }
 
+void addPrintfRequirements(const MachineInstr &MI,
+                           SPIRV::RequirementHandler &Reqs,
+                           const SPIRVSubtarget &ST) {
+  SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
+  const SPIRVType *PtrType = GR->getSPIRVTypeForVReg(MI.getOperand(4).getReg());
+  if (PtrType) {
+    MachineOperand ASOp = PtrType->getOperand(1);
+    if (ASOp.isImm()) {
+      unsigned AddrSpace = ASOp.getImm();
+      if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
+        if (!ST.canUseExtension(
+                SPIRV::Extension::
+                    SPV_EXT_relaxed_printf_string_address_space)) {
+          report_fatal_error("SPV_EXT_relaxed_printf_string_address_space is "
+                             "required because printf uses a format string not "
+                             "in constant address space.",
+                             false);
+        }
+        Reqs.addExtension(
+            SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
+      }
+    }
+  }
+}
+
 void addInstrRequirements(const MachineInstr &MI,
                           SPIRV::RequirementHandler &Reqs,
                           const SPIRVSubtarget &ST) {
@@ -1296,6 +1321,12 @@ void addInstrRequirements(const MachineInstr &MI,
         static_cast<int64_t>(
             SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
       Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
+      break;
+    }
+    if (MI.getOperand(3).getImm() ==
+        static_cast<int64_t>(SPIRV::OpenCLExtInst::printf)) {
+      addPrintfRequirements(MI, Reqs, ST);
+      break;
     }
     break;
   }
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
index c7c6cc05c13f4..093d172c5c1b1 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/builtin_printf.ll
@@ -1,9 +1,24 @@
- at .str = external addrspace(1) constant [21 x i8]
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space %s -o - | FileCheck %s
+; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
 
-define spir_kernel void @_ZTSZZ4mainENKUlRN4sycl3_V17handlerEE_clES2_EUlvE_() {
+; CHECK: OpExtension "SPV_EXT_relaxed_printf_string_address_space"
+; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] printf
+
+; CHECK-ERROR: LLVM ERROR: SPV_EXT_relaxed_printf_string_address_space is required because printf uses a format string not in constant address space.
+
+ at .str = private unnamed_addr addrspace(1) constant [4 x i8] c"%d\0A\00", align 1
+
+declare spir_func i32 @printf(ptr addrspace(4), ...)
+
+define spir_kernel void @test_kernel() {
 entry:
-  %call.i = tail call spir_func i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) addrspacecast (ptr addrspace(1) @.str to ptr addrspace(4)), ptr addrspace(4) null, ptr addrspace(4) null, i32 0, i32 0, i32 0, ptr addrspace(4) null)
+  ; Format string in addrspace(1) → cast to addrspace(4)
+  %format = addrspacecast ptr addrspace(1) @.str to ptr addrspace(4)
+  %val = alloca i32, align 4
+  store i32 123, ptr %val, align 4
+  %loaded = load i32, ptr %val, align 4
+
+  ; Call printf with non-constant format string
+  %call = call spir_func i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) %format, i32 %loaded)
   ret void
 }
-
-declare spir_func i32 @printf(ptr addrspace(4), ...)
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll
index 9901d9fdd8798..b54d59b30309f 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll
@@ -1,97 +1,48 @@
-; RUN: llvm-as %s -o %t.bc
-; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT
-
-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space
-; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
-
-; RUN: llvm-spirv -to-binary %t.spt -o %t.spv
-; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
-; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
-; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
-
-; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension:
-; CHECK-WO-EXT: SPV_EXT_relaxed_printf_string_address_space extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant).
-
-; CHECK-SPIRV: Extension "SPV_EXT_relaxed_printf_string_address_space"
-; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std"
-; CHECK-SPIRV-DAG: TypeInt [[#TypeInt32Id:]] 32 0
-; CHECK-SPIRV-DAG: TypeInt [[#TypeInt8Id:]] 8 0
-; CHECK-SPIRV-DAG: TypeInt [[#TypeInt64Id:]] 64 0
-; CHECK-SPIRV: TypeArray [[#TypeArrayId:]] [[#TypeInt8Id]] [[#]]
-; CHECK-SPIRV: TypePointer [[#ConstantStorClassGlobalPtrTy:]] 0 [[#TypeArrayId]]
-; CHECK-SPIRV: TypePointer [[#WGStorClassGlobalPtrTy:]] 5 [[#TypeArrayId]]
-; CHECK-SPIRV: TypePointer [[#CrossWFStorClassGlobalPtrTy:]] 4 [[#TypeArrayId]]
-; CHECK-SPIRV: TypePointer [[#GenericStorClassGlobalPtrTy:]] 8 [[#TypeArrayId]]
-; CHECK-SPIRV: TypePointer [[#FunctionStorClassPtrTy:]] 7 [[#TypeInt8Id]]
-; CHECK-SPIRV: TypePointer [[#WGStorClassPtrTy:]] 5 [[#TypeInt8Id]]
-; CHECK-SPIRV: TypePointer [[#CrossWFStorClassPtrTy:]] 4 [[#TypeInt8Id]]
-; CHECK-SPIRV: TypePointer [[#GenericStorClassPtrTy:]] 8 [[#TypeInt8Id]]
-; CHECK-SPIRV: ConstantComposite [[#TypeArrayId]] [[#ConstantCompositeId:]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]]
-; CHECK-SPIRV: Variable [[#ConstantStorClassGlobalPtrTy]] [[#]] 0 [[#ConstantCompositeId:]]
-; CHECK-SPIRV: Variable [[#WGStorClassGlobalPtrTy]] [[#]] 5 [[#ConstantCompositeId:]]
-; CHECK-SPIRV: Variable [[#CrossWFStorClassGlobalPtrTy]] [[#]] 4 [[#ConstantCompositeId:]]
-; CHECK-SPIRV: Variable [[#GenericStorClassGlobalPtrTy]] [[#]] 8 [[#ConstantCompositeId:]]
-; CHECK-SPIRV: InBoundsPtrAccessChain [[#FunctionStorClassPtrTy]] [[#GEP1:]]
-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP1]]
-; CHECK-SPIRV: InBoundsPtrAccessChain [[#WGStorClassPtrTy]] [[#GEP2:]]
-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP2]]
-; CHECK-SPIRV: InBoundsPtrAccessChain [[#CrossWFStorClassPtrTy:]] [[#GEP3:]]
-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP3]]
-; CHECK-SPIRV: InBoundsPtrAccessChain [[#GenericStorClassPtrTy:]] [[#GEP4:]]
-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP4]]
-
-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr {{.*}}
-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) {{.*}}
-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) {{.*}}
-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(ptr addrspace(4) {{.*}}
-
-; ModuleID = 'non-constant-printf'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
-target triple = "spir-unknown-unknown"
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space %s -o - | FileCheck %s
+; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+; CHECK: OpExtension "SPV_EXT_relaxed_printf_string_address_space"
+; CHECK: %[[#ExtInstSetId:]] = OpExtInstImport "OpenCL.std"
+; CHECK-DAG: %[[#TypeInt32Id:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#TypeInt8Id:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#TypeInt64Id:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#TypeArrayId:]] = OpTypeArray %[[#TypeInt8Id]] %[[#]]
+; CHECK-DAG: %[[#ConstantStorClassGlobalPtrTy:]] = OpTypePointer UniformConstant %[[#TypeArrayId]]
+; CHECK-DAG: %[[#WGStorClassGlobalPtrTy:]] = OpTypePointer Workgroup %[[#TypeArrayId]]
+; CHECK-DAG: %[[#CrossWFStorClassGlobalPtrTy:]] = OpTypePointer CrossWorkgroup %[[#TypeArrayId]]
+; CHECK-DAG: %[[#FunctionStorClassPtrTy:]] = OpTypePointer Function %[[#TypeInt8Id]]
+; CHECK-DAG: %[[#WGStorClassPtrTy:]] = OpTypePointer Workgroup %[[#TypeInt8Id]]
+; CHECK-DAG: %[[#CrossWFStorClassPtrTy:]] = OpTypePointer CrossWorkgroup %[[#TypeInt8Id]]
+; CHECK: %[[#ConstantCompositeId:]] = OpConstantComposite %[[#TypeArrayId]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]]
+; CHECK: %[[#]] = OpVariable %[[#ConstantStorClassGlobalPtrTy]] UniformConstant %[[#ConstantCompositeId]]
+; CHECK: %[[#]] = OpVariable %[[#CrossWFStorClassGlobalPtrTy]] CrossWorkgroup %[[#ConstantCompositeId]]
+; CHECK: %[[#]] = OpVariable %[[#WGStorClassGlobalPtrTy]] Workgroup %[[#ConstantCompositeId]]
+; CHECK: %[[#GEP1:]] = OpInBoundsPtrAccessChain %[[#FunctionStorClassPtrTy]] %[[#]] %[[#]] %[[#]]
+; CHECK: %[[#]] = OpExtInst %[[#TypeInt32Id]] %[[#ExtInstSetId:]] printf %[[#GEP1]]
+; CHECK: %[[#GEP2:]] = OpInBoundsPtrAccessChain %[[#CrossWFStorClassPtrTy]] %[[#]] %[[#]] %[[#]]
+; CHECK: %[[#]] = OpExtInst %[[#TypeInt32Id]] %[[#ExtInstSetId:]] printf %[[#GEP2]]
+; CHECK: %[[#GEP3:]] = OpInBoundsPtrAccessChain %[[#WGStorClassPtrTy]] %[[#]] %[[#]] %[[#]]
+; CHECK: %[[#]] = OpExtInst %[[#TypeInt32Id]] %[[#ExtInstSetId:]] printf %[[#GEP3]]
+
+; CHECK-ERROR: LLVM ERROR: SPV_EXT_relaxed_printf_string_address_space is required because printf uses a format string not in constant address space.
 
 @0 = internal unnamed_addr addrspace(2) constant [6 x i8] c"Test\0A\00", align 1
 @1 = internal unnamed_addr addrspace(1) constant [6 x i8] c"Test\0A\00", align 1
 @2 = internal unnamed_addr addrspace(3) constant [6 x i8] c"Test\0A\00", align 1
 
-; Function Attrs: nounwind
-define spir_kernel void @test() #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !3 !kernel_arg_type !3 !kernel_arg_type_qual !3 !kernel_arg_base_type !3 {
+define spir_kernel void @test() {
   %tmp1 = alloca [6 x i8], align 1
   call void @llvm.memcpy.p0.p2.i64(ptr align 1 %tmp1, ptr addrspace(2) align 1 @0, i64 6, i1 false)
   %1 = getelementptr inbounds [6 x i8], ptr %tmp1, i32 0, i32 0
-  %2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr %1) #0
+  %2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr %1)
   %3 = getelementptr inbounds [6 x i8], ptr addrspace(1) @1, i32 0, i32 0
-  %4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) %3) #0
+  %4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) %3)
   %5 = getelementptr inbounds [6 x i8], ptr addrspace(3) @2, i32 0, i32 0
-  %6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) %5) #0
+  %6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) %5)
   ret void
 }
 
-; Function Attrs: nounwind
-declare spir_func i32 @_Z18__spirv_ocl_printfPc(ptr) #0
-
-; Function Attrs: nounwind
-declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1)) #0
-
-; Function Attrs: nounwind
-declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3)) #0
-
-
-; Function Attrs: nounwind
-declare void @llvm.memcpy.p0.p2.i64(ptr captures(none), ptr addrspace(2) captures(none) readonly, i64, i1) #0
-
-attributes #0 = { nounwind }
-
-!spirv.MemoryModel = !{!0}
-!opencl.enable.FP_CONTRACT = !{}
-!spirv.Source = !{!1}
-!opencl.spir.version = !{!2}
-!opencl.ocl.version = !{!2}
-!opencl.used.extensions = !{!3}
-!opencl.used.optional.core.features = !{!3}
-!spirv.Generator = !{!4}
-
-!0 = !{i32 1, i32 2}
-!1 = !{i32 3, i32 200000}
-!2 = !{i32 2, i32 0}
-!3 = !{}
-!4 = !{i16 7, i16 0}
+declare spir_func i32 @_Z18__spirv_ocl_printfPc(ptr)
+declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1))
+declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3))
+declare void @llvm.memcpy.p0.p2.i64(ptr captures(none), ptr addrspace(2) captures(none) readonly, i64, i1)



More information about the llvm-commits mailing list