diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1098,14 +1098,33 @@ static bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - // TODO: Add support for other image query builtins. - Register Image = Call->Arguments[0]; - assert(Call->ReturnType->getOpcode() == SPIRV::OpTypeInt && "Image samples query result must be of int type!"); - assert(GR->getSPIRVTypeForVReg(Image)->getOperand(2).getImm() == 1 && - "Image must be of 2D dimensionality"); - MIRBuilder.buildInstr(SPIRV::OpImageQuerySamples) + + // Lookup the instruction opcode in the TableGen records. + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + unsigned Opcode = + SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode; + + Register Image = Call->Arguments[0]; + SPIRV::Dim::Dim ImageDimensionality = static_cast( + GR->getSPIRVTypeForVReg(Image)->getOperand(2).getImm()); + + switch (Opcode) { + case SPIRV::OpImageQuerySamples: + assert(ImageDimensionality == SPIRV::Dim::DIM_2D && + "Image must be of 2D dimensionality"); + break; + case SPIRV::OpImageQueryLevels: + assert((ImageDimensionality == SPIRV::Dim::DIM_1D || + ImageDimensionality == SPIRV::Dim::DIM_2D || + ImageDimensionality == SPIRV::Dim::DIM_3D || + ImageDimensionality == SPIRV::Dim::DIM_Cube) && + "Image must be of 1D/2D/3D/Cube dimensionality"); + break; + } + + MIRBuilder.buildInstr(Opcode) .addDef(Call->ReturnRegister) .addUse(GR->getSPIRVTypeID(Call->ReturnType)) .addUse(Image); diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -954,6 +954,7 @@ defm : DemangledImageQueryBuiltin<"get_image_array_size", OpenCL_std, 3>; defm : DemangledNativeBuiltin<"get_image_num_samples", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQuerySamples>; +defm : DemangledNativeBuiltin<"get_image_num_mip_levels", OpenCL_std, ImageMiscQuery, 1, 1, OpImageQueryLevels>; //===----------------------------------------------------------------------===// // Class defining a "convert_destType<_sat><_roundingMode>" call record for diff --git a/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll @@ -0,0 +1,82 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s + +;; Types: +; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 +; CHECK-DAG: %[[#VOID:]] = OpTypeVoid +; CHECK-DAG: %[[#IMAGE1D_T:]] = OpTypeImage %[[#VOID]] 1D 0 0 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE2D_T:]] = OpTypeImage %[[#VOID]] 2D 0 0 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE3D_T:]] = OpTypeImage %[[#VOID]] 3D 0 0 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE1D_ARRAY_T:]] = OpTypeImage %[[#VOID]] 1D 0 1 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE2D_ARRAY_T:]] = OpTypeImage %[[#VOID]] 2D 0 1 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE2D_DEPTH_T:]] = OpTypeImage %[[#VOID]] 2D 1 0 0 0 Unknown ReadOnly +; CHECK-DAG: %[[#IMAGE2D_ARRAY_DEPTH_T:]] = OpTypeImage %[[#VOID]] 2D 1 1 0 0 Unknown ReadOnly +;; Instructions: +; CHECK: %[[#IMAGE1D:]] = OpLoad %[[#IMAGE1D_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE1D]] +; CHECK: %[[#IMAGE2D:]] = OpLoad %[[#IMAGE2D_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE2D]] +; CHECK: %[[#IMAGE3D:]] = OpLoad %[[#IMAGE3D_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE3D]] +; CHECK: %[[#IMAGE1D_ARRAY:]] = OpLoad %[[#IMAGE1D_ARRAY_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE1D_ARRAY]] +; CHECK: %[[#IMAGE2D_ARRAY:]] = OpLoad %[[#IMAGE2D_ARRAY_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE2D_ARRAY]] +; CHECK: %[[#IMAGE2D_DEPTH:]] = OpLoad %[[#IMAGE2D_DEPTH_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE2D_DEPTH]] +; CHECK: %[[#IMAGE2D_ARRAY_DEPTH:]] = OpLoad %[[#IMAGE2D_ARRAY_DEPTH_T]] +; CHECK-NEXT: %[[#]] = OpImageQueryLevels %[[#INT]] %[[#IMAGE2D_ARRAY_DEPTH]] + +%opencl.image1d_ro_t = type opaque +%opencl.image2d_ro_t = type opaque +%opencl.image3d_ro_t = type opaque +%opencl.image1d_array_ro_t = type opaque +%opencl.image2d_array_ro_t = type opaque +%opencl.image2d_depth_ro_t = type opaque +%opencl.image2d_array_depth_ro_t = type opaque + +define spir_func void @testimage1d(%opencl.image1d_ro_t addrspace(1)* %img1, %opencl.image2d_ro_t addrspace(1)* %img2, %opencl.image3d_ro_t addrspace(1)* %img3, %opencl.image1d_array_ro_t addrspace(1)* %img4, %opencl.image2d_array_ro_t addrspace(1)* %img5, %opencl.image2d_depth_ro_t addrspace(1)* %img6, %opencl.image2d_array_depth_ro_t addrspace(1)* %img7) { +entry: + %img1.addr = alloca %opencl.image1d_ro_t addrspace(1)*, align 4 + %img2.addr = alloca %opencl.image2d_ro_t addrspace(1)*, align 4 + %img3.addr = alloca %opencl.image3d_ro_t addrspace(1)*, align 4 + %img4.addr = alloca %opencl.image1d_array_ro_t addrspace(1)*, align 4 + %img5.addr = alloca %opencl.image2d_array_ro_t addrspace(1)*, align 4 + %img6.addr = alloca %opencl.image2d_depth_ro_t addrspace(1)*, align 4 + %img7.addr = alloca %opencl.image2d_array_depth_ro_t addrspace(1)*, align 4 + store %opencl.image1d_ro_t addrspace(1)* %img1, %opencl.image1d_ro_t addrspace(1)** %img1.addr, align 4 + store %opencl.image2d_ro_t addrspace(1)* %img2, %opencl.image2d_ro_t addrspace(1)** %img2.addr, align 4 + store %opencl.image3d_ro_t addrspace(1)* %img3, %opencl.image3d_ro_t addrspace(1)** %img3.addr, align 4 + store %opencl.image1d_array_ro_t addrspace(1)* %img4, %opencl.image1d_array_ro_t addrspace(1)** %img4.addr, align 4 + store %opencl.image2d_array_ro_t addrspace(1)* %img5, %opencl.image2d_array_ro_t addrspace(1)** %img5.addr, align 4 + store %opencl.image2d_depth_ro_t addrspace(1)* %img6, %opencl.image2d_depth_ro_t addrspace(1)** %img6.addr, align 4 + store %opencl.image2d_array_depth_ro_t addrspace(1)* %img7, %opencl.image2d_array_depth_ro_t addrspace(1)** %img7.addr, align 4 + %0 = load %opencl.image1d_ro_t addrspace(1)*, %opencl.image1d_ro_t addrspace(1)** %img1.addr, align 4 + %call = call spir_func i32 @_Z24get_image_num_mip_levels14ocl_image1d_ro(%opencl.image1d_ro_t addrspace(1)* %0) + %1 = load %opencl.image2d_ro_t addrspace(1)*, %opencl.image2d_ro_t addrspace(1)** %img2.addr, align 4 + %call1 = call spir_func i32 @_Z24get_image_num_mip_levels14ocl_image2d_ro(%opencl.image2d_ro_t addrspace(1)* %1) + %2 = load %opencl.image3d_ro_t addrspace(1)*, %opencl.image3d_ro_t addrspace(1)** %img3.addr, align 4 + %call2 = call spir_func i32 @_Z24get_image_num_mip_levels14ocl_image3d_ro(%opencl.image3d_ro_t addrspace(1)* %2) + %3 = load %opencl.image1d_array_ro_t addrspace(1)*, %opencl.image1d_array_ro_t addrspace(1)** %img4.addr, align 4 + %call3 = call spir_func i32 @_Z24get_image_num_mip_levels20ocl_image1d_array_ro(%opencl.image1d_array_ro_t addrspace(1)* %3) + %4 = load %opencl.image2d_array_ro_t addrspace(1)*, %opencl.image2d_array_ro_t addrspace(1)** %img5.addr, align 4 + %call4 = call spir_func i32 @_Z24get_image_num_mip_levels20ocl_image2d_array_ro(%opencl.image2d_array_ro_t addrspace(1)* %4) + %5 = load %opencl.image2d_depth_ro_t addrspace(1)*, %opencl.image2d_depth_ro_t addrspace(1)** %img6.addr, align 4 + %call5 = call spir_func i32 @_Z24get_image_num_mip_levels20ocl_image2d_depth_ro(%opencl.image2d_depth_ro_t addrspace(1)* %5) + %6 = load %opencl.image2d_array_depth_ro_t addrspace(1)*, %opencl.image2d_array_depth_ro_t addrspace(1)** %img7.addr, align 4 + %call6 = call spir_func i32 @_Z24get_image_num_mip_levels26ocl_image2d_array_depth_ro(%opencl.image2d_array_depth_ro_t addrspace(1)* %6) + ret void +} + +declare spir_func i32 @_Z24get_image_num_mip_levels14ocl_image1d_ro(%opencl.image1d_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels14ocl_image2d_ro(%opencl.image2d_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels14ocl_image3d_ro(%opencl.image3d_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels20ocl_image1d_array_ro(%opencl.image1d_array_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels20ocl_image2d_array_ro(%opencl.image2d_array_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels20ocl_image2d_depth_ro(%opencl.image2d_depth_ro_t addrspace(1)*) + +declare spir_func i32 @_Z24get_image_num_mip_levels26ocl_image2d_array_depth_ro(%opencl.image2d_array_depth_ro_t addrspace(1)*)