Skip to content

Commit 9b88fdf

Browse files
committed
pr-feedback: move to GR & alternative lowering
Moved more EmitIntrinsic function to GR, and changed the lowering to use shuffle and reuse array load logic.
1 parent cb95680 commit 9b88fdf

File tree

9 files changed

+134
-183
lines changed

9 files changed

+134
-183
lines changed

llvm/lib/Target/SPIRV/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ add_llvm_target(SPIRVCodeGen
2727
SPIRVInstrInfo.cpp
2828
SPIRVInstructionSelector.cpp
2929
SPIRVStripConvergentIntrinsics.cpp
30-
SPIRVLegalizePointerLoad.cpp
30+
SPIRVLegalizePointerCast.cpp
3131
SPIRVMergeRegionExitTargets.cpp
3232
SPIRVISelLowering.cpp
3333
SPIRVLegalizerInfo.cpp

llvm/lib/Target/SPIRV/SPIRV.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ModulePass *createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine &TM);
2323
FunctionPass *createSPIRVStructurizerPass();
2424
FunctionPass *createSPIRVMergeRegionExitTargetsPass();
2525
FunctionPass *createSPIRVStripConvergenceIntrinsicsPass();
26-
FunctionPass *createSPIRVLegalizePointerLoadPass(SPIRVTargetMachine *TM);
26+
FunctionPass *createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM);
2727
FunctionPass *createSPIRVRegularizerPass();
2828
FunctionPass *createSPIRVPreLegalizerCombiner();
2929
FunctionPass *createSPIRVPreLegalizerPass();

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,6 @@ class SPIRVEmitIntrinsics
139139
Type *reconstructType(Value *Op, bool UnknownElemTypeI8,
140140
bool IsPostprocessing);
141141

142-
void buildAssignType(IRBuilder<> &B, Type *ElemTy, Value *Arg);
143-
144142
void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B);
145143
void processInstrAfterVisit(Instruction *I, IRBuilder<> &B);
146144
bool insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B,
@@ -254,18 +252,6 @@ bool expectIgnoredInIRTranslation(const Instruction *I) {
254252
}
255253
}
256254

257-
bool allowEmitFakeUse(const Value *Arg) {
258-
if (isSpvIntrinsic(Arg))
259-
return false;
260-
if (dyn_cast<AtomicCmpXchgInst>(Arg) || dyn_cast<InsertValueInst>(Arg) ||
261-
dyn_cast<UndefValue>(Arg))
262-
return false;
263-
if (const auto *LI = dyn_cast<LoadInst>(Arg))
264-
if (LI->getType()->isAggregateType())
265-
return false;
266-
return true;
267-
}
268-
269255
} // namespace
270256

271257
char SPIRVEmitIntrinsics::ID = 0;
@@ -336,10 +322,7 @@ static void emitAssignName(Instruction *I, IRBuilder<> &B) {
336322

337323
void SPIRVEmitIntrinsics::replaceAllUsesWith(Value *Src, Value *Dest,
338324
bool DeleteOld) {
339-
Src->replaceAllUsesWith(Dest);
340-
// Update deduced type records
341-
GR->updateIfExistDeducedElementType(Src, Dest, DeleteOld);
342-
GR->updateIfExistAssignPtrTypeInstr(Src, Dest, DeleteOld);
325+
GR->replaceAllUsesWith(Src, Dest, DeleteOld);
343326
// Update uncomplete type records if any
344327
if (isTodoType(Src)) {
345328
if (DeleteOld)
@@ -406,26 +389,6 @@ Type *SPIRVEmitIntrinsics::reconstructType(Value *Op, bool UnknownElemTypeI8,
406389
return nullptr;
407390
}
408391

409-
void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
410-
Value *Arg) {
411-
Value *OfType = getNormalizedPoisonValue(Ty);
412-
CallInst *AssignCI = nullptr;
413-
if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
414-
allowEmitFakeUse(Arg)) {
415-
LLVMContext &Ctx = Arg->getContext();
416-
SmallVector<Metadata *, 2> ArgMDs{
417-
MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)),
418-
MDString::get(Ctx, Arg->getName())};
419-
B.CreateIntrinsic(Intrinsic::spv_value_md, {},
420-
{MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});
421-
AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {}, {Arg});
422-
} else {
423-
AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},
424-
OfType, Arg, {}, B);
425-
}
426-
GR->addAssignPtrTypeInstr(Arg, AssignCI);
427-
}
428-
429392
CallInst *SPIRVEmitIntrinsics::buildSpvPtrcast(Function *F, Value *Op,
430393
Type *ElemTy) {
431394
IRBuilder<> B(Op->getContext());
@@ -1453,7 +1416,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
14531416

14541417
CallInst *AssignCI = GR->findAssignPtrTypeInstr(V);
14551418
if (!AssignCI) {
1456-
buildAssignType(B, AssignedType, V);
1419+
GR->buildAssignType(B, AssignedType, V);
14571420
return;
14581421
}
14591422

@@ -1907,8 +1870,8 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
19071870
setInsertPointAfterDef(B, I);
19081871
switch (ResIt->second) {
19091872
case WellKnownTypes::Event:
1910-
buildAssignType(B, TargetExtType::get(I->getContext(), "spirv.Event"),
1911-
I);
1873+
GR->buildAssignType(
1874+
B, TargetExtType::get(I->getContext(), "spirv.Event"), I);
19121875
break;
19131876
}
19141877
}
@@ -1953,7 +1916,7 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
19531916
}
19541917
}
19551918
TypeToAssign = restoreMutatedType(GR, I, TypeToAssign);
1956-
buildAssignType(B, TypeToAssign, I);
1919+
GR->buildAssignType(B, TypeToAssign, I);
19571920
}
19581921
for (const auto &Op : I->operands()) {
19591922
if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@
3232

3333
using namespace llvm;
3434

35+
namespace {
36+
37+
bool allowEmitFakeUse(const Value *Arg) {
38+
if (isSpvIntrinsic(Arg))
39+
return false;
40+
if (dyn_cast<AtomicCmpXchgInst>(Arg) || dyn_cast<InsertValueInst>(Arg) ||
41+
dyn_cast<UndefValue>(Arg))
42+
return false;
43+
if (const auto *LI = dyn_cast<LoadInst>(Arg))
44+
if (LI->getType()->isAggregateType())
45+
return false;
46+
return true;
47+
}
48+
3549
inline unsigned typeToAddressSpace(const Type *Ty) {
3650
if (auto PType = dyn_cast<TypedPointerType>(Ty))
3751
return PType->getAddressSpace();
@@ -43,6 +57,8 @@ inline unsigned typeToAddressSpace(const Type *Ty) {
4357
report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
4458
}
4559

60+
} // anonymous namespace
61+
4662
SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize)
4763
: PointerSize(PointerSize), Bound(0) {}
4864

@@ -1743,6 +1759,33 @@ LLT SPIRVGlobalRegistry::getRegType(SPIRVType *SpvType) const {
17431759
return LLT::scalar(64);
17441760
}
17451761

1762+
void SPIRVGlobalRegistry::replaceAllUsesWith(Value *Old, Value *New,
1763+
bool DeleteOld) {
1764+
Old->replaceAllUsesWith(New);
1765+
updateIfExistDeducedElementType(Old, New, DeleteOld);
1766+
updateIfExistAssignPtrTypeInstr(Old, New, DeleteOld);
1767+
}
1768+
1769+
void SPIRVGlobalRegistry::buildAssignType(IRBuilder<> &B, Type *Ty,
1770+
Value *Arg) {
1771+
Value *OfType = getNormalizedPoisonValue(Ty);
1772+
CallInst *AssignCI = nullptr;
1773+
if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
1774+
allowEmitFakeUse(Arg)) {
1775+
LLVMContext &Ctx = Arg->getContext();
1776+
SmallVector<Metadata *, 2> ArgMDs{
1777+
MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)),
1778+
MDString::get(Ctx, Arg->getName())};
1779+
B.CreateIntrinsic(Intrinsic::spv_value_md, {},
1780+
{MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});
1781+
AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {}, {Arg});
1782+
} else {
1783+
AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},
1784+
OfType, Arg, {}, B);
1785+
}
1786+
addAssignPtrTypeInstr(Arg, AssignCI);
1787+
}
1788+
17461789
void SPIRVGlobalRegistry::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,
17471790
Value *Arg) {
17481791
Value *OfType = PoisonValue::get(ElemTy);

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,11 @@ class SPIRVGlobalRegistry {
621621
const TargetRegisterClass *getRegClass(SPIRVType *SpvType) const;
622622
LLT getRegType(SPIRVType *SpvType) const;
623623

624+
// Replace all uses of a |Old| with |New| updates the global registry type
625+
// mappings.
626+
void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld = true);
627+
628+
void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg);
624629
void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg);
625630
void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType);
626631
};

llvm/lib/Target/SPIRV/SPIRVLegalizePointerLoad.cpp renamed to llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp

Lines changed: 42 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===-- SPIRVLegalizePointerLoad.cpp ----------------------*- C++ -*-===//
1+
//===-- SPIRVLegalizePointerCast.cpp ----------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -13,8 +13,8 @@
1313
// by logical SPIR-V.
1414
//
1515
// This pass relies on the assign_ptr_type intrinsic to deduce the type of the
16-
// pointee. All occurrences of `ptrcast` must be replaced because the lead to
17-
// invalid SPIR-V. Unhandled cases result in an error.
16+
// pointed values, must replace all occurences of `ptrcast`. This is why
17+
// unhandled cases are reported as unreachable: we MUST cover all cases.
1818
//
1919
// 1. Loading the first element of an array
2020
//
@@ -57,18 +57,10 @@
5757
using namespace llvm;
5858

5959
namespace llvm {
60-
void initializeSPIRVLegalizePointerLoadPass(PassRegistry &);
60+
void initializeSPIRVLegalizePointerCastPass(PassRegistry &);
6161
}
6262

63-
class SPIRVLegalizePointerLoad : public FunctionPass {
64-
65-
// Replace all uses of a |Old| with |New| updates the global registry type
66-
// mappings.
67-
void replaceAllUsesWith(Value *Old, Value *New) {
68-
Old->replaceAllUsesWith(New);
69-
GR->updateIfExistDeducedElementType(Old, New, /* deleteOld = */ true);
70-
GR->updateIfExistAssignPtrTypeInstr(Old, New, /* deleteOld = */ true);
71-
}
63+
class SPIRVLegalizePointerCast : public FunctionPass {
7264

7365
// Builds the `spv_assign_type` assigning |Ty| to |Value| at the current
7466
// builder position.
@@ -79,89 +71,54 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
7971
GR->addAssignPtrTypeInstr(Arg, AssignCI);
8072
}
8173

82-
// Loads a single scalar of type |To| from the vector pointed by |Source| of
83-
// the type |From|. Returns the loaded value.
84-
Value *loadScalarFromVector(IRBuilder<> &B, Value *Source,
85-
FixedVectorType *From) {
86-
87-
LoadInst *NewLoad = B.CreateLoad(From, Source);
88-
buildAssignType(B, From, NewLoad);
89-
90-
SmallVector<Value *, 2> Args = {NewLoad, B.getInt64(0)};
91-
SmallVector<Type *, 3> Types = {From->getElementType(), Args[0]->getType(),
92-
Args[1]->getType()};
93-
Value *Extracted =
94-
B.CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
95-
buildAssignType(B, Extracted->getType(), Extracted);
96-
return Extracted;
97-
}
98-
99-
// Loads parts of the vector of type |From| from the pointer |Source| and
100-
// create a new vector of type |To|. |To| must be a vector type, and element
101-
// types of |To| and |From| must match. Returns the loaded value.
102-
Value *loadVectorFromVector(IRBuilder<> &B, FixedVectorType *From,
103-
FixedVectorType *To, Value *Source) {
74+
// Loads parts of the vector of type |SourceType| from the pointer |Source|
75+
// and create a new vector of type |TargetType|. |TargetType| must be a vector
76+
// type, and element types of |TargetType| and |SourceType| must match.
77+
// Returns the loaded value.
78+
Value *loadVectorFromVector(IRBuilder<> &B, FixedVectorType *SourceType,
79+
FixedVectorType *TargetType, Value *Source) {
10480
// We expect the codegen to avoid doing implicit bitcast from a load.
105-
assert(To->getElementType() == From->getElementType());
106-
assert(To->getNumElements() < From->getNumElements());
107-
108-
LoadInst *NewLoad = B.CreateLoad(From, Source);
109-
buildAssignType(B, From, NewLoad);
81+
assert(TargetType->getElementType() == SourceType->getElementType());
82+
assert(TargetType->getNumElements() < SourceType->getNumElements());
11083

111-
auto ConstInt = ConstantInt::get(IntegerType::get(B.getContext(), 32), 0);
112-
ElementCount VecElemCount = ElementCount::getFixed(To->getNumElements());
113-
Value *Output = ConstantVector::getSplat(VecElemCount, ConstInt);
114-
for (unsigned I = 0; I < To->getNumElements(); ++I) {
115-
Value *Extracted = nullptr;
116-
{
117-
SmallVector<Value *, 2> Args = {NewLoad, B.getInt64(I)};
118-
SmallVector<Type *, 3> Types = {To->getElementType(),
119-
Args[0]->getType(), Args[1]->getType()};
120-
Extracted =
121-
B.CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
122-
buildAssignType(B, Extracted->getType(), Extracted);
123-
}
124-
assert(Extracted != nullptr);
84+
LoadInst *NewLoad = B.CreateLoad(SourceType, Source);
85+
buildAssignType(B, SourceType, NewLoad);
12586

126-
{
127-
SmallVector<Value *, 3> Args = {Output, Extracted, B.getInt64(I)};
128-
SmallVector<Type *, 4> Types = {Args[0]->getType(), Args[0]->getType(),
129-
Args[1]->getType(), Args[2]->getType()};
130-
Output = B.CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
131-
buildAssignType(B, Output->getType(), Output);
132-
}
133-
}
87+
SmallVector<int> Mask(/* Size= */ TargetType->getNumElements(),
88+
/* Value= */ 0);
89+
Value *Output = B.CreateShuffleVector(NewLoad, NewLoad, Mask);
90+
buildAssignType(B, TargetType, Output);
13491
return Output;
13592
}
13693

137-
// Loads the first value in an array pointed by |Source| of type |From|. Load
138-
// flags will be copied from |BadLoad|, which should be the illegal load being
139-
// legalized. Returns the loaded value.
140-
Value *loadFirstValueFromArray(IRBuilder<> &B, ArrayType *From, Value *Source,
141-
LoadInst *BadLoad) {
94+
// Loads the first value in an aggregate pointed by |Source| of containing
95+
// elements of type |ElementType|. Load flags will be copied from |BadLoad|,
96+
// which should be the load being legalized. Returns the loaded value.
97+
Value *loadFirstValueFromAggregate(IRBuilder<> &B, Type *ElementType,
98+
Value *Source, LoadInst *BadLoad) {
14299
SmallVector<Type *, 2> Types = {BadLoad->getPointerOperandType(),
143100
BadLoad->getPointerOperandType()};
144-
SmallVector<Value *, 3> Args{/* isInBounds= */ B.getInt1(true), Source,
145-
B.getInt64(0), B.getInt64(0)};
101+
SmallVector<Value *, 3> Args{/* isInBounds= */ B.getInt1(false), Source,
102+
B.getInt32(0), B.getInt32(0)};
146103
auto *GEP = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
147-
GR->buildAssignPtr(B, From->getElementType(), GEP);
104+
GR->buildAssignPtr(B, ElementType, GEP);
148105

149106
const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
150107
MachineMemOperand::Flags Flags = TLI->getLoadMemOperandFlags(
151108
*BadLoad, BadLoad->getFunction()->getDataLayout());
152109
Instruction *LI = B.CreateIntrinsic(
153110
Intrinsic::spv_load, {BadLoad->getOperand(0)->getType()},
154111
{GEP, B.getInt16(Flags), B.getInt8(BadLoad->getAlign().value())});
155-
buildAssignType(B, From->getElementType(), LI);
112+
buildAssignType(B, ElementType, LI);
156113
return LI;
157114
}
158115

159-
// Transforms an illegal partial load into a sequence we can lower to logical
160-
// SPIR-V.
116+
// Replaces the load instruction to get rid of the ptrcast used as source
117+
// operand.
161118
void transformLoad(IRBuilder<> &B, LoadInst *LI, Value *CastedOperand,
162119
Value *OriginalOperand) {
163120
Type *FromTy = GR->findDeducedElementType(OriginalOperand);
164-
Type *ToTy /*-fruity*/ = GR->findDeducedElementType(CastedOperand);
121+
Type *ToTy = GR->findDeducedElementType(CastedOperand);
165122
Value *Output = nullptr;
166123

167124
auto *SAT = dyn_cast<ArrayType>(FromTy);
@@ -174,12 +131,14 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
174131
// Loading 1st element.
175132
// - float a = array[0];
176133
if (SAT && SAT->getElementType() == ToTy)
177-
Output = loadFirstValueFromArray(B, SAT, OriginalOperand, LI);
134+
Output = loadFirstValueFromAggregate(B, SAT->getElementType(),
135+
OriginalOperand, LI);
178136
// Destination is the element type of Source, and source is a vector ->
179137
// Vector to scalar.
180138
// - float a = vector.x;
181139
else if (!DVT && SVT && SVT->getElementType() == ToTy) {
182-
Output = loadScalarFromVector(B, OriginalOperand, SVT);
140+
Output = loadFirstValueFromAggregate(B, SVT->getElementType(),
141+
OriginalOperand, LI);
183142
}
184143
// Destination is a smaller vector than source.
185144
// - float3 v3 = vector4;
@@ -188,7 +147,7 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
188147
else
189148
llvm_unreachable("Unimplemented implicit down-cast from load.");
190149

191-
replaceAllUsesWith(LI, Output);
150+
GR->replaceAllUsesWith(LI, Output, /* DeleteOld= */ true);
192151
DeadInstructions.push_back(LI);
193152
}
194153

@@ -220,8 +179,8 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
220179
}
221180

222181
public:
223-
SPIRVLegalizePointerLoad(SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {
224-
initializeSPIRVLegalizePointerLoadPass(*PassRegistry::getPassRegistry());
182+
SPIRVLegalizePointerCast(SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {
183+
initializeSPIRVLegalizePointerCastPass(*PassRegistry::getPassRegistry());
225184
};
226185

227186
virtual bool runOnFunction(Function &F) override {
@@ -256,10 +215,10 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
256215
static char ID;
257216
};
258217

259-
char SPIRVLegalizePointerLoad::ID = 0;
260-
INITIALIZE_PASS(SPIRVLegalizePointerLoad, "spirv-legalize-bitcast",
218+
char SPIRVLegalizePointerCast::ID = 0;
219+
INITIALIZE_PASS(SPIRVLegalizePointerCast, "spirv-legalize-bitcast",
261220
"SPIRV legalize bitcast pass", false, false)
262221

263-
FunctionPass *llvm::createSPIRVLegalizePointerLoadPass(SPIRVTargetMachine *TM) {
264-
return new SPIRVLegalizePointerLoad(TM);
222+
FunctionPass *llvm::createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM) {
223+
return new SPIRVLegalizePointerCast(TM);
265224
}

0 commit comments

Comments
 (0)