R600/SI: Clean up checks for legality of immediate operands
[oota-llvm.git] / lib / Target / R600 / SIRegisterInfo.cpp
1 //===-- SIRegisterInfo.cpp - SI Register Information ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// \brief SI implementation of the TargetRegisterInfo class.
12 //
13 //===----------------------------------------------------------------------===//
14
15
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"
25
26 using namespace llvm;
27
28 SIRegisterInfo::SIRegisterInfo(const AMDGPUSubtarget &st)
29 : AMDGPURegisterInfo(st)
30   { }
31
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);
37   return Reserved;
38 }
39
40 unsigned SIRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
41                                              MachineFunction &MF) const {
42   return RC->getNumRegs();
43 }
44
45 bool SIRegisterInfo::requiresRegisterScavenging(const MachineFunction &Fn) const {
46   return Fn.getFrameInfo()->hasStackObjects();
47 }
48
49 static unsigned getNumSubRegsForSpillOp(unsigned Op) {
50
51   switch (Op) {
52   case AMDGPU::SI_SPILL_S512_SAVE:
53   case AMDGPU::SI_SPILL_S512_RESTORE:
54     return 16;
55   case AMDGPU::SI_SPILL_S256_SAVE:
56   case AMDGPU::SI_SPILL_S256_RESTORE:
57     return 8;
58   case AMDGPU::SI_SPILL_S128_SAVE:
59   case AMDGPU::SI_SPILL_S128_RESTORE:
60     return 4;
61   case AMDGPU::SI_SPILL_S64_SAVE:
62   case AMDGPU::SI_SPILL_S64_RESTORE:
63     return 2;
64   case AMDGPU::SI_SPILL_S32_SAVE:
65   case AMDGPU::SI_SPILL_S32_RESTORE:
66     return 1;
67   default: llvm_unreachable("Invalid spill opcode");
68   }
69 }
70
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();
80
81   MachineOperand &FIOp = MI->getOperand(FIOperandNum);
82   int Index = MI->getOperand(FIOperandNum).getIndex();
83
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());
92
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);
98
99         if (Spill.VGPR == AMDGPU::NoRegister) {
100            LLVMContext &Ctx = MF->getFunction()->getContext();
101            Ctx.emitError("Ran out of VGPRs for spilling SGPR");
102         }
103
104         BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_WRITELANE_B32), Spill.VGPR)
105                 .addReg(SubReg)
106                 .addImm(Spill.Lane);
107
108       }
109       MI->eraseFromParent();
110       break;
111     }
112
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());
120
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);
126
127         if (Spill.VGPR == AMDGPU::NoRegister) {
128            LLVMContext &Ctx = MF->getFunction()->getContext();
129            Ctx.emitError("Ran out of VGPRs for spilling SGPR");
130         }
131
132         BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32), SubReg)
133                 .addReg(Spill.VGPR)
134                 .addImm(Spill.Lane);
135
136       }
137       TII->insertNOPs(MI, 3);
138       MI->eraseFromParent();
139       break;
140     }
141
142     default: {
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)
149                 .addImm(Offset);
150         FIOp.ChangeToRegister(TmpReg, false);
151       }
152     }
153   }
154 }
155
156 const TargetRegisterClass * SIRegisterInfo::getCFGStructurizerRegClass(
157                                                                    MVT VT) const {
158   switch(VT.SimpleTy) {
159     default:
160     case MVT::i32: return &AMDGPU::VReg_32RegClass;
161   }
162 }
163
164 unsigned SIRegisterInfo::getHWRegIndex(unsigned Reg) const {
165   return getEncodingValue(Reg) & 0xff;
166 }
167
168 const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const {
169   assert(!TargetRegisterInfo::isVirtualRegister(Reg));
170
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
178   };
179
180   for (const TargetRegisterClass *BaseClass : BaseClasses) {
181     if (BaseClass->contains(Reg)) {
182       return BaseClass;
183     }
184   }
185   return nullptr;
186 }
187
188 bool SIRegisterInfo::isSGPRClass(const TargetRegisterClass *RC) const {
189   if (!RC) {
190     return false;
191   }
192   return !hasVGPRs(RC);
193 }
194
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);
202 }
203
204 const TargetRegisterClass *SIRegisterInfo::getEquivalentVGPRClass(
205                                          const TargetRegisterClass *SRC) const {
206     if (hasVGPRs(SRC)) {
207       return SRC;
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;
220     }
221     return nullptr;
222 }
223
224 const TargetRegisterClass *SIRegisterInfo::getSubRegClass(
225                          const TargetRegisterClass *RC, unsigned SubIdx) const {
226   if (SubIdx == AMDGPU::NoSubRegister)
227     return RC;
228
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;
233   } else {
234     return &AMDGPU::VGPR_32RegClass;
235   }
236 }
237
238 unsigned SIRegisterInfo::getPhysRegSubReg(unsigned Reg,
239                                           const TargetRegisterClass *SubRC,
240                                           unsigned Channel) const {
241
242   switch (Reg) {
243     case AMDGPU::VCC:
244       switch(Channel) {
245         case 0: return AMDGPU::VCC_LO;
246         case 1: return AMDGPU::VCC_HI;
247         default: llvm_unreachable("Invalid SubIdx for VCC");
248       }
249       break;
250
251   case AMDGPU::FLAT_SCR:
252     switch (Channel) {
253     case 0:
254       return AMDGPU::FLAT_SCR_LO;
255     case 1:
256       return AMDGPU::FLAT_SCR_HI;
257     default:
258       llvm_unreachable("Invalid SubIdx for FLAT_SCR");
259     }
260     break;
261
262   case AMDGPU::EXEC:
263     switch (Channel) {
264     case 0:
265       return AMDGPU::EXEC_LO;
266     case 1:
267       return AMDGPU::EXEC_HI;
268     default:
269       llvm_unreachable("Invalid SubIdx for EXEC");
270     }
271     break;
272   }
273
274   unsigned Index = getHWRegIndex(Reg);
275   return SubRC->getRegister(Index + Channel);
276 }
277
278 bool SIRegisterInfo::regClassCanUseLiteralConstant(int RCID) const {
279   switch (RCID) {
280   default: return false;
281   case AMDGPU::SSrc_32RegClassID:
282   case AMDGPU::SSrc_64RegClassID:
283   case AMDGPU::VSrc_32RegClassID:
284   case AMDGPU::VSrc_64RegClassID:
285     return true;
286   }
287 }
288
289 bool SIRegisterInfo::regClassCanUseLiteralConstant(
290                              const TargetRegisterClass *RC) const {
291   return regClassCanUseLiteralConstant(RC->getID());
292 }
293
294 bool SIRegisterInfo::regClassCanUseInlineConstant(int RCID) const {
295   if (regClassCanUseLiteralConstant(RCID))
296     return true;
297
298   switch (RCID) {
299   default: return false;
300   case AMDGPU::VCSrc_32RegClassID:
301   case AMDGPU::VCSrc_64RegClassID:
302     return true;
303   }
304 }
305
306 bool SIRegisterInfo::regClassCanUseInlineConstant(
307                             const TargetRegisterClass *RC) const {
308   return regClassCanUseInlineConstant(RC->getID());
309 }
310
311
312 unsigned SIRegisterInfo::getPreloadedValue(const MachineFunction &MF,
313                                            enum PreloadedValue Value) const {
314
315   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
316   switch (Value) {
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;
335   }
336   llvm_unreachable("unexpected preloaded value type");
337 }