[llvm] r283175 - AMDGPU: Factor SGPR spilling into separate functions
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 3 18:14:56 PDT 2016
Author: arsenm
Date: Mon Oct 3 20:14:56 2016
New Revision: 283175
URL: http://llvm.org/viewvc/llvm-project?rev=283175&view=rev
Log:
AMDGPU: Factor SGPR spilling into separate functions
Modified:
llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp
llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h
Modified: llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp?rev=283175&r1=283174&r2=283175&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp Mon Oct 3 20:14:56 2016
@@ -404,6 +404,164 @@ void SIRegisterInfo::buildScratchLoadSto
}
}
+void SIRegisterInfo::spillSGPR(MachineBasicBlock::iterator MI,
+ int Index,
+ RegScavenger *RS) const {
+ MachineFunction *MF = MI->getParent()->getParent();
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ MachineBasicBlock *MBB = MI->getParent();
+ SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
+ MachineFrameInfo &FrameInfo = MF->getFrameInfo();
+ const SISubtarget &ST = MF->getSubtarget<SISubtarget>();
+ const SIInstrInfo *TII = ST.getInstrInfo();
+ const DebugLoc &DL = MI->getDebugLoc();
+
+ unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
+ unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
+ unsigned SuperReg = MI->getOperand(0).getReg();
+ bool IsKill = MI->getOperand(0).isKill();
+
+ // SubReg carries the "Kill" flag when SubReg == SuperReg.
+ unsigned SubKillState = getKillRegState((NumSubRegs == 1) && IsKill);
+ for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
+ unsigned SubReg = NumSubRegs == 1 ?
+ SuperReg : getSubReg(SuperReg, getSubRegFromChannel(i));
+
+ struct SIMachineFunctionInfo::SpilledReg Spill =
+ MFI->getSpilledReg(MF, Index, i);
+ if (Spill.hasReg()) {
+ if (SuperReg == AMDGPU::M0) {
+ assert(NumSubRegs == 1);
+ unsigned CopyM0
+ = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
+ BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), CopyM0)
+ .addReg(SuperReg, getKillRegState(IsKill));
+
+ // The real spill now kills the temp copy.
+ SubReg = SuperReg = CopyM0;
+ IsKill = true;
+ }
+
+ BuildMI(*MBB, MI, DL,
+ TII->getMCOpcodeFromPseudo(AMDGPU::V_WRITELANE_B32),
+ Spill.VGPR)
+ .addReg(SubReg, getKillRegState(IsKill))
+ .addImm(Spill.Lane);
+
+ // FIXME: Since this spills to another register instead of an actual
+ // frame index, we should delete the frame index when all references to
+ // it are fixed.
+ } else {
+ // Spill SGPR to a frame index.
+ // FIXME we should use S_STORE_DWORD here for VI.
+ MachineInstrBuilder Mov
+ = BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
+ .addReg(SubReg, SubKillState);
+
+
+ // There could be undef components of a spilled super register.
+ // TODO: Can we detect this and skip the spill?
+ if (NumSubRegs > 1) {
+ // The last implicit use of the SuperReg carries the "Kill" flag.
+ unsigned SuperKillState = 0;
+ if (i + 1 == e)
+ SuperKillState |= getKillRegState(IsKill);
+ Mov.addReg(SuperReg, RegState::Implicit | SuperKillState);
+ }
+
+ unsigned Size = FrameInfo.getObjectSize(Index);
+ unsigned Align = FrameInfo.getObjectAlignment(Index);
+ MachinePointerInfo PtrInfo
+ = MachinePointerInfo::getFixedStack(*MF, Index);
+ MachineMemOperand *MMO
+ = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
+ Size, Align);
+ BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_SAVE))
+ .addReg(TmpReg, RegState::Kill) // src
+ .addFrameIndex(Index) // vaddr
+ .addReg(MFI->getScratchRSrcReg()) // srrsrc
+ .addReg(MFI->getScratchWaveOffsetReg()) // soffset
+ .addImm(i * 4) // offset
+ .addMemOperand(MMO);
+ }
+ }
+
+ MI->eraseFromParent();
+ MFI->addToSpilledSGPRs(NumSubRegs);
+}
+
+void SIRegisterInfo::restoreSGPR(MachineBasicBlock::iterator MI,
+ int Index,
+ RegScavenger *RS) const {
+ MachineFunction *MF = MI->getParent()->getParent();
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ MachineBasicBlock *MBB = MI->getParent();
+ SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
+ MachineFrameInfo &FrameInfo = MF->getFrameInfo();
+ const SISubtarget &ST = MF->getSubtarget<SISubtarget>();
+ const SIInstrInfo *TII = ST.getInstrInfo();
+ const DebugLoc &DL = MI->getDebugLoc();
+
+ unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
+ unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
+ unsigned SuperReg = MI->getOperand(0).getReg();
+
+ // m0 is not allowed as with readlane/writelane, so a temporary SGPR and
+ // extra copy is needed.
+ bool IsM0 = (SuperReg == AMDGPU::M0);
+ if (IsM0) {
+ assert(NumSubRegs == 1);
+ SuperReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
+ }
+
+ for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
+ unsigned SubReg = NumSubRegs == 1 ?
+ SuperReg : getSubReg(SuperReg, getSubRegFromChannel(i));
+
+ SIMachineFunctionInfo::SpilledReg Spill
+ = MFI->getSpilledReg(MF, Index, i);
+
+ if (Spill.hasReg()) {
+ BuildMI(*MBB, MI, DL,
+ TII->getMCOpcodeFromPseudo(AMDGPU::V_READLANE_B32),
+ SubReg)
+ .addReg(Spill.VGPR)
+ .addImm(Spill.Lane)
+ .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
+ } else {
+ // Restore SGPR from a stack slot.
+ // FIXME: We should use S_LOAD_DWORD here for VI.
+
+ unsigned Align = FrameInfo.getObjectAlignment(Index);
+ unsigned Size = FrameInfo.getObjectSize(Index);
+
+ MachinePointerInfo PtrInfo
+ = MachinePointerInfo::getFixedStack(*MF, Index);
+
+ MachineMemOperand *MMO = MF->getMachineMemOperand(
+ PtrInfo, MachineMemOperand::MOLoad, Size, Align);
+
+ BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_RESTORE), TmpReg)
+ .addFrameIndex(Index) // vaddr
+ .addReg(MFI->getScratchRSrcReg()) // srsrc
+ .addReg(MFI->getScratchWaveOffsetReg()) // soffset
+ .addImm(i * 4) // offset
+ .addMemOperand(MMO);
+ BuildMI(*MBB, MI, DL,
+ TII->get(AMDGPU::V_READFIRSTLANE_B32), SubReg)
+ .addReg(TmpReg, RegState::Kill)
+ .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
+ }
+ }
+
+ if (IsM0 && SuperReg != AMDGPU::M0) {
+ BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), AMDGPU::M0)
+ .addReg(SuperReg);
+ }
+
+ MI->eraseFromParent();
+}
+
void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
@@ -426,77 +584,7 @@ void SIRegisterInfo::eliminateFrameIndex
case AMDGPU::SI_SPILL_S128_SAVE:
case AMDGPU::SI_SPILL_S64_SAVE:
case AMDGPU::SI_SPILL_S32_SAVE: {
- unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
- unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
- unsigned SuperReg = MI->getOperand(0).getReg();
- bool IsKill = MI->getOperand(0).isKill();
-
- // SubReg carries the "Kill" flag when SubReg == SuperReg.
- unsigned SubKillState = getKillRegState((NumSubRegs == 1) && IsKill);
- for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
- unsigned SubReg = NumSubRegs == 1 ?
- SuperReg : getSubReg(SuperReg, getSubRegFromChannel(i));
-
- struct SIMachineFunctionInfo::SpilledReg Spill =
- MFI->getSpilledReg(MF, Index, i);
- if (Spill.hasReg()) {
- if (SuperReg == AMDGPU::M0) {
- assert(NumSubRegs == 1);
- unsigned CopyM0
- = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
- BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), CopyM0)
- .addReg(SuperReg, getKillRegState(IsKill));
-
- // The real spill now kills the temp copy.
- SubReg = SuperReg = CopyM0;
- IsKill = true;
- }
-
- BuildMI(*MBB, MI, DL,
- TII->getMCOpcodeFromPseudo(AMDGPU::V_WRITELANE_B32),
- Spill.VGPR)
- .addReg(SubReg, getKillRegState(IsKill))
- .addImm(Spill.Lane);
-
- // FIXME: Since this spills to another register instead of an actual
- // frame index, we should delete the frame index when all references to
- // it are fixed.
- } else {
- // Spill SGPR to a frame index.
- // FIXME we should use S_STORE_DWORD here for VI.
- MachineInstrBuilder Mov
- = BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
- .addReg(SubReg, SubKillState);
-
-
- // There could be undef components of a spilled super register.
- // TODO: Can we detect this and skip the spill?
- if (NumSubRegs > 1) {
- // The last implicit use of the SuperReg carries the "Kill" flag.
- unsigned SuperKillState = 0;
- if (i + 1 == e)
- SuperKillState |= getKillRegState(IsKill);
- Mov.addReg(SuperReg, RegState::Implicit | SuperKillState);
- }
-
- unsigned Size = FrameInfo.getObjectSize(Index);
- unsigned Align = FrameInfo.getObjectAlignment(Index);
- MachinePointerInfo PtrInfo
- = MachinePointerInfo::getFixedStack(*MF, Index);
- MachineMemOperand *MMO
- = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
- Size, Align);
- BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_SAVE))
- .addReg(TmpReg, RegState::Kill) // src
- .addFrameIndex(Index) // vaddr
- .addReg(MFI->getScratchRSrcReg()) // srrsrc
- .addReg(MFI->getScratchWaveOffsetReg()) // soffset
- .addImm(i * 4) // offset
- .addMemOperand(MMO);
- }
- }
- MI->eraseFromParent();
- MFI->addToSpilledSGPRs(NumSubRegs);
+ spillSGPR(MI, Index, RS);
break;
}
@@ -506,64 +594,7 @@ void SIRegisterInfo::eliminateFrameIndex
case AMDGPU::SI_SPILL_S128_RESTORE:
case AMDGPU::SI_SPILL_S64_RESTORE:
case AMDGPU::SI_SPILL_S32_RESTORE: {
- unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
- unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
- unsigned SuperReg = MI->getOperand(0).getReg();
-
- // m0 is not allowed as with readlane/writelane, so a temporary SGPR and
- // extra copy is needed.
- bool IsM0 = (SuperReg == AMDGPU::M0);
- if (IsM0) {
- assert(NumSubRegs == 1);
- SuperReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
- }
-
- for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
- unsigned SubReg = NumSubRegs == 1 ?
- SuperReg : getSubReg(SuperReg, getSubRegFromChannel(i));
-
- SIMachineFunctionInfo::SpilledReg Spill
- = MFI->getSpilledReg(MF, Index, i);
-
- if (Spill.hasReg()) {
- BuildMI(*MBB, MI, DL,
- TII->getMCOpcodeFromPseudo(AMDGPU::V_READLANE_B32),
- SubReg)
- .addReg(Spill.VGPR)
- .addImm(Spill.Lane)
- .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
- } else {
- // Restore SGPR from a stack slot.
- // FIXME: We should use S_LOAD_DWORD here for VI.
-
- unsigned Align = FrameInfo.getObjectAlignment(Index);
- unsigned Size = FrameInfo.getObjectSize(Index);
-
- MachinePointerInfo PtrInfo
- = MachinePointerInfo::getFixedStack(*MF, Index);
-
- MachineMemOperand *MMO = MF->getMachineMemOperand(
- PtrInfo, MachineMemOperand::MOLoad, Size, Align);
-
- BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_RESTORE), TmpReg)
- .addFrameIndex(Index) // vaddr
- .addReg(MFI->getScratchRSrcReg()) // srsrc
- .addReg(MFI->getScratchWaveOffsetReg()) // soffset
- .addImm(i * 4) // offset
- .addMemOperand(MMO);
- BuildMI(*MBB, MI, DL,
- TII->get(AMDGPU::V_READFIRSTLANE_B32), SubReg)
- .addReg(TmpReg, RegState::Kill)
- .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
- }
- }
-
- if (IsM0 && SuperReg != AMDGPU::M0) {
- BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), AMDGPU::M0)
- .addReg(SuperReg);
- }
-
- MI->eraseFromParent();
+ restoreSGPR(MI, Index, RS);
break;
}
Modified: llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h?rev=283175&r1=283174&r2=283175&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h Mon Oct 3 20:14:56 2016
@@ -73,6 +73,12 @@ public:
const TargetRegisterClass *getPointerRegClass(
const MachineFunction &MF, unsigned Kind = 0) const override;
+ void spillSGPR(MachineBasicBlock::iterator MI,
+ int FI, RegScavenger *RS) const;
+
+ void restoreSGPR(MachineBasicBlock::iterator MI,
+ int FI, RegScavenger *RS) const;
+
void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS) const override;
More information about the llvm-commits
mailing list