Index: llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h +++ llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.h @@ -171,7 +171,8 @@ 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 Index: llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ llvm/trunk/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -246,29 +246,42 @@ 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(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 @@ 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 @@ .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 @@ 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 @@ 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; }