From ebe2ad53070c1147437b2c68a4f67832068a5c5d Mon Sep 17 00:00:00 2001 From: EbinJose2002 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(&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> {"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 @@ +@.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" + +@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 { + %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 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(&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( SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) { Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info); + break; + } + if (MI.getOperand(3).getImm() == + static_cast(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 @@ -@.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. + +@.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)