forked from OSchip/llvm-project
AMDGPU: Limit the search in finding the instruction pattern for v_swap generation.
Summary: Current implementation of matchSwap in SIShrinkInstructions searches the entire use_nodbg_operands set to find the possible pattern to generate v_swap instruction. This approach will lead to a O(N^3) in compile time for SIShrinkInstructions. But in reality, the matching pattern only exists within nearby instructions in the same basic block. This work limits the search to a maximum of 16 instructions, and has a linear compile time comsumption. Reviewers: rampitec, arsenm Differential Revision: https://reviews.llvm.org/D74180
This commit is contained in:
parent
4a1a0690ad
commit
6370c7c13e
|
@ -471,26 +471,30 @@ static MachineInstr* matchSwap(MachineInstr &MovT, MachineRegisterInfo &MRI,
|
||||||
if (!TRI.isVGPR(MRI, X))
|
if (!TRI.isVGPR(MRI, X))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
for (MachineOperand &YTop : MRI.use_nodbg_operands(T)) {
|
const unsigned SearchLimit = 16;
|
||||||
if (YTop.getSubReg() != Tsub)
|
unsigned Count = 0;
|
||||||
|
for (auto Iter = std::next(MovT.getIterator()),
|
||||||
|
E = MovT.getParent()->instr_end();
|
||||||
|
Iter != E && Count < SearchLimit; ++Iter, ++Count) {
|
||||||
|
|
||||||
|
MachineInstr *MovY = &*Iter;
|
||||||
|
if ((MovY->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
|
||||||
|
MovY->getOpcode() != AMDGPU::COPY) ||
|
||||||
|
!MovY->getOperand(1).isReg() ||
|
||||||
|
MovY->getOperand(1).getReg() != T ||
|
||||||
|
MovY->getOperand(1).getSubReg() != Tsub)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MachineInstr &MovY = *YTop.getParent();
|
Register Y = MovY->getOperand(0).getReg();
|
||||||
if ((MovY.getOpcode() != AMDGPU::V_MOV_B32_e32 &&
|
unsigned Ysub = MovY->getOperand(0).getSubReg();
|
||||||
MovY.getOpcode() != AMDGPU::COPY) ||
|
|
||||||
MovY.getOperand(1).getSubReg() != Tsub)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Register Y = MovY.getOperand(0).getReg();
|
if (!TRI.isVGPR(MRI, Y))
|
||||||
unsigned Ysub = MovY.getOperand(0).getSubReg();
|
|
||||||
|
|
||||||
if (!TRI.isVGPR(MRI, Y) || MovT.getParent() != MovY.getParent())
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MachineInstr *MovX = nullptr;
|
MachineInstr *MovX = nullptr;
|
||||||
auto I = std::next(MovT.getIterator()), E = MovT.getParent()->instr_end();
|
for (auto IY = MovY->getIterator(), I = std::next(MovT.getIterator());
|
||||||
for (auto IY = MovY.getIterator(); I != E && I != IY; ++I) {
|
I != IY; ++I) {
|
||||||
if (instReadsReg(&*I, X, Xsub, TRI) ||
|
if (instReadsReg(&*I, X, Xsub, TRI) ||
|
||||||
instModifiesReg(&*I, Y, Ysub, TRI) ||
|
instModifiesReg(&*I, Y, Ysub, TRI) ||
|
||||||
instModifiesReg(&*I, T, Tsub, TRI) ||
|
instModifiesReg(&*I, T, Tsub, TRI) ||
|
||||||
(MovX && instModifiesReg(&*I, X, Xsub, TRI))) {
|
(MovX && instModifiesReg(&*I, X, Xsub, TRI))) {
|
||||||
|
@ -515,7 +519,7 @@ static MachineInstr* matchSwap(MachineInstr &MovT, MachineRegisterInfo &MRI,
|
||||||
MovX = &*I;
|
MovX = &*I;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MovX || I == E)
|
if (!MovX)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "Matched v_swap_b32:\n" << MovT << *MovX << MovY);
|
LLVM_DEBUG(dbgs() << "Matched v_swap_b32:\n" << MovT << *MovX << MovY);
|
||||||
|
@ -532,7 +536,7 @@ static MachineInstr* matchSwap(MachineInstr &MovT, MachineRegisterInfo &MRI,
|
||||||
.addReg(X1.Reg, 0, X1.SubReg).getInstr();
|
.addReg(X1.Reg, 0, X1.SubReg).getInstr();
|
||||||
}
|
}
|
||||||
MovX->eraseFromParent();
|
MovX->eraseFromParent();
|
||||||
MovY.eraseFromParent();
|
MovY->eraseFromParent();
|
||||||
MachineInstr *Next = &*std::next(MovT.getIterator());
|
MachineInstr *Next = &*std::next(MovT.getIterator());
|
||||||
if (MRI.use_nodbg_empty(T))
|
if (MRI.use_nodbg_empty(T))
|
||||||
MovT.eraseFromParent();
|
MovT.eraseFromParent();
|
||||||
|
|
|
@ -562,3 +562,113 @@ body: |
|
||||||
%1.sub0 = COPY %2.sub0
|
%1.sub0 = COPY %2.sub0
|
||||||
S_ENDPGM 0
|
S_ENDPGM 0
|
||||||
...
|
...
|
||||||
|
|
||||||
|
# GCN-LABEL: name: swap_exact_max_insns_apart
|
||||||
|
# GCN: bb.0:
|
||||||
|
# GCN-NEXT: %0:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %1:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %0:vgpr_32, %1:vgpr_32 = V_SWAP_B32 %1, %0, implicit $exec
|
||||||
|
# GCN-NEXT: S_ENDPGM 0
|
||||||
|
|
||||||
|
---
|
||||||
|
name: swap_exact_max_insns_apart
|
||||||
|
registers:
|
||||||
|
- { id: 0, class: vgpr_32 }
|
||||||
|
- { id: 1, class: vgpr_32 }
|
||||||
|
- { id: 2, class: vgpr_32 }
|
||||||
|
- { id: 3, class: vgpr_32 }
|
||||||
|
- { id: 4, class: vgpr_32 }
|
||||||
|
body: |
|
||||||
|
bb.0:
|
||||||
|
%0 = IMPLICIT_DEF
|
||||||
|
%1 = IMPLICIT_DEF
|
||||||
|
%2 = COPY %0
|
||||||
|
%3 = IMPLICIT_DEF
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%0 = COPY %1
|
||||||
|
%1 = COPY %2
|
||||||
|
S_ENDPGM 0
|
||||||
|
...
|
||||||
|
|
||||||
|
# GCN-LABEL: name: swap_too_far
|
||||||
|
# GCN: bb.0:
|
||||||
|
# GCN-NEXT: %0:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %1:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %2:vgpr_32 = COPY %0
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = IMPLICIT_DEF
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %4:vgpr_32 = COPY %3
|
||||||
|
# GCN-NEXT: %3:vgpr_32 = COPY %4
|
||||||
|
# GCN-NEXT: %0:vgpr_32 = COPY %1
|
||||||
|
# GCN-NEXT: %1:vgpr_32 = COPY %2
|
||||||
|
# GCN-NEXT: S_ENDPGM 0
|
||||||
|
|
||||||
|
---
|
||||||
|
name: swap_too_far
|
||||||
|
registers:
|
||||||
|
- { id: 0, class: vgpr_32 }
|
||||||
|
- { id: 1, class: vgpr_32 }
|
||||||
|
- { id: 2, class: vgpr_32 }
|
||||||
|
- { id: 3, class: vgpr_32 }
|
||||||
|
- { id: 4, class: vgpr_32 }
|
||||||
|
body: |
|
||||||
|
bb.0:
|
||||||
|
%0 = IMPLICIT_DEF
|
||||||
|
%1 = IMPLICIT_DEF
|
||||||
|
%2 = COPY %0
|
||||||
|
%3 = IMPLICIT_DEF
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%4 = COPY %3
|
||||||
|
%3 = COPY %4
|
||||||
|
%0 = COPY %1
|
||||||
|
%1 = COPY %2
|
||||||
|
S_ENDPGM 0
|
||||||
|
...
|
||||||
|
|
Loading…
Reference in New Issue