aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-07-26 22:04:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-07-26 22:04:10 +0000
commitac9a064cb179f3425b310fa2847f8764ac970a4d (patch)
tree6f945cdaa68c2b4c688dcf9fec4f922d35f4d1a4 /llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
parent4df029cc74e5ec124f14a5682e44999ce4f086df (diff)
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp335
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