Skip to content

Commit aaa2e13

Browse files
[SPIR-V][OpaquePointers] Temporary workaround for IGC issue. (#10407)
IGC has some issues with reverse translation of SPIR-V builtins resulting from code compiled with opaque pointers enabled. To enable opaque pointers to be enabled for offloaded code before the new driver version is propagated to CI, this change is temporarily necessary to ensure we have test coverage.
1 parent 24fb635 commit aaa2e13

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

llvm-spirv/lib/SPIRV/SPIRVRegularizeLLVM.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,74 @@ bool SPIRVRegularizeLLVMBase::runRegularizeLLVM(Module &Module) {
359359
return true;
360360
}
361361

362+
// This is a temporary workaround to deal with a graphics driver failure not
363+
// able to support the typed pointer reverse translation of
364+
// getelementptr i8, ptr @__spirv_Builtin* patterns. This replaces such
365+
// accesses with getelementptr i32, ptr @__spirv_Builtin instead.
366+
static void simplifyBuiltinVarAccesses(GlobalValue *GV) {
367+
// IGC only supports:
368+
// load GV
369+
// load (addrspacecast GV)
370+
// load (gep (addrspacecast GV))
371+
// load (gep GV)
372+
// Opaque pointers will cause the optimizer to use i8 geps, or to remove
373+
// 0-index geps entirely (adding bitcasts to the result). Restore these to
374+
// avoid bitcasts in the resulting IR.
375+
if (GV->getContext().supportsTypedPointers())
376+
return;
377+
378+
Type *Ty = GV->getValueType();
379+
Type *ScalarTy = Ty->getScalarType();
380+
SmallVector<Value *, 4> Users;
381+
for (auto User : GV->users()) {
382+
if (auto *LI = dyn_cast<LoadInst>(User)) {
383+
if (LI->getType() != Ty)
384+
Users.push_back(LI);
385+
} else if (auto *GEP = dyn_cast<GEPOperator>(User)) {
386+
if (GEP->getSourceElementType() != Ty)
387+
Users.push_back(GEP);
388+
}
389+
}
390+
391+
Type *Int32Ty = Type::getInt32Ty(GV->getContext());
392+
auto GetGep = [&](unsigned Offset) {
393+
return ConstantExpr::getGetElementPtr(
394+
Ty, GV,
395+
ArrayRef<Constant *>(
396+
{ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, Offset)}),
397+
true, 0);
398+
};
399+
400+
const DataLayout &DL = GV->getParent()->getDataLayout();
401+
for (auto *User : Users) {
402+
if (auto *LI = dyn_cast<LoadInst>(User)) {
403+
LI->setOperand(0, GetGep(0));
404+
} else if (auto *GEP = dyn_cast<GEPOperator>(User)) {
405+
APInt Offset(64, 0);
406+
GEP->accumulateConstantOffset(DL, Offset);
407+
APInt Index;
408+
uint64_t Remainder;
409+
APInt::udivrem(Offset, ScalarTy->getScalarSizeInBits() / 8, Index,
410+
Remainder);
411+
assert(Remainder == 0 && "Cannot handle misaligned access to builtins");
412+
GEP->replaceAllUsesWith(GetGep(Index.getZExtValue()));
413+
if (auto *Inst = dyn_cast<Instruction>(GEP))
414+
Inst->eraseFromParent();
415+
}
416+
}
417+
}
418+
362419
/// Remove entities not representable by SPIR-V
363420
bool SPIRVRegularizeLLVMBase::regularize() {
364421
eraseUselessFunctions(M);
365422
expandSYCLTypeUsing(M);
366423

424+
for (auto &GV : M->globals()) {
425+
SPIRVBuiltinVariableKind Kind;
426+
if (isSPIRVBuiltinVariable(&GV, &Kind))
427+
simplifyBuiltinVarAccesses(&GV);
428+
}
429+
367430
for (auto I = M->begin(), E = M->end(); I != E;) {
368431
Function *F = &(*I++);
369432
if (F->isDeclaration() && F->use_empty()) {

0 commit comments

Comments
 (0)