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);
36 Reserved.set(AMDGPU::FLAT_SCR);
40 unsigned SIRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
41 MachineFunction &MF) const {
42 return RC->getNumRegs();
45 bool SIRegisterInfo::requiresRegisterScavenging(const MachineFunction &Fn) const {
46 return Fn.getFrameInfo()->hasStackObjects();
49 static unsigned getNumSubRegsForSpillOp(unsigned Op) {
52 case AMDGPU::SI_SPILL_S512_SAVE:
53 case AMDGPU::SI_SPILL_S512_RESTORE:
55 case AMDGPU::SI_SPILL_S256_SAVE:
56 case AMDGPU::SI_SPILL_S256_RESTORE:
58 case AMDGPU::SI_SPILL_S128_SAVE:
59 case AMDGPU::SI_SPILL_S128_RESTORE:
61 case AMDGPU::SI_SPILL_S64_SAVE:
62 case AMDGPU::SI_SPILL_S64_RESTORE:
64 case AMDGPU::SI_SPILL_S32_SAVE:
65 case AMDGPU::SI_SPILL_S32_RESTORE:
67 default: llvm_unreachable("Invalid spill opcode");
71 void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
72 int SPAdj, unsigned FIOperandNum,
73 RegScavenger *RS) const {
74 MachineFunction *MF = MI->getParent()->getParent();
75 MachineBasicBlock *MBB = MI->getParent();
76 SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
77 MachineFrameInfo *FrameInfo = MF->getFrameInfo();
78 const SIInstrInfo *TII = static_cast<const SIInstrInfo*>(ST.getInstrInfo());
79 DebugLoc DL = MI->getDebugLoc();
81 MachineOperand &FIOp = MI->getOperand(FIOperandNum);
82 int Index = MI->getOperand(FIOperandNum).getIndex();
84 switch (MI->getOpcode()) {
85 // SGPR register spill
86 case AMDGPU::SI_SPILL_S512_SAVE:
87 case AMDGPU::SI_SPILL_S256_SAVE:
88 case AMDGPU::SI_SPILL_S128_SAVE:
89 case AMDGPU::SI_SPILL_S64_SAVE:
90 case AMDGPU::SI_SPILL_S32_SAVE: {
91 unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
93 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
94 unsigned SubReg = getPhysRegSubReg(MI->getOperand(0).getReg(),
95 &AMDGPU::SGPR_32RegClass, i);
96 struct SIMachineFunctionInfo::SpilledReg Spill =
97 MFI->getSpilledReg(MF, Index, i);
99 if (Spill.VGPR == AMDGPU::NoRegister) {
100 LLVMContext &Ctx = MF->getFunction()->getContext();
101 Ctx.emitError("Ran out of VGPRs for spilling SGPR");
104 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_WRITELANE_B32), Spill.VGPR)
109 MI->eraseFromParent();
113 // SGPR register restore
114 case AMDGPU::SI_SPILL_S512_RESTORE:
115 case AMDGPU::SI_SPILL_S256_RESTORE:
116 case AMDGPU::SI_SPILL_S128_RESTORE:
117 case AMDGPU::SI_SPILL_S64_RESTORE:
118 case AMDGPU::SI_SPILL_S32_RESTORE: {
119 unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
121 for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
122 unsigned SubReg = getPhysRegSubReg(MI->getOperand(0).getReg(),
123 &AMDGPU::SGPR_32RegClass, i);
124 struct SIMachineFunctionInfo::SpilledReg Spill =
125 MFI->getSpilledReg(MF, Index, i);
127 if (Spill.VGPR == AMDGPU::NoRegister) {
128 LLVMContext &Ctx = MF->getFunction()->getContext();
129 Ctx.emitError("Ran out of VGPRs for spilling SGPR");
132 BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32), SubReg)
137 TII->insertNOPs(MI, 3);
138 MI->eraseFromParent();
143 int64_t Offset = FrameInfo->getObjectOffset(Index);
144 FIOp.ChangeToImmediate(Offset);
145 if (!TII->isImmOperandLegal(MI, FIOperandNum, FIOp)) {
146 unsigned TmpReg = RS->scavengeRegister(&AMDGPU::VReg_32RegClass, MI, SPAdj);
147 BuildMI(*MBB, MI, MI->getDebugLoc(),
148 TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
150 FIOp.ChangeToRegister(TmpReg, false);
156 const TargetRegisterClass * SIRegisterInfo::getCFGStructurizerRegClass(
158 switch(VT.SimpleTy) {
160 case MVT::i32: return &AMDGPU::VReg_32RegClass;
164 unsigned SIRegisterInfo::getHWRegIndex(unsigned Reg) const {
165 return getEncodingValue(Reg) & 0xff;
168 const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const {
169 assert(!TargetRegisterInfo::isVirtualRegister(Reg));
171 const TargetRegisterClass *BaseClasses[] = {
172 &AMDGPU::VReg_32RegClass,
173 &AMDGPU::SReg_32RegClass,
174 &AMDGPU::VReg_64RegClass,
175 &AMDGPU::SReg_64RegClass,
176 &AMDGPU::SReg_128RegClass,
177 &AMDGPU::SReg_256RegClass
180 for (const TargetRegisterClass *BaseClass : BaseClasses) {
181 if (BaseClass->contains(Reg)) {
188 bool SIRegisterInfo::isSGPRClass(const TargetRegisterClass *RC) const {
192 return !hasVGPRs(RC);
195 bool SIRegisterInfo::hasVGPRs(const TargetRegisterClass *RC) const {
196 return getCommonSubClass(&AMDGPU::VReg_32RegClass, RC) ||
197 getCommonSubClass(&AMDGPU::VReg_64RegClass, RC) ||
198 getCommonSubClass(&AMDGPU::VReg_96RegClass, RC) ||
199 getCommonSubClass(&AMDGPU::VReg_128RegClass, RC) ||
200 getCommonSubClass(&AMDGPU::VReg_256RegClass, RC) ||
201 getCommonSubClass(&AMDGPU::VReg_512RegClass, RC);
204 const TargetRegisterClass *SIRegisterInfo::getEquivalentVGPRClass(
205 const TargetRegisterClass *SRC) const {
208 } else if (SRC == &AMDGPU::SCCRegRegClass) {
209 return &AMDGPU::VCCRegRegClass;
210 } else if (getCommonSubClass(SRC, &AMDGPU::SGPR_32RegClass)) {
211 return &AMDGPU::VReg_32RegClass;
212 } else if (getCommonSubClass(SRC, &AMDGPU::SGPR_64RegClass)) {
213 return &AMDGPU::VReg_64RegClass;
214 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_128RegClass)) {
215 return &AMDGPU::VReg_128RegClass;
216 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_256RegClass)) {
217 return &AMDGPU::VReg_256RegClass;
218 } else if (getCommonSubClass(SRC, &AMDGPU::SReg_512RegClass)) {
219 return &AMDGPU::VReg_512RegClass;
224 const TargetRegisterClass *SIRegisterInfo::getSubRegClass(
225 const TargetRegisterClass *RC, unsigned SubIdx) const {
226 if (SubIdx == AMDGPU::NoSubRegister)
229 // If this register has a sub-register, we can safely assume it is a 32-bit
230 // register, because all of SI's sub-registers are 32-bit.
231 if (isSGPRClass(RC)) {
232 return &AMDGPU::SGPR_32RegClass;
234 return &AMDGPU::VGPR_32RegClass;
238 unsigned SIRegisterInfo::getPhysRegSubReg(unsigned Reg,
239 const TargetRegisterClass *SubRC,
240 unsigned Channel) const {
245 case 0: return AMDGPU::VCC_LO;
246 case 1: return AMDGPU::VCC_HI;
247 default: llvm_unreachable("Invalid SubIdx for VCC");
251 case AMDGPU::FLAT_SCR:
254 return AMDGPU::FLAT_SCR_LO;
256 return AMDGPU::FLAT_SCR_HI;
258 llvm_unreachable("Invalid SubIdx for FLAT_SCR");
265 return AMDGPU::EXEC_LO;
267 return AMDGPU::EXEC_HI;
269 llvm_unreachable("Invalid SubIdx for EXEC");
274 unsigned Index = getHWRegIndex(Reg);
275 return SubRC->getRegister(Index + Channel);
278 bool SIRegisterInfo::regClassCanUseLiteralConstant(int RCID) const {
280 default: return false;
281 case AMDGPU::SSrc_32RegClassID:
282 case AMDGPU::SSrc_64RegClassID:
283 case AMDGPU::VSrc_32RegClassID:
284 case AMDGPU::VSrc_64RegClassID:
289 bool SIRegisterInfo::regClassCanUseLiteralConstant(
290 const TargetRegisterClass *RC) const {
291 return regClassCanUseLiteralConstant(RC->getID());
294 bool SIRegisterInfo::regClassCanUseInlineConstant(int RCID) const {
295 if (regClassCanUseLiteralConstant(RCID))
299 default: return false;
300 case AMDGPU::VCSrc_32RegClassID:
301 case AMDGPU::VCSrc_64RegClassID:
306 bool SIRegisterInfo::regClassCanUseInlineConstant(
307 const TargetRegisterClass *RC) const {
308 return regClassCanUseInlineConstant(RC->getID());
312 unsigned SIRegisterInfo::getPreloadedValue(const MachineFunction &MF,
313 enum PreloadedValue Value) const {
315 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
317 case SIRegisterInfo::TGID_X:
318 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 0);
319 case SIRegisterInfo::TGID_Y:
320 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 1);
321 case SIRegisterInfo::TGID_Z:
322 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 2);
323 case SIRegisterInfo::SCRATCH_WAVE_OFFSET:
324 return AMDGPU::SReg_32RegClass.getRegister(MFI->NumUserSGPRs + 4);
325 case SIRegisterInfo::SCRATCH_PTR:
326 return AMDGPU::SGPR2_SGPR3;
327 case SIRegisterInfo::INPUT_PTR:
328 return AMDGPU::SGPR0_SGPR1;
329 case SIRegisterInfo::TIDIG_X:
330 return AMDGPU::VGPR0;
331 case SIRegisterInfo::TIDIG_Y:
332 return AMDGPU::VGPR1;
333 case SIRegisterInfo::TIDIG_Z:
334 return AMDGPU::VGPR2;
336 llvm_unreachable("unexpected preloaded value type");