Skip to content

Commit 54cc414

Browse files
[SPIR-V] Rework duplicate tracker and tracking of IR entities and types to improve compile-time performance (#130605)
This PR is to thoroughly rework duplicate tracker implementation and tracking of IR entities and types. These are legacy parts of the project resulting in an extremely bloated intermediate representation and computational delays due to inefficient data flow and structure choices. Main results of the rework: 1) Improved compile-time performance. The reference binary LLVM IR used to measure speed gains in #120415 shows ~x5 speed up also after this PR. The timing before this PR is ~42s and after this PR it's ~7.5s. In total this PR and the previous overhaul of the module analysis in #120415 results in ~x25 speed improvement. ``` $ time llc -O0 -mtriple=spirv64v1.6-unknown-unknown _group_barrier_phi.bc -o 1 --filetype=obj real 0m7.545s user 0m6.685s sys 0m0.859s ``` 2) Less bloated intermediate representation of internal translation steps. Elimination of `spv_track_constant` intrinsic usage for scalar constants, rework of `spv_assign_name`, removal of the gMIR `GET_XXX` pseudo code and a smaller number of generated `ASSIGN_TYPE` pseudo codes substantially decrease volume of data generated during translation. 3) Simpler code and easier maintenance. The duplicate tracker implementation is simplified, as well as other features. 4) Numerous fixes of issues and logical flaws in different passes. The main achievement is rework of the duplicate tracker itself that had never guaranteed a correct caching of LLVM IR entities, rarely and randomly returning stale/incorrect records (like, remove an instruction from gMIR but still refer to it). Other fixes comprise consistent generation of OpConstantNull, assigning types to newly created registers, creation of integer/bool types, and other minor fixes. 5) Numerous fixes of LIT tests: mainly CHECK-DAG to properly reflect SPIR-V spec guarantees, `{{$}}` at the end of constants to avoid matching of substrings, and XFAILS for `SPV_INTEL_long_composites` test cases, because the feature is not completed in full yet and doesn't generate a requested by the extension sequence of instructions. 6) New test cases are added.
1 parent 074af0f commit 54cc414

File tree

88 files changed

+2086
-1712
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+2086
-1712
lines changed

llvm/include/llvm/IR/IntrinsicsSPIRV.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
let TargetPrefix = "spv" in {
1414
def int_spv_assign_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
1515
def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
16-
def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
16+
def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
1717
def int_spv_assign_decoration : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
1818
def int_spv_value_md : Intrinsic<[], [llvm_metadata_ty]>;
1919

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

+17-19
Original file line numberDiff line numberDiff line change
@@ -391,12 +391,9 @@ static MachineInstr *getBlockStructInstr(Register ParamReg,
391391
// TODO: maybe unify with prelegalizer pass.
392392
static unsigned getConstFromIntrinsic(Register Reg, MachineRegisterInfo *MRI) {
393393
MachineInstr *DefMI = MRI->getUniqueVRegDef(Reg);
394-
assert(isSpvIntrinsic(*DefMI, Intrinsic::spv_track_constant) &&
395-
DefMI->getOperand(2).isReg());
396-
MachineInstr *DefMI2 = MRI->getUniqueVRegDef(DefMI->getOperand(2).getReg());
397-
assert(DefMI2->getOpcode() == TargetOpcode::G_CONSTANT &&
398-
DefMI2->getOperand(1).isCImm());
399-
return DefMI2->getOperand(1).getCImm()->getValue().getZExtValue();
394+
assert(DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
395+
DefMI->getOperand(1).isCImm());
396+
return DefMI->getOperand(1).getCImm()->getValue().getZExtValue();
400397
}
401398

402399
// Return type of the instruction result from spv_assign_type intrinsic.
@@ -538,10 +535,9 @@ static Register buildBuiltinVariableLoad(
538535
/// assign SPIRVType to both registers. If SpirvTy is provided, use it as
539536
/// SPIRVType in ASSIGN_TYPE, otherwise create it from \p Ty. Defined in
540537
/// SPIRVPreLegalizer.cpp.
541-
extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
542-
SPIRVGlobalRegistry *GR,
543-
MachineIRBuilder &MIB,
544-
MachineRegisterInfo &MRI);
538+
extern void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
539+
SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
540+
MachineRegisterInfo &MRI);
545541

546542
// TODO: Move to TableGen.
547543
static SPIRV::MemorySemantics::MemorySemantics
@@ -1818,20 +1814,23 @@ static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call,
18181814
// Query result may either be a vector or a scalar. If return type is not a
18191815
// vector, expect only a single size component. Otherwise get the number of
18201816
// expected components.
1821-
SPIRVType *RetTy = Call->ReturnType;
1822-
unsigned NumExpectedRetComponents = RetTy->getOpcode() == SPIRV::OpTypeVector
1823-
? RetTy->getOperand(2).getImm()
1824-
: 1;
1817+
unsigned NumExpectedRetComponents =
1818+
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector
1819+
? Call->ReturnType->getOperand(2).getImm()
1820+
: 1;
18251821
// Get the actual number of query result/size components.
18261822
SPIRVType *ImgType = GR->getSPIRVTypeForVReg(Call->Arguments[0]);
18271823
unsigned NumActualRetComponents = getNumSizeComponents(ImgType);
18281824
Register QueryResult = Call->ReturnRegister;
18291825
SPIRVType *QueryResultType = Call->ReturnType;
18301826
if (NumExpectedRetComponents != NumActualRetComponents) {
1827+
unsigned Bitwidth = Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
1828+
? Call->ReturnType->getOperand(1).getImm()
1829+
: 32;
18311830
QueryResult = MIRBuilder.getMRI()->createGenericVirtualRegister(
1832-
LLT::fixed_vector(NumActualRetComponents, 32));
1831+
LLT::fixed_vector(NumActualRetComponents, Bitwidth));
18331832
MIRBuilder.getMRI()->setRegClass(QueryResult, &SPIRV::vIDRegClass);
1834-
SPIRVType *IntTy = GR->getOrCreateSPIRVIntegerType(32, MIRBuilder);
1833+
SPIRVType *IntTy = GR->getOrCreateSPIRVIntegerType(Bitwidth, MIRBuilder);
18351834
QueryResultType = GR->getOrCreateSPIRVVectorType(
18361835
IntTy, NumActualRetComponents, MIRBuilder, true);
18371836
GR->assignSPIRVTypeToVReg(QueryResultType, QueryResult, MIRBuilder.getMF());
@@ -1971,8 +1970,7 @@ static bool generateReadImageInst(const StringRef DemangledCall,
19711970
Sampler = GR->buildConstantSampler(
19721971
Register(), getSamplerAddressingModeFromBitmask(SamplerMask),
19731972
getSamplerParamFromBitmask(SamplerMask),
1974-
getSamplerFilterModeFromBitmask(SamplerMask), MIRBuilder,
1975-
GR->getSPIRVTypeForVReg(Sampler));
1973+
getSamplerFilterModeFromBitmask(SamplerMask), MIRBuilder);
19761974
}
19771975
SPIRVType *ImageType = GR->getSPIRVTypeForVReg(Image);
19781976
SPIRVType *SampledImageType =
@@ -2059,7 +2057,7 @@ static bool generateSampleImageInst(const StringRef DemangledCall,
20592057
Register Sampler = GR->buildConstantSampler(
20602058
Call->ReturnRegister, getSamplerAddressingModeFromBitmask(Bitmask),
20612059
getSamplerParamFromBitmask(Bitmask),
2062-
getSamplerFilterModeFromBitmask(Bitmask), MIRBuilder, Call->ReturnType);
2060+
getSamplerFilterModeFromBitmask(Bitmask), MIRBuilder);
20632061
return Sampler.isValid();
20642062
} else if (Call->Builtin->Name.contains_insensitive("__spirv_SampledImage")) {
20652063
// Create OpSampledImage.

llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,6 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
398398
auto MRI = MIRBuilder.getMRI();
399399
Register FuncVReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
400400
MRI->setRegClass(FuncVReg, &SPIRV::iIDRegClass);
401-
if (F.isDeclaration())
402-
GR->add(&F, &MIRBuilder.getMF(), FuncVReg);
403401
FunctionType *FTy = getOriginalFunctionType(F);
404402
Type *FRetTy = FTy->getReturnType();
405403
if (isUntypedPointerTy(FRetTy)) {
@@ -425,6 +423,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
425423
.addUse(GR->getSPIRVTypeID(FuncTy));
426424
GR->recordFunctionDefinition(&F, &MB.getInstr()->getOperand(0));
427425
GR->addGlobalObject(&F, &MIRBuilder.getMF(), FuncVReg);
426+
if (F.isDeclaration())
427+
GR->add(&F, MB);
428428

429429
// Add OpFunctionParameter instructions
430430
int i = 0;
@@ -433,11 +433,11 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
433433
Register ArgReg = VRegs[i][0];
434434
MRI->setRegClass(ArgReg, GR->getRegClass(ArgTypeVRegs[i]));
435435
MRI->setType(ArgReg, GR->getRegType(ArgTypeVRegs[i]));
436-
MIRBuilder.buildInstr(SPIRV::OpFunctionParameter)
437-
.addDef(ArgReg)
438-
.addUse(GR->getSPIRVTypeID(ArgTypeVRegs[i]));
436+
auto MIB = MIRBuilder.buildInstr(SPIRV::OpFunctionParameter)
437+
.addDef(ArgReg)
438+
.addUse(GR->getSPIRVTypeID(ArgTypeVRegs[i]));
439439
if (F.isDeclaration())
440-
GR->add(&Arg, &MIRBuilder.getMF(), ArgReg);
440+
GR->add(&Arg, MIB);
441441
GR->addGlobalObject(&Arg, &MIRBuilder.getMF(), ArgReg);
442442
i++;
443443
}

0 commit comments

Comments
 (0)