1 //===-- SIRegisterInfo.cpp - SI Register Information ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief SI implementation of the TargetRegisterInfo class.
13 //===----------------------------------------------------------------------===//
16 #include "SIRegisterInfo.h"
17 #include "AMDGPUSubtarget.h"
18 #include "SIInstrInfo.h"
19 #include "SIMachineFunctionInfo.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/RegisterScavenging.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/LLVMContext.h"
28 SIRegisterInfo::SIRegisterInfo(const AMDGPUSubtarget &st)
29 : AMDGPURegisterInfo(st)
32 BitVector SIRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
33 BitVector Reserved(getNumRegs());
34 Reserved.set(AMDGPU::EXEC);
35 Reserved.set(AMDGPU::INDIRECT_BASE_ADDR);
39 unsigned SIRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
40 MachineFunction &MF) const {
41 return RC->getNumRegs();
44 bool SIRegisterInfo::requiresRegisterScavenging(const MachineFunction &Fn) const {
45 return Fn.getFrameInfo()->hasStackObjects();
48 static unsigned getNumSubRegsForSpillOp(unsigned Op) {
51 case AMDGPU::SI_SPILL_S512_SAVE:
52 case AMDGPU::SI_SPILL_S512_RESTORE:
54 case AMDGPU::SI_SPILL_S256_SAVE:
55 case AMDGPU::SI_SPILL_S256_RESTORE:
57 case AMDGPU::SI_SPILL_S128_SAVE:
58 case AMDGPU::SI_SPILL_S128_RESTORE:
60 case AMDGPU::SI_SPILL_S64_SAVE:
61 case AMDGPU::SI_SPILL_S64_RESTORE:
63 case AMDGPU::SI_SPILL_S32_SAVE:
64 case AMDGPU::SI_SPILL_S32_RESTORE:
66 default: llvm_unreachable("Invalid spill opcode");
70 void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
71 int SPAdj, unsigned FIOperandNum,
72 RegScavenger *RS) const {
73 MachineFunction *MF = MI->getParent()->getParent();
74 MachineBasicBlock *MBB = MI->getParent();
75 SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
76 MachineFrameInfo *FrameInfo = MF->getFrameInfo();
77 const SIInstrInfo *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo());
78 DebugLoc DL = MI->getDebugLoc();
80 MachineOperand &FIOp = MI->getOperand(FIOperandNum);
81 int Index = MI->getOperand(FIOperandNum).getIndex();
83 switch (MI->getOpcode()) {
84 // SGPR register spill
85 case AMDGPU::SI_SPILL_S512_SAVE:
86 case AMDGPU::SI_SPILL_S256_SAVE:
87 case AMDGPU::SI_SPILL_S128_SAVE:
88 case AMDGPU::SI_SPILL_S64_SAVE:
89 case AMDGPU::SI_SPILL_S32_SAVE: {
90 unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
92 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
93 unsigned SubReg = getPhysRegSubReg(MI->getOperand(0).getReg(),
94 &AMDGPU::SGPR_32RegClass, i);
95 struct SIMachineFunctionInfo::SpilledReg Spill =
96 MFI->getSpilledReg(MF, Index, i);
98 if (Spill.VGPR == AMDGPU::NoRegister) {
99 LLVMContext &Ctx = MF->getFunction()->getContext();
100 Ctx.emitError("Ran out of VGPRs for spilling SGPR");
103 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_WRITELANE_B32), Spill.VGPR)
108 MI->eraseFromParent();
112 // SGPR register restore
113 case AMDGPU::SI_SPILL_S512_RESTORE:
114 case AMDGPU::SI_SPILL_S256_RESTORE:
115 case AMDGPU::SI_SPILL_S128_RESTORE:
116 case AMDGPU::SI_SPILL_S64_RESTORE:
117 case AMDGPU::SI_SPILL_S32_RESTORE: {
118 unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
120 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
121 unsigned SubReg = getPhysRegSubReg(MI->getOperand(0).getReg(),
122 &AMDGPU::SGPR_32RegClass, i);
123 struct SIMachineFunctionInfo::SpilledReg Spill =
124 MFI->getSpilledReg(MF, Index, i);
126 if (Spill.VGPR == AMDGPU::NoRegister) {
127 LLVMContext &Ctx = MF->getFunction()->getContext();
128 Ctx.emitError("Ran out of VGPRs for spilling SGPR");
131 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32), SubReg)
136 TII->insertNOPs(MI, 3);
137 MI->eraseFromParent();
142 int64_t Offset = FrameInfo->getObjectOffset(Index);
143 FIOp.ChangeToImmediate(Offset);
144 if (!TII->isImmOperandLegal(MI, FIOperandNum, FIOp)) {
145 unsigned TmpReg = RS->scavengeRegister(&AMDGPU::VReg_32RegClass, MI, SPAdj);
146 BuildMI(*MBB, MI, MI->getDebugLoc(),
147 TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
149 FIOp.ChangeToRegister(TmpReg, false);
155 const TargetRegisterClass * SIRegisterInfo::getCFGStructurizerRegClass(
157 switch(VT.SimpleTy) {
159 case MVT::i32: return &AMDGPU::VReg_32RegClass;
163 unsigned SIRegisterInfo::getHWRegIndex(unsigned Reg) const {
164 return getEncodingValue(Reg) & 0xff;
167 const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const {
168 assert(!TargetRegisterInfo::isVirtualRegister(Reg));
170 const TargetRegisterClass *BaseClasses[] = {
171 &AMDGPU::VReg_32RegClass,
172 &AMDGPU::SReg_32RegClass,
173 &AMDGPU::VReg_64RegClass,
174 &AMDGPU::SReg_64RegClass,
175 &AMDGPU::SReg_128RegClass,
176 &AMDGPU::SReg_256RegClass
179 for (const TargetRegisterClass *BaseClass : BaseClasses) {
180 if (BaseClass->contains(Reg)) {
187 bool SIRegisterInfo::isSGPRClass(const TargetRegisterClass *RC) const {
191 return !hasVGPRs(RC);
194 bool SIRegisterInfo::hasVGPRs(const TargetRegisterClass *RC) const {
195 return getCommonSubClass(&AMDGPU::VReg_32RegClass, RC) ||
196 getCommonSubClass(&AMDGPU::VReg_64RegClass, RC) ||
197 getCommonSubClass(&AMDGPU::VReg_96RegClass, RC) ||
198 getCommonSubClass(&AMDGPU::VReg_128RegClass, RC) ||
199 getCommonSubClass(&AMDGPU::VReg_256RegClass, RC) ||
200 getCommonSubClass(&AMDGPU::VReg_512RegClass, RC);
203 const TargetRegisterClass *SIRegisterInfo::getEquivalentVGPRClass(
204 const TargetRegisterClass *SRC) const {
207 } else if (SRC == &AMDGPU::SCCRegRegClass) {
208 return &AMDGPU::VCCRegRegClass;
209 } else if (getCommonSubClass(SRC, &AMDGPU::SGPR_32RegClass)) {
210 return &AMDGPU::VReg_32RegClass;
211 } else if (getCommonSubClass(SRC, &AMDGPU::SGPR_64RegClass)) {
212 return &AMDGPU::VReg_64RegClass;
213 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_128RegClass)) {
214 return &AMDGPU::VReg_128RegClass;
215 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_256RegClass)) {
216 return &AMDGPU::VReg_256RegClass;
217 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_512RegClass)) {
218 return &AMDGPU::VReg_512RegClass;
223 const TargetRegisterClass *SIRegisterInfo::getSubRegClass(
224 const TargetRegisterClass *RC, unsigned SubIdx) const {
225 if (SubIdx == AMDGPU::NoSubRegister)
228 // If this register has a sub-register, we can safely assume it is a 32-bit
229 // register, because all of SI's sub-registers are 32-bit.
230 if (isSGPRClass(RC)) {
231 return &AMDGPU::SGPR_32RegClass;
233 return &AMDGPU::VGPR_32RegClass;
237 unsigned SIRegisterInfo::getPhysRegSubReg(unsigned Reg,
238 const TargetRegisterClass *SubRC,
239 unsigned Channel) const {
244 case 0: return AMDGPU::VCC_LO;
245 case 1: return AMDGPU::VCC_HI;
246 default: llvm_unreachable("Invalid SubIdx for VCC");
251 unsigned Index = getHWRegIndex(Reg);
252 return SubRC->getRegister(Index + Channel);
255 bool SIRegisterInfo::regClassCanUseImmediate(int RCID) const {
257 default: return false;
258 case AMDGPU::SSrc_32RegClassID:
259 case AMDGPU::SSrc_64RegClassID:
260 case AMDGPU::VSrc_32RegClassID:
261 case AMDGPU::VSrc_64RegClassID:
266 bool SIRegisterInfo::regClassCanUseImmediate(
267 const TargetRegisterClass *RC) const {
268 return regClassCanUseImmediate(RC->getID());
271 unsigned SIRegisterInfo::getPreloadedValue(const MachineFunction &MF,
272 enum PreloadedValue Value) const {
274 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
276 case SIRegisterInfo::TGID_X:
277 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 0);
278 case SIRegisterInfo::TGID_Y:
279 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 1);
280 case SIRegisterInfo::TGID_Z:
281 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 2);
282 case SIRegisterInfo::SCRATCH_WAVE_OFFSET:
283 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 4);
284 case SIRegisterInfo::SCRATCH_PTR:
285 return AMDGPU::SGPR2_SGPR3;
287 llvm_unreachable("unexpected preloaded value type");