@@ -117,6 +117,45 @@ static SPIRVWord convertFloatToSPIRVWord(float F) {
117
117
return FPMaxError.Spir ;
118
118
}
119
119
120
+ // / Return one of the SPIR-V 1.4 SignExtend or ZeroExtend image operands
121
+ // / for a function name, or 0 if the function does not return or
122
+ // / write an integer type.
123
+ int getImageSignZeroExt (Function *F) {
124
+ bool IsSigned = false ;
125
+ bool IsUnsigned = false ;
126
+
127
+ ParamSignedness RetSignedness;
128
+ SmallVector<ParamSignedness, 4 > ArgSignedness;
129
+ if (!getRetParamSignedness (F, RetSignedness, ArgSignedness))
130
+ return 0 ;
131
+
132
+ StringRef Name = F->getName ();
133
+ Name = Name.substr (Name.find (kSPIRVName ::Prefix));
134
+ Name.consume_front (kSPIRVName ::Prefix);
135
+ if (Name.consume_front (" ImageRead" ) ||
136
+ Name.consume_front (" ImageSampleExplicitLod" )) {
137
+ if (RetSignedness == ParamSignedness::Signed)
138
+ IsSigned = true ;
139
+ else if (RetSignedness == ParamSignedness::Unsigned)
140
+ IsUnsigned = true ;
141
+ else if (F->getReturnType ()->isIntOrIntVectorTy () &&
142
+ Name.consume_front (" _R" )) {
143
+ // Return type is mangled after _R, e.g. _Z23__spirv_ImageRead_Rint2li
144
+ IsSigned = isMangledTypeSigned (Name[0 ]);
145
+ IsUnsigned = Name.starts_with (" u" );
146
+ }
147
+ } else if (Name.starts_with (" ImageWrite" )) {
148
+ IsSigned = (ArgSignedness[2 ] == ParamSignedness::Signed);
149
+ IsUnsigned = (ArgSignedness[2 ] == ParamSignedness::Unsigned);
150
+ }
151
+
152
+ if (IsSigned)
153
+ return ImageOperandsMask::ImageOperandsSignExtendMask;
154
+ if (IsUnsigned)
155
+ return ImageOperandsMask::ImageOperandsZeroExtendMask;
156
+ return 0 ;
157
+ }
158
+
120
159
} // namespace
121
160
122
161
namespace SPIRV {
@@ -6009,6 +6048,47 @@ LLVMToSPIRVBase::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
6009
6048
transValue (Image, BB),
6010
6049
transValue (Sampler, BB), BB);
6011
6050
}
6051
+ case OpImageRead:
6052
+ case OpImageSampleExplicitLod:
6053
+ case OpImageWrite: {
6054
+ // Image Op needs handling of SignExtend or ZeroExtend image operands.
6055
+ auto Args = getArguments (CI);
6056
+ SPIRVType *SPRetTy =
6057
+ CI->getType ()->isVoidTy () ? nullptr : transScavengedType (CI);
6058
+ auto *SPI = SPIRVInstTemplateBase::create (OC);
6059
+ std::vector<SPIRVWord> SPArgs;
6060
+ for (size_t I = 0 , E = Args.size (); I != E; ++I) {
6061
+ if (Args[I]->getType ()->isPointerTy ()) {
6062
+ [[maybe_unused]] Value *Pointee = Args[I]->stripPointerCasts ();
6063
+ assert ((Pointee == Args[I] || !isa<Function>(Pointee)) &&
6064
+ " Illegal use of a function pointer type" );
6065
+ }
6066
+ SPArgs.push_back (SPI->isOperandLiteral (I)
6067
+ ? cast<ConstantInt>(Args[I])->getZExtValue ()
6068
+ : transValue (Args[I], BB)->getId ());
6069
+ }
6070
+ if (BM->isAllowedToUseVersion (VersionNumber::SPIRV_1_4)) {
6071
+ size_t ImOpIdx = getImageOperandsIndex (OC);
6072
+ if (Args.size () > ImOpIdx) {
6073
+ // Update existing ImageOperands with SignExtendMask/ZeroExtendMask.
6074
+ if (auto *ImOp = dyn_cast<ConstantInt>(Args[ImOpIdx])) {
6075
+ uint64_t ImOpVal = ImOp->getZExtValue ();
6076
+ unsigned SignZeroExtMasks =
6077
+ ImageOperandsMask::ImageOperandsSignExtendMask |
6078
+ ImageOperandsMask::ImageOperandsZeroExtendMask;
6079
+ if (!(ImOpVal & SignZeroExtMasks))
6080
+ if (int SignZeroExt = getImageSignZeroExt (CI->getCalledFunction ()))
6081
+ SPArgs[ImOpIdx] = ImOpVal | SignZeroExt;
6082
+ }
6083
+ } else {
6084
+ // Add new ImageOperands argument.
6085
+ if (int SignZeroExt = getImageSignZeroExt (CI->getCalledFunction ()))
6086
+ SPArgs.push_back (SignZeroExt);
6087
+ }
6088
+ }
6089
+ BM->addInstTemplate (SPI, SPArgs, BB, SPRetTy);
6090
+ return SPI;
6091
+ }
6012
6092
case OpFixedSqrtINTEL:
6013
6093
case OpFixedRecipINTEL:
6014
6094
case OpFixedRsqrtINTEL:
0 commit comments