mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	AMDGPU::SI_SPILL_V96_RESTORE was missing from a switch statement, which caused the srsrc and soffset register to not be set correctly. This commit replaces the switch statement with a SITargetInfo query to make sure all spill instructions are covered. Differential Revision: http://reviews.llvm.org/D9582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237164 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			195 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- SIPrepareScratchRegs.cpp - Use predicates for control flow --------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| /// \file
 | |
| ///
 | |
| /// This pass loads scratch pointer and scratch offset into a register or a
 | |
| /// frame index which can be used anywhere in the program.  These values will
 | |
| /// be used for spilling VGPRs.
 | |
| ///
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "AMDGPU.h"
 | |
| #include "AMDGPUSubtarget.h"
 | |
| #include "SIDefines.h"
 | |
| #include "SIInstrInfo.h"
 | |
| #include "SIMachineFunctionInfo.h"
 | |
| #include "llvm/CodeGen/MachineFrameInfo.h"
 | |
| #include "llvm/CodeGen/MachineFunction.h"
 | |
| #include "llvm/CodeGen/MachineFunctionPass.h"
 | |
| #include "llvm/CodeGen/MachineInstrBuilder.h"
 | |
| #include "llvm/CodeGen/MachineRegisterInfo.h"
 | |
| #include "llvm/CodeGen/RegisterScavenging.h"
 | |
| #include "llvm/IR/Function.h"
 | |
| #include "llvm/IR/LLVMContext.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| class SIPrepareScratchRegs : public MachineFunctionPass {
 | |
| 
 | |
| private:
 | |
|   static char ID;
 | |
| 
 | |
| public:
 | |
|   SIPrepareScratchRegs() : MachineFunctionPass(ID) { }
 | |
| 
 | |
|   bool runOnMachineFunction(MachineFunction &MF) override;
 | |
| 
 | |
|   const char *getPassName() const override {
 | |
|     return "SI prepare scratch registers";
 | |
|   }
 | |
| 
 | |
| };
 | |
| 
 | |
| } // End anonymous namespace
 | |
| 
 | |
| char SIPrepareScratchRegs::ID = 0;
 | |
| 
 | |
| FunctionPass *llvm::createSIPrepareScratchRegs() {
 | |
|   return new SIPrepareScratchRegs();
 | |
| }
 | |
| 
 | |
| bool SIPrepareScratchRegs::runOnMachineFunction(MachineFunction &MF) {
 | |
|   SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
 | |
|   const SIInstrInfo *TII =
 | |
|       static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo());
 | |
|   const SIRegisterInfo *TRI = &TII->getRegisterInfo();
 | |
|   MachineRegisterInfo &MRI = MF.getRegInfo();
 | |
|   MachineFrameInfo *FrameInfo = MF.getFrameInfo();
 | |
|   MachineBasicBlock *Entry = MF.begin();
 | |
|   MachineBasicBlock::iterator I = Entry->begin();
 | |
|   DebugLoc DL = I->getDebugLoc();
 | |
| 
 | |
|   // FIXME: If we don't have enough VGPRs for SGPR spilling we will need to
 | |
|   // run this pass.
 | |
|   if (!MFI->hasSpilledVGPRs())
 | |
|     return false;
 | |
| 
 | |
|   unsigned ScratchPtrPreloadReg =
 | |
|       TRI->getPreloadedValue(MF, SIRegisterInfo::SCRATCH_PTR);
 | |
|   unsigned ScratchOffsetPreloadReg =
 | |
|       TRI->getPreloadedValue(MF, SIRegisterInfo::SCRATCH_WAVE_OFFSET);
 | |
| 
 | |
|   if (!Entry->isLiveIn(ScratchPtrPreloadReg))
 | |
|     Entry->addLiveIn(ScratchPtrPreloadReg);
 | |
| 
 | |
|   if (!Entry->isLiveIn(ScratchOffsetPreloadReg))
 | |
|     Entry->addLiveIn(ScratchOffsetPreloadReg);
 | |
| 
 | |
|   // Load the scratch offset.
 | |
|   unsigned ScratchOffsetReg =
 | |
|       TRI->findUnusedRegister(MRI, &AMDGPU::SGPR_32RegClass);
 | |
|   int ScratchOffsetFI = -1;
 | |
| 
 | |
|   if (ScratchOffsetReg != AMDGPU::NoRegister) {
 | |
|     // Found an SGPR to use
 | |
|     MRI.setPhysRegUsed(ScratchOffsetReg);
 | |
|     BuildMI(*Entry, I, DL, TII->get(AMDGPU::S_MOV_B32), ScratchOffsetReg)
 | |
|             .addReg(ScratchOffsetPreloadReg);
 | |
|   } else {
 | |
|     // No SGPR is available, we must spill.
 | |
|     ScratchOffsetFI = FrameInfo->CreateSpillStackObject(4,4);
 | |
|     BuildMI(*Entry, I, DL, TII->get(AMDGPU::SI_SPILL_S32_SAVE))
 | |
|             .addReg(ScratchOffsetPreloadReg)
 | |
|             .addFrameIndex(ScratchOffsetFI)
 | |
|             .addReg(AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3, RegState::Undef)
 | |
|             .addReg(AMDGPU::SGPR0, RegState::Undef);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   // Now that we have the scratch pointer and offset values, we need to
 | |
|   // add them to all the SI_SPILL_V* instructions.
 | |
| 
 | |
|   RegScavenger RS;
 | |
|   unsigned ScratchRsrcFI = FrameInfo->CreateSpillStackObject(16, 4);
 | |
|   RS.addScavengingFrameIndex(ScratchRsrcFI);
 | |
| 
 | |
|   for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
 | |
|        BI != BE; ++BI) {
 | |
| 
 | |
|     MachineBasicBlock &MBB = *BI;
 | |
|     // Add the scratch offset reg as a live-in so that the register scavenger
 | |
|     // doesn't re-use it.
 | |
|     if (!MBB.isLiveIn(ScratchOffsetReg) &&
 | |
|         ScratchOffsetReg != AMDGPU::NoRegister)
 | |
|       MBB.addLiveIn(ScratchOffsetReg);
 | |
|     RS.enterBasicBlock(&MBB);
 | |
| 
 | |
|     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
 | |
|          I != E; ++I) {
 | |
|       MachineInstr &MI = *I;
 | |
|       RS.forward(I);
 | |
|       DebugLoc DL = MI.getDebugLoc();
 | |
|       if (!TII->isVGPRSpill(MI.getOpcode()))
 | |
|         continue;
 | |
| 
 | |
|       // Scratch resource
 | |
|       unsigned ScratchRsrcReg =
 | |
|           RS.scavengeRegister(&AMDGPU::SReg_128RegClass, 0);
 | |
| 
 | |
|       uint64_t Rsrc = AMDGPU::RSRC_DATA_FORMAT | AMDGPU::RSRC_TID_ENABLE |
 | |
|                       0xffffffff; // Size
 | |
| 
 | |
|       unsigned Rsrc0 = TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub0);
 | |
|       unsigned Rsrc1 = TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub1);
 | |
|       unsigned Rsrc2 = TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub2);
 | |
|       unsigned Rsrc3 = TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub3);
 | |
| 
 | |
|       BuildMI(MBB, I, DL, TII->get(AMDGPU::S_MOV_B32), Rsrc0)
 | |
|               .addExternalSymbol("SCRATCH_RSRC_DWORD0")
 | |
|               .addReg(ScratchRsrcReg, RegState::ImplicitDefine);
 | |
| 
 | |
|       BuildMI(MBB, I, DL, TII->get(AMDGPU::S_MOV_B32), Rsrc1)
 | |
|               .addExternalSymbol("SCRATCH_RSRC_DWORD1")
 | |
|               .addReg(ScratchRsrcReg, RegState::ImplicitDefine);
 | |
| 
 | |
|       BuildMI(MBB, I, DL, TII->get(AMDGPU::S_MOV_B32), Rsrc2)
 | |
|               .addImm(Rsrc & 0xffffffff)
 | |
|               .addReg(ScratchRsrcReg, RegState::ImplicitDefine);
 | |
| 
 | |
|       BuildMI(MBB, I, DL, TII->get(AMDGPU::S_MOV_B32), Rsrc3)
 | |
|               .addImm(Rsrc >> 32)
 | |
|               .addReg(ScratchRsrcReg, RegState::ImplicitDefine);
 | |
| 
 | |
|       // Scratch Offset
 | |
|       if (ScratchOffsetReg == AMDGPU::NoRegister) {
 | |
|         ScratchOffsetReg = RS.scavengeRegister(&AMDGPU::SGPR_32RegClass, 0);
 | |
|         BuildMI(MBB, I, DL, TII->get(AMDGPU::SI_SPILL_S32_RESTORE),
 | |
|                 ScratchOffsetReg)
 | |
|                 .addFrameIndex(ScratchOffsetFI)
 | |
|                 .addReg(AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3, RegState::Undef)
 | |
|                 .addReg(AMDGPU::SGPR0, RegState::Undef);
 | |
|       } else if (!MBB.isLiveIn(ScratchOffsetReg)) {
 | |
|         MBB.addLiveIn(ScratchOffsetReg);
 | |
|       }
 | |
| 
 | |
|       if (ScratchRsrcReg == AMDGPU::NoRegister ||
 | |
|           ScratchOffsetReg == AMDGPU::NoRegister) {
 | |
|         LLVMContext &Ctx = MF.getFunction()->getContext();
 | |
|         Ctx.emitError("ran out of SGPRs for spilling VGPRs");
 | |
|         ScratchRsrcReg = AMDGPU::SGPR0;
 | |
|         ScratchOffsetReg = AMDGPU::SGPR0;
 | |
|       }
 | |
|       MI.getOperand(2).setReg(ScratchRsrcReg);
 | |
|       MI.getOperand(2).setIsKill(true);
 | |
|       MI.getOperand(2).setIsUndef(false);
 | |
|       MI.getOperand(3).setReg(ScratchOffsetReg);
 | |
|       MI.getOperand(3).setIsUndef(false);
 | |
|       MI.getOperand(3).setIsKill(false);
 | |
|       MI.addOperand(MachineOperand::CreateReg(Rsrc0, false, true, true));
 | |
|       MI.addOperand(MachineOperand::CreateReg(Rsrc1, false, true, true));
 | |
|       MI.addOperand(MachineOperand::CreateReg(Rsrc2, false, true, true));
 | |
|       MI.addOperand(MachineOperand::CreateReg(Rsrc3, false, true, true));
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 |