aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp109
1 files changed, 69 insertions, 40 deletions
diff --git a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
index 1349d3b6bf3f..30405059530e 100644
--- a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
+++ b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
@@ -16,19 +16,12 @@
//===----------------------------------------------------------------------===//
#include "AMDGPU.h"
-#include "AMDGPUSubtarget.h"
-#include "SIInstrInfo.h"
+#include "GCNSubtarget.h"
+#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "SIMachineFunctionInfo.h"
#include "llvm/CodeGen/LiveIntervals.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/InitializePasses.h"
-#include "llvm/Target/TargetMachine.h"
using namespace llvm;
@@ -97,7 +90,7 @@ static void insertCSRSaves(MachineBasicBlock &SaveBlock,
if (!TFI->spillCalleeSavedRegisters(SaveBlock, I, CSI, TRI)) {
for (const CalleeSavedInfo &CS : CSI) {
// Insert the spill to the stack frame.
- unsigned Reg = CS.getReg();
+ MCRegister Reg = CS.getReg();
MachineInstrSpan MIS(I, &SaveBlock);
const TargetRegisterClass *RC =
@@ -184,6 +177,16 @@ void SILowerSGPRSpills::calculateSaveRestoreBlocks(MachineFunction &MF) {
}
}
+// TODO: To support shrink wrapping, this would need to copy
+// PrologEpilogInserter's updateLiveness.
+static void updateLiveness(MachineFunction &MF, ArrayRef<CalleeSavedInfo> CSI) {
+ MachineBasicBlock &EntryBB = MF.front();
+
+ for (const CalleeSavedInfo &CSIReg : CSI)
+ EntryBB.addLiveIn(CSIReg.getReg());
+ EntryBB.sortUniqueLiveIns();
+}
+
bool SILowerSGPRSpills::spillCalleeSavedRegs(MachineFunction &MF) {
MachineRegisterInfo &MRI = MF.getRegInfo();
const Function &F = MF.getFunction();
@@ -206,7 +209,8 @@ bool SILowerSGPRSpills::spillCalleeSavedRegs(MachineFunction &MF) {
const MCPhysReg *CSRegs = MRI.getCalleeSavedRegs();
for (unsigned I = 0; CSRegs[I]; ++I) {
- unsigned Reg = CSRegs[I];
+ MCRegister Reg = CSRegs[I];
+
if (SavedRegs.test(Reg)) {
const TargetRegisterClass *RC =
TRI->getMinimalPhysRegClass(Reg, MVT::i32);
@@ -221,6 +225,10 @@ bool SILowerSGPRSpills::spillCalleeSavedRegs(MachineFunction &MF) {
for (MachineBasicBlock *SaveBlock : SaveBlocks)
insertCSRSaves(*SaveBlock, CSI, LIS);
+ // Add live ins to save blocks.
+ assert(SaveBlocks.size() == 1 && "shrink wrapping not fully implemented");
+ updateLiveness(MF, CSI);
+
for (MachineBasicBlock *RestoreBlock : RestoreBlocks)
insertCSRRestores(*RestoreBlock, CSI, LIS);
return true;
@@ -233,38 +241,44 @@ bool SILowerSGPRSpills::spillCalleeSavedRegs(MachineFunction &MF) {
// Find lowest available VGPR and use it as VGPR reserved for SGPR spills.
static bool lowerShiftReservedVGPR(MachineFunction &MF,
const GCNSubtarget &ST) {
- MachineRegisterInfo &MRI = MF.getRegInfo();
- MachineFrameInfo &FrameInfo = MF.getFrameInfo();
SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
- Register LowestAvailableVGPR, ReservedVGPR;
- ArrayRef<MCPhysReg> AllVGPR32s = ST.getRegisterInfo()->getAllVGPR32(MF);
- for (MCPhysReg Reg : AllVGPR32s) {
- if (MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg)) {
- LowestAvailableVGPR = Reg;
- break;
- }
- }
+ const Register PreReservedVGPR = FuncInfo->VGPRReservedForSGPRSpill;
+ // Early out if pre-reservation of a VGPR for SGPR spilling is disabled.
+ if (!PreReservedVGPR)
+ return false;
+ // If there are no free lower VGPRs available, default to using the
+ // pre-reserved register instead.
+ const SIRegisterInfo *TRI = ST.getRegisterInfo();
+ Register LowestAvailableVGPR =
+ TRI->findUnusedRegister(MF.getRegInfo(), &AMDGPU::VGPR_32RegClass, MF);
if (!LowestAvailableVGPR)
- return false;
+ LowestAvailableVGPR = PreReservedVGPR;
- ReservedVGPR = FuncInfo->VGPRReservedForSGPRSpill;
const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
- int i = 0;
+ MachineFrameInfo &FrameInfo = MF.getFrameInfo();
+ Optional<int> FI;
+ // Check if we are reserving a CSR. Create a stack object for a possible spill
+ // in the function prologue.
+ if (FuncInfo->isCalleeSavedReg(CSRegs, LowestAvailableVGPR))
+ FI = FrameInfo.CreateSpillStackObject(4, Align(4));
- for (MachineBasicBlock &MBB : MF) {
- for (auto Reg : FuncInfo->getSGPRSpillVGPRs()) {
- if (Reg.VGPR == ReservedVGPR) {
- MBB.removeLiveIn(ReservedVGPR);
- MBB.addLiveIn(LowestAvailableVGPR);
- Optional<int> FI;
- if (FuncInfo->isCalleeSavedReg(CSRegs, LowestAvailableVGPR))
- FI = FrameInfo.CreateSpillStackObject(4, Align(4));
+ // Find saved info about the pre-reserved register.
+ const auto *ReservedVGPRInfoItr =
+ llvm::find_if(FuncInfo->getSGPRSpillVGPRs(),
+ [PreReservedVGPR](const auto &SpillRegInfo) {
+ return SpillRegInfo.VGPR == PreReservedVGPR;
+ });
- FuncInfo->setSGPRSpillVGPRs(LowestAvailableVGPR, FI, i);
- }
- ++i;
- }
+ assert(ReservedVGPRInfoItr != FuncInfo->getSGPRSpillVGPRs().end());
+ auto Index =
+ std::distance(FuncInfo->getSGPRSpillVGPRs().begin(), ReservedVGPRInfoItr);
+
+ FuncInfo->setSGPRSpillVGPRs(LowestAvailableVGPR, FI, Index);
+
+ for (MachineBasicBlock &MBB : MF) {
+ assert(LowestAvailableVGPR.isValid() && "Did not find an available VGPR");
+ MBB.addLiveIn(LowestAvailableVGPR);
MBB.sortUniqueLiveIns();
}
@@ -300,11 +314,15 @@ bool SILowerSGPRSpills::runOnMachineFunction(MachineFunction &MF) {
bool MadeChange = false;
const bool SpillToAGPR = EnableSpillVGPRToAGPR && ST.hasMAIInsts();
+ std::unique_ptr<RegScavenger> RS;
+
+ bool NewReservedRegs = false;
// TODO: CSR VGPRs will never be spilled to AGPRs. These can probably be
// handled as SpilledToReg in regular PrologEpilogInserter.
- if ((TRI->spillSGPRToVGPR() && (HasCSRs || FuncInfo->hasSpilledSGPRs())) ||
- SpillVGPRToAGPR) {
+ const bool HasSGPRSpillToVGPR = TRI->spillSGPRToVGPR() &&
+ (HasCSRs || FuncInfo->hasSpilledSGPRs());
+ if (HasSGPRSpillToVGPR || SpillVGPRToAGPR) {
// Process all SGPR spills before frame offsets are finalized. Ideally SGPRs
// are spilled to VGPRs, in which case we can eliminate the stack usage.
//
@@ -329,7 +347,13 @@ bool SILowerSGPRSpills::runOnMachineFunction(MachineFunction &MF) {
TII->getNamedOperand(MI, AMDGPU::OpName::vdata)->getReg();
if (FuncInfo->allocateVGPRSpillToAGPR(MF, FI,
TRI->isAGPR(MRI, VReg))) {
- TRI->eliminateFrameIndex(MI, 0, FIOp, nullptr);
+ NewReservedRegs = true;
+ if (!RS)
+ RS.reset(new RegScavenger());
+
+ // FIXME: change to enterBasicBlockEnd()
+ RS->enterBasicBlock(MBB);
+ TRI->eliminateFrameIndex(MI, 0, FIOp, RS.get());
continue;
}
}
@@ -340,6 +364,7 @@ bool SILowerSGPRSpills::runOnMachineFunction(MachineFunction &MF) {
int FI = TII->getNamedOperand(MI, AMDGPU::OpName::addr)->getIndex();
assert(MFI.getStackID(FI) == TargetStackID::SGPRSpill);
if (FuncInfo->allocateSGPRSpillToVGPR(MF, FI)) {
+ NewReservedRegs = true;
bool Spilled = TRI->eliminateSGPRToVGPRSpillFrameIndex(MI, FI, nullptr);
(void)Spilled;
assert(Spilled && "failed to spill SGPR to VGPR when allocated");
@@ -368,5 +393,9 @@ bool SILowerSGPRSpills::runOnMachineFunction(MachineFunction &MF) {
SaveBlocks.clear();
RestoreBlocks.clear();
+ // Updated the reserved registers with any VGPRs added for SGPR spills.
+ if (NewReservedRegs)
+ MRI.freezeReservedRegs(MF);
+
return MadeChange;
}