From 722dc162c92737541e9671ca120263ef55b95885 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Sat, 3 Feb 2024 01:31:27 +0800 Subject: [PATCH] [PATCH 79/79] [Backport to 15][SPV -> SPV-IR] Fix image builtin mangling of unsigned type (#2273) (#2338) Return type of image read and Texel type of image write builtins may be unsigned. Before this PR, the builtin names in SPIR-V Friendly IR were always mangled with signed type. (cherry picked from commit e9b95fb) Gbp-Pq: Name 0079-Backport-to-15-SPV-SPV-IR-Fix-image-builtin-mangling.patch --- lib/SPIRV/SPIRVInternal.h | 7 ++++- lib/SPIRV/SPIRVReader.cpp | 18 +++++++++--- lib/SPIRV/SPIRVUtil.cpp | 37 +++++++++++++++++++++---- lib/SPIRV/libSPIRV/SPIRVInstruction.cpp | 15 ++-------- lib/SPIRV/libSPIRV/SPIRVInstruction.h | 3 -- test/transcoding/image_signedness.ll | 9 ++++++ 6 files changed, 62 insertions(+), 27 deletions(-) diff --git a/lib/SPIRV/SPIRVInternal.h b/lib/SPIRV/SPIRVInternal.h index 30241c8..9adb620 100644 --- a/lib/SPIRV/SPIRVInternal.h +++ b/lib/SPIRV/SPIRVInternal.h @@ -925,6 +925,9 @@ std::string getImageBaseTypeName(StringRef Name); /// Map OpenCL opaque type name to SPIR-V type name. std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc = ""); +/// Return the index of image operands given an image op. +size_t getImageOperandsIndex(Op OpCode); + /// Check if access qualifier is encoded in the type name. bool hasAccessQualifiedName(StringRef TyName); @@ -998,10 +1001,12 @@ std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId, /// \param OC opcode of corresponding built-in instruction. Used to gather info /// for unsigned/constant arguments. /// \param Types of arguments of SPIR-V built-in function +/// \param Ops Operands of SPIRVInstruction /// \return IA64 mangled name. std::string getSPIRVFriendlyIRFunctionName(const std::string &UniqName, spv::Op OC, ArrayRef ArgTys, - ArrayRef PETs); + ArrayRef PETs, + ArrayRef Ops); /// Cast a function to a void(void) funtion pointer. Constant *castToVoidFuncPtr(Function *F); diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 89b39b1..b842450 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -3163,8 +3163,8 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName, if (BM->getDesiredBIsRepresentation() != BIsRepresentation::SPIRVFriendlyIR) mangleOpenClBuiltin(FuncName, ArgTys, PointerElementTys, MangledName); else - MangledName = getSPIRVFriendlyIRFunctionName(FuncName, BI->getOpCode(), - ArgTys, PointerElementTys); + MangledName = getSPIRVFriendlyIRFunctionName( + FuncName, BI->getOpCode(), ArgTys, PointerElementTys, Ops); Function *Func = M->getFunction(MangledName); FunctionType *FT = FunctionType::get(RetTy, ArgTys, false); @@ -3301,7 +3301,7 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI, } } - bool IsRetSigned; + bool IsRetSigned = true; switch (OC) { case OpConvertFToU: case OpSatConvertSToU: @@ -3310,8 +3310,18 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI, case OpUDotAccSatKHR: IsRetSigned = false; break; + case OpImageRead: + case OpImageSampleExplicitLod: { + const size_t Idx = getImageOperandsIndex(OC); + auto Ops = BI->getOperands(); + if (Ops.size() > Idx) { + auto ImOp = static_cast(Ops[Idx])->getZExtIntValue(); + IsRetSigned = !(ImOp & ImageOperandsMask::ImageOperandsZeroExtendMask); + } + break; + } default: - IsRetSigned = true; + break; } if (AddRetTypePostfix) { diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp index 4c5a11b..88b3684 100644 --- a/lib/SPIRV/SPIRVUtil.cpp +++ b/lib/SPIRV/SPIRVUtil.cpp @@ -1525,6 +1525,18 @@ std::string getImageBaseTypeName(StringRef Name) { return ImageTyName; } +size_t getImageOperandsIndex(Op OpCode) { + switch (OpCode) { + case OpImageRead: + case OpImageSampleExplicitLod: + return 2; + case OpImageWrite: + return 3; + default: + return ~0U; + } +} + std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc) { std::string BaseTy; std::string Postfixes; @@ -2161,8 +2173,9 @@ bool postProcessBuiltinsWithArrayArguments(Module *M, bool IsCpp) { namespace { class SPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo { public: - SPIRVFriendlyIRMangleInfo(spv::Op OC, ArrayRef ArgTys) - : OC(OC), ArgTys(ArgTys) {} + SPIRVFriendlyIRMangleInfo(spv::Op OC, ArrayRef ArgTys, + ArrayRef Ops) + : OC(OC), ArgTys(ArgTys), Ops(Ops) {} void init(StringRef UniqUnmangledName) override { UnmangledName = UniqUnmangledName.str(); @@ -2322,6 +2335,15 @@ public: case OpSUDotAccSatKHR: addUnsignedArg(1); break; + case OpImageWrite: { + const size_t Idx = getImageOperandsIndex(OC); + if (Ops.size() > Idx) { + auto ImOp = static_cast(Ops[Idx])->getZExtIntValue(); + if (ImOp & ImageOperandsMask::ImageOperandsZeroExtendMask) + addUnsignedArg(2); + } + break; + } default:; // No special handling is needed } @@ -2330,6 +2352,7 @@ public: private: spv::Op OC; ArrayRef ArgTys; + ArrayRef Ops; }; class OpenCLStdToSPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo { public: @@ -2407,10 +2430,12 @@ getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId, ArrayRef ArgTys, return mangleBuiltin(MangleInfo.getUnmangledName(), ArgTys, &MangleInfo); } -std::string getSPIRVFriendlyIRFunctionName( - const std::string &UniqName, spv::Op OC, ArrayRef ArgTys, - ArrayRef PointerElementTys) { - SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys); +std::string +getSPIRVFriendlyIRFunctionName(const std::string &UniqName, spv::Op OC, + ArrayRef ArgTys, + ArrayRef PointerElementTys, + ArrayRef Ops) { + SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys, Ops); MangleInfo.fillPointerElementTypes(PointerElementTys); return mangleBuiltin(UniqName, ArgTys, &MangleInfo); } diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp b/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp index 5d5defd..a34e5cc 100644 --- a/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp +++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp @@ -40,6 +40,7 @@ #include "SPIRVInstruction.h" #include "SPIRVBasicBlock.h" #include "SPIRVFunction.h" +#include "SPIRVInternal.h" #include @@ -157,25 +158,13 @@ std::vector SPIRVInstruction::getOperandTypes() { return getOperandTypes(getOperands()); } -size_t SPIRVImageInstBase::getImageOperandsIndex() const { - switch (OpCode) { - case OpImageRead: - case OpImageSampleExplicitLod: - return 2; - case OpImageWrite: - return 3; - default: - return ~0U; - } -} - void SPIRVImageInstBase::setOpWords(const std::vector &OpsArg) { std::vector Ops = OpsArg; // If the Image Operands field has the SignExtend or ZeroExtend bit set, // either raise the minimum SPIR-V version to 1.4, or drop the operand // if SPIR-V 1.4 cannot be emitted. - size_t ImgOpsIndex = getImageOperandsIndex(); + const size_t ImgOpsIndex = getImageOperandsIndex(OpCode); if (ImgOpsIndex != ~0U && ImgOpsIndex < Ops.size()) { SPIRVWord ImgOps = Ops[ImgOpsIndex]; unsigned SignZeroExtMasks = ImageOperandsMask::ImageOperandsSignExtendMask | diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h index 23d29dc..5d369db 100644 --- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -2812,9 +2812,6 @@ public: protected: void setOpWords(const std::vector &OpsArg) override; - -private: - size_t getImageOperandsIndex() const; }; #define _SPIRV_OP(x, ...) \ diff --git a/test/transcoding/image_signedness.ll b/test/transcoding/image_signedness.ll index d169251..14cb6fe 100644 --- a/test/transcoding/image_signedness.ll +++ b/test/transcoding/image_signedness.ll @@ -5,6 +5,8 @@ ; RUN: spirv-val %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM +; RUN: llvm-spirv -r --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR ; ModuleID = 'image_signedness.ll' target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" @@ -21,6 +23,11 @@ target triple = "spir-unknown-unknown" ; CHECK-LLVM: call spir_func <4 x i32> @_Z12read_imageui20ocl_image1d_array_rwDv2_i( ; CHECK-LLVM: call spir_func <4 x i32> @_Z12read_imageui14ocl_image1d_roi( ; CHECK-LLVM: call spir_func <4 x i32> @_Z11read_imagei14ocl_image1d_roi( +; CHECK-SPV-IR: call spir_func <4 x i32> @_Z37__spirv_ImageSampleExplicitLod_Ruint4PU3AS140__spirv_SampledImage__void_0_0_0_0_0_0_0iif( +; CHECK-SPV-IR: call spir_func <4 x i32> @_Z36__spirv_ImageSampleExplicitLod_Rint4PU3AS140__spirv_SampledImage__void_0_0_0_0_0_0_0iif( +; CHECK-SPV-IR: call spir_func <4 x i32> @_Z24__spirv_ImageRead_Ruint4PU3AS133__spirv_Image__void_0_0_1_0_0_0_2Dv2_ii( +; CHECK-SPV-IR: call spir_func <4 x i32> @_Z24__spirv_ImageRead_Ruint4PU3AS133__spirv_Image__void_0_0_0_0_0_0_0ii( +; CHECK-SPV-IR: call spir_func <4 x i32> @_Z23__spirv_ImageRead_Rint4PU3AS133__spirv_Image__void_0_0_0_0_0_0_0ii( ; Function Attrs: convergent nounwind define dso_local spir_kernel void @imagereads(%opencl.image1d_ro_t addrspace(1)* %im, %opencl.image1d_array_rw_t addrspace(1)* %ima, <4 x i32> addrspace(1)* nocapture %res, <4 x i32> addrspace(1)* nocapture %resu) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !7 !kernel_arg_type_qual !8 { @@ -42,6 +49,8 @@ entry: ; CHECK-LLVM-LABEL: @imagewrites ; CHECK-LLVM: call spir_func void @_Z12write_imagei14ocl_image2d_woDv2_iDv4_i( ; CHECK-LLVM: call spir_func void @_Z13write_imageui14ocl_image2d_woDv2_iDv4_j( +; CHECK-SPV-IR: call spir_func void @_Z18__spirv_ImageWritePU3AS133__spirv_Image__void_1_0_0_0_0_0_1Dv2_iDv4_ii( +; CHECK-SPV-IR: call spir_func void @_Z18__spirv_ImageWritePU3AS133__spirv_Image__void_1_0_0_0_0_0_1Dv2_iDv4_ji( ; Function Attrs: alwaysinline convergent nounwind define spir_kernel void @imagewrites(i32 %offset, <4 x i32> addrspace(1)* nocapture readonly %input, <4 x i32> addrspace(1)* nocapture readonly %inputu, %opencl.image2d_wo_t addrspace(1)* %output) local_unnamed_addr #0 !kernel_arg_addr_space !14 !kernel_arg_access_qual !15 !kernel_arg_type !16 !kernel_arg_base_type !17 !kernel_arg_type_qual !18 !kernel_arg_name !19 !kernel_attributes !20 { -- 2.30.2