1
1
/* ========================== begin_copyright_notice ============================
2
2
3
- Copyright (C) 2021-2023 Intel Corporation
3
+ Copyright (C) 2021-2024 Intel Corporation
4
4
5
5
SPDX-License-Identifier: MIT
6
6
@@ -84,16 +84,15 @@ class PromoteToBindless {
84
84
bool run ();
85
85
86
86
private:
87
- Optional<unsigned > tryConvertBuffer (unsigned Kind, StringRef Desc);
88
87
unsigned convertSingleArg (unsigned Kind, StringRef Desc);
89
88
bool convertKernelArguments (Function &F);
90
89
bool convertArguments ();
91
90
92
91
GlobalVariable &getOrCreateBSSVariable ();
93
92
94
93
CallInst *createBindlessSurfaceDataportIntrinsicChain (CallInst &CI);
95
- void rewriteBufferIntrinsic (CallInst &CI);
96
- bool rewriteBufferIntrinsics ();
94
+ void rewriteStatefulIntrinsic (CallInst &CI);
95
+ bool rewriteStatefulIntrinsics ();
97
96
bool rewriteIntrinsics ();
98
97
};
99
98
@@ -146,48 +145,16 @@ bool GenXPromoteStatefulToBindless::runOnModule(Module &M) {
146
145
return PTM.run ();
147
146
}
148
147
149
- // Error reporting function for not yet supported functionality.
150
- // When every intrinsic will be supported there will be no need for this.
151
- // Currently, simply fail on unsupported ones.
152
- static void reportUnhandledIntrinsic (const char *Func, GenXIntrinsic::ID Id) {
153
- std::ostringstream SS;
154
- SS << " In function '" << Func << " ': Intrinsic '" << getGenXName (Id)
155
- << " ' is not yet supported" ;
156
- llvm::report_fatal_error (llvm::StringRef (SS.str ()));
157
- }
158
-
159
- static void reportUnhandledIntrinsic (const char *Func,
160
- vc::InternalIntrinsic::ID Id) {
161
- std::ostringstream SS;
162
- SS << " In function '" << Func << " ': Intrinsic '"
163
- << vc::InternalIntrinsic::getInternalName (Id) << " ' is not yet supported" ;
164
- llvm::report_fatal_error (llvm::StringRef (SS.str ()));
165
- }
166
-
167
- // Buffer argument kind is converted to GENERAL to denote that
168
- // argument is not BTI but SSO.
169
- Optional<unsigned > PromoteToBindless::tryConvertBuffer (unsigned Kind,
170
- StringRef Desc) {
171
- // Do not change kind if promotion is not enabled.
172
- if (!BC.useBindlessBuffers ())
173
- return None;
148
+ // Convert single stateful argument to bindless counterpart.
149
+ // Currently only buffers and images are supported
150
+ // extra objects can be easily added here later.
151
+ unsigned PromoteToBindless::convertSingleArg (unsigned Kind, StringRef Desc) {
174
152
175
153
if (Kind != vc::KernelMetadata::AK_SURFACE)
176
- return None ;
154
+ return Kind ;
177
155
178
- if (!vc::isDescBufferType (Desc))
179
- return None;
180
-
181
- // If this is a buffer, change argument kind to general value.
182
- return vc::KernelMetadata::AK_NORMAL;
183
- }
184
-
185
- // Convert single stateful argument to bindless counterpart.
186
- // Currently only buffers are supported -- extra objects can be easily added
187
- // here later.
188
- unsigned PromoteToBindless::convertSingleArg (unsigned Kind, StringRef Desc) {
189
- if (auto MaybeKind = tryConvertBuffer (Kind, Desc))
190
- return MaybeKind.getValue ();
156
+ if (BC.useBindlessBuffers () && vc::isDescBufferType (Desc))
157
+ return vc::KernelMetadata::AK_NORMAL;
191
158
192
159
return Kind;
193
160
}
@@ -232,7 +199,7 @@ GlobalVariable &PromoteToBindless::getOrCreateBSSVariable() {
232
199
}
233
200
234
201
// Get surface operand number for given intrinsic.
235
- static unsigned getSurfaceOperandNo (GenXIntrinsic::ID Id) {
202
+ static int getSurfaceOperandNo (unsigned Id) {
236
203
using namespace GenXIntrinsic ;
237
204
238
205
switch (Id) {
@@ -270,17 +237,43 @@ static unsigned getSurfaceOperandNo(GenXIntrinsic::ID Id) {
270
237
271
238
case genx_oword_st:
272
239
return 0 ;
240
+
241
+ case vc::InternalIntrinsic::lsc_atomic_bti:
242
+ case vc::InternalIntrinsic::lsc_load_bti:
243
+ case vc::InternalIntrinsic::lsc_prefetch_bti:
244
+ case vc::InternalIntrinsic::lsc_store_bti:
245
+ case vc::InternalIntrinsic::lsc_load_quad_bti:
246
+ case vc::InternalIntrinsic::lsc_prefetch_quad_bti:
247
+ case vc::InternalIntrinsic::lsc_store_quad_bti:
248
+ return 5 ;
249
+
250
+
273
251
default :
274
- reportUnhandledIntrinsic ( " getSurfaceOperandNo " , Id) ;
252
+ return - 1 ;
275
253
}
276
- return 0 ;
277
254
}
278
255
279
- // Check whether instruction operates on buffer surface.
256
+ // Get address size operand number for given intrinsic.
257
+ static int getAddrSizeOperandNo (unsigned Id) {
258
+ switch (Id) {
259
+ case vc::InternalIntrinsic::lsc_atomic_bti:
260
+ case vc::InternalIntrinsic::lsc_load_bti:
261
+ case vc::InternalIntrinsic::lsc_prefetch_bti:
262
+ case vc::InternalIntrinsic::lsc_store_bti:
263
+ case vc::InternalIntrinsic::lsc_load_quad_bti:
264
+ case vc::InternalIntrinsic::lsc_prefetch_quad_bti:
265
+ case vc::InternalIntrinsic::lsc_store_quad_bti:
266
+ return 1 ;
267
+ default :
268
+ return -1 ;
269
+ }
270
+ }
271
+
272
+ // Check whether instruction operates on BTI surface.
280
273
// Only new versions of intrinsics are handled.
281
274
// They are coming from CM and this also allows to prevent
282
275
// code bloat because of supporting of legacy versions.
283
- static bool isBufferIntrinsic (const Instruction &I) {
276
+ static bool isStatefulIntrinsic (const Instruction &I) {
284
277
const auto ID = vc::getAnyIntrinsicID (&I);
285
278
switch (ID) {
286
279
// LSC.
@@ -332,22 +325,22 @@ static bool isBufferIntrinsic(const Instruction &I) {
332
325
// Check additionally that surface argument in not a constant.
333
326
// If argument is a constant then promotion cannot happen because
334
327
// it can be SLM, stack or stateless access.
335
- const unsigned SurfOpNo =
336
- getSurfaceOperandNo ( static_cast <GenXIntrinsic::ID>(ID) );
337
- return !isa<ConstantInt>(cast<CallInst>(I).getArgOperand (SurfOpNo ));
328
+ const auto SurfaceOpNo = getSurfaceOperandNo (ID);
329
+ IGC_ASSERT_EXIT_MESSAGE (SurfaceOpNo >= 0 , " Unknown surface operand number " );
330
+ return !isa<ConstantInt>(cast<CallInst>(I).getArgOperand (SurfaceOpNo ));
338
331
}
339
332
default :
340
333
break ;
341
334
}
342
335
return false ;
343
336
}
344
337
345
- static std::vector<CallInst *> collectBufferIntrinsics (Module &M) {
338
+ static std::vector<CallInst *> collectStatefulIntrinsics (Module &M) {
346
339
std::vector<CallInst *> Collected;
347
340
348
341
for (Function &F : M)
349
342
for (auto &I : instructions (F)) {
350
- if (isBufferIntrinsic (I))
343
+ if (isStatefulIntrinsic (I))
351
344
Collected.push_back (cast<CallInst>(&I));
352
345
}
353
346
@@ -367,7 +360,7 @@ static void createSurfaceStateOffsetWrite(Value &SSO, IRBuilder<> &IRB,
367
360
368
361
// For given intrinsic ID get version with predefined surface variable
369
362
// that allows to use it with %bss variable.
370
- static GenXIntrinsic::ID getBindlessDataportIntrinsicID (GenXIntrinsic::ID Id) {
363
+ static GenXIntrinsic::ID getBindlessDataportIntrinsicID (unsigned Id) {
371
364
using namespace GenXIntrinsic ;
372
365
373
366
#define MAP (intr ) \
@@ -406,19 +399,18 @@ static GenXIntrinsic::ID getBindlessDataportIntrinsicID(GenXIntrinsic::ID Id) {
406
399
MAP (genx_oword_ld_unaligned);
407
400
MAP (genx_oword_st);
408
401
default :
409
- reportUnhandledIntrinsic ( " getBindlessDataportIntrinsicID " , Id) ;
402
+ return not_genx_intrinsic ;
410
403
}
411
404
#undef MAP
412
405
413
- return not_genx_intrinsic;
414
406
}
415
407
416
408
// Second part of transformation for dataport intrinsic: create bindless version
417
409
// that uses %bss. Mostly it is a copy of original intrinsic with a little
418
410
// change: BSS global is used instead of BTI.
419
411
static CallInst *createBindlessSurfaceDataportIntrinsic (
420
412
CallInst &CI, IRBuilder<> &IRB, Module &M, GlobalVariable &BSS,
421
- GenXIntrinsic::ID Id, unsigned SurfaceOpNo) {
413
+ unsigned Id, unsigned SurfaceOpNo) {
422
414
using namespace GenXIntrinsic ;
423
415
424
416
SmallVector<Value *, 8 > Args{CI.arg_begin (), CI.arg_end ()};
@@ -438,8 +430,9 @@ static CallInst *createBindlessSurfaceDataportIntrinsic(
438
430
// Return newly created bindless instruction (second instruction in chain).
439
431
CallInst *
440
432
PromoteToBindless::createBindlessSurfaceDataportIntrinsicChain (CallInst &CI) {
441
- const auto ID = GenXIntrinsic::getGenXIntrinsicID (&CI);
442
- const unsigned SurfaceOpNo = getSurfaceOperandNo (ID);
433
+ const auto ID = vc::getAnyIntrinsicID (&CI);
434
+ const auto SurfaceOpNo = getSurfaceOperandNo (ID);
435
+ IGC_ASSERT_EXIT_MESSAGE (SurfaceOpNo >= 0 , " Unknown surface operand number" );
443
436
444
437
IRBuilder<> IRB{&CI};
445
438
GlobalVariable &BSS = getOrCreateBSSVariable ();
@@ -454,8 +447,7 @@ PromoteToBindless::createBindlessSurfaceDataportIntrinsicChain(CallInst &CI) {
454
447
455
448
// Get bindless version of given bti lsc intrinsic.
456
449
static vc::InternalIntrinsic::ID
457
- getBindlessLscIntrinsicID (vc::InternalIntrinsic::ID IID,
458
- const GenXSubtarget &ST) {
450
+ getBindlessLscIntrinsicID (unsigned IID, const GenXSubtarget &ST) {
459
451
460
452
#define MAP (INTR ) \
461
453
case vc::InternalIntrinsic::INTR##_bti: \
@@ -470,11 +462,10 @@ getBindlessLscIntrinsicID(vc::InternalIntrinsic::ID IID,
470
462
MAP (lsc_store);
471
463
MAP (lsc_store_quad);
472
464
default :
473
- reportUnhandledIntrinsic ( " getBindlessLscIntrinsicID " , IID) ;
465
+ return vc::InternalIntrinsic::not_any_intrinsic ;
474
466
}
475
467
#undef MAP
476
468
477
- return vc::InternalIntrinsic::not_any_intrinsic;
478
469
}
479
470
480
471
// Create bindless version of lsc bti intrinsic.
@@ -485,20 +476,19 @@ getBindlessLscIntrinsicID(vc::InternalIntrinsic::ID IID,
485
476
// instruction.
486
477
static CallInst *createBindlessLscIntrinsic (CallInst &CI,
487
478
const GenXSubtarget &ST) {
488
- const auto ID = vc::InternalIntrinsic::getInternalIntrinsicID (&CI);
479
+ const auto ID = vc::getAnyIntrinsicID (&CI);
489
480
const auto NewId = getBindlessLscIntrinsicID (ID, ST);
490
481
491
482
SmallVector<Value *, 16 > Args{CI.args ()};
492
483
IRBuilder<> IRB{&CI};
493
484
494
-
495
485
auto *Decl = vc::getInternalDeclarationForIdFromArgs (CI.getType (), Args,
496
486
NewId, *CI.getModule ());
497
487
498
488
return IRB.CreateCall (Decl->getFunctionType (), Decl, Args, CI.getName ());
499
489
}
500
490
501
- void PromoteToBindless::rewriteBufferIntrinsic (CallInst &CI) {
491
+ void PromoteToBindless::rewriteStatefulIntrinsic (CallInst &CI) {
502
492
const auto ID = vc::getAnyIntrinsicID (&CI);
503
493
CallInst *BindlessCI = nullptr ;
504
494
switch (ID) {
@@ -551,14 +541,14 @@ void PromoteToBindless::rewriteBufferIntrinsic(CallInst &CI) {
551
541
CI.eraseFromParent ();
552
542
}
553
543
554
- bool PromoteToBindless::rewriteBufferIntrinsics () {
555
- std::vector<CallInst *> bufferIntrinsics = collectBufferIntrinsics (M);
544
+ bool PromoteToBindless::rewriteStatefulIntrinsics () {
545
+ std::vector<CallInst *> Intrinsics = collectStatefulIntrinsics (M);
556
546
557
- if (bufferIntrinsics .empty ())
547
+ if (Intrinsics .empty ())
558
548
return false ;
559
549
560
- for (CallInst *CI : bufferIntrinsics )
561
- rewriteBufferIntrinsic (*CI);
550
+ for (CallInst *CI : Intrinsics )
551
+ rewriteStatefulIntrinsic (*CI);
562
552
563
553
return true ;
564
554
}
@@ -570,7 +560,7 @@ bool PromoteToBindless::rewriteIntrinsics() {
570
560
if (!BC.useBindlessBuffers ())
571
561
return false ;
572
562
573
- return rewriteBufferIntrinsics ();
563
+ return rewriteStatefulIntrinsics ();
574
564
}
575
565
576
566
bool PromoteToBindless::run () {
0 commit comments