Skip to content

Commit cd26fa9

Browse files
vsemenov368igcbot
authored andcommitted
Prepare to support bindless images in VC
Initial changes to enable bindless images in future.
1 parent d12bb9f commit cd26fa9

File tree

3 files changed

+95
-98
lines changed

3 files changed

+95
-98
lines changed

IGC/VectorCompiler/include/vc/Utils/GenX/KernelInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ inline bool isDescBufferType(llvm::StringRef TypeDesc) {
145145
!IGCLLVM::contains_insensitive(TypeDesc, "image1d_buffer_t"));
146146
}
147147

148+
inline bool isDescImageType(llvm::StringRef TypeDesc) {
149+
return IGCLLVM::contains_insensitive(TypeDesc, "image1d_t") ||
150+
IGCLLVM::contains_insensitive(TypeDesc, "image1d_array_t") ||
151+
IGCLLVM::contains_insensitive(TypeDesc, "image2d_t") ||
152+
IGCLLVM::contains_insensitive(TypeDesc, "image2d_array_t") ||
153+
IGCLLVM::contains_insensitive(TypeDesc, "image2d_media_block_t") ||
154+
IGCLLVM::contains_insensitive(TypeDesc, "image3d_t") ||
155+
IGCLLVM::contains_insensitive(TypeDesc, "image1d_buffer_t");
156+
}
157+
158+
inline bool isDescReadOnly(llvm::StringRef TypeDesc) {
159+
return IGCLLVM::contains_insensitive(TypeDesc, "read_only");
160+
}
161+
162+
inline bool isDescSvmPtr(llvm::StringRef TypeDesc) {
163+
return IGCLLVM::contains_insensitive(TypeDesc, "svmptr_t");
164+
}
165+
148166
/// KernelMetadata : class to parse and update kernel metadata
149167
class KernelMetadata {
150168
public:

IGC/VectorCompiler/lib/GenXCodeGen/GenXPromoteStatefulToBindless.cpp

Lines changed: 62 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2021-2023 Intel Corporation
3+
Copyright (C) 2021-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -84,16 +84,15 @@ class PromoteToBindless {
8484
bool run();
8585

8686
private:
87-
Optional<unsigned> tryConvertBuffer(unsigned Kind, StringRef Desc);
8887
unsigned convertSingleArg(unsigned Kind, StringRef Desc);
8988
bool convertKernelArguments(Function &F);
9089
bool convertArguments();
9190

9291
GlobalVariable &getOrCreateBSSVariable();
9392

9493
CallInst *createBindlessSurfaceDataportIntrinsicChain(CallInst &CI);
95-
void rewriteBufferIntrinsic(CallInst &CI);
96-
bool rewriteBufferIntrinsics();
94+
void rewriteStatefulIntrinsic(CallInst &CI);
95+
bool rewriteStatefulIntrinsics();
9796
bool rewriteIntrinsics();
9897
};
9998

@@ -146,48 +145,16 @@ bool GenXPromoteStatefulToBindless::runOnModule(Module &M) {
146145
return PTM.run();
147146
}
148147

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) {
174152

175153
if (Kind != vc::KernelMetadata::AK_SURFACE)
176-
return None;
154+
return Kind;
177155

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;
191158

192159
return Kind;
193160
}
@@ -232,7 +199,7 @@ GlobalVariable &PromoteToBindless::getOrCreateBSSVariable() {
232199
}
233200

234201
// Get surface operand number for given intrinsic.
235-
static unsigned getSurfaceOperandNo(GenXIntrinsic::ID Id) {
202+
static int getSurfaceOperandNo(unsigned Id) {
236203
using namespace GenXIntrinsic;
237204

238205
switch (Id) {
@@ -270,17 +237,43 @@ static unsigned getSurfaceOperandNo(GenXIntrinsic::ID Id) {
270237

271238
case genx_oword_st:
272239
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+
273251
default:
274-
reportUnhandledIntrinsic("getSurfaceOperandNo", Id);
252+
return -1;
275253
}
276-
return 0;
277254
}
278255

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.
280273
// Only new versions of intrinsics are handled.
281274
// They are coming from CM and this also allows to prevent
282275
// code bloat because of supporting of legacy versions.
283-
static bool isBufferIntrinsic(const Instruction &I) {
276+
static bool isStatefulIntrinsic(const Instruction &I) {
284277
const auto ID = vc::getAnyIntrinsicID(&I);
285278
switch (ID) {
286279
// LSC.
@@ -332,22 +325,22 @@ static bool isBufferIntrinsic(const Instruction &I) {
332325
// Check additionally that surface argument in not a constant.
333326
// If argument is a constant then promotion cannot happen because
334327
// 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));
338331
}
339332
default:
340333
break;
341334
}
342335
return false;
343336
}
344337

345-
static std::vector<CallInst *> collectBufferIntrinsics(Module &M) {
338+
static std::vector<CallInst *> collectStatefulIntrinsics(Module &M) {
346339
std::vector<CallInst *> Collected;
347340

348341
for (Function &F : M)
349342
for (auto &I : instructions(F)) {
350-
if (isBufferIntrinsic(I))
343+
if (isStatefulIntrinsic(I))
351344
Collected.push_back(cast<CallInst>(&I));
352345
}
353346

@@ -367,7 +360,7 @@ static void createSurfaceStateOffsetWrite(Value &SSO, IRBuilder<> &IRB,
367360

368361
// For given intrinsic ID get version with predefined surface variable
369362
// that allows to use it with %bss variable.
370-
static GenXIntrinsic::ID getBindlessDataportIntrinsicID(GenXIntrinsic::ID Id) {
363+
static GenXIntrinsic::ID getBindlessDataportIntrinsicID(unsigned Id) {
371364
using namespace GenXIntrinsic;
372365

373366
#define MAP(intr) \
@@ -406,19 +399,18 @@ static GenXIntrinsic::ID getBindlessDataportIntrinsicID(GenXIntrinsic::ID Id) {
406399
MAP(genx_oword_ld_unaligned);
407400
MAP(genx_oword_st);
408401
default:
409-
reportUnhandledIntrinsic("getBindlessDataportIntrinsicID", Id);
402+
return not_genx_intrinsic;
410403
}
411404
#undef MAP
412405

413-
return not_genx_intrinsic;
414406
}
415407

416408
// Second part of transformation for dataport intrinsic: create bindless version
417409
// that uses %bss. Mostly it is a copy of original intrinsic with a little
418410
// change: BSS global is used instead of BTI.
419411
static CallInst *createBindlessSurfaceDataportIntrinsic(
420412
CallInst &CI, IRBuilder<> &IRB, Module &M, GlobalVariable &BSS,
421-
GenXIntrinsic::ID Id, unsigned SurfaceOpNo) {
413+
unsigned Id, unsigned SurfaceOpNo) {
422414
using namespace GenXIntrinsic;
423415

424416
SmallVector<Value *, 8> Args{CI.arg_begin(), CI.arg_end()};
@@ -438,8 +430,9 @@ static CallInst *createBindlessSurfaceDataportIntrinsic(
438430
// Return newly created bindless instruction (second instruction in chain).
439431
CallInst *
440432
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");
443436

444437
IRBuilder<> IRB{&CI};
445438
GlobalVariable &BSS = getOrCreateBSSVariable();
@@ -454,8 +447,7 @@ PromoteToBindless::createBindlessSurfaceDataportIntrinsicChain(CallInst &CI) {
454447

455448
// Get bindless version of given bti lsc intrinsic.
456449
static vc::InternalIntrinsic::ID
457-
getBindlessLscIntrinsicID(vc::InternalIntrinsic::ID IID,
458-
const GenXSubtarget &ST) {
450+
getBindlessLscIntrinsicID(unsigned IID, const GenXSubtarget &ST) {
459451

460452
#define MAP(INTR) \
461453
case vc::InternalIntrinsic::INTR##_bti: \
@@ -470,11 +462,10 @@ getBindlessLscIntrinsicID(vc::InternalIntrinsic::ID IID,
470462
MAP(lsc_store);
471463
MAP(lsc_store_quad);
472464
default:
473-
reportUnhandledIntrinsic("getBindlessLscIntrinsicID", IID);
465+
return vc::InternalIntrinsic::not_any_intrinsic;
474466
}
475467
#undef MAP
476468

477-
return vc::InternalIntrinsic::not_any_intrinsic;
478469
}
479470

480471
// Create bindless version of lsc bti intrinsic.
@@ -485,20 +476,19 @@ getBindlessLscIntrinsicID(vc::InternalIntrinsic::ID IID,
485476
// instruction.
486477
static CallInst *createBindlessLscIntrinsic(CallInst &CI,
487478
const GenXSubtarget &ST) {
488-
const auto ID = vc::InternalIntrinsic::getInternalIntrinsicID(&CI);
479+
const auto ID = vc::getAnyIntrinsicID(&CI);
489480
const auto NewId = getBindlessLscIntrinsicID(ID, ST);
490481

491482
SmallVector<Value *, 16> Args{CI.args()};
492483
IRBuilder<> IRB{&CI};
493484

494-
495485
auto *Decl = vc::getInternalDeclarationForIdFromArgs(CI.getType(), Args,
496486
NewId, *CI.getModule());
497487

498488
return IRB.CreateCall(Decl->getFunctionType(), Decl, Args, CI.getName());
499489
}
500490

501-
void PromoteToBindless::rewriteBufferIntrinsic(CallInst &CI) {
491+
void PromoteToBindless::rewriteStatefulIntrinsic(CallInst &CI) {
502492
const auto ID = vc::getAnyIntrinsicID(&CI);
503493
CallInst *BindlessCI = nullptr;
504494
switch (ID) {
@@ -551,14 +541,14 @@ void PromoteToBindless::rewriteBufferIntrinsic(CallInst &CI) {
551541
CI.eraseFromParent();
552542
}
553543

554-
bool PromoteToBindless::rewriteBufferIntrinsics() {
555-
std::vector<CallInst *> bufferIntrinsics = collectBufferIntrinsics(M);
544+
bool PromoteToBindless::rewriteStatefulIntrinsics() {
545+
std::vector<CallInst *> Intrinsics = collectStatefulIntrinsics(M);
556546

557-
if (bufferIntrinsics.empty())
547+
if (Intrinsics.empty())
558548
return false;
559549

560-
for (CallInst *CI : bufferIntrinsics)
561-
rewriteBufferIntrinsic(*CI);
550+
for (CallInst *CI : Intrinsics)
551+
rewriteStatefulIntrinsic(*CI);
562552

563553
return true;
564554
}
@@ -570,7 +560,7 @@ bool PromoteToBindless::rewriteIntrinsics() {
570560
if (!BC.useBindlessBuffers())
571561
return false;
572562

573-
return rewriteBufferIntrinsics();
563+
return rewriteStatefulIntrinsics();
574564
}
575565

576566
bool PromoteToBindless::run() {

0 commit comments

Comments
 (0)