Skip to content

Commit ead8404

Browse files
authored
[SPIR-V] W/A for builtin vars translation (#7632)
The translator was crashing in case if builin GV was accessed via GEP without AS cast due to incorrect assumption. The W/A replaced GEP with ExtractElementInst. This W/A is exclusive for intel/llvm . Proper fix is done in SPIR-V consumer, but it will take take time to have the drivers be updated in CI. Signed-off-by: Sidorov, Dmitry <[email protected]>
1 parent 374adca commit ead8404

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,55 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
18181818
BM->addExtension(ExtensionID::SPV_INTEL_hw_thread_queries);
18191819
}
18201820

1821+
// TODO: it's W/A for intel/llvm to prevent not fixed SPIR-V consumers
1822+
// see https://github.com/intel/llvm/issues/7592
1823+
// from crashing. Need to remove, when we have the fixed drivers
1824+
// to remove: begin
1825+
{
1826+
std::vector<Instruction *> GEPs;
1827+
std::vector<Instruction *> Loads;
1828+
auto *GVTy = GV->getType();
1829+
auto *VecTy = GVTy->isOpaquePointerTy()
1830+
? nullptr
1831+
: dyn_cast<FixedVectorType>(
1832+
GVTy->getNonOpaquePointerElementType());
1833+
auto ReplaceIfLoad = [&](User *I, ConstantInt *Idx) -> void {
1834+
auto *LD = dyn_cast<LoadInst>(I);
1835+
if (!LD)
1836+
return;
1837+
Loads.push_back(LD);
1838+
const DebugLoc &DLoc = LD->getDebugLoc();
1839+
LoadInst *Load = new LoadInst(VecTy, GV, "", LD);
1840+
ExtractElementInst *Extract = ExtractElementInst::Create(Load, Idx);
1841+
if (DLoc)
1842+
Extract->setDebugLoc(DLoc);
1843+
Extract->insertAfter(cast<Instruction>(Load));
1844+
LD->replaceAllUsesWith(Extract);
1845+
};
1846+
for (auto *UI : GV->users()) {
1847+
if (!VecTy)
1848+
break;
1849+
if (auto *GEP = dyn_cast<GetElementPtrInst>(UI)) {
1850+
GEPs.push_back(GEP);
1851+
for (auto *GEPUser : GEP->users()) {
1852+
assert(GEP->getNumIndices() == 2 &&
1853+
"GEP to ID vector is expected to have exactly 2 indices");
1854+
auto *Idx = cast<ConstantInt>(GEP->getOperand(2));
1855+
ReplaceIfLoad(GEPUser, Idx);
1856+
}
1857+
}
1858+
}
1859+
auto Erase = [](std::vector<Instruction *> &ToErase) {
1860+
for (Instruction *I : ToErase) {
1861+
assert(I->user_empty());
1862+
I->eraseFromParent();
1863+
}
1864+
};
1865+
Erase(Loads);
1866+
Erase(GEPs);
1867+
}
1868+
// to remove: end
1869+
18211870
BVar->setBuiltin(Builtin);
18221871
return BVar;
18231872
}

llvm-spirv/test/transcoding/builtin_vars_gep.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ entry:
2828
; CHECK-OCL-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1
2929
; CHECK-OCL-IR: %[[#ID3:]] = call spir_func i64 @_Z13get_global_idj(i32 2)
3030
; CHECK-OCL-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2
31-
; CHECK-OCL-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0
31+
; CHECK-OCL-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i32 0
3232

3333
; CHECK-SPV-IR: %[[#ID1:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 0)
3434
; CHECK-SPV-IR: %[[#VEC1:]] = insertelement <3 x i64> undef, i64 %[[#ID1]], i32 0
3535
; CHECK-SPV-IR: %[[#ID2:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1)
3636
; CHECK-SPV-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1
3737
; CHECK-SPV-IR: %[[#ID3:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 2)
3838
; CHECK-SPV-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2
39-
; CHECK-SPV-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0
39+
; CHECK-SPV-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i32 0
4040

4141
ret void
4242
}

0 commit comments

Comments
 (0)