Skip to content

Commit 2f8de7b

Browse files
[SPIR-V] Type inference must realize that a <1 x Type> vector type is not a legal vector type in LLT (#124560)
In this PR we account for possible <1 x LLVM Type> input to ensure that we produce legal vector types during type inference. We modify an LLVM type to conform with future transformations in IRTranslator, if it's a <1 x Type> vector type, replacing it by the element type, because <1 x Type> vector type is not a legal vector type in LLT and IRTranslator will represent it as the scalar eventually.
1 parent ba45592 commit 2f8de7b

File tree

3 files changed

+276
-19
lines changed

3 files changed

+276
-19
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ Type *SPIRVEmitIntrinsics::reconstructType(Value *Op, bool UnknownElemTypeI8,
427427

428428
void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
429429
Value *Arg) {
430-
Value *OfType = PoisonValue::get(Ty);
430+
Value *OfType = getNormalizedPoisonValue(Ty);
431431
CallInst *AssignCI = nullptr;
432432
if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
433433
allowEmitFakeUse(Arg)) {
@@ -447,6 +447,7 @@ void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
447447

448448
void SPIRVEmitIntrinsics::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,
449449
Value *Arg) {
450+
ElemTy = normalizeType(ElemTy);
450451
Value *OfType = PoisonValue::get(ElemTy);
451452
CallInst *AssignPtrTyCI = GR->findAssignPtrTypeInstr(Arg);
452453
if (AssignPtrTyCI == nullptr ||
@@ -470,7 +471,7 @@ void SPIRVEmitIntrinsics::updateAssignType(CallInst *AssignCI, Value *Arg,
470471
return;
471472

472473
// update association with the pointee type
473-
Type *ElemTy = OfType->getType();
474+
Type *ElemTy = normalizeType(OfType->getType());
474475
GR->addDeducedElementType(AssignCI, ElemTy);
475476
GR->addDeducedElementType(Arg, ElemTy);
476477
}
@@ -490,7 +491,7 @@ CallInst *SPIRVEmitIntrinsics::buildSpvPtrcast(Function *F, Value *Op,
490491
}
491492
Type *OpTy = Op->getType();
492493
SmallVector<Type *, 2> Types = {OpTy, OpTy};
493-
SmallVector<Value *, 2> Args = {Op, buildMD(PoisonValue::get(ElemTy)),
494+
SmallVector<Value *, 2> Args = {Op, buildMD(getNormalizedPoisonValue(ElemTy)),
494495
B.getInt32(getPointerAddressSpace(OpTy))};
495496
CallInst *PtrCasted =
496497
B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
@@ -771,7 +772,7 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
771772
// remember the found relationship
772773
if (Ty && !IgnoreKnownType) {
773774
// specify nested types if needed, otherwise return unchanged
774-
GR->addDeducedElementType(I, Ty);
775+
GR->addDeducedElementType(I, normalizeType(Ty));
775776
}
776777

777778
return Ty;
@@ -857,7 +858,7 @@ Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(
857858
}
858859
if (Ty != OpTy) {
859860
Type *NewTy = VectorType::get(Ty, VecTy->getElementCount());
860-
GR->addDeducedCompositeType(U, NewTy);
861+
GR->addDeducedCompositeType(U, normalizeType(NewTy));
861862
return NewTy;
862863
}
863864
}
@@ -995,6 +996,7 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
995996
if (KnownElemTy)
996997
return false;
997998
if (Type *OpElemTy = GR->findDeducedElementType(Op)) {
999+
OpElemTy = normalizeType(OpElemTy);
9981000
GR->addDeducedElementType(F, OpElemTy);
9991001
GR->addReturnType(
10001002
F, TypedPointerType::get(OpElemTy,
@@ -1007,7 +1009,7 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
10071009
continue;
10081010
if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(CI)) {
10091011
if (Type *PrevElemTy = GR->findDeducedElementType(CI)) {
1010-
updateAssignType(AssignCI, CI, PoisonValue::get(OpElemTy));
1012+
updateAssignType(AssignCI, CI, getNormalizedPoisonValue(OpElemTy));
10111013
propagateElemType(CI, PrevElemTy, VisitedSubst);
10121014
}
10131015
}
@@ -1167,11 +1169,11 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
11671169
Type *Ty = AskTy ? AskTy : GR->findDeducedElementType(Op);
11681170
if (Ty == KnownElemTy)
11691171
continue;
1170-
Value *OpTyVal = PoisonValue::get(KnownElemTy);
1172+
Value *OpTyVal = getNormalizedPoisonValue(KnownElemTy);
11711173
Type *OpTy = Op->getType();
11721174
if (!Ty || AskTy || isUntypedPointerTy(Ty) || isTodoType(Op)) {
11731175
Type *PrevElemTy = GR->findDeducedElementType(Op);
1174-
GR->addDeducedElementType(Op, KnownElemTy);
1176+
GR->addDeducedElementType(Op, normalizeType(KnownElemTy));
11751177
// check if KnownElemTy is complete
11761178
if (!Uncomplete)
11771179
eraseTodoType(Op);
@@ -1497,7 +1499,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
14971499

14981500
// Our previous guess about the type seems to be wrong, let's update
14991501
// inferred type according to a new, more precise type information.
1500-
updateAssignType(AssignCI, V, PoisonValue::get(AssignedType));
1502+
updateAssignType(AssignCI, V, getNormalizedPoisonValue(AssignedType));
15011503
}
15021504

15031505
void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
@@ -1512,7 +1514,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
15121514
return;
15131515

15141516
setInsertPointSkippingPhis(B, I);
1515-
Value *ExpectedElementVal = PoisonValue::get(ExpectedElementType);
1517+
Value *ExpectedElementVal = getNormalizedPoisonValue(ExpectedElementType);
15161518
MetadataAsValue *VMD = buildMD(ExpectedElementVal);
15171519
unsigned AddressSpace = getPointerAddressSpace(Pointer->getType());
15181520
bool FirstPtrCastOrAssignPtrType = true;
@@ -1658,7 +1660,7 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
16581660
if (!ElemTy) {
16591661
ElemTy = getPointeeTypeByCallInst(DemangledName, CalledF, OpIdx);
16601662
if (ElemTy) {
1661-
GR->addDeducedElementType(CalledArg, ElemTy);
1663+
GR->addDeducedElementType(CalledArg, normalizeType(ElemTy));
16621664
} else {
16631665
for (User *U : CalledArg->users()) {
16641666
if (Instruction *Inst = dyn_cast<Instruction>(U)) {
@@ -1709,6 +1711,11 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
17091711
}
17101712

17111713
Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
1714+
// If it's a <1 x Type> vector type, don't modify it. It's not a legal vector
1715+
// type in LLT and IRTranslator will replace it by the scalar.
1716+
if (isVector1(I.getType()))
1717+
return &I;
1718+
17121719
SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
17131720
I.getOperand(1)->getType(),
17141721
I.getOperand(2)->getType()};
@@ -1722,6 +1729,11 @@ Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
17221729

17231730
Instruction *
17241731
SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
1732+
// If it's a <1 x Type> vector type, don't modify it. It's not a legal vector
1733+
// type in LLT and IRTranslator will replace it by the scalar.
1734+
if (isVector1(I.getVectorOperandType()))
1735+
return &I;
1736+
17251737
IRBuilder<> B(I.getParent());
17261738
B.SetInsertPoint(&I);
17271739
SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
@@ -1989,8 +2001,9 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
19892001
Type *ElemTy = GR->findDeducedElementType(Op);
19902002
buildAssignPtr(B, ElemTy ? ElemTy : deduceElementType(Op, true), Op);
19912003
} else {
1992-
CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
1993-
{OpTy}, Op, Op, {}, B);
2004+
CallInst *AssignCI =
2005+
buildIntrWithMD(Intrinsic::spv_assign_type, {OpTy},
2006+
getNormalizedPoisonValue(OpTy), Op, {}, B);
19942007
GR->addAssignPtrTypeInstr(Op, AssignCI);
19952008
}
19962009
}
@@ -2039,7 +2052,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
20392052
Type *OpTy = Op->getType();
20402053
Value *OpTyVal = Op;
20412054
if (OpTy->isTargetExtTy())
2042-
OpTyVal = PoisonValue::get(OpTy);
2055+
OpTyVal = getNormalizedPoisonValue(OpTy);
20432056
CallInst *NewOp =
20442057
buildIntrWithMD(Intrinsic::spv_track_constant,
20452058
{OpTy, OpTyVal->getType()}, Op, OpTyVal, {}, B);
@@ -2050,7 +2063,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
20502063
buildAssignPtr(B, IntegerType::getInt8Ty(I->getContext()), NewOp);
20512064
SmallVector<Type *, 2> Types = {OpTy, OpTy};
20522065
SmallVector<Value *, 2> Args = {
2053-
NewOp, buildMD(PoisonValue::get(OpElemTy)),
2066+
NewOp, buildMD(getNormalizedPoisonValue(OpElemTy)),
20542067
B.getInt32(getPointerAddressSpace(OpTy))};
20552068
CallInst *PtrCasted =
20562069
B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
@@ -2183,7 +2196,7 @@ void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
21832196
if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr) {
21842197
if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Arg)) {
21852198
DenseSet<std::pair<Value *, Value *>> VisitedSubst;
2186-
updateAssignType(AssignCI, Arg, PoisonValue::get(ElemTy));
2199+
updateAssignType(AssignCI, Arg, getNormalizedPoisonValue(ElemTy));
21872200
propagateElemType(Arg, IntegerType::getInt8Ty(F->getContext()),
21882201
VisitedSubst);
21892202
} else {
@@ -2237,7 +2250,7 @@ bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
22372250
continue;
22382251
if (II->getIntrinsicID() == Intrinsic::spv_assign_ptr_type ||
22392252
II->getIntrinsicID() == Intrinsic::spv_ptrcast) {
2240-
updateAssignType(II, &F, PoisonValue::get(FPElemTy));
2253+
updateAssignType(II, &F, getNormalizedPoisonValue(FPElemTy));
22412254
break;
22422255
}
22432256
}
@@ -2261,7 +2274,7 @@ bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
22612274
for (Function *F : Worklist) {
22622275
SmallVector<Value *> Args;
22632276
for (const auto &Arg : F->args())
2264-
Args.push_back(PoisonValue::get(Arg.getType()));
2277+
Args.push_back(getNormalizedPoisonValue(Arg.getType()));
22652278
IRB.CreateCall(F, Args);
22662279
}
22672280
IRB.CreateRetVoid();
@@ -2291,7 +2304,7 @@ void SPIRVEmitIntrinsics::applyDemangledPtrArgTypes(IRBuilder<> &B) {
22912304
buildAssignPtr(B, ElemTy, Arg);
22922305
}
22932306
} else if (isa<Instruction>(Param)) {
2294-
GR->addDeducedElementType(Param, ElemTy);
2307+
GR->addDeducedElementType(Param, normalizeType(ElemTy));
22952308
// insertAssignTypeIntrs() will complete buildAssignPtr()
22962309
} else {
22972310
B.SetInsertPoint(CI->getParent()
@@ -2307,6 +2320,7 @@ void SPIRVEmitIntrinsics::applyDemangledPtrArgTypes(IRBuilder<> &B) {
23072320
if (!RefF || !isPointerTy(RefF->getReturnType()) ||
23082321
GR->findDeducedElementType(RefF))
23092322
continue;
2323+
ElemTy = normalizeType(ElemTy);
23102324
GR->addDeducedElementType(RefF, ElemTy);
23112325
GR->addReturnType(
23122326
RefF, TypedPointerType::get(

llvm/lib/Target/SPIRV/SPIRVUtils.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,28 @@ inline const Type *unifyPtrType(const Type *Ty) {
383383
return toTypedPointer(const_cast<Type *>(Ty));
384384
}
385385

386+
inline bool isVector1(Type *Ty) {
387+
auto *FVTy = dyn_cast<FixedVectorType>(Ty);
388+
return FVTy && FVTy->getNumElements() == 1;
389+
}
390+
391+
// Modify an LLVM type to conform with future transformations in IRTranslator.
392+
// At the moment use cases comprise only a <1 x Type> vector. To extend when/if
393+
// needed.
394+
inline Type *normalizeType(Type *Ty) {
395+
auto *FVTy = dyn_cast<FixedVectorType>(Ty);
396+
if (!FVTy || FVTy->getNumElements() != 1)
397+
return Ty;
398+
// If it's a <1 x Type> vector type, replace it by the element type, because
399+
// it's not a legal vector type in LLT and IRTranslator will represent it as
400+
// the scalar eventually.
401+
return normalizeType(FVTy->getElementType());
402+
}
403+
404+
inline PoisonValue *getNormalizedPoisonValue(Type *Ty) {
405+
return PoisonValue::get(normalizeType(Ty));
406+
}
407+
386408
MachineInstr *getVRegDef(MachineRegisterInfo &MRI, Register Reg);
387409

388410
#define SPIRV_BACKEND_SERVICE_FUN_NAME "__spirv_backend_service_fun"

0 commit comments

Comments
 (0)