Skip to content

Commit 97f4230

Browse files
KornevNikitavmaksimo
authored andcommitted
Support SPV_INTEL_non_constant_addrspace_printf
Spec: #5227 Original commit: KhronosGroup/SPIRV-LLVM-Translator@6e70d1c
1 parent d4fad9b commit 97f4230

File tree

6 files changed

+122
-4
lines changed

6 files changed

+122
-4
lines changed

llvm-spirv/include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ EXT(SPV_INTEL_bfloat16_conversion)
4949
EXT(SPV_INTEL_joint_matrix)
5050
EXT(SPV_INTEL_hw_thread_queries)
5151
EXT(SPV_INTEL_global_variable_decorations)
52+
EXT(SPV_INTEL_non_constant_addrspace_printf)

llvm-spirv/lib/SPIRV/SPIRVToOCL.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,14 @@ void SPIRVToOCLBase::visitCallInst(CallInst &CI) {
6969
case OpenCLLIB::Vstorea_halfn_r:
7070
visitCallSPIRVVStore(&CI, ExtOp);
7171
break;
72-
case OpenCLLIB::Printf:
73-
visitCallSPIRVPrintf(&CI, ExtOp);
72+
case OpenCLLIB::Printf: {
73+
// TODO: Lower the printf instruction with the non-constant address space
74+
// format string to suitable for OpenCL representation
75+
if (dyn_cast<PointerType>(CI.getOperand(0)->getType())
76+
->getAddressSpace() == SPIR::TypeAttributeEnum::ATTR_CONST)
77+
visitCallSPIRVPrintf(&CI, ExtOp);
7478
break;
79+
}
7580
default:
7681
visitCallSPIRVOCLExt(&CI, ExtOp);
7782
break;

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3610,14 +3610,34 @@ SPIRVValue *LLVMToSPIRVBase::transDirectCallInst(CallInst *CI,
36103610

36113611
SmallVector<std::string, 2> Dec;
36123612
if (isBuiltinTransToExtInst(CI->getCalledFunction(), &ExtSetKind, &ExtOp,
3613-
&Dec))
3613+
&Dec)) {
3614+
if (DemangledName.find("__spirv_ocl_printf") != StringRef::npos) {
3615+
auto *FormatStrPtr = cast<PointerType>(CI->getArgOperand(0)->getType());
3616+
if (FormatStrPtr->getAddressSpace() !=
3617+
SPIR::TypeAttributeEnum::ATTR_CONST) {
3618+
if (!BM->isAllowedToUseExtension(
3619+
ExtensionID::SPV_INTEL_non_constant_addrspace_printf)) {
3620+
std::string ErrorStr =
3621+
"The SPV_INTEL_non_constant_addrspace_printf extension should be "
3622+
"allowed to translate this module, because this LLVM module "
3623+
"contains the printf function with format string, whose address "
3624+
"space is not equal to 2 (constant).";
3625+
getErrorLog().checkError(false, SPIRVEC_RequiresExtension, CI,
3626+
ErrorStr);
3627+
}
3628+
BM->addExtension(ExtensionID::SPV_INTEL_non_constant_addrspace_printf);
3629+
BM->addCapability(internal::CapabilityNonConstantAddrspacePrintfINTEL);
3630+
}
3631+
}
3632+
36143633
return addDecorations(
36153634
BM->addExtInst(
36163635
transType(CI->getType()), BM->getExtInstSetId(ExtSetKind), ExtOp,
36173636
transArguments(CI, BB,
36183637
SPIRVEntry::createUnique(ExtSetKind, ExtOp).get()),
36193638
BB),
36203639
Dec);
3640+
}
36213641

36223642
Function *Callee = CI->getCalledFunction();
36233643
if (Callee->isDeclaration()) {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
591591
add(internal::CapabilityHWThreadQueryINTEL, "HWThreadQueryINTEL");
592592
add(internal::CapabilityGlobalVariableDecorationsINTEL,
593593
"GlobalVariableDecorationsINTEL");
594+
add(internal::CapabilityNonConstantAddrspacePrintfINTEL,
595+
"NonConstantAddrspacePrintfINTEL");
594596
}
595597
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
596598

llvm-spirv/lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ enum InternalCapability {
7474
ICapabilityJointMatrixINTEL = 6118,
7575
ICapabilityHWThreadQueryINTEL = 6134,
7676
ICapFPArithmeticFenceINTEL = 6144,
77-
ICapGlobalVariableDecorationsINTEL = 6146
77+
ICapGlobalVariableDecorationsINTEL = 6146,
78+
ICapabilityNonConstantAddrspacePrintfINTEL = 6411
7879
};
7980

8081
enum InternalFunctionControlMask { IFunctionControlOptNoneINTELMask = 0x10000 };
@@ -106,6 +107,8 @@ _SPIRV_OP(Op, JointMatrixWorkItemLengthINTEL)
106107
_SPIRV_OP(Capability, HWThreadQueryINTEL)
107108
_SPIRV_OP(BuiltIn, SubDeviceIDINTEL)
108109
_SPIRV_OP(BuiltIn, GlobalHWThreadIDINTEL)
110+
111+
_SPIRV_OP(Capability, NonConstantAddrspacePrintfINTEL)
109112
#undef _SPIRV_OP
110113

111114
constexpr Op OpForward = static_cast<Op>(IOpForward);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT
3+
4+
; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_INTEL_non_constant_addrspace_printf
5+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
6+
7+
; RUN: llvm-spirv -to-binary %t.spt -o %t.spv
8+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
9+
; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
10+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
11+
12+
; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension:
13+
; CHECK-WO-EXT: The SPV_INTEL_non_constant_addrspace_printf 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).
14+
15+
; CHECK-SPIRV: Capability NonConstantAddrspacePrintfINTEL
16+
; CHECK-SPIRV: Extension "SPV_INTEL_non_constant_addrspace_printf"
17+
; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std"
18+
; CHECK-SPIRV: TypeInt [[#TypeInt8Id:]] 8 0
19+
; CHECK-SPIRV: TypeInt [[#TypeInt32Id:]] 32 0
20+
; CHECK-SPIRV: TypePointer [[#FunctionStorClassPtrTy:]] 7 [[#TypeInt8Id]]
21+
; CHECK-SPIRV: TypePointer [[#WGStorClassPtrTy:]] 5 [[#TypeInt8Id]]
22+
; CHECK-SPIRV: TypePointer [[#CrossWFStorClassPtrTy:]] 4 [[#TypeInt8Id]]
23+
; CHECK-SPIRV: TypePointer [[#GenericStorCalssPtrTy:]] 8 [[#TypeInt8Id]]
24+
; CHECK-SPIRV: InBoundsPtrAccessChain [[#FunctionStorClassPtrTy]] [[#GEP1:]]
25+
; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP1]]
26+
; CHECK-SPIRV: InBoundsPtrAccessChain [[#WGStorClassPtrTy]] [[#GEP2:]]
27+
; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP2]]
28+
; CHECK-SPIRV: InBoundsPtrAccessChain [[#CrossWFStorClassPtrTy:]] [[#GEP3:]]
29+
; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP3]]
30+
; CHECK-SPIRV: InBoundsPtrAccessChain [[#GenericStorCalssPtrTy:]] [[#GEP4:]]
31+
; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP4]]
32+
33+
; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPc(i8* {{.*}}
34+
; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)* {{.*}}
35+
; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)* {{.*}}
36+
; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)* {{.*}}
37+
38+
; ModuleID = 'non-constant-printf'
39+
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"
40+
target triple = "spir-unknown-unknown"
41+
42+
@0 = internal unnamed_addr addrspace(0) constant [6 x i8] c"Test\0A\00", align 1
43+
@1 = internal unnamed_addr addrspace(1) constant [6 x i8] c"Test\0A\00", align 1
44+
@2 = internal unnamed_addr addrspace(3) constant [6 x i8] c"Test\0A\00", align 1
45+
@3 = internal unnamed_addr addrspace(4) constant [6 x i8] c"Test\0A\00", align 1
46+
47+
; Function Attrs: nounwind
48+
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 {
49+
%1 = getelementptr inbounds [6 x i8], [6 x i8]* @0, i32 0, i32 0
50+
%2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(i8* %1) #0
51+
%3 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(1)* @1, i32 0, i32 0
52+
%4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)* %3) #0
53+
%5 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(3)* @2, i32 0, i32 0
54+
%6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)* %5) #0
55+
%7 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(4)* @3, i32 0, i32 0
56+
%8 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)* %7) #0
57+
ret void
58+
}
59+
60+
; Function Attrs: nounwind
61+
declare spir_func i32 @_Z18__spirv_ocl_printfPc(i8*) #0
62+
63+
; Function Attrs: nounwind
64+
declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)*) #0
65+
66+
; Function Attrs: nounwind
67+
declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)*) #0
68+
69+
; Function Attrs: nounwind
70+
declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)*) #0
71+
72+
attributes #0 = { nounwind }
73+
74+
!spirv.MemoryModel = !{!0}
75+
!opencl.enable.FP_CONTRACT = !{}
76+
!spirv.Source = !{!1}
77+
!opencl.spir.version = !{!2}
78+
!opencl.ocl.version = !{!2}
79+
!opencl.used.extensions = !{!3}
80+
!opencl.used.optional.core.features = !{!3}
81+
!spirv.Generator = !{!4}
82+
83+
!0 = !{i32 1, i32 2}
84+
!1 = !{i32 3, i32 200000}
85+
!2 = !{i32 2, i32 0}
86+
!3 = !{}
87+
!4 = !{i16 7, i16 0}

0 commit comments

Comments
 (0)