diff options
Diffstat (limited to 'llvm/lib/Target/R600/SIMachineFunctionInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/R600/SIMachineFunctionInfo.cpp | 57 | 
1 files changed, 48 insertions, 9 deletions
| diff --git a/llvm/lib/Target/R600/SIMachineFunctionInfo.cpp b/llvm/lib/Target/R600/SIMachineFunctionInfo.cpp index ea04346e509..af609958129 100644 --- a/llvm/lib/Target/R600/SIMachineFunctionInfo.cpp +++ b/llvm/lib/Target/R600/SIMachineFunctionInfo.cpp @@ -10,8 +10,11 @@  #include "SIMachineFunctionInfo.h" +#include "SIInstrInfo.h"  #include "SIRegisterInfo.h"  #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h"  #define MAX_LANES 64 @@ -26,21 +29,57 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)      PSInputAddr(0),      SpillTracker() { } -static unsigned createLaneVGPR(MachineRegisterInfo &MRI) { -  return MRI.createVirtualRegister(&AMDGPU::VReg_32RegClass); +static unsigned createLaneVGPR(MachineRegisterInfo &MRI, MachineFunction *MF) { +  unsigned VGPR = MRI.createVirtualRegister(&AMDGPU::VReg_32RegClass); + +  // We need to add this register as live out for the function, in order to +  // have the live range calculated directly. +  // +  // When register spilling begins, we have already calculated the live +  // live intervals for all the registers.  Since we are spilling SGPRs to +  // VGPRs, we need to update the Lane VGPR's live interval every time we +  // spill or restore a register. +  // +  // Unfortunately, there is no good way to update the live interval as +  // the TargetInstrInfo callbacks for spilling and restoring don't give +  // us access to the live interval information. +  // +  // We are lucky, though, because the InlineSpiller calls +  // LiveRangeEdit::calculateRegClassAndHint() which iterates through +  // all the new register that have been created when restoring a register +  // and calls LiveIntervals::getInterval(), which creates and computes +  // the live interval for the newly created register.  However, once this +  // live intervals is created, it doesn't change and since we usually reuse +  // the Lane VGPR multiple times, this means any uses after the first aren't +  // added to the live interval. +  // +  // To work around this, we add Lane VGPRs to the functions live out list, +  // so that we can guarantee its live range will cover all of its uses. + +  for (MachineBasicBlock &MBB : *MF) { +    if (MBB.back().getOpcode() == AMDGPU::S_ENDPGM) { +      MBB.back().addOperand(*MF, MachineOperand::CreateReg(VGPR, false, true)); +      return VGPR; +    } +  } +  MF->getFunction()->getContext().emitError( +      "Could not found S_ENGPGM instrtuction."); +  return VGPR;  } -unsigned SIMachineFunctionInfo::RegSpillTracker::getNextLane(MachineRegisterInfo &MRI) { +unsigned SIMachineFunctionInfo::RegSpillTracker::reserveLanes( +    MachineRegisterInfo &MRI, MachineFunction *MF, unsigned NumRegs) { +  unsigned StartLane = CurrentLane; +  CurrentLane += NumRegs;    if (!LaneVGPR) { -    LaneVGPR = createLaneVGPR(MRI); +    LaneVGPR = createLaneVGPR(MRI, MF);    } else { -    CurrentLane++; -    if (CurrentLane == MAX_LANES) { -      CurrentLane = 0; -      LaneVGPR = createLaneVGPR(MRI); +    if (CurrentLane >= MAX_LANES) { +      StartLane = CurrentLane = 0; +      LaneVGPR = createLaneVGPR(MRI, MF);      }    } -  return CurrentLane; +  return StartLane;  }  void SIMachineFunctionInfo::RegSpillTracker::addSpilledReg(unsigned FrameIndex, | 

