@@ -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 {
@@ -5948,6 +5987,47 @@ LLVMToSPIRVBase::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
5948
5987
transValue (Image, BB),
5949
5988
transValue (Sampler, BB), BB);
5950
5989
}
5990
+ case OpImageRead:
5991
+ case OpImageSampleExplicitLod:
5992
+ case OpImageWrite: {
5993
+ // Image Op needs handling of SignExtend or ZeroExtend image operands.
5994
+ auto Args = getArguments (CI);
5995
+ SPIRVType *SPRetTy =
5996
+ CI->getType ()->isVoidTy () ? nullptr : transScavengedType (CI);
5997
+ auto *SPI = SPIRVInstTemplateBase::create (OC);
5998
+ std::vector<SPIRVWord> SPArgs;
5999
+ for (size_t I = 0 , E = Args.size (); I != E; ++I) {
6000
+ if (Args[I]->getType ()->isPointerTy ()) {
6001
+ [[maybe_unused]] Value *Pointee = Args[I]->stripPointerCasts ();
6002
+ assert ((Pointee == Args[I] || !isa<Function>(Pointee)) &&
6003
+ " Illegal use of a function pointer type" );
6004
+ }
6005
+ SPArgs.push_back (SPI->isOperandLiteral (I)
6006
+ ? cast<ConstantInt>(Args[I])->getZExtValue ()
6007
+ : transValue (Args[I], BB)->getId ());
6008
+ }
6009
+ if (BM->isAllowedToUseVersion (VersionNumber::SPIRV_1_4)) {
6010
+ size_t ImOpIdx = getImageOperandsIndex (OC);
6011
+ if (Args.size () > ImOpIdx) {
6012
+ // Update existing ImageOperands with SignExtendMask/ZeroExtendMask.
6013
+ if (auto *ImOp = dyn_cast<ConstantInt>(Args[ImOpIdx])) {
6014
+ uint64_t ImOpVal = ImOp->getZExtValue ();
6015
+ unsigned SignZeroExtMasks =
6016
+ ImageOperandsMask::ImageOperandsSignExtendMask |
6017
+ ImageOperandsMask::ImageOperandsZeroExtendMask;
6018
+ if (!(ImOpVal & SignZeroExtMasks))
6019
+ if (int SignZeroExt = getImageSignZeroExt (CI->getCalledFunction ()))
6020
+ SPArgs[ImOpIdx] = ImOpVal | SignZeroExt;
6021
+ }
6022
+ } else {
6023
+ // Add new ImageOperands argument.
6024
+ if (int SignZeroExt = getImageSignZeroExt (CI->getCalledFunction ()))
6025
+ SPArgs.push_back (SignZeroExt);
6026
+ }
6027
+ }
6028
+ BM->addInstTemplate (SPI, SPArgs, BB, SPRetTy);
6029
+ return SPI;
6030
+ }
5951
6031
case OpFixedSqrtINTEL:
5952
6032
case OpFixedRecipINTEL:
5953
6033
case OpFixedRsqrtINTEL:
0 commit comments