mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-09 22:13:07 +00:00
AMDGPU/SI: Add support for spilling VGPRs without having to scavenge registers
Summary: When we are spilling SGPRs to scratch memory, we usually don't have free SGPRs to do the address calculation, so we need to re-use the ScratchOffset register for the calculation. Reviewers: arsenm Subscribers: arsenm, llvm-commits Differential Revision: http://reviews.llvm.org/D18917 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266244 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f301f27d4e
commit
a092aaccd0
@ -246,29 +246,42 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI,
|
||||
unsigned Value,
|
||||
unsigned ScratchRsrcReg,
|
||||
unsigned ScratchOffset,
|
||||
int64_t Offset) const {
|
||||
int64_t Offset,
|
||||
RegScavenger *RS) const {
|
||||
|
||||
MachineBasicBlock *MBB = MI->getParent();
|
||||
MachineFunction *MF = MI->getParent()->getParent();
|
||||
MachineRegisterInfo &MRI = MF->getRegInfo();
|
||||
const SIInstrInfo *TII =
|
||||
static_cast<const SIInstrInfo *>(MF->getSubtarget().getInstrInfo());
|
||||
LLVMContext &Ctx = MF->getFunction()->getContext();
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
bool IsStore = TII->get(LoadStoreOp).mayStore();
|
||||
|
||||
bool RanOutOfSGPRs = false;
|
||||
bool Scavenged = false;
|
||||
unsigned SOffset = ScratchOffset;
|
||||
unsigned OriginalImmOffset = Offset;
|
||||
|
||||
unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
|
||||
unsigned Size = NumSubRegs * 4;
|
||||
|
||||
if (!isUInt<12>(Offset + Size)) {
|
||||
SOffset = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
|
||||
SOffset = AMDGPU::NoRegister;
|
||||
|
||||
// We don't have access to the register scavenger if this function is called
|
||||
// during PEI::scavengeFrameVirtualRegs().
|
||||
if (RS)
|
||||
SOffset = RS->FindUnusedReg(&AMDGPU::SGPR_32RegClass);
|
||||
|
||||
if (SOffset == AMDGPU::NoRegister) {
|
||||
// There are no free SGPRs, and since we are in the process of spilling
|
||||
// VGPRs too. Since we need a VGPR in order to spill SGPRs (this is true
|
||||
// on SI/CI and on VI it is true until we implement spilling using scalar
|
||||
// stores), we have no way to free up an SGPR. Our solution here is to
|
||||
// add the offset directly to the ScratchOffset register, and then
|
||||
// subtract the offset after the spill to return ScratchOffset to it's
|
||||
// original value.
|
||||
RanOutOfSGPRs = true;
|
||||
SOffset = AMDGPU::SGPR0;
|
||||
SOffset = ScratchOffset;
|
||||
} else {
|
||||
Scavenged = true;
|
||||
}
|
||||
@ -278,9 +291,6 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI,
|
||||
Offset = 0;
|
||||
}
|
||||
|
||||
if (RanOutOfSGPRs)
|
||||
Ctx.emitError("Ran out of SGPRs for spilling VGPRS");
|
||||
|
||||
for (unsigned i = 0, e = NumSubRegs; i != e; ++i, Offset += 4) {
|
||||
unsigned SubReg = NumSubRegs > 1 ?
|
||||
getPhysRegSubReg(Value, &AMDGPU::VGPR_32RegClass, i) :
|
||||
@ -301,6 +311,13 @@ void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI,
|
||||
.addReg(Value, RegState::Implicit | getDefRegState(!IsStore))
|
||||
.setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
|
||||
}
|
||||
|
||||
if (RanOutOfSGPRs) {
|
||||
// Subtract the offset we added to the ScratchOffset register.
|
||||
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_SUB_U32), ScratchOffset)
|
||||
.addReg(ScratchOffset)
|
||||
.addImm(OriginalImmOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
@ -451,7 +468,7 @@ void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_rsrc)->getReg(),
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_offset)->getReg(),
|
||||
FrameInfo->getObjectOffset(Index) +
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm());
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), RS);
|
||||
MI->eraseFromParent();
|
||||
break;
|
||||
case AMDGPU::SI_SPILL_V32_RESTORE:
|
||||
@ -465,7 +482,7 @@ void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_rsrc)->getReg(),
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_offset)->getReg(),
|
||||
FrameInfo->getObjectOffset(Index) +
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm());
|
||||
TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), RS);
|
||||
MI->eraseFromParent();
|
||||
break;
|
||||
}
|
||||
|
@ -171,7 +171,8 @@ private:
|
||||
void buildScratchLoadStore(MachineBasicBlock::iterator MI,
|
||||
unsigned LoadStoreOp, unsigned Value,
|
||||
unsigned ScratchRsrcReg, unsigned ScratchOffset,
|
||||
int64_t Offset) const;
|
||||
int64_t Offset,
|
||||
RegScavenger *RS) const;
|
||||
};
|
||||
|
||||
} // End namespace llvm
|
||||
|
Loading…
x
Reference in New Issue
Block a user