diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2025-02-03 18:51:27 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2025-02-03 18:51:27 +0000 |
| commit | 32a711e1c447004eb1fd015925f305ed1d8426de (patch) | |
| tree | 6647b84917053748367f573f9bdc66e809cb17f5 /llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp | |
| parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) | |
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp')
| -rw-r--r-- | llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp | 160 |
1 files changed, 127 insertions, 33 deletions
diff --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp index ae537b194f50..904321a344db 100644 --- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp @@ -57,6 +57,7 @@ // //===----------------------------------------------------------------------===// +#include "SILoadStoreOptimizer.h" #include "AMDGPU.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" @@ -104,7 +105,7 @@ struct AddressRegs { // GFX10 image_sample instructions can have 12 vaddrs + srsrc + ssamp. const unsigned MaxAddressRegs = 12 + 1 + 1; -class SILoadStoreOptimizer : public MachineFunctionPass { +class SILoadStoreOptimizer { struct CombineInfo { MachineBasicBlock::iterator I; unsigned EltSize; @@ -295,17 +296,21 @@ private: static InstClassEnum getCommonInstClass(const CombineInfo &CI, const CombineInfo &Paired); -public: - static char ID; - - SILoadStoreOptimizer() : MachineFunctionPass(ID) { - initializeSILoadStoreOptimizerPass(*PassRegistry::getPassRegistry()); - } - bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList, bool &OptimizeListAgain); bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts); +public: + SILoadStoreOptimizer(AliasAnalysis *AA) : AA(AA) {} + bool run(MachineFunction &MF); +}; + +class SILoadStoreOptimizerLegacy : public MachineFunctionPass { +public: + static char ID; + + SILoadStoreOptimizerLegacy() : MachineFunctionPass(ID) {} + bool runOnMachineFunction(MachineFunction &MF) override; StringRef getPassName() const override { return "SI Load Store Optimizer"; } @@ -352,6 +357,8 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { return 1; case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec: case AMDGPU::S_LOAD_DWORDX2_IMM: case AMDGPU::S_LOAD_DWORDX2_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX2: @@ -363,6 +370,8 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { return 2; case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec: case AMDGPU::S_LOAD_DWORDX3_IMM: case AMDGPU::S_LOAD_DWORDX3_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX3: @@ -374,6 +383,8 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { return 3; case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec: case AMDGPU::S_LOAD_DWORDX4_IMM: case AMDGPU::S_LOAD_DWORDX4_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX4: @@ -385,6 +396,8 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { return 4; case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec: case AMDGPU::S_LOAD_DWORDX8_IMM: case AMDGPU::S_LOAD_DWORDX8_IMM_ec: return 8; @@ -499,12 +512,20 @@ static InstClassEnum getInstClass(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec: return S_BUFFER_LOAD_IMM; case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec: return S_BUFFER_LOAD_SGPR_IMM; case AMDGPU::S_LOAD_DWORD_IMM: case AMDGPU::S_LOAD_DWORDX2_IMM: @@ -587,12 +608,20 @@ static unsigned getInstSubclass(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec: return AMDGPU::S_BUFFER_LOAD_DWORD_IMM; case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec: return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM; case AMDGPU::S_LOAD_DWORD_IMM: case AMDGPU::S_LOAD_DWORDX2_IMM: @@ -703,6 +732,10 @@ static AddressRegs getRegs(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec: Result.SOffset = true; [[fallthrough]]; case AMDGPU::S_BUFFER_LOAD_DWORD_IMM: @@ -710,6 +743,10 @@ static AddressRegs getRegs(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM: + case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec: case AMDGPU::S_LOAD_DWORD_IMM: case AMDGPU::S_LOAD_DWORDX2_IMM: case AMDGPU::S_LOAD_DWORDX3_IMM: @@ -850,18 +887,18 @@ void SILoadStoreOptimizer::CombineInfo::setMI(MachineBasicBlock::iterator MI, } // end anonymous namespace. -INITIALIZE_PASS_BEGIN(SILoadStoreOptimizer, DEBUG_TYPE, +INITIALIZE_PASS_BEGIN(SILoadStoreOptimizerLegacy, DEBUG_TYPE, "SI Load Store Optimizer", false, false) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(SILoadStoreOptimizer, DEBUG_TYPE, "SI Load Store Optimizer", - false, false) +INITIALIZE_PASS_END(SILoadStoreOptimizerLegacy, DEBUG_TYPE, + "SI Load Store Optimizer", false, false) -char SILoadStoreOptimizer::ID = 0; +char SILoadStoreOptimizerLegacy::ID = 0; -char &llvm::SILoadStoreOptimizerID = SILoadStoreOptimizer::ID; +char &llvm::SILoadStoreOptimizerLegacyID = SILoadStoreOptimizerLegacy::ID; -FunctionPass *llvm::createSILoadStoreOptimizerPass() { - return new SILoadStoreOptimizer(); +FunctionPass *llvm::createSILoadStoreOptimizerLegacyPass() { + return new SILoadStoreOptimizerLegacy(); } static void addDefsUsesToList(const MachineInstr &MI, @@ -1679,6 +1716,14 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeFlatStorePair( return New; } +static bool needsConstrainedOpcode(const GCNSubtarget &STM, + ArrayRef<MachineMemOperand *> MMOs, + unsigned Width) { + // Conservatively returns true if not found the MMO. + return STM.isXNACKEnabled() && + (MMOs.size() != 1 || MMOs[0]->getAlign().value() < Width * 4); +} + unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI, const CombineInfo &Paired) { const unsigned Width = CI.Width + Paired.Width; @@ -1696,38 +1741,55 @@ unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI, case UNKNOWN: llvm_unreachable("Unknown instruction class"); - case S_BUFFER_LOAD_IMM: + case S_BUFFER_LOAD_IMM: { + // If XNACK is enabled, use the constrained opcodes when the first load is + // under-aligned. + bool NeedsConstrainedOpc = + needsConstrainedOpcode(*STM, CI.I->memoperands(), Width); switch (Width) { default: return 0; case 2: - return AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM; case 3: - return AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM; case 4: - return AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM; case 8: - return AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM; } - case S_BUFFER_LOAD_SGPR_IMM: + } + case S_BUFFER_LOAD_SGPR_IMM: { + // If XNACK is enabled, use the constrained opcodes when the first load is + // under-aligned. + bool NeedsConstrainedOpc = + needsConstrainedOpcode(*STM, CI.I->memoperands(), Width); switch (Width) { default: return 0; case 2: - return AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM; case 3: - return AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM; case 4: - return AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM; case 8: - return AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec + : AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM; } + } case S_LOAD_IMM: { // If XNACK is enabled, use the constrained opcodes when the first load is // under-aligned. - const MachineMemOperand *MMO = *CI.I->memoperands_begin(); bool NeedsConstrainedOpc = - STM->isXNACKEnabled() && MMO->getAlign().value() < Width * 4; + needsConstrainedOpcode(*STM, CI.I->memoperands(), Width); switch (Width) { default: return 0; @@ -1952,7 +2014,7 @@ Register SILoadStoreOptimizer::computeBase(MachineInstr &MI, MachineOperand OffsetHi = createRegOrImm(static_cast<int32_t>(Addr.Offset >> 32), MI); - const auto *CarryRC = TRI->getRegClass(AMDGPU::SReg_1_XEXECRegClassID); + const auto *CarryRC = TRI->getWaveMaskRegClass(); Register CarryReg = MRI->createVirtualRegister(CarryRC); Register DeadCarryReg = MRI->createVirtualRegister(CarryRC); @@ -1994,7 +2056,7 @@ Register SILoadStoreOptimizer::computeBase(MachineInstr &MI, void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &MI, Register NewBase, int32_t NewOffset) const { - auto Base = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr); + auto *Base = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr); Base->setReg(NewBase); Base->setIsKill(false); TII->getNamedOperand(MI, AMDGPU::OpName::offset)->setImm(NewOffset); @@ -2060,6 +2122,9 @@ void SILoadStoreOptimizer::processBaseWithConstOffset(const MachineOperand &Base BaseLo = *Src0; } + if (!BaseLo.isReg()) + return; + Src0 = TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0); Src1 = TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1); @@ -2072,6 +2137,9 @@ void SILoadStoreOptimizer::processBaseWithConstOffset(const MachineOperand &Base uint64_t Offset1 = Src1->getImm(); BaseHi = *Src0; + if (!BaseHi.isReg()) + return; + Addr.Base.LoReg = BaseLo.getReg(); Addr.Base.HiReg = BaseHi.getReg(); Addr.Base.LoSubReg = BaseLo.getSubReg(); @@ -2119,8 +2187,9 @@ bool SILoadStoreOptimizer::promoteConstantOffsetToImm( return false; } - LLVM_DEBUG(dbgs() << " BASE: {" << MAddr.Base.HiReg << ", " - << MAddr.Base.LoReg << "} Offset: " << MAddr.Offset << "\n\n";); + LLVM_DEBUG(dbgs() << " BASE: {" << printReg(MAddr.Base.HiReg, TRI) << ", " + << printReg(MAddr.Base.LoReg, TRI) + << "} Offset: " << MAddr.Offset << "\n\n";); // Step2: Traverse through MI's basic block and find an anchor(that has the // same base-registers) with the highest 13bit distance from MI's offset. @@ -2459,10 +2528,15 @@ SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr( return Modified; } -bool SILoadStoreOptimizer::runOnMachineFunction(MachineFunction &MF) { +bool SILoadStoreOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(MF.getFunction())) return false; + return SILoadStoreOptimizer( + &getAnalysis<AAResultsWrapperPass>().getAAResults()) + .run(MF); +} +bool SILoadStoreOptimizer::run(MachineFunction &MF) { STM = &MF.getSubtarget<GCNSubtarget>(); if (!STM->loadStoreOptEnabled()) return false; @@ -2471,7 +2545,6 @@ bool SILoadStoreOptimizer::runOnMachineFunction(MachineFunction &MF) { TRI = &TII->getRegisterInfo(); MRI = &MF.getRegInfo(); - AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); LLVM_DEBUG(dbgs() << "Running SILoadStoreOptimizer\n"); @@ -2508,3 +2581,24 @@ bool SILoadStoreOptimizer::runOnMachineFunction(MachineFunction &MF) { return Modified; } + +PreservedAnalyses +SILoadStoreOptimizerPass::run(MachineFunction &MF, + MachineFunctionAnalysisManager &MFAM) { + MFPropsModifier _(*this, MF); + + if (MF.getFunction().hasOptNone()) + return PreservedAnalyses::all(); + + auto &FAM = MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF) + .getManager(); + AAResults &AA = FAM.getResult<AAManager>(MF.getFunction()); + + bool Changed = SILoadStoreOptimizer(&AA).run(MF); + if (!Changed) + return PreservedAnalyses::all(); + + PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses(); + PA.preserveSet<CFGAnalyses>(); + return PA; +} |
