@@ -41,6 +41,67 @@ PreprocessSPVIR::PreprocessSPVIR() : ModulePass(ID)
41
41
initializePreprocessSPVIRPass (*PassRegistry::getPassRegistry ());
42
42
}
43
43
44
+ uint64_t PreprocessSPVIR::parseSampledImageTy (StructType* sampledImageTy)
45
+ {
46
+ std::string Name = sampledImageTy->getName ().str ();
47
+ std::smatch match;
48
+ std::regex reg (" spirv.SampledImage._void_([0-6])_([0-2])_([0-1])_([0-1])_([0-2])_([0-9]+)_([0-2])" );
49
+
50
+ if (std::regex_match (Name, match, reg))
51
+ {
52
+ IGC_ASSERT (match.size () == 8 );
53
+ uint64_t ImageType = 0 ;
54
+
55
+ uint64_t Dim = stoi (match[1 ]);
56
+ ImageType |= Dim << 59 ;
57
+ uint64_t Depth = stoi (match[2 ]);
58
+ ImageType |= Depth << 58 ;
59
+ uint64_t Arrayed = stoi (match[3 ]);
60
+ ImageType |= Arrayed << 57 ;
61
+ uint64_t MS = stoi (match[4 ]);
62
+ ImageType |= MS << 56 ;
63
+ uint64_t Sampled = stoi (match[5 ]);
64
+ ImageType |= Sampled << 62 ;
65
+ uint64_t Access = stoi (match[6 ]);
66
+ ImageType |= Access << 54 ;
67
+
68
+ return ImageType;
69
+ }
70
+ else
71
+ {
72
+ IGC_ASSERT_MESSAGE (0 , " SampledImage opaque type is incorrect!" );
73
+ return 0 ;
74
+ }
75
+ }
76
+
77
+ Value* PreprocessSPVIR::getWidenImageCoordsArg (Value* Coords)
78
+ {
79
+ Type* coordsType = Coords->getType ();
80
+ Value* newCoords = nullptr ;
81
+ if (!isa<IGCLLVM::FixedVectorType>(coordsType))
82
+ {
83
+ Value* undef = UndefValue::get (IGCLLVM::FixedVectorType::get (coordsType, 4 ));
84
+ newCoords = m_Builder->CreateInsertElement (undef, Coords, ConstantInt::get (m_Builder->getInt32Ty (), 0 ));
85
+ }
86
+ else if (cast<IGCLLVM::FixedVectorType>(coordsType)->getNumElements () < 4 )
87
+ {
88
+ SmallVector<Constant*, 4 > shuffleIdx;
89
+ for (uint64_t i = 0 ; i < cast<IGCLLVM::FixedVectorType>(coordsType)->getNumElements (); i++)
90
+ shuffleIdx.push_back (ConstantInt::get (m_Builder->getInt32Ty (), i));
91
+
92
+ for (uint64_t i = cast<IGCLLVM::FixedVectorType>(coordsType)->getNumElements (); i < 4 ; i++)
93
+ shuffleIdx.push_back (ConstantInt::get (m_Builder->getInt32Ty (), 0 ));
94
+
95
+ newCoords = m_Builder->CreateShuffleVector (Coords, UndefValue::get (coordsType), ConstantVector::get (shuffleIdx));
96
+ }
97
+ else
98
+ {
99
+ // coordinate argument has already a desired width
100
+ newCoords = Coords;
101
+ }
102
+ return newCoords;
103
+ }
104
+
44
105
void PreprocessSPVIR::createCallAndReplace (CallInst& oldCallInst, StringRef newFuncName, std::vector<Value*>& args )
45
106
{
46
107
Function* F = oldCallInst.getCalledFunction ();
@@ -59,6 +120,137 @@ void PreprocessSPVIR::createCallAndReplace(CallInst& oldCallInst, StringRef newF
59
120
oldCallInst.replaceAllUsesWith (newCall);
60
121
}
61
122
123
+ // Transform:
124
+ // %SampledImage = call spir_func %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImage14ocl_image2d_ro11ocl_sampler(
125
+ // %opencl.image2d_ro_t addrspace(1)* %image, %opencl.sampler_t addrspace(2)* %sampler)
126
+ // call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS140__spirv_SampledImage__void_1_0_0_0_0_0_0Dv2_fif(
127
+ // %spirv.SampledImage._void_1_0_0_0_0_0_0 addrspace(1)*% SampledImage, <2 x float> %coords, i32 2, float 0.000000e+00)
128
+ //
129
+ // ---->
130
+ //
131
+ // %0 = ptrtoint %opencl.image2d_ro_t addrspace(1)* %image to i64
132
+ // %1 = ptrtoint % opencl.sampler_t addrspace(2) * %sampler to i64
133
+ // %2 = insertelement <3 x i64> undef, i64 %0, i32 0
134
+ // %3 = insertelement <3 x i64> %2, i64 576460752303423488, i32 1
135
+ // %4 = insertelement <3 x i64> %3, i64 %1, i32 2
136
+ // %5 = shufflevector <2 x float> %coords, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 0>
137
+ // %6 = call <4 x float> @__intel_sample_image_lod_fcoords_Rfloat4(<3 x i64> %4, <4 x float> %5, i32 2, float 0.000000e+00)
138
+ void PreprocessSPVIR::visitImageSampleExplicitLod (CallInst& CI)
139
+ {
140
+ m_Builder->SetInsertPoint (&CI);
141
+
142
+ enum {
143
+ SAMPLED_IMAGE_INDEX,
144
+ COORDS_INDEX,
145
+ IMAGE_OPERANDS_INDEX,
146
+ LOD_INDEX,
147
+ DX_INDEX = LOD_INDEX,
148
+ DY_INDEX
149
+ };
150
+
151
+ auto callSampledImage = cast<CallInst>(CI.getArgOperand (0 ));
152
+ auto sampledImagePtr = cast<PointerType>(callSampledImage->getType ());
153
+ auto sampledImageTy = cast<StructType>(sampledImagePtr->getElementType ());
154
+
155
+ std::vector<Value*> args;
156
+ for (size_t i = 0 ; i < CI.getNumArgOperands (); i++)
157
+ args.push_back (CI.getArgOperand (i));
158
+
159
+ // Khronos SPIRV-LLVM Translator represents OpTypeSampledImage as a global pointer to opaque type:
160
+ // %spirv.SampledImage._{SampledType}_{Dim}_{Depth}_{Arrayed}_{MS}_{Sampled}_{Format}_{Access}.
161
+ // Such representation cannot be optimally handled in BiFModule itself, since it would require to temporary
162
+ // allocate global memory and then clear this up once image/sampler intrinsics are resolved.
163
+ // It's easier to transform it into <3 x i64> vector containing:
164
+ // -image,
165
+ // -image type which comes from parsing opaque type
166
+ // -sampler.
167
+ Value* unifiedSampledImage = UndefValue::get (IGCLLVM::FixedVectorType::get (m_Builder->getInt64Ty (), 3 ));
168
+
169
+ Value* imageAsInt = m_Builder->CreatePtrToInt (callSampledImage->getArgOperand (0 ), m_Builder->getInt64Ty ());
170
+ Value* samplerAsInt = m_Builder->CreatePtrToInt (callSampledImage->getArgOperand (1 ), m_Builder->getInt64Ty ());
171
+
172
+ unifiedSampledImage = m_Builder->CreateInsertElement (unifiedSampledImage, imageAsInt, m_Builder->getInt32 (0 ));
173
+ uint64_t imageType = parseSampledImageTy (sampledImageTy);
174
+ unifiedSampledImage = m_Builder->CreateInsertElement (unifiedSampledImage, m_Builder->getInt64 (imageType), m_Builder->getInt32 (1 ));
175
+ unifiedSampledImage = m_Builder->CreateInsertElement (unifiedSampledImage, samplerAsInt, m_Builder->getInt32 (2 ));
176
+
177
+ args[SAMPLED_IMAGE_INDEX] = unifiedSampledImage;
178
+
179
+ // Widen coords argument, since __intel_sample_image always takes coordinates as 4-elements vector type
180
+ Value* coords = getWidenImageCoordsArg (args[COORDS_INDEX]);
181
+ args[COORDS_INDEX] = coords;
182
+
183
+ // Prepare a new builtin name
184
+ std::string unifiedImageSampleName = " __intel_sample_image" ;
185
+ auto imageOperand = cast<ConstantInt>(args[IMAGE_OPERANDS_INDEX]);
186
+ switch (imageOperand->getZExtValue ())
187
+ {
188
+ case 2 : // Lod
189
+ {
190
+ unifiedImageSampleName += " _lod" ;
191
+
192
+ Type* scalarCoordsType = coords->getType ()->getScalarType ();
193
+ if (scalarCoordsType->isFloatTy ())
194
+ unifiedImageSampleName += " _fcoords" ;
195
+ else if (scalarCoordsType->isIntegerTy ())
196
+ unifiedImageSampleName += " _icoords" ;
197
+ else
198
+ IGC_ASSERT_MESSAGE (0 , " Unsupported coordinates type of ImageSampleExplicitLod builtin." );
199
+ }
200
+ break ;
201
+ case 4 : // Grad
202
+ {
203
+ unifiedImageSampleName += " _grad" ;
204
+ Type* dxType = args[DX_INDEX]->getType ();
205
+ Type* dyType = args[DY_INDEX]->getType ();
206
+ IGC_ASSERT (dxType == dyType);
207
+
208
+ Type* scalarDxType = dxType->getScalarType ();
209
+ if (scalarDxType->isFloatTy ())
210
+ unifiedImageSampleName += " _float" ;
211
+ else if (scalarDxType->isIntegerTy ())
212
+ unifiedImageSampleName += " _uint" ;
213
+ else
214
+ IGC_ASSERT_MESSAGE (0 , " Unsupported dx/dy types of ImageSampleExplicitLod builtin." );
215
+
216
+ if (auto *VT = dyn_cast<IGCLLVM::FixedVectorType>(dxType))
217
+ {
218
+ unifiedImageSampleName += std::to_string (VT->getNumElements ());
219
+ }
220
+ }
221
+ break ;
222
+ default :
223
+ IGC_ASSERT_MESSAGE (0 , " Unsupported image operand!" );
224
+ break ;
225
+ }
226
+
227
+ Type* retType = CI.getType ();
228
+ auto *VT = dyn_cast<IGCLLVM::FixedVectorType>(retType);
229
+ if (VT && VT->getNumElements () == 4 )
230
+ {
231
+ Type* retScalarType = retType->getScalarType ();
232
+ if (retScalarType->isIntegerTy ())
233
+ unifiedImageSampleName += " _Ruint4" ;
234
+ else if (retScalarType->isFloatTy ())
235
+ unifiedImageSampleName += " _Rfloat4" ;
236
+ else if (retScalarType->isHalfTy ())
237
+ unifiedImageSampleName += " _Rhalf4" ;
238
+ else
239
+ IGC_ASSERT_MESSAGE (0 , " Unsupported return type of ImageSampleExplicitLod builtin." );
240
+ }
241
+ else
242
+ IGC_ASSERT_MESSAGE (0 , " ImageSampleExplicitLod builtin must return vector 4-elements type." );
243
+
244
+ // Create function call to __intel_sample_image_{Lod|Grad}_{i|f}coords_R{returnType}
245
+ createCallAndReplace (CI, unifiedImageSampleName, args);
246
+ CI.eraseFromParent ();
247
+
248
+ if (callSampledImage->use_empty ())
249
+ callSampledImage->eraseFromParent ();
250
+
251
+ m_changed = true ;
252
+ }
253
+
62
254
// Replace functions like:
63
255
// i32 @_Z18__spirv_ocl_printfPU3AS2c(i8 addrspace(2)*)
64
256
// i32 @_Z18__spirv_ocl_printfPU3AS2ci(i8 addrspace(2)*, i32)
@@ -172,7 +364,11 @@ void PreprocessSPVIR::visitCallInst(CallInst& CI)
172
364
StringRef Name = F->getName ();
173
365
if (!isSPVIR (Name)) return ;
174
366
175
- if (Name.contains (" printf" ))
367
+ if (Name.contains (" ImageSampleExplicitLod" ))
368
+ {
369
+ visitImageSampleExplicitLod (CI);
370
+ }
371
+ else if (Name.contains (" printf" ))
176
372
{
177
373
visitOpenCLEISPrintf (CI);
178
374
}
0 commit comments