[PATCH 79/79] [Backport to 15][SPV -> SPV-IR] Fix image builtin mangling of unsigned...
authorWenju He <wenju.he@intel.com>
Fri, 2 Feb 2024 17:31:27 +0000 (01:31 +0800)
committerAndreas Beckmann <anbe@debian.org>
Thu, 14 Mar 2024 19:01:08 +0000 (20:01 +0100)
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
lib/SPIRV/SPIRVReader.cpp
lib/SPIRV/SPIRVUtil.cpp
lib/SPIRV/libSPIRV/SPIRVInstruction.cpp
lib/SPIRV/libSPIRV/SPIRVInstruction.h
test/transcoding/image_signedness.ll

index 30241c89b9f8f02aafa88291cb00546cd67bfc0f..9adb620e8f407db1be730256197f725fc5dfbe50 100644 (file)
@@ -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<Type *> ArgTys,
-                                           ArrayRef<PointerIndirectPair> PETs);
+                                           ArrayRef<PointerIndirectPair> PETs,
+                                           ArrayRef<SPIRVValue *> Ops);
 
 /// Cast a function to a void(void) funtion pointer.
 Constant *castToVoidFuncPtr(Function *F);
index 89b39b1cfae0151db95623b6ce8117bc2042b4d6..b8424503107fcb38f2531c9a80a562ae0734dd79 100644 (file)
@@ -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<SPIRVConstant *>(Ops[Idx])->getZExtIntValue();
+      IsRetSigned = !(ImOp & ImageOperandsMask::ImageOperandsZeroExtendMask);
+    }
+    break;
+  }
   default:
-    IsRetSigned = true;
+    break;
   }
 
   if (AddRetTypePostfix) {
index 4c5a11b8c9459b7a52a23eeaccf2452dd0d36fc1..88b3684fd626d9bc8306b3c6193fa27eed23d9bb 100644 (file)
@@ -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<Type *> ArgTys)
-      : OC(OC), ArgTys(ArgTys) {}
+  SPIRVFriendlyIRMangleInfo(spv::Op OC, ArrayRef<Type *> ArgTys,
+                            ArrayRef<SPIRVValue *> 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<SPIRVConstant *>(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<Type *> ArgTys;
+  ArrayRef<SPIRVValue *> Ops;
 };
 class OpenCLStdToSPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo {
 public:
@@ -2407,10 +2430,12 @@ getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId, ArrayRef<Type *> ArgTys,
   return mangleBuiltin(MangleInfo.getUnmangledName(), ArgTys, &MangleInfo);
 }
 
-std::string getSPIRVFriendlyIRFunctionName(
-    const std::string &UniqName, spv::Op OC, ArrayRef<Type *> ArgTys,
-    ArrayRef<PointerIndirectPair> PointerElementTys) {
-  SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys);
+std::string
+getSPIRVFriendlyIRFunctionName(const std::string &UniqName, spv::Op OC,
+                               ArrayRef<Type *> ArgTys,
+                               ArrayRef<PointerIndirectPair> PointerElementTys,
+                               ArrayRef<SPIRVValue *> Ops) {
+  SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys, Ops);
   MangleInfo.fillPointerElementTypes(PointerElementTys);
   return mangleBuiltin(UniqName, ArgTys, &MangleInfo);
 }
index 5d5defdd650a5ea42c558c21455f6074abbcaa7a..a34e5ccb6a14917169d4959b84d43e5f469ffda4 100644 (file)
@@ -40,6 +40,7 @@
 #include "SPIRVInstruction.h"
 #include "SPIRVBasicBlock.h"
 #include "SPIRVFunction.h"
+#include "SPIRVInternal.h"
 
 #include <unordered_set>
 
@@ -157,25 +158,13 @@ std::vector<SPIRVType *> 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<SPIRVWord> &OpsArg) {
   std::vector<SPIRVWord> 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 |
index 23d29dca60eb04c5bc7f4624da82d37d17f233a6..5d369db3356c13318126d34eb64f6f7e9fc12142 100644 (file)
@@ -2812,9 +2812,6 @@ public:
 
 protected:
   void setOpWords(const std::vector<SPIRVWord> &OpsArg) override;
-
-private:
-  size_t getImageOperandsIndex() const;
 };
 
 #define _SPIRV_OP(x, ...)                                                      \
index d169251edc2eb08781e876de9c867784da64c3ac..14cb6fe7b49b650bc40519e3996e6e7c85492d78 100644 (file)
@@ -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 {