@@ -184,6 +184,42 @@ void HandleSpirvDecorationMetadata::visitPrefetchCallInst(CallInst& I)
184
184
}
185
185
}
186
186
187
+ void HandleSpirvDecorationMetadata::visit1DBlockReadCallInst (CallInst& I)
188
+ {
189
+ Value* ptr = I.getArgOperand (0 );
190
+ auto spirvDecorations = parseSPIRVDecorationsFromMD (ptr);
191
+ for (auto & [DecorationId, MDNodes] : spirvDecorations)
192
+ {
193
+ switch (DecorationId)
194
+ {
195
+ // IDecCacheControlLoadINTEL
196
+ case DecorationIdCacheControlLoad:
197
+ {
198
+ handleCacheControlINTELFor1DBlockIO<LoadCacheControl>(I, MDNodes);
199
+ break ;
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ void HandleSpirvDecorationMetadata::visit1DBlockWriteCallInst (CallInst& I)
206
+ {
207
+ Value* ptr = I.getArgOperand (0 );
208
+ auto spirvDecorations = parseSPIRVDecorationsFromMD (ptr);
209
+ for (auto & [DecorationId, MDNodes] : spirvDecorations)
210
+ {
211
+ switch (DecorationId)
212
+ {
213
+ // IDecCacheControlStoreINTEL
214
+ case DecorationIdCacheControlStore:
215
+ {
216
+ handleCacheControlINTELFor1DBlockIO<StoreCacheControl>(I, MDNodes);
217
+ break ;
218
+ }
219
+ }
220
+ }
221
+ }
222
+
187
223
void HandleSpirvDecorationMetadata::visitCallInst (CallInst& I)
188
224
{
189
225
Function* F = I.getCalledFunction ();
@@ -195,8 +231,12 @@ void HandleSpirvDecorationMetadata::visitCallInst(CallInst& I)
195
231
" _Z[0-9]+(intel_sub_group_2d_block_write_[0-9]+b_[0-9]+r[0-9]+x[0-9]+c)" );
196
232
#if defined(IGC_SCALAR_USE_KHRONOS_SPIRV_TRANSLATOR)
197
233
Regex patternPrefetch (" _Z[0-9]+__spirv_ocl_prefetch" );
234
+ Regex pattern1DBlockRead (" _Z[0-9]+__spirv_SubgroupBlockReadINTEL" );
235
+ Regex pattern1DBlockWrite (" _Z[0-9]+__spirv_SubgroupBlockWriteINTEL" );
198
236
#else // IGC Legacy SPIRV Translator
199
237
Regex patternPrefetch (" __builtin_spirv_OpenCL_prefetch" );
238
+ Regex pattern1DBlockRead (" __builtin_spirv_OpSubgroupBlockReadINTEL" );
239
+ Regex pattern1DBlockWrite (" __builtin_spirv_OpSubgroupBlockWriteINTEL" );
200
240
#endif
201
241
202
242
SmallVector<StringRef, 4 > Matches;
@@ -214,6 +254,14 @@ void HandleSpirvDecorationMetadata::visitCallInst(CallInst& I)
214
254
{
215
255
visitPrefetchCallInst (I);
216
256
}
257
+ else if (pattern1DBlockRead.match (funcName, &Matches))
258
+ {
259
+ visit1DBlockReadCallInst (I);
260
+ }
261
+ else if (pattern1DBlockWrite.match (funcName, &Matches))
262
+ {
263
+ visit1DBlockWriteCallInst (I);
264
+ }
217
265
}
218
266
219
267
template <typename T>
@@ -327,3 +375,86 @@ void HandleSpirvDecorationMetadata::handleCacheControlINTELForPrefetch(llvm::Cal
327
375
if (F->getNumUses () == 0 )
328
376
m_BuiltinsToRemove.insert (F);
329
377
}
378
+
379
+ template <typename T>
380
+ void HandleSpirvDecorationMetadata::handleCacheControlINTELFor1DBlockIO (CallInst& I, SmallPtrSetImpl<MDNode*>& MDNodes)
381
+ {
382
+ static_assert (std::is_same_v<T, LoadCacheControl> || std::is_same_v<T, StoreCacheControl>);
383
+ CacheControlFromMDNodes cacheControl = resolveCacheControlFromMDNodes<T>(m_pCtx, MDNodes);
384
+ if (cacheControl.isEmpty ) return ;
385
+ if (cacheControl.isInvalid )
386
+ {
387
+ m_pCtx->EmitWarning (" Unsupported cache controls configuration requested. Applying default configuration." );
388
+ return ;
389
+ }
390
+
391
+ Function* F = I.getCalledFunction ();
392
+ IGC_ASSERT (F);
393
+
394
+ Type* operationType = nullptr ;
395
+ std::string funcName;
396
+ if constexpr (std::is_same_v<T, LoadCacheControl>)
397
+ {
398
+ operationType = I.getType ();
399
+ funcName = " SubgroupBlockReadINTEL" ;
400
+ }
401
+ else
402
+ {
403
+ operationType = I.getArgOperand (1 )->getType ();
404
+ funcName = " SubgroupBlockWriteINTEL" ;
405
+ }
406
+
407
+ std::string typeName;
408
+ uint32_t numElements = 1 ;
409
+ Type* elementType = operationType;
410
+ if (auto * vecTy = dyn_cast<IGCLLVM::FixedVectorType>(operationType))
411
+ {
412
+ numElements = (uint32_t )vecTy->getNumElements ();
413
+ elementType = vecTy->getElementType ();
414
+ }
415
+
416
+ if (elementType->isIntegerTy ())
417
+ {
418
+ switch (elementType->getIntegerBitWidth ())
419
+ {
420
+ case 8 :
421
+ typeName = " char" ;
422
+ break ;
423
+ case 16 :
424
+ typeName = " short" ;
425
+ break ;
426
+ case 32 :
427
+ typeName = " int" ;
428
+ break ;
429
+ case 64 :
430
+ typeName = " long" ;
431
+ break ;
432
+ default :
433
+ IGC_ASSERT (0 && " Unsupported integer type" );
434
+ break ;
435
+ }
436
+ }
437
+
438
+ if (numElements > 1 )
439
+ typeName += std::to_string (numElements);
440
+
441
+ SmallVector<Value*, 3 > args (I.args ());
442
+ args.push_back (ConstantInt::get (Type::getInt32Ty (I.getContext ()), cacheControl.value ));
443
+
444
+ SmallVector<Type*, 3 > argTypes;
445
+ for (const auto & arg : args)
446
+ argTypes.push_back (arg->getType ());
447
+
448
+ FunctionType* funcTy = FunctionType::get (I.getType (), argTypes, false );
449
+ std::string newFuncName = " __internal_" + funcName + " _" + typeName + " _cache_controls" ;
450
+ auto newFunction = m_Module->getOrInsertFunction (newFuncName, funcTy);
451
+
452
+ auto newCall = CallInst::Create (newFunction, args, " " , &I);
453
+ I.replaceAllUsesWith (newCall);
454
+ I.eraseFromParent ();
455
+ m_changed = true ;
456
+
457
+ // Cleanup unused function if all calls have been replaced with the internal version
458
+ if (F->getNumUses () == 0 )
459
+ m_BuiltinsToRemove.insert (F);
460
+ }
0 commit comments