diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-26 22:04:10 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-07-26 22:04:10 +0000 |
| commit | ac9a064cb179f3425b310fa2847f8764ac970a4d (patch) | |
| tree | 6f945cdaa68c2b4c688dcf9fec4f922d35f4d1a4 /llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp | |
| parent | 4df029cc74e5ec124f14a5682e44999ce4f086df (diff) | |
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp')
| -rw-r--r-- | llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp | 335 |
1 files changed, 154 insertions, 181 deletions
diff --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp index 9c85ff3c43e2..ae537b194f50 100644 --- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp @@ -216,15 +216,23 @@ private: CombineInfo &Paired, bool Modify = false); static bool widthsFit(const GCNSubtarget &STI, const CombineInfo &CI, const CombineInfo &Paired); - static unsigned getNewOpcode(const CombineInfo &CI, const CombineInfo &Paired); + unsigned getNewOpcode(const CombineInfo &CI, const CombineInfo &Paired); static std::pair<unsigned, unsigned> getSubRegIdxs(const CombineInfo &CI, const CombineInfo &Paired); - const TargetRegisterClass *getTargetRegisterClass(const CombineInfo &CI, - const CombineInfo &Paired); + const TargetRegisterClass * + getTargetRegisterClass(const CombineInfo &CI, + const CombineInfo &Paired) const; const TargetRegisterClass *getDataRegClass(const MachineInstr &MI) const; CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired); + void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired, + MachineBasicBlock::iterator InsertBefore, int OpName, + Register DestReg) const; + Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired, + MachineBasicBlock::iterator InsertBefore, + int OpName) const; + unsigned read2Opcode(unsigned EltSize) const; unsigned read2ST64Opcode(unsigned EltSize) const; MachineBasicBlock::iterator @@ -345,6 +353,7 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM: case AMDGPU::S_LOAD_DWORDX2_IMM: + case AMDGPU::S_LOAD_DWORDX2_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX2: case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR: case AMDGPU::GLOBAL_STORE_DWORDX2: @@ -355,6 +364,7 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM: case AMDGPU::S_LOAD_DWORDX3_IMM: + case AMDGPU::S_LOAD_DWORDX3_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX3: case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR: case AMDGPU::GLOBAL_STORE_DWORDX3: @@ -365,6 +375,7 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM: case AMDGPU::S_LOAD_DWORDX4_IMM: + case AMDGPU::S_LOAD_DWORDX4_IMM_ec: case AMDGPU::GLOBAL_LOAD_DWORDX4: case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR: case AMDGPU::GLOBAL_STORE_DWORDX4: @@ -375,15 +386,16 @@ static unsigned getOpcodeWidth(const MachineInstr &MI, const SIInstrInfo &TII) { case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM: case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM: case AMDGPU::S_LOAD_DWORDX8_IMM: + case AMDGPU::S_LOAD_DWORDX8_IMM_ec: return 8; - case AMDGPU::DS_READ_B32: [[fallthrough]]; - case AMDGPU::DS_READ_B32_gfx9: [[fallthrough]]; - case AMDGPU::DS_WRITE_B32: [[fallthrough]]; + case AMDGPU::DS_READ_B32: + case AMDGPU::DS_READ_B32_gfx9: + case AMDGPU::DS_WRITE_B32: case AMDGPU::DS_WRITE_B32_gfx9: return 1; - case AMDGPU::DS_READ_B64: [[fallthrough]]; - case AMDGPU::DS_READ_B64_gfx9: [[fallthrough]]; - case AMDGPU::DS_WRITE_B64: [[fallthrough]]; + case AMDGPU::DS_READ_B64: + case AMDGPU::DS_READ_B64_gfx9: + case AMDGPU::DS_WRITE_B64: case AMDGPU::DS_WRITE_B64_gfx9: return 2; default: @@ -399,19 +411,35 @@ static InstClassEnum getInstClass(unsigned Opc, const SIInstrInfo &TII) { switch (AMDGPU::getMUBUFBaseOpcode(Opc)) { default: return UNKNOWN; + case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN: + case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact: + case AMDGPU::BUFFER_LOAD_DWORD_IDXEN: + case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_OFFEN: case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_OFFSET: case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact: return BUFFER_LOAD; + case AMDGPU::BUFFER_STORE_DWORD_BOTHEN: + case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact: + case AMDGPU::BUFFER_STORE_DWORD_IDXEN: + case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact: case AMDGPU::BUFFER_STORE_DWORD_OFFEN: case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact: case AMDGPU::BUFFER_STORE_DWORD_OFFSET: case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET: @@ -483,6 +511,10 @@ static InstClassEnum getInstClass(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_LOAD_DWORDX3_IMM: case AMDGPU::S_LOAD_DWORDX4_IMM: case AMDGPU::S_LOAD_DWORDX8_IMM: + case AMDGPU::S_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_LOAD_DWORDX8_IMM_ec: return S_LOAD_IMM; case AMDGPU::DS_READ_B32: case AMDGPU::DS_READ_B32_gfx9: @@ -567,6 +599,10 @@ static unsigned getInstSubclass(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_LOAD_DWORDX3_IMM: case AMDGPU::S_LOAD_DWORDX4_IMM: case AMDGPU::S_LOAD_DWORDX8_IMM: + case AMDGPU::S_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_LOAD_DWORDX8_IMM_ec: return AMDGPU::S_LOAD_DWORD_IMM; case AMDGPU::GLOBAL_LOAD_DWORD: case AMDGPU::GLOBAL_LOAD_DWORDX2: @@ -679,6 +715,10 @@ static AddressRegs getRegs(unsigned Opc, const SIInstrInfo &TII) { case AMDGPU::S_LOAD_DWORDX3_IMM: case AMDGPU::S_LOAD_DWORDX4_IMM: case AMDGPU::S_LOAD_DWORDX8_IMM: + case AMDGPU::S_LOAD_DWORDX2_IMM_ec: + case AMDGPU::S_LOAD_DWORDX3_IMM_ec: + case AMDGPU::S_LOAD_DWORDX4_IMM_ec: + case AMDGPU::S_LOAD_DWORDX8_IMM_ec: Result.SBase = true; return Result; case AMDGPU::DS_READ_B32: @@ -862,7 +902,7 @@ SILoadStoreOptimizer::combineKnownAdjacentMMOs(const CombineInfo &CI, const MachineMemOperand *MMOa = *CI.I->memoperands_begin(); const MachineMemOperand *MMOb = *Paired.I->memoperands_begin(); - unsigned Size = MMOa->getSize() + MMOb->getSize(); + unsigned Size = MMOa->getSize().getValue() + MMOb->getSize().getValue(); // A base pointer for the combined operation is the same as the leading // operation's pointer. @@ -1175,6 +1215,63 @@ SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI, return Where; } +// Copy the merged load result from DestReg to the original dest regs of CI and +// Paired. +void SILoadStoreOptimizer::copyToDestRegs( + CombineInfo &CI, CombineInfo &Paired, + MachineBasicBlock::iterator InsertBefore, int OpName, + Register DestReg) const { + MachineBasicBlock *MBB = CI.I->getParent(); + DebugLoc DL = CI.I->getDebugLoc(); + + auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired); + + // Copy to the old destination registers. + const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); + auto *Dest0 = TII->getNamedOperand(*CI.I, OpName); + auto *Dest1 = TII->getNamedOperand(*Paired.I, OpName); + + // The constrained sload instructions in S_LOAD_IMM class will have + // `early-clobber` flag in the dst operand. Remove the flag before using the + // MOs in copies. + Dest0->setIsEarlyClobber(false); + Dest1->setIsEarlyClobber(false); + + BuildMI(*MBB, InsertBefore, DL, CopyDesc) + .add(*Dest0) // Copy to same destination including flags and sub reg. + .addReg(DestReg, 0, SubRegIdx0); + BuildMI(*MBB, InsertBefore, DL, CopyDesc) + .add(*Dest1) + .addReg(DestReg, RegState::Kill, SubRegIdx1); +} + +// Return a register for the source of the merged store after copying the +// original source regs of CI and Paired into it. +Register +SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired, + MachineBasicBlock::iterator InsertBefore, + int OpName) const { + MachineBasicBlock *MBB = CI.I->getParent(); + DebugLoc DL = CI.I->getDebugLoc(); + + auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired); + + // Copy to the new source register. + const TargetRegisterClass *SuperRC = getTargetRegisterClass(CI, Paired); + Register SrcReg = MRI->createVirtualRegister(SuperRC); + + const auto *Src0 = TII->getNamedOperand(*CI.I, OpName); + const auto *Src1 = TII->getNamedOperand(*Paired.I, OpName); + + BuildMI(*MBB, InsertBefore, DL, TII->get(AMDGPU::REG_SEQUENCE), SrcReg) + .add(*Src0) + .addImm(SubRegIdx0) + .add(*Src1) + .addImm(SubRegIdx1); + + return SrcReg; +} + unsigned SILoadStoreOptimizer::read2Opcode(unsigned EltSize) const { if (STM->ldsRequiresM0Init()) return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64; @@ -1198,23 +1295,11 @@ SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired, // cases, like vectors of pointers. const auto *AddrReg = TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdst); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdst); - - unsigned NewOffset0 = CI.Offset; - unsigned NewOffset1 = Paired.Offset; + unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset); + unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset); unsigned Opc = CI.UseST64 ? read2ST64Opcode(CI.EltSize) : read2Opcode(CI.EltSize); - unsigned SubRegIdx0 = (CI.EltSize == 4) ? AMDGPU::sub0 : AMDGPU::sub0_sub1; - unsigned SubRegIdx1 = (CI.EltSize == 4) ? AMDGPU::sub1 : AMDGPU::sub2_sub3; - - if (NewOffset0 > NewOffset1) { - // Canonicalize the merged instruction so the smaller offset comes first. - std::swap(NewOffset0, NewOffset1); - std::swap(SubRegIdx0, SubRegIdx1); - } - assert((isUInt<8>(NewOffset0) && isUInt<8>(NewOffset1)) && (NewOffset0 != NewOffset1) && "Computed offset doesn't fit"); @@ -1251,17 +1336,7 @@ SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired, .addImm(0) // gds .cloneMergedMemRefs({&*CI.I, &*Paired.I}); - (void)Read2; - - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - - // Copy to the old destination registers. - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdst, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1381,20 +1456,7 @@ SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired, MachineInstr *New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired)); - unsigned SubRegIdx0, SubRegIdx1; - std::tie(SubRegIdx0, SubRegIdx1) = getSubRegIdxs(CI, Paired); - - // Copy to the old destination registers. - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1426,21 +1488,7 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeSMemLoadImmPair( New.addImm(MergedOffset); New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired)); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the old destination registers. - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::sdst); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::sdst); - - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::sdst, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1481,21 +1529,7 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeBufferLoadPair( .addImm(0) // swz .addMemOperand(combineKnownAdjacentMMOs(CI, Paired)); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the old destination registers. - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1540,21 +1574,7 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeTBufferLoadPair( .addImm(0) // swz .addMemOperand(combineKnownAdjacentMMOs(CI, Paired)); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the old destination registers. - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1569,22 +1589,8 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeTBufferStorePair( const unsigned Opcode = getNewOpcode(CI, Paired); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the new source register. - const TargetRegisterClass *SuperRC = getTargetRegisterClass(CI, Paired); - Register SrcReg = MRI->createVirtualRegister(SuperRC); - - const auto *Src0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Src1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, TII->get(AMDGPU::REG_SEQUENCE), SrcReg) - .add(*Src0) - .addImm(SubRegIdx0) - .add(*Src1) - .addImm(SubRegIdx1); + Register SrcReg = + copyFromSrcRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata); auto MIB = BuildMI(*MBB, InsertBefore, DL, TII->get(Opcode)) .addReg(SrcReg, RegState::Kill); @@ -1638,21 +1644,7 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeFlatLoadPair( .addImm(CI.CPol) .addMemOperand(combineKnownAdjacentMMOs(CI, Paired)); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the old destination registers. - const MCInstrDesc &CopyDesc = TII->get(TargetOpcode::COPY); - const auto *Dest0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdst); - const auto *Dest1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdst); - - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest0) // Copy to same destination including flags and sub reg. - .addReg(DestReg, 0, SubRegIdx0); - BuildMI(*MBB, InsertBefore, DL, CopyDesc) - .add(*Dest1) - .addReg(DestReg, RegState::Kill, SubRegIdx1); + copyToDestRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdst, DestReg); CI.I->eraseFromParent(); Paired.I->eraseFromParent(); @@ -1667,22 +1659,8 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeFlatStorePair( const unsigned Opcode = getNewOpcode(CI, Paired); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the new source register. - const TargetRegisterClass *SuperRC = getTargetRegisterClass(CI, Paired); - Register SrcReg = MRI->createVirtualRegister(SuperRC); - - const auto *Src0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Src1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, TII->get(AMDGPU::REG_SEQUENCE), SrcReg) - .add(*Src0) - .addImm(SubRegIdx0) - .add(*Src1) - .addImm(SubRegIdx1); + Register SrcReg = + copyFromSrcRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata); auto MIB = BuildMI(*MBB, InsertBefore, DL, TII->get(Opcode)) .add(*TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr)) @@ -1744,19 +1722,29 @@ unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI, case 8: return AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM; } - case S_LOAD_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; switch (Width) { default: return 0; case 2: - return AMDGPU::S_LOAD_DWORDX2_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec + : AMDGPU::S_LOAD_DWORDX2_IMM; case 3: - return AMDGPU::S_LOAD_DWORDX3_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec + : AMDGPU::S_LOAD_DWORDX3_IMM; case 4: - return AMDGPU::S_LOAD_DWORDX4_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec + : AMDGPU::S_LOAD_DWORDX4_IMM; case 8: - return AMDGPU::S_LOAD_DWORDX8_IMM; + return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec + : AMDGPU::S_LOAD_DWORDX8_IMM; } + } case GLOBAL_LOAD: switch (Width) { default: @@ -1860,12 +1848,12 @@ SILoadStoreOptimizer::getSubRegIdxs(const CombineInfo &CI, Idx1 = Idxs[CI.Width][Paired.Width - 1]; } - return std::pair(Idx0, Idx1); + return {Idx0, Idx1}; } const TargetRegisterClass * SILoadStoreOptimizer::getTargetRegisterClass(const CombineInfo &CI, - const CombineInfo &Paired) { + const CombineInfo &Paired) const { if (CI.InstClass == S_BUFFER_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) { switch (CI.Width + Paired.Width) { @@ -1898,22 +1886,8 @@ MachineBasicBlock::iterator SILoadStoreOptimizer::mergeBufferStorePair( const unsigned Opcode = getNewOpcode(CI, Paired); - std::pair<unsigned, unsigned> SubRegIdx = getSubRegIdxs(CI, Paired); - const unsigned SubRegIdx0 = std::get<0>(SubRegIdx); - const unsigned SubRegIdx1 = std::get<1>(SubRegIdx); - - // Copy to the new source register. - const TargetRegisterClass *SuperRC = getTargetRegisterClass(CI, Paired); - Register SrcReg = MRI->createVirtualRegister(SuperRC); - - const auto *Src0 = TII->getNamedOperand(*CI.I, AMDGPU::OpName::vdata); - const auto *Src1 = TII->getNamedOperand(*Paired.I, AMDGPU::OpName::vdata); - - BuildMI(*MBB, InsertBefore, DL, TII->get(AMDGPU::REG_SEQUENCE), SrcReg) - .add(*Src0) - .addImm(SubRegIdx0) - .add(*Src1) - .addImm(SubRegIdx1); + Register SrcReg = + copyFromSrcRegs(CI, Paired, InsertBefore, AMDGPU::OpName::vdata); auto MIB = BuildMI(*MBB, InsertBefore, DL, TII->get(Opcode)) .addReg(SrcReg, RegState::Kill); @@ -2092,7 +2066,7 @@ void SILoadStoreOptimizer::processBaseWithConstOffset(const MachineOperand &Base if (Src0->isImm()) std::swap(Src0, Src1); - if (!Src1->isImm()) + if (!Src1->isImm() || Src0->isImm()) return; uint64_t Offset1 = Src1->getImm(); @@ -2110,16 +2084,15 @@ bool SILoadStoreOptimizer::promoteConstantOffsetToImm( MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &AnchorList) const { - if (!(MI.mayLoad() ^ MI.mayStore())) + if (!STM->hasFlatInstOffsets() || !SIInstrInfo::isFLAT(MI)) return false; - // TODO: Support flat and scratch. - if (AMDGPU::getGlobalSaddrOp(MI.getOpcode()) < 0) + // TODO: Support FLAT_SCRATCH. Currently code expects 64-bit pointers. + if (SIInstrInfo::isFLATScratch(MI)) return false; - if (MI.mayLoad() && - TII->getNamedOperand(MI, AMDGPU::OpName::vdata) != nullptr) - return false; + unsigned AS = SIInstrInfo::isFLATGlobal(MI) ? AMDGPUAS::GLOBAL_ADDRESS + : AMDGPUAS::FLAT_ADDRESS; if (AnchorList.count(&MI)) return false; @@ -2209,13 +2182,13 @@ bool SILoadStoreOptimizer::promoteConstantOffsetToImm( MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg) continue; - InstsWCommonBase.push_back(std::pair(&MINext, MAddrNext.Offset)); + InstsWCommonBase.emplace_back(&MINext, MAddrNext.Offset); int64_t Dist = MAddr.Offset - MAddrNext.Offset; TargetLoweringBase::AddrMode AM; AM.HasBaseReg = true; AM.BaseOffs = Dist; - if (TLI->isLegalGlobalAddressingMode(AM) && + if (TLI->isLegalFlatAddressingMode(AM, AS) && (uint32_t)std::abs(Dist) > MaxDist) { MaxDist = std::abs(Dist); @@ -2236,16 +2209,16 @@ bool SILoadStoreOptimizer::promoteConstantOffsetToImm( updateBaseAndOffset(MI, Base, MAddr.Offset - AnchorAddr.Offset); LLVM_DEBUG(dbgs() << " After promotion: "; MI.dump();); - for (auto P : InstsWCommonBase) { + for (auto [OtherMI, OtherOffset] : InstsWCommonBase) { TargetLoweringBase::AddrMode AM; AM.HasBaseReg = true; - AM.BaseOffs = P.second - AnchorAddr.Offset; + AM.BaseOffs = OtherOffset - AnchorAddr.Offset; - if (TLI->isLegalGlobalAddressingMode(AM)) { - LLVM_DEBUG(dbgs() << " Promote Offset(" << P.second; - dbgs() << ")"; P.first->dump()); - updateBaseAndOffset(*P.first, Base, P.second - AnchorAddr.Offset); - LLVM_DEBUG(dbgs() << " After promotion: "; P.first->dump()); + if (TLI->isLegalFlatAddressingMode(AM, AS)) { + LLVM_DEBUG(dbgs() << " Promote Offset(" << OtherOffset; dbgs() << ")"; + OtherMI->dump()); + updateBaseAndOffset(*OtherMI, Base, OtherOffset - AnchorAddr.Offset); + LLVM_DEBUG(dbgs() << " After promotion: "; OtherMI->dump()); } } AnchorList.insert(AnchorInst); @@ -2359,7 +2332,7 @@ SILoadStoreOptimizer::collectMergeableInsts( ++I; } - return std::pair(BlockI, Modified); + return {BlockI, Modified}; } // Scan through looking for adjacent LDS operations with constant offsets from |
