Skip to content

Commit cf257d4

Browse files
fix intertwined load/store/function call LLVM IR input with bitcasts inserted between instruction uses
1 parent b5132b7 commit cf257d4

File tree

3 files changed

+4724
-23
lines changed

3 files changed

+4724
-23
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ void SPIRVEmitIntrinsics::propagateElemType(
475475
DenseMap<Function *, CallInst *> Ptrcasts;
476476
SmallVector<User *> Users(Op->users());
477477
for (auto *U : Users) {
478-
if (!isa<Instruction>(U) || isa<BitCastInst>(U) || isSpvIntrinsic(U))
478+
if (!isa<Instruction>(U) || isSpvIntrinsic(U))
479479
continue;
480480
if (!VisitedSubst.insert(std::make_pair(U, Op)).second)
481481
continue;
@@ -506,7 +506,7 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
506506
return;
507507
SmallVector<User *> Users(Op->users());
508508
for (auto *U : Users) {
509-
if (!isa<Instruction>(U) || isa<BitCastInst>(U) || isSpvIntrinsic(U))
509+
if (!isa<Instruction>(U) || isSpvIntrinsic(U))
510510
continue;
511511
if (!VisitedSubst.insert(std::make_pair(U, Op)).second)
512512
continue;
@@ -958,6 +958,14 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
958958
return;
959959
Uncomplete = isTodoType(I);
960960
Ops.push_back(std::make_pair(Ref->getPointerOperand(), 0));
961+
} else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
962+
if (!isPointerTy(I->getType()))
963+
return;
964+
KnownElemTy = GR->findDeducedElementType(I);
965+
if (!KnownElemTy)
966+
return;
967+
Uncomplete = isTodoType(I);
968+
Ops.push_back(std::make_pair(Ref->getOperand(0), 0));
961969
} else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
962970
if (GR->findDeducedElementType(Ref->getPointerOperand()))
963971
return;
@@ -1030,7 +1038,6 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
10301038
}
10311039
}
10321040
}
1033-
TypeValidated.insert(I);
10341041
// Non-recursive update of types in the function uncomplete returns.
10351042
// This may happen just once per a function, the latch is a pair of
10361043
// findDeducedElementType(F) / addDeducedElementType(F, ...).
@@ -1043,6 +1050,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
10431050
} else if (UncompleteRets) {
10441051
UncompleteRets->insert(I);
10451052
}
1053+
TypeValidated.insert(I);
10461054
return;
10471055
}
10481056
Uncomplete = isTodoType(CurrF);
@@ -1369,10 +1377,6 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
13691377
Instruction *I, Value *Pointer, Type *ExpectedElementType,
13701378
unsigned OperandToReplace, IRBuilder<> &B) {
13711379
TypeValidated.insert(I);
1372-
// If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source
1373-
// pointer instead. The BitCastInst should be later removed when visited.
1374-
while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer))
1375-
Pointer = BC->getOperand(0);
13761380

13771381
// Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType
13781382
Type *PointerElemTy = deduceElementTypeHelper(Pointer, false);
@@ -1759,8 +1763,7 @@ bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
17591763
IRBuilder<> &B,
17601764
bool UnknownElemTypeI8) {
17611765
reportFatalOnTokenType(I);
1762-
if (!isPointerTy(I->getType()) || !requireAssignType(I) ||
1763-
isa<BitCastInst>(I))
1766+
if (!isPointerTy(I->getType()) || !requireAssignType(I))
17641767
return false;
17651768

17661769
setInsertPointAfterDef(B, I);
@@ -1861,8 +1864,9 @@ void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
18611864
void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
18621865
IRBuilder<> &B) {
18631866
auto *II = dyn_cast<IntrinsicInst>(I);
1864-
if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite &&
1865-
TrackConstants) {
1867+
bool IsConstComposite =
1868+
II && II->getIntrinsicID() == Intrinsic::spv_const_composite;
1869+
if (IsConstComposite && TrackConstants) {
18661870
setInsertPointAfterDef(B, I);
18671871
auto t = AggrConsts.find(I);
18681872
assert(t != AggrConsts.end());
@@ -1886,12 +1890,27 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
18861890
: B.SetInsertPoint(I);
18871891
BPrepared = true;
18881892
}
1893+
Type *OpTy = Op->getType();
18891894
Value *OpTyVal = Op;
1890-
if (Op->getType()->isTargetExtTy())
1891-
OpTyVal = PoisonValue::get(Op->getType());
1892-
auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
1893-
{Op->getType(), OpTyVal->getType()}, Op,
1894-
OpTyVal, {}, B);
1895+
if (OpTy->isTargetExtTy())
1896+
OpTyVal = PoisonValue::get(OpTy);
1897+
CallInst *NewOp =
1898+
buildIntrWithMD(Intrinsic::spv_track_constant,
1899+
{OpTy, OpTyVal->getType()}, Op, OpTyVal, {}, B);
1900+
Type *OpElemTy = nullptr;
1901+
if (!IsConstComposite && isPointerTy(OpTy) &&
1902+
(OpElemTy = GR->findDeducedElementType(Op)) != nullptr &&
1903+
OpElemTy != IntegerType::getInt8Ty(I->getContext())) {
1904+
buildAssignPtr(B, IntegerType::getInt8Ty(I->getContext()), NewOp);
1905+
SmallVector<Type *, 2> Types = {OpTy, OpTy};
1906+
SmallVector<Value *, 2> Args = {
1907+
NewOp, buildMD(PoisonValue::get(OpElemTy)),
1908+
B.getInt32(getPointerAddressSpace(OpTy))};
1909+
CallInst *PtrCasted =
1910+
B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
1911+
buildAssignPtr(B, OpElemTy, PtrCasted);
1912+
NewOp = PtrCasted;
1913+
}
18951914
I->setOperand(OpNo, NewOp);
18961915
}
18971916
}
@@ -2022,8 +2041,16 @@ void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
20222041
if (!isUntypedPointerTy(Arg->getType()))
20232042
continue;
20242043
Type *ElemTy = GR->findDeducedElementType(Arg);
2025-
if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr)
2026-
buildAssignPtr(B, ElemTy, Arg);
2044+
if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr) {
2045+
if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Arg)) {
2046+
DenseSet<std::pair<Value *, Value *>> VisitedSubst;
2047+
updateAssignType(AssignCI, Arg, PoisonValue::get(ElemTy));
2048+
propagateElemType(Arg, IntegerType::getInt8Ty(F->getContext()),
2049+
VisitedSubst);
2050+
} else {
2051+
buildAssignPtr(B, ElemTy, Arg);
2052+
}
2053+
}
20272054
}
20282055
}
20292056

llvm/test/CodeGen/SPIRV/transcoding/OpPhi_ArgumentsPlaceholders.ll

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
;; }
1313
;; }
1414

15-
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
15+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
16+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
1617
; XFAIL: *
1718

1819
%struct.Node = type { %struct.Node.0 addrspace(1)* }
@@ -25,8 +26,8 @@ entry:
2526
for.cond: ; preds = %for.inc, %entry
2627
%pNode.0 = phi %struct.Node addrspace(1)* [ %pNodes, %entry ], [ %1, %for.inc ]
2728
%j.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
28-
; CHECK-SPIRV: %[[#]] = OpPhi %[[#]] %[[#]] %[[#]] %[[#BitcastResultId:]] %[[#]]
29-
; CHECK-SPIRV-NEXT: OpPhi
29+
; CHECK: %[[#]] = OpPhi %[[#]] %[[#]] %[[#]] %[[#BitcastResultId:]] %[[#]]
30+
; CHECK-NEXT: OpPhi
3031

3132
%cmp = icmp slt i32 %j.0, 10
3233
br i1 %cmp, label %for.body, label %for.end
@@ -36,8 +37,8 @@ for.body: ; preds = %for.cond
3637

3738
%0 = load %struct.Node.0 addrspace(1)*, %struct.Node.0 addrspace(1)* addrspace(1)* %pNext, align 4
3839
%1 = bitcast %struct.Node.0 addrspace(1)* %0 to %struct.Node addrspace(1)*
39-
; CHECK-SPIRV: %[[#LoadResultId:]] = OpLoad %[[#]]
40-
; CHECK-SPIRV: %[[#BitcastResultId]] = OpBitcast %[[#]] %[[#LoadResultId]]
40+
; CHECK: %[[#LoadResultId:]] = OpLoad %[[#]]
41+
; CHECK: %[[#BitcastResultId]] = OpBitcast %[[#]] %[[#LoadResultId]]
4142

4243
br label %for.inc
4344

0 commit comments

Comments
 (0)