xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SIRegisterInfo.cpp - SI Register Information ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief SI implementation of the TargetRegisterInfo class.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "SIRegisterInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "SIInstrInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "SIMachineFunctionInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterScavenging.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker 
getMaxWaveCountPerSIMD(const MachineFunction & MF)27*9880d681SAndroid Build Coastguard Worker static unsigned getMaxWaveCountPerSIMD(const MachineFunction &MF) {
28*9880d681SAndroid Build Coastguard Worker   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
29*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
30*9880d681SAndroid Build Coastguard Worker   unsigned SIMDPerCU = 4;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker   unsigned MaxInvocationsPerWave = SIMDPerCU * ST.getWavefrontSize();
33*9880d681SAndroid Build Coastguard Worker   return alignTo(MFI.getMaximumWorkGroupSize(MF), MaxInvocationsPerWave) /
34*9880d681SAndroid Build Coastguard Worker            MaxInvocationsPerWave;
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker 
getMaxWorkGroupSGPRCount(const MachineFunction & MF)37*9880d681SAndroid Build Coastguard Worker static unsigned getMaxWorkGroupSGPRCount(const MachineFunction &MF) {
38*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
39*9880d681SAndroid Build Coastguard Worker   unsigned MaxWaveCountPerSIMD = getMaxWaveCountPerSIMD(MF);
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker   unsigned TotalSGPRCountPerSIMD, AddressableSGPRCount, SGPRUsageAlignment;
42*9880d681SAndroid Build Coastguard Worker   unsigned ReservedSGPRCount;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker   if (ST.getGeneration() >= SISubtarget::VOLCANIC_ISLANDS) {
45*9880d681SAndroid Build Coastguard Worker     TotalSGPRCountPerSIMD = 800;
46*9880d681SAndroid Build Coastguard Worker     AddressableSGPRCount = 102;
47*9880d681SAndroid Build Coastguard Worker     SGPRUsageAlignment = 16;
48*9880d681SAndroid Build Coastguard Worker     ReservedSGPRCount = 6; // VCC, FLAT_SCRATCH, XNACK
49*9880d681SAndroid Build Coastguard Worker   } else {
50*9880d681SAndroid Build Coastguard Worker     TotalSGPRCountPerSIMD = 512;
51*9880d681SAndroid Build Coastguard Worker     AddressableSGPRCount = 104;
52*9880d681SAndroid Build Coastguard Worker     SGPRUsageAlignment = 8;
53*9880d681SAndroid Build Coastguard Worker     ReservedSGPRCount = 2; // VCC
54*9880d681SAndroid Build Coastguard Worker   }
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   unsigned MaxSGPRCount = (TotalSGPRCountPerSIMD / MaxWaveCountPerSIMD);
57*9880d681SAndroid Build Coastguard Worker   MaxSGPRCount = alignDown(MaxSGPRCount, SGPRUsageAlignment);
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   if (ST.hasSGPRInitBug())
60*9880d681SAndroid Build Coastguard Worker     MaxSGPRCount = SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG;
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   return std::min(MaxSGPRCount - ReservedSGPRCount, AddressableSGPRCount);
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker 
getMaxWorkGroupVGPRCount(const MachineFunction & MF)65*9880d681SAndroid Build Coastguard Worker static unsigned getMaxWorkGroupVGPRCount(const MachineFunction &MF) {
66*9880d681SAndroid Build Coastguard Worker   unsigned MaxWaveCountPerSIMD = getMaxWaveCountPerSIMD(MF);
67*9880d681SAndroid Build Coastguard Worker   unsigned TotalVGPRCountPerSIMD = 256;
68*9880d681SAndroid Build Coastguard Worker   unsigned VGPRUsageAlignment = 4;
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   return alignDown(TotalVGPRCountPerSIMD / MaxWaveCountPerSIMD,
71*9880d681SAndroid Build Coastguard Worker                    VGPRUsageAlignment);
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker 
hasPressureSet(const int * PSets,unsigned PSetID)74*9880d681SAndroid Build Coastguard Worker static bool hasPressureSet(const int *PSets, unsigned PSetID) {
75*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; PSets[i] != -1; ++i) {
76*9880d681SAndroid Build Coastguard Worker     if (PSets[i] == (int)PSetID)
77*9880d681SAndroid Build Coastguard Worker       return true;
78*9880d681SAndroid Build Coastguard Worker   }
79*9880d681SAndroid Build Coastguard Worker   return false;
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
classifyPressureSet(unsigned PSetID,unsigned Reg,BitVector & PressureSets) const82*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::classifyPressureSet(unsigned PSetID, unsigned Reg,
83*9880d681SAndroid Build Coastguard Worker                                          BitVector &PressureSets) const {
84*9880d681SAndroid Build Coastguard Worker   for (MCRegUnitIterator U(Reg, this); U.isValid(); ++U) {
85*9880d681SAndroid Build Coastguard Worker     const int *PSets = getRegUnitPressureSets(*U);
86*9880d681SAndroid Build Coastguard Worker     if (hasPressureSet(PSets, PSetID)) {
87*9880d681SAndroid Build Coastguard Worker       PressureSets.set(PSetID);
88*9880d681SAndroid Build Coastguard Worker       break;
89*9880d681SAndroid Build Coastguard Worker     }
90*9880d681SAndroid Build Coastguard Worker   }
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker 
SIRegisterInfo()93*9880d681SAndroid Build Coastguard Worker SIRegisterInfo::SIRegisterInfo() : AMDGPURegisterInfo(),
94*9880d681SAndroid Build Coastguard Worker                                    SGPRPressureSets(getNumRegPressureSets()),
95*9880d681SAndroid Build Coastguard Worker                                    VGPRPressureSets(getNumRegPressureSets()) {
96*9880d681SAndroid Build Coastguard Worker   unsigned NumRegPressureSets = getNumRegPressureSets();
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker   SGPR32SetID = NumRegPressureSets;
99*9880d681SAndroid Build Coastguard Worker   VGPR32SetID = NumRegPressureSets;
100*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < NumRegPressureSets; ++i) {
101*9880d681SAndroid Build Coastguard Worker     if (strncmp("SGPR_32", getRegPressureSetName(i), 7) == 0)
102*9880d681SAndroid Build Coastguard Worker       SGPR32SetID = i;
103*9880d681SAndroid Build Coastguard Worker     else if (strncmp("VGPR_32", getRegPressureSetName(i), 7) == 0)
104*9880d681SAndroid Build Coastguard Worker       VGPR32SetID = i;
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker     classifyPressureSet(i, AMDGPU::SGPR0, SGPRPressureSets);
107*9880d681SAndroid Build Coastguard Worker     classifyPressureSet(i, AMDGPU::VGPR0, VGPRPressureSets);
108*9880d681SAndroid Build Coastguard Worker   }
109*9880d681SAndroid Build Coastguard Worker   assert(SGPR32SetID < NumRegPressureSets &&
110*9880d681SAndroid Build Coastguard Worker          VGPR32SetID < NumRegPressureSets);
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker 
reserveRegisterTuples(BitVector & Reserved,unsigned Reg) const113*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::reserveRegisterTuples(BitVector &Reserved, unsigned Reg) const {
114*9880d681SAndroid Build Coastguard Worker   MCRegAliasIterator R(Reg, this, true);
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   for (; R.isValid(); ++R)
117*9880d681SAndroid Build Coastguard Worker     Reserved.set(*R);
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker 
reservedPrivateSegmentBufferReg(const MachineFunction & MF) const120*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::reservedPrivateSegmentBufferReg(
121*9880d681SAndroid Build Coastguard Worker   const MachineFunction &MF) const {
122*9880d681SAndroid Build Coastguard Worker   unsigned BaseIdx = alignDown(getMaxWorkGroupSGPRCount(MF), 4) - 4;
123*9880d681SAndroid Build Coastguard Worker   unsigned BaseReg(AMDGPU::SGPR_32RegClass.getRegister(BaseIdx));
124*9880d681SAndroid Build Coastguard Worker   return getMatchingSuperReg(BaseReg, AMDGPU::sub0, &AMDGPU::SReg_128RegClass);
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker 
reservedPrivateSegmentWaveByteOffsetReg(const MachineFunction & MF) const127*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::reservedPrivateSegmentWaveByteOffsetReg(
128*9880d681SAndroid Build Coastguard Worker   const MachineFunction &MF) const {
129*9880d681SAndroid Build Coastguard Worker   unsigned RegCount = getMaxWorkGroupSGPRCount(MF);
130*9880d681SAndroid Build Coastguard Worker   unsigned Reg;
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker   // Try to place it in a hole after PrivateSegmentbufferReg.
133*9880d681SAndroid Build Coastguard Worker   if (RegCount & 3) {
134*9880d681SAndroid Build Coastguard Worker     // We cannot put the segment buffer in (Idx - 4) ... (Idx - 1) due to
135*9880d681SAndroid Build Coastguard Worker     // alignment constraints, so we have a hole where can put the wave offset.
136*9880d681SAndroid Build Coastguard Worker     Reg = RegCount - 1;
137*9880d681SAndroid Build Coastguard Worker   } else {
138*9880d681SAndroid Build Coastguard Worker     // We can put the segment buffer in (Idx - 4) ... (Idx - 1) and put the
139*9880d681SAndroid Build Coastguard Worker     // wave offset before it.
140*9880d681SAndroid Build Coastguard Worker     Reg = RegCount - 5;
141*9880d681SAndroid Build Coastguard Worker   }
142*9880d681SAndroid Build Coastguard Worker   return AMDGPU::SGPR_32RegClass.getRegister(Reg);
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker 
getReservedRegs(const MachineFunction & MF) const145*9880d681SAndroid Build Coastguard Worker BitVector SIRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
146*9880d681SAndroid Build Coastguard Worker   BitVector Reserved(getNumRegs());
147*9880d681SAndroid Build Coastguard Worker   Reserved.set(AMDGPU::INDIRECT_BASE_ADDR);
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker   // EXEC_LO and EXEC_HI could be allocated and used as regular register, but
150*9880d681SAndroid Build Coastguard Worker   // this seems likely to result in bugs, so I'm marking them as reserved.
151*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::EXEC);
152*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::FLAT_SCR);
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   // Reserve Trap Handler registers - support is not implemented in Codegen.
155*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TBA);
156*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TMA);
157*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP0_TTMP1);
158*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP2_TTMP3);
159*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP4_TTMP5);
160*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP6_TTMP7);
161*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP8_TTMP9);
162*9880d681SAndroid Build Coastguard Worker   reserveRegisterTuples(Reserved, AMDGPU::TTMP10_TTMP11);
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker   unsigned MaxWorkGroupSGPRCount = getMaxWorkGroupSGPRCount(MF);
165*9880d681SAndroid Build Coastguard Worker   unsigned MaxWorkGroupVGPRCount = getMaxWorkGroupVGPRCount(MF);
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
168*9880d681SAndroid Build Coastguard Worker   unsigned NumVGPRs = AMDGPU::VGPR_32RegClass.getNumRegs();
169*9880d681SAndroid Build Coastguard Worker   for (unsigned i = MaxWorkGroupSGPRCount; i < NumSGPRs; ++i) {
170*9880d681SAndroid Build Coastguard Worker     unsigned Reg = AMDGPU::SGPR_32RegClass.getRegister(i);
171*9880d681SAndroid Build Coastguard Worker     reserveRegisterTuples(Reserved, Reg);
172*9880d681SAndroid Build Coastguard Worker   }
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker   for (unsigned i = MaxWorkGroupVGPRCount; i < NumVGPRs; ++i) {
176*9880d681SAndroid Build Coastguard Worker     unsigned Reg = AMDGPU::VGPR_32RegClass.getRegister(i);
177*9880d681SAndroid Build Coastguard Worker     reserveRegisterTuples(Reserved, Reg);
178*9880d681SAndroid Build Coastguard Worker   }
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker   unsigned ScratchWaveOffsetReg = MFI->getScratchWaveOffsetReg();
183*9880d681SAndroid Build Coastguard Worker   if (ScratchWaveOffsetReg != AMDGPU::NoRegister) {
184*9880d681SAndroid Build Coastguard Worker     // Reserve 1 SGPR for scratch wave offset in case we need to spill.
185*9880d681SAndroid Build Coastguard Worker     reserveRegisterTuples(Reserved, ScratchWaveOffsetReg);
186*9880d681SAndroid Build Coastguard Worker   }
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker   unsigned ScratchRSrcReg = MFI->getScratchRSrcReg();
189*9880d681SAndroid Build Coastguard Worker   if (ScratchRSrcReg != AMDGPU::NoRegister) {
190*9880d681SAndroid Build Coastguard Worker     // Reserve 4 SGPRs for the scratch buffer resource descriptor in case we need
191*9880d681SAndroid Build Coastguard Worker     // to spill.
192*9880d681SAndroid Build Coastguard Worker     // TODO: May need to reserve a VGPR if doing LDS spilling.
193*9880d681SAndroid Build Coastguard Worker     reserveRegisterTuples(Reserved, ScratchRSrcReg);
194*9880d681SAndroid Build Coastguard Worker     assert(!isSubRegister(ScratchRSrcReg, ScratchWaveOffsetReg));
195*9880d681SAndroid Build Coastguard Worker   }
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   // Reserve registers for debugger usage if "amdgpu-debugger-reserve-trap-regs"
198*9880d681SAndroid Build Coastguard Worker   // attribute was specified.
199*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
200*9880d681SAndroid Build Coastguard Worker   if (ST.debuggerReserveRegs()) {
201*9880d681SAndroid Build Coastguard Worker     unsigned ReservedVGPRFirst =
202*9880d681SAndroid Build Coastguard Worker       MaxWorkGroupVGPRCount - MFI->getDebuggerReservedVGPRCount();
203*9880d681SAndroid Build Coastguard Worker     for (unsigned i = ReservedVGPRFirst; i < MaxWorkGroupVGPRCount; ++i) {
204*9880d681SAndroid Build Coastguard Worker       unsigned Reg = AMDGPU::VGPR_32RegClass.getRegister(i);
205*9880d681SAndroid Build Coastguard Worker       reserveRegisterTuples(Reserved, Reg);
206*9880d681SAndroid Build Coastguard Worker     }
207*9880d681SAndroid Build Coastguard Worker   }
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker   return Reserved;
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker 
getRegPressureSetLimit(const MachineFunction & MF,unsigned Idx) const212*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::getRegPressureSetLimit(const MachineFunction &MF,
213*9880d681SAndroid Build Coastguard Worker                                                 unsigned Idx) const {
214*9880d681SAndroid Build Coastguard Worker   const SISubtarget &STI = MF.getSubtarget<SISubtarget>();
215*9880d681SAndroid Build Coastguard Worker   // FIXME: We should adjust the max number of waves based on LDS size.
216*9880d681SAndroid Build Coastguard Worker   unsigned SGPRLimit = getNumSGPRsAllowed(STI, STI.getMaxWavesPerCU());
217*9880d681SAndroid Build Coastguard Worker   unsigned VGPRLimit = getNumVGPRsAllowed(STI.getMaxWavesPerCU());
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   unsigned VSLimit = SGPRLimit + VGPRLimit;
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker   if (SGPRPressureSets.test(Idx) && VGPRPressureSets.test(Idx)) {
222*9880d681SAndroid Build Coastguard Worker     // FIXME: This is a hack. We should never be considering the pressure of
223*9880d681SAndroid Build Coastguard Worker     // these since no virtual register should ever have this class.
224*9880d681SAndroid Build Coastguard Worker     return VSLimit;
225*9880d681SAndroid Build Coastguard Worker   }
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker   if (SGPRPressureSets.test(Idx))
228*9880d681SAndroid Build Coastguard Worker     return SGPRLimit;
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   return VGPRLimit;
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker 
requiresRegisterScavenging(const MachineFunction & Fn) const233*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::requiresRegisterScavenging(const MachineFunction &Fn) const {
234*9880d681SAndroid Build Coastguard Worker   return Fn.getFrameInfo()->hasStackObjects();
235*9880d681SAndroid Build Coastguard Worker }
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker bool
requiresFrameIndexScavenging(const MachineFunction & MF) const238*9880d681SAndroid Build Coastguard Worker SIRegisterInfo::requiresFrameIndexScavenging(const MachineFunction &MF) const {
239*9880d681SAndroid Build Coastguard Worker   return MF.getFrameInfo()->hasStackObjects();
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker 
requiresVirtualBaseRegisters(const MachineFunction &) const242*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::requiresVirtualBaseRegisters(
243*9880d681SAndroid Build Coastguard Worker   const MachineFunction &) const {
244*9880d681SAndroid Build Coastguard Worker   // There are no special dedicated stack or frame pointers.
245*9880d681SAndroid Build Coastguard Worker   return true;
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker 
trackLivenessAfterRegAlloc(const MachineFunction & MF) const248*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
249*9880d681SAndroid Build Coastguard Worker   // This helps catch bugs as verifier errors.
250*9880d681SAndroid Build Coastguard Worker   return true;
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker 
getFrameIndexInstrOffset(const MachineInstr * MI,int Idx) const253*9880d681SAndroid Build Coastguard Worker int64_t SIRegisterInfo::getFrameIndexInstrOffset(const MachineInstr *MI,
254*9880d681SAndroid Build Coastguard Worker                                                  int Idx) const {
255*9880d681SAndroid Build Coastguard Worker   if (!SIInstrInfo::isMUBUF(*MI))
256*9880d681SAndroid Build Coastguard Worker     return 0;
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker   assert(Idx == AMDGPU::getNamedOperandIdx(MI->getOpcode(),
259*9880d681SAndroid Build Coastguard Worker                                            AMDGPU::OpName::vaddr) &&
260*9880d681SAndroid Build Coastguard Worker          "Should never see frame index on non-address operand");
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker   int OffIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
263*9880d681SAndroid Build Coastguard Worker                                           AMDGPU::OpName::offset);
264*9880d681SAndroid Build Coastguard Worker   return MI->getOperand(OffIdx).getImm();
265*9880d681SAndroid Build Coastguard Worker }
266*9880d681SAndroid Build Coastguard Worker 
needsFrameBaseReg(MachineInstr * MI,int64_t Offset) const267*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const {
268*9880d681SAndroid Build Coastguard Worker   return MI->mayLoadOrStore();
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker 
materializeFrameBaseRegister(MachineBasicBlock * MBB,unsigned BaseReg,int FrameIdx,int64_t Offset) const271*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB,
272*9880d681SAndroid Build Coastguard Worker                                                   unsigned BaseReg,
273*9880d681SAndroid Build Coastguard Worker                                                   int FrameIdx,
274*9880d681SAndroid Build Coastguard Worker                                                   int64_t Offset) const {
275*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator Ins = MBB->begin();
276*9880d681SAndroid Build Coastguard Worker   DebugLoc DL; // Defaults to "unknown"
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   if (Ins != MBB->end())
279*9880d681SAndroid Build Coastguard Worker     DL = Ins->getDebugLoc();
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MBB->getParent();
282*9880d681SAndroid Build Coastguard Worker   const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>();
283*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *TII = Subtarget.getInstrInfo();
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   if (Offset == 0) {
286*9880d681SAndroid Build Coastguard Worker     BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), BaseReg)
287*9880d681SAndroid Build Coastguard Worker       .addFrameIndex(FrameIdx);
288*9880d681SAndroid Build Coastguard Worker     return;
289*9880d681SAndroid Build Coastguard Worker   }
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI = MF->getRegInfo();
292*9880d681SAndroid Build Coastguard Worker   unsigned UnusedCarry = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
293*9880d681SAndroid Build Coastguard Worker   unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg)
296*9880d681SAndroid Build Coastguard Worker     .addImm(Offset);
297*9880d681SAndroid Build Coastguard Worker   BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_ADD_I32_e64), BaseReg)
298*9880d681SAndroid Build Coastguard Worker     .addReg(UnusedCarry, RegState::Define | RegState::Dead)
299*9880d681SAndroid Build Coastguard Worker     .addReg(OffsetReg, RegState::Kill)
300*9880d681SAndroid Build Coastguard Worker     .addFrameIndex(FrameIdx);
301*9880d681SAndroid Build Coastguard Worker }
302*9880d681SAndroid Build Coastguard Worker 
resolveFrameIndex(MachineInstr & MI,unsigned BaseReg,int64_t Offset) const303*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg,
304*9880d681SAndroid Build Coastguard Worker                                        int64_t Offset) const {
305*9880d681SAndroid Build Coastguard Worker 
306*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = MI.getParent();
307*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MBB->getParent();
308*9880d681SAndroid Build Coastguard Worker   const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>();
309*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *TII = Subtarget.getInstrInfo();
310*9880d681SAndroid Build Coastguard Worker 
311*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
312*9880d681SAndroid Build Coastguard Worker   // FIXME: Is it possible to be storing a frame index to itself?
313*9880d681SAndroid Build Coastguard Worker   bool SeenFI = false;
314*9880d681SAndroid Build Coastguard Worker   for (const MachineOperand &MO: MI.operands()) {
315*9880d681SAndroid Build Coastguard Worker     if (MO.isFI()) {
316*9880d681SAndroid Build Coastguard Worker       if (SeenFI)
317*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("should not see multiple frame indices");
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker       SeenFI = true;
320*9880d681SAndroid Build Coastguard Worker     }
321*9880d681SAndroid Build Coastguard Worker   }
322*9880d681SAndroid Build Coastguard Worker #endif
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   MachineOperand *FIOp = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr);
325*9880d681SAndroid Build Coastguard Worker   assert(FIOp && FIOp->isFI() && "frame index must be address operand");
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker   assert(TII->isMUBUF(MI));
328*9880d681SAndroid Build Coastguard Worker 
329*9880d681SAndroid Build Coastguard Worker   MachineOperand *OffsetOp = TII->getNamedOperand(MI, AMDGPU::OpName::offset);
330*9880d681SAndroid Build Coastguard Worker   int64_t NewOffset = OffsetOp->getImm() + Offset;
331*9880d681SAndroid Build Coastguard Worker   if (isUInt<12>(NewOffset)) {
332*9880d681SAndroid Build Coastguard Worker     // If we have a legal offset, fold it directly into the instruction.
333*9880d681SAndroid Build Coastguard Worker     FIOp->ChangeToRegister(BaseReg, false);
334*9880d681SAndroid Build Coastguard Worker     OffsetOp->setImm(NewOffset);
335*9880d681SAndroid Build Coastguard Worker     return;
336*9880d681SAndroid Build Coastguard Worker   }
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker   // The offset is not legal, so we must insert an add of the offset.
339*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI = MF->getRegInfo();
340*9880d681SAndroid Build Coastguard Worker   unsigned NewReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
341*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MI.getDebugLoc();
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   assert(Offset != 0 && "Non-zero offset expected");
344*9880d681SAndroid Build Coastguard Worker 
345*9880d681SAndroid Build Coastguard Worker   unsigned UnusedCarry = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
346*9880d681SAndroid Build Coastguard Worker   unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
347*9880d681SAndroid Build Coastguard Worker 
348*9880d681SAndroid Build Coastguard Worker   // In the case the instruction already had an immediate offset, here only
349*9880d681SAndroid Build Coastguard Worker   // the requested new offset is added because we are leaving the original
350*9880d681SAndroid Build Coastguard Worker   // immediate in place.
351*9880d681SAndroid Build Coastguard Worker   BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg)
352*9880d681SAndroid Build Coastguard Worker     .addImm(Offset);
353*9880d681SAndroid Build Coastguard Worker   BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_ADD_I32_e64), NewReg)
354*9880d681SAndroid Build Coastguard Worker     .addReg(UnusedCarry, RegState::Define | RegState::Dead)
355*9880d681SAndroid Build Coastguard Worker     .addReg(OffsetReg, RegState::Kill)
356*9880d681SAndroid Build Coastguard Worker     .addReg(BaseReg);
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker   FIOp->ChangeToRegister(NewReg, false);
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker 
isFrameOffsetLegal(const MachineInstr * MI,unsigned BaseReg,int64_t Offset) const361*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
362*9880d681SAndroid Build Coastguard Worker                                         unsigned BaseReg,
363*9880d681SAndroid Build Coastguard Worker                                         int64_t Offset) const {
364*9880d681SAndroid Build Coastguard Worker   return SIInstrInfo::isMUBUF(*MI) && isUInt<12>(Offset);
365*9880d681SAndroid Build Coastguard Worker }
366*9880d681SAndroid Build Coastguard Worker 
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const367*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SIRegisterInfo::getPointerRegClass(
368*9880d681SAndroid Build Coastguard Worker   const MachineFunction &MF, unsigned Kind) const {
369*9880d681SAndroid Build Coastguard Worker   // This is inaccurate. It depends on the instruction and address space. The
370*9880d681SAndroid Build Coastguard Worker   // only place where we should hit this is for dealing with frame indexes /
371*9880d681SAndroid Build Coastguard Worker   // private accesses, so this is correct in that case.
372*9880d681SAndroid Build Coastguard Worker   return &AMDGPU::VGPR_32RegClass;
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker 
getNumSubRegsForSpillOp(unsigned Op)375*9880d681SAndroid Build Coastguard Worker static unsigned getNumSubRegsForSpillOp(unsigned Op) {
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker   switch (Op) {
378*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S512_SAVE:
379*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S512_RESTORE:
380*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V512_SAVE:
381*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V512_RESTORE:
382*9880d681SAndroid Build Coastguard Worker     return 16;
383*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S256_SAVE:
384*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S256_RESTORE:
385*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V256_SAVE:
386*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V256_RESTORE:
387*9880d681SAndroid Build Coastguard Worker     return 8;
388*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S128_SAVE:
389*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S128_RESTORE:
390*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V128_SAVE:
391*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V128_RESTORE:
392*9880d681SAndroid Build Coastguard Worker     return 4;
393*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V96_SAVE:
394*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V96_RESTORE:
395*9880d681SAndroid Build Coastguard Worker     return 3;
396*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S64_SAVE:
397*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S64_RESTORE:
398*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V64_SAVE:
399*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V64_RESTORE:
400*9880d681SAndroid Build Coastguard Worker     return 2;
401*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S32_SAVE:
402*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_S32_RESTORE:
403*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V32_SAVE:
404*9880d681SAndroid Build Coastguard Worker   case AMDGPU::SI_SPILL_V32_RESTORE:
405*9880d681SAndroid Build Coastguard Worker     return 1;
406*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("Invalid spill opcode");
407*9880d681SAndroid Build Coastguard Worker   }
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker 
buildScratchLoadStore(MachineBasicBlock::iterator MI,unsigned LoadStoreOp,const MachineOperand * SrcDst,unsigned ScratchRsrcReg,unsigned ScratchOffset,int64_t Offset,RegScavenger * RS) const410*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::buildScratchLoadStore(MachineBasicBlock::iterator MI,
411*9880d681SAndroid Build Coastguard Worker                                            unsigned LoadStoreOp,
412*9880d681SAndroid Build Coastguard Worker                                            const MachineOperand *SrcDst,
413*9880d681SAndroid Build Coastguard Worker                                            unsigned ScratchRsrcReg,
414*9880d681SAndroid Build Coastguard Worker                                            unsigned ScratchOffset,
415*9880d681SAndroid Build Coastguard Worker                                            int64_t Offset,
416*9880d681SAndroid Build Coastguard Worker                                            RegScavenger *RS) const {
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   unsigned Value = SrcDst->getReg();
419*9880d681SAndroid Build Coastguard Worker   bool IsKill = SrcDst->isKill();
420*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = MI->getParent();
421*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MI->getParent()->getParent();
422*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST =  MF->getSubtarget<SISubtarget>();
423*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *TII = ST.getInstrInfo();
424*9880d681SAndroid Build Coastguard Worker 
425*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MI->getDebugLoc();
426*9880d681SAndroid Build Coastguard Worker   bool IsStore = MI->mayStore();
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker   bool RanOutOfSGPRs = false;
429*9880d681SAndroid Build Coastguard Worker   bool Scavenged = false;
430*9880d681SAndroid Build Coastguard Worker   unsigned SOffset = ScratchOffset;
431*9880d681SAndroid Build Coastguard Worker   unsigned OriginalImmOffset = Offset;
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker   unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
434*9880d681SAndroid Build Coastguard Worker   unsigned Size = NumSubRegs * 4;
435*9880d681SAndroid Build Coastguard Worker 
436*9880d681SAndroid Build Coastguard Worker   if (!isUInt<12>(Offset + Size)) {
437*9880d681SAndroid Build Coastguard Worker     SOffset = AMDGPU::NoRegister;
438*9880d681SAndroid Build Coastguard Worker 
439*9880d681SAndroid Build Coastguard Worker     // We don't have access to the register scavenger if this function is called
440*9880d681SAndroid Build Coastguard Worker     // during  PEI::scavengeFrameVirtualRegs().
441*9880d681SAndroid Build Coastguard Worker     if (RS)
442*9880d681SAndroid Build Coastguard Worker       SOffset = RS->FindUnusedReg(&AMDGPU::SGPR_32RegClass);
443*9880d681SAndroid Build Coastguard Worker 
444*9880d681SAndroid Build Coastguard Worker     if (SOffset == AMDGPU::NoRegister) {
445*9880d681SAndroid Build Coastguard Worker       // There are no free SGPRs, and since we are in the process of spilling
446*9880d681SAndroid Build Coastguard Worker       // VGPRs too.  Since we need a VGPR in order to spill SGPRs (this is true
447*9880d681SAndroid Build Coastguard Worker       // on SI/CI and on VI it is true until we implement spilling using scalar
448*9880d681SAndroid Build Coastguard Worker       // stores), we have no way to free up an SGPR.  Our solution here is to
449*9880d681SAndroid Build Coastguard Worker       // add the offset directly to the ScratchOffset register, and then
450*9880d681SAndroid Build Coastguard Worker       // subtract the offset after the spill to return ScratchOffset to it's
451*9880d681SAndroid Build Coastguard Worker       // original value.
452*9880d681SAndroid Build Coastguard Worker       RanOutOfSGPRs = true;
453*9880d681SAndroid Build Coastguard Worker       SOffset = ScratchOffset;
454*9880d681SAndroid Build Coastguard Worker     } else {
455*9880d681SAndroid Build Coastguard Worker       Scavenged = true;
456*9880d681SAndroid Build Coastguard Worker     }
457*9880d681SAndroid Build Coastguard Worker     BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), SOffset)
458*9880d681SAndroid Build Coastguard Worker             .addReg(ScratchOffset)
459*9880d681SAndroid Build Coastguard Worker             .addImm(Offset);
460*9880d681SAndroid Build Coastguard Worker     Offset = 0;
461*9880d681SAndroid Build Coastguard Worker   }
462*9880d681SAndroid Build Coastguard Worker 
463*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = NumSubRegs; i != e; ++i, Offset += 4) {
464*9880d681SAndroid Build Coastguard Worker     unsigned SubReg = NumSubRegs > 1 ?
465*9880d681SAndroid Build Coastguard Worker         getPhysRegSubReg(Value, &AMDGPU::VGPR_32RegClass, i) :
466*9880d681SAndroid Build Coastguard Worker         Value;
467*9880d681SAndroid Build Coastguard Worker 
468*9880d681SAndroid Build Coastguard Worker     unsigned SOffsetRegState = 0;
469*9880d681SAndroid Build Coastguard Worker     unsigned SrcDstRegState = getDefRegState(!IsStore);
470*9880d681SAndroid Build Coastguard Worker     if (i + 1 == e) {
471*9880d681SAndroid Build Coastguard Worker       SOffsetRegState |= getKillRegState(Scavenged);
472*9880d681SAndroid Build Coastguard Worker       // The last implicit use carries the "Kill" flag.
473*9880d681SAndroid Build Coastguard Worker       SrcDstRegState |= getKillRegState(IsKill);
474*9880d681SAndroid Build Coastguard Worker     }
475*9880d681SAndroid Build Coastguard Worker 
476*9880d681SAndroid Build Coastguard Worker     BuildMI(*MBB, MI, DL, TII->get(LoadStoreOp))
477*9880d681SAndroid Build Coastguard Worker       .addReg(SubReg, getDefRegState(!IsStore))
478*9880d681SAndroid Build Coastguard Worker       .addReg(ScratchRsrcReg)
479*9880d681SAndroid Build Coastguard Worker       .addReg(SOffset, SOffsetRegState)
480*9880d681SAndroid Build Coastguard Worker       .addImm(Offset)
481*9880d681SAndroid Build Coastguard Worker       .addImm(0) // glc
482*9880d681SAndroid Build Coastguard Worker       .addImm(0) // slc
483*9880d681SAndroid Build Coastguard Worker       .addImm(0) // tfe
484*9880d681SAndroid Build Coastguard Worker       .addReg(Value, RegState::Implicit | SrcDstRegState)
485*9880d681SAndroid Build Coastguard Worker       .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
486*9880d681SAndroid Build Coastguard Worker   }
487*9880d681SAndroid Build Coastguard Worker   if (RanOutOfSGPRs) {
488*9880d681SAndroid Build Coastguard Worker     // Subtract the offset we added to the ScratchOffset register.
489*9880d681SAndroid Build Coastguard Worker     BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_SUB_U32), ScratchOffset)
490*9880d681SAndroid Build Coastguard Worker             .addReg(ScratchOffset)
491*9880d681SAndroid Build Coastguard Worker             .addImm(OriginalImmOffset);
492*9880d681SAndroid Build Coastguard Worker   }
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker 
eliminateFrameIndex(MachineBasicBlock::iterator MI,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const495*9880d681SAndroid Build Coastguard Worker void SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
496*9880d681SAndroid Build Coastguard Worker                                         int SPAdj, unsigned FIOperandNum,
497*9880d681SAndroid Build Coastguard Worker                                         RegScavenger *RS) const {
498*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MI->getParent()->getParent();
499*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI = MF->getRegInfo();
500*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = MI->getParent();
501*9880d681SAndroid Build Coastguard Worker   SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
502*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *FrameInfo = MF->getFrameInfo();
503*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST =  MF->getSubtarget<SISubtarget>();
504*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *TII = ST.getInstrInfo();
505*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MI->getDebugLoc();
506*9880d681SAndroid Build Coastguard Worker 
507*9880d681SAndroid Build Coastguard Worker   MachineOperand &FIOp = MI->getOperand(FIOperandNum);
508*9880d681SAndroid Build Coastguard Worker   int Index = MI->getOperand(FIOperandNum).getIndex();
509*9880d681SAndroid Build Coastguard Worker 
510*9880d681SAndroid Build Coastguard Worker   switch (MI->getOpcode()) {
511*9880d681SAndroid Build Coastguard Worker     // SGPR register spill
512*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S512_SAVE:
513*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S256_SAVE:
514*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S128_SAVE:
515*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S64_SAVE:
516*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S32_SAVE: {
517*9880d681SAndroid Build Coastguard Worker       unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
518*9880d681SAndroid Build Coastguard Worker       unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker       unsigned SuperReg = MI->getOperand(0).getReg();
521*9880d681SAndroid Build Coastguard Worker       bool IsKill = MI->getOperand(0).isKill();
522*9880d681SAndroid Build Coastguard Worker       // SubReg carries the "Kill" flag when SubReg == SuperReg.
523*9880d681SAndroid Build Coastguard Worker       unsigned SubKillState = getKillRegState((NumSubRegs == 1) && IsKill);
524*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
525*9880d681SAndroid Build Coastguard Worker         unsigned SubReg = getPhysRegSubReg(SuperReg,
526*9880d681SAndroid Build Coastguard Worker                                            &AMDGPU::SGPR_32RegClass, i);
527*9880d681SAndroid Build Coastguard Worker 
528*9880d681SAndroid Build Coastguard Worker         struct SIMachineFunctionInfo::SpilledReg Spill =
529*9880d681SAndroid Build Coastguard Worker             MFI->getSpilledReg(MF, Index, i);
530*9880d681SAndroid Build Coastguard Worker 
531*9880d681SAndroid Build Coastguard Worker         if (Spill.hasReg()) {
532*9880d681SAndroid Build Coastguard Worker           BuildMI(*MBB, MI, DL,
533*9880d681SAndroid Build Coastguard Worker                   TII->getMCOpcodeFromPseudo(AMDGPU::V_WRITELANE_B32),
534*9880d681SAndroid Build Coastguard Worker                   Spill.VGPR)
535*9880d681SAndroid Build Coastguard Worker                   .addReg(SubReg, getKillRegState(IsKill))
536*9880d681SAndroid Build Coastguard Worker                   .addImm(Spill.Lane);
537*9880d681SAndroid Build Coastguard Worker 
538*9880d681SAndroid Build Coastguard Worker           // FIXME: Since this spills to another register instead of an actual
539*9880d681SAndroid Build Coastguard Worker           // frame index, we should delete the frame index when all references to
540*9880d681SAndroid Build Coastguard Worker           // it are fixed.
541*9880d681SAndroid Build Coastguard Worker         } else {
542*9880d681SAndroid Build Coastguard Worker           // Spill SGPR to a frame index.
543*9880d681SAndroid Build Coastguard Worker           // FIXME we should use S_STORE_DWORD here for VI.
544*9880d681SAndroid Build Coastguard Worker           MachineInstrBuilder Mov
545*9880d681SAndroid Build Coastguard Worker             = BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
546*9880d681SAndroid Build Coastguard Worker             .addReg(SubReg, SubKillState);
547*9880d681SAndroid Build Coastguard Worker 
548*9880d681SAndroid Build Coastguard Worker 
549*9880d681SAndroid Build Coastguard Worker           // There could be undef components of a spilled super register.
550*9880d681SAndroid Build Coastguard Worker           // TODO: Can we detect this and skip the spill?
551*9880d681SAndroid Build Coastguard Worker           if (NumSubRegs > 1) {
552*9880d681SAndroid Build Coastguard Worker             // The last implicit use of the SuperReg carries the "Kill" flag.
553*9880d681SAndroid Build Coastguard Worker             unsigned SuperKillState = 0;
554*9880d681SAndroid Build Coastguard Worker             if (i + 1 == e)
555*9880d681SAndroid Build Coastguard Worker               SuperKillState |= getKillRegState(IsKill);
556*9880d681SAndroid Build Coastguard Worker             Mov.addReg(SuperReg, RegState::Implicit | SuperKillState);
557*9880d681SAndroid Build Coastguard Worker           }
558*9880d681SAndroid Build Coastguard Worker 
559*9880d681SAndroid Build Coastguard Worker           unsigned Size = FrameInfo->getObjectSize(Index);
560*9880d681SAndroid Build Coastguard Worker           unsigned Align = FrameInfo->getObjectAlignment(Index);
561*9880d681SAndroid Build Coastguard Worker           MachinePointerInfo PtrInfo
562*9880d681SAndroid Build Coastguard Worker               = MachinePointerInfo::getFixedStack(*MF, Index);
563*9880d681SAndroid Build Coastguard Worker           MachineMemOperand *MMO
564*9880d681SAndroid Build Coastguard Worker               = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
565*9880d681SAndroid Build Coastguard Worker                                          Size, Align);
566*9880d681SAndroid Build Coastguard Worker           BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_SAVE))
567*9880d681SAndroid Build Coastguard Worker                   .addReg(TmpReg, RegState::Kill)         // src
568*9880d681SAndroid Build Coastguard Worker                   .addFrameIndex(Index)                   // frame_idx
569*9880d681SAndroid Build Coastguard Worker                   .addReg(MFI->getScratchRSrcReg())       // scratch_rsrc
570*9880d681SAndroid Build Coastguard Worker                   .addReg(MFI->getScratchWaveOffsetReg()) // scratch_offset
571*9880d681SAndroid Build Coastguard Worker                   .addImm(i * 4)                          // offset
572*9880d681SAndroid Build Coastguard Worker                   .addMemOperand(MMO);
573*9880d681SAndroid Build Coastguard Worker         }
574*9880d681SAndroid Build Coastguard Worker       }
575*9880d681SAndroid Build Coastguard Worker       MI->eraseFromParent();
576*9880d681SAndroid Build Coastguard Worker       MFI->addToSpilledSGPRs(NumSubRegs);
577*9880d681SAndroid Build Coastguard Worker       break;
578*9880d681SAndroid Build Coastguard Worker     }
579*9880d681SAndroid Build Coastguard Worker 
580*9880d681SAndroid Build Coastguard Worker     // SGPR register restore
581*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S512_RESTORE:
582*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S256_RESTORE:
583*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S128_RESTORE:
584*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S64_RESTORE:
585*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_S32_RESTORE: {
586*9880d681SAndroid Build Coastguard Worker       unsigned NumSubRegs = getNumSubRegsForSpillOp(MI->getOpcode());
587*9880d681SAndroid Build Coastguard Worker       unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
588*9880d681SAndroid Build Coastguard Worker 
589*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0, e = NumSubRegs; i < e; ++i) {
590*9880d681SAndroid Build Coastguard Worker         unsigned SubReg = getPhysRegSubReg(MI->getOperand(0).getReg(),
591*9880d681SAndroid Build Coastguard Worker                                            &AMDGPU::SGPR_32RegClass, i);
592*9880d681SAndroid Build Coastguard Worker         struct SIMachineFunctionInfo::SpilledReg Spill =
593*9880d681SAndroid Build Coastguard Worker             MFI->getSpilledReg(MF, Index, i);
594*9880d681SAndroid Build Coastguard Worker 
595*9880d681SAndroid Build Coastguard Worker         if (Spill.hasReg()) {
596*9880d681SAndroid Build Coastguard Worker           BuildMI(*MBB, MI, DL,
597*9880d681SAndroid Build Coastguard Worker                   TII->getMCOpcodeFromPseudo(AMDGPU::V_READLANE_B32),
598*9880d681SAndroid Build Coastguard Worker                   SubReg)
599*9880d681SAndroid Build Coastguard Worker                   .addReg(Spill.VGPR)
600*9880d681SAndroid Build Coastguard Worker                   .addImm(Spill.Lane)
601*9880d681SAndroid Build Coastguard Worker                   .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
602*9880d681SAndroid Build Coastguard Worker         } else {
603*9880d681SAndroid Build Coastguard Worker           // Restore SGPR from a stack slot.
604*9880d681SAndroid Build Coastguard Worker           // FIXME: We should use S_LOAD_DWORD here for VI.
605*9880d681SAndroid Build Coastguard Worker 
606*9880d681SAndroid Build Coastguard Worker           unsigned Align = FrameInfo->getObjectAlignment(Index);
607*9880d681SAndroid Build Coastguard Worker           unsigned Size = FrameInfo->getObjectSize(Index);
608*9880d681SAndroid Build Coastguard Worker 
609*9880d681SAndroid Build Coastguard Worker           MachinePointerInfo PtrInfo
610*9880d681SAndroid Build Coastguard Worker               = MachinePointerInfo::getFixedStack(*MF, Index);
611*9880d681SAndroid Build Coastguard Worker 
612*9880d681SAndroid Build Coastguard Worker           MachineMemOperand *MMO = MF->getMachineMemOperand(
613*9880d681SAndroid Build Coastguard Worker               PtrInfo, MachineMemOperand::MOLoad, Size, Align);
614*9880d681SAndroid Build Coastguard Worker 
615*9880d681SAndroid Build Coastguard Worker           BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_RESTORE), TmpReg)
616*9880d681SAndroid Build Coastguard Worker                   .addFrameIndex(Index)                   // frame_idx
617*9880d681SAndroid Build Coastguard Worker                   .addReg(MFI->getScratchRSrcReg())       // scratch_rsrc
618*9880d681SAndroid Build Coastguard Worker                   .addReg(MFI->getScratchWaveOffsetReg()) // scratch_offset
619*9880d681SAndroid Build Coastguard Worker                   .addImm(i * 4)                          // offset
620*9880d681SAndroid Build Coastguard Worker                   .addMemOperand(MMO);
621*9880d681SAndroid Build Coastguard Worker           BuildMI(*MBB, MI, DL,
622*9880d681SAndroid Build Coastguard Worker                   TII->get(AMDGPU::V_READFIRSTLANE_B32), SubReg)
623*9880d681SAndroid Build Coastguard Worker                   .addReg(TmpReg, RegState::Kill)
624*9880d681SAndroid Build Coastguard Worker                   .addReg(MI->getOperand(0).getReg(), RegState::ImplicitDefine);
625*9880d681SAndroid Build Coastguard Worker         }
626*9880d681SAndroid Build Coastguard Worker       }
627*9880d681SAndroid Build Coastguard Worker 
628*9880d681SAndroid Build Coastguard Worker       MI->eraseFromParent();
629*9880d681SAndroid Build Coastguard Worker       break;
630*9880d681SAndroid Build Coastguard Worker     }
631*9880d681SAndroid Build Coastguard Worker 
632*9880d681SAndroid Build Coastguard Worker     // VGPR register spill
633*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V512_SAVE:
634*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V256_SAVE:
635*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V128_SAVE:
636*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V96_SAVE:
637*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V64_SAVE:
638*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V32_SAVE:
639*9880d681SAndroid Build Coastguard Worker       buildScratchLoadStore(MI, AMDGPU::BUFFER_STORE_DWORD_OFFSET,
640*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::src),
641*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_rsrc)->getReg(),
642*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_offset)->getReg(),
643*9880d681SAndroid Build Coastguard Worker             FrameInfo->getObjectOffset(Index) +
644*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), RS);
645*9880d681SAndroid Build Coastguard Worker       MI->eraseFromParent();
646*9880d681SAndroid Build Coastguard Worker       MFI->addToSpilledVGPRs(getNumSubRegsForSpillOp(MI->getOpcode()));
647*9880d681SAndroid Build Coastguard Worker       break;
648*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V32_RESTORE:
649*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V64_RESTORE:
650*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V96_RESTORE:
651*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V128_RESTORE:
652*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V256_RESTORE:
653*9880d681SAndroid Build Coastguard Worker     case AMDGPU::SI_SPILL_V512_RESTORE: {
654*9880d681SAndroid Build Coastguard Worker       buildScratchLoadStore(MI, AMDGPU::BUFFER_LOAD_DWORD_OFFSET,
655*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::dst),
656*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_rsrc)->getReg(),
657*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::scratch_offset)->getReg(),
658*9880d681SAndroid Build Coastguard Worker             FrameInfo->getObjectOffset(Index) +
659*9880d681SAndroid Build Coastguard Worker             TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), RS);
660*9880d681SAndroid Build Coastguard Worker       MI->eraseFromParent();
661*9880d681SAndroid Build Coastguard Worker       break;
662*9880d681SAndroid Build Coastguard Worker     }
663*9880d681SAndroid Build Coastguard Worker 
664*9880d681SAndroid Build Coastguard Worker     default: {
665*9880d681SAndroid Build Coastguard Worker       int64_t Offset = FrameInfo->getObjectOffset(Index);
666*9880d681SAndroid Build Coastguard Worker       FIOp.ChangeToImmediate(Offset);
667*9880d681SAndroid Build Coastguard Worker       if (!TII->isImmOperandLegal(*MI, FIOperandNum, FIOp)) {
668*9880d681SAndroid Build Coastguard Worker         unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
669*9880d681SAndroid Build Coastguard Worker         BuildMI(*MBB, MI, MI->getDebugLoc(),
670*9880d681SAndroid Build Coastguard Worker                 TII->get(AMDGPU::V_MOV_B32_e32), TmpReg)
671*9880d681SAndroid Build Coastguard Worker                 .addImm(Offset);
672*9880d681SAndroid Build Coastguard Worker         FIOp.ChangeToRegister(TmpReg, false, false, true);
673*9880d681SAndroid Build Coastguard Worker       }
674*9880d681SAndroid Build Coastguard Worker     }
675*9880d681SAndroid Build Coastguard Worker   }
676*9880d681SAndroid Build Coastguard Worker }
677*9880d681SAndroid Build Coastguard Worker 
678*9880d681SAndroid Build Coastguard Worker // FIXME: This is very slow. It might be worth creating a map from physreg to
679*9880d681SAndroid Build Coastguard Worker // register class.
getPhysRegClass(unsigned Reg) const680*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const {
681*9880d681SAndroid Build Coastguard Worker   assert(!TargetRegisterInfo::isVirtualRegister(Reg));
682*9880d681SAndroid Build Coastguard Worker 
683*9880d681SAndroid Build Coastguard Worker   static const TargetRegisterClass *const BaseClasses[] = {
684*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VGPR_32RegClass,
685*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SReg_32RegClass,
686*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VReg_64RegClass,
687*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SReg_64RegClass,
688*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VReg_96RegClass,
689*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VReg_128RegClass,
690*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SReg_128RegClass,
691*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VReg_256RegClass,
692*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SReg_256RegClass,
693*9880d681SAndroid Build Coastguard Worker     &AMDGPU::VReg_512RegClass,
694*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SReg_512RegClass,
695*9880d681SAndroid Build Coastguard Worker     &AMDGPU::SCC_CLASSRegClass,
696*9880d681SAndroid Build Coastguard Worker   };
697*9880d681SAndroid Build Coastguard Worker 
698*9880d681SAndroid Build Coastguard Worker   for (const TargetRegisterClass *BaseClass : BaseClasses) {
699*9880d681SAndroid Build Coastguard Worker     if (BaseClass->contains(Reg)) {
700*9880d681SAndroid Build Coastguard Worker       return BaseClass;
701*9880d681SAndroid Build Coastguard Worker     }
702*9880d681SAndroid Build Coastguard Worker   }
703*9880d681SAndroid Build Coastguard Worker   return nullptr;
704*9880d681SAndroid Build Coastguard Worker }
705*9880d681SAndroid Build Coastguard Worker 
706*9880d681SAndroid Build Coastguard Worker // TODO: It might be helpful to have some target specific flags in
707*9880d681SAndroid Build Coastguard Worker // TargetRegisterClass to mark which classes are VGPRs to make this trivial.
hasVGPRs(const TargetRegisterClass * RC) const708*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::hasVGPRs(const TargetRegisterClass *RC) const {
709*9880d681SAndroid Build Coastguard Worker   switch (RC->getSize()) {
710*9880d681SAndroid Build Coastguard Worker   case 0: return false;
711*9880d681SAndroid Build Coastguard Worker   case 1: return false;
712*9880d681SAndroid Build Coastguard Worker   case 4:
713*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VGPR_32RegClass, RC) != nullptr;
714*9880d681SAndroid Build Coastguard Worker   case 8:
715*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VReg_64RegClass, RC) != nullptr;
716*9880d681SAndroid Build Coastguard Worker   case 12:
717*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VReg_96RegClass, RC) != nullptr;
718*9880d681SAndroid Build Coastguard Worker   case 16:
719*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VReg_128RegClass, RC) != nullptr;
720*9880d681SAndroid Build Coastguard Worker   case 32:
721*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VReg_256RegClass, RC) != nullptr;
722*9880d681SAndroid Build Coastguard Worker   case 64:
723*9880d681SAndroid Build Coastguard Worker     return getCommonSubClass(&AMDGPU::VReg_512RegClass, RC) != nullptr;
724*9880d681SAndroid Build Coastguard Worker   default:
725*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Invalid register class size");
726*9880d681SAndroid Build Coastguard Worker   }
727*9880d681SAndroid Build Coastguard Worker }
728*9880d681SAndroid Build Coastguard Worker 
getEquivalentVGPRClass(const TargetRegisterClass * SRC) const729*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SIRegisterInfo::getEquivalentVGPRClass(
730*9880d681SAndroid Build Coastguard Worker                                          const TargetRegisterClass *SRC) const {
731*9880d681SAndroid Build Coastguard Worker   switch (SRC->getSize()) {
732*9880d681SAndroid Build Coastguard Worker   case 4:
733*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VGPR_32RegClass;
734*9880d681SAndroid Build Coastguard Worker   case 8:
735*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VReg_64RegClass;
736*9880d681SAndroid Build Coastguard Worker   case 12:
737*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VReg_96RegClass;
738*9880d681SAndroid Build Coastguard Worker   case 16:
739*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VReg_128RegClass;
740*9880d681SAndroid Build Coastguard Worker   case 32:
741*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VReg_256RegClass;
742*9880d681SAndroid Build Coastguard Worker   case 64:
743*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::VReg_512RegClass;
744*9880d681SAndroid Build Coastguard Worker   default:
745*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Invalid register class size");
746*9880d681SAndroid Build Coastguard Worker   }
747*9880d681SAndroid Build Coastguard Worker }
748*9880d681SAndroid Build Coastguard Worker 
getEquivalentSGPRClass(const TargetRegisterClass * VRC) const749*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SIRegisterInfo::getEquivalentSGPRClass(
750*9880d681SAndroid Build Coastguard Worker                                          const TargetRegisterClass *VRC) const {
751*9880d681SAndroid Build Coastguard Worker   switch (VRC->getSize()) {
752*9880d681SAndroid Build Coastguard Worker   case 4:
753*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::SGPR_32RegClass;
754*9880d681SAndroid Build Coastguard Worker   case 8:
755*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::SReg_64RegClass;
756*9880d681SAndroid Build Coastguard Worker   case 16:
757*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::SReg_128RegClass;
758*9880d681SAndroid Build Coastguard Worker   case 32:
759*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::SReg_256RegClass;
760*9880d681SAndroid Build Coastguard Worker   case 64:
761*9880d681SAndroid Build Coastguard Worker     return &AMDGPU::SReg_512RegClass;
762*9880d681SAndroid Build Coastguard Worker   default:
763*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Invalid register class size");
764*9880d681SAndroid Build Coastguard Worker   }
765*9880d681SAndroid Build Coastguard Worker }
766*9880d681SAndroid Build Coastguard Worker 
getSubRegClass(const TargetRegisterClass * RC,unsigned SubIdx) const767*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SIRegisterInfo::getSubRegClass(
768*9880d681SAndroid Build Coastguard Worker                          const TargetRegisterClass *RC, unsigned SubIdx) const {
769*9880d681SAndroid Build Coastguard Worker   if (SubIdx == AMDGPU::NoSubRegister)
770*9880d681SAndroid Build Coastguard Worker     return RC;
771*9880d681SAndroid Build Coastguard Worker 
772*9880d681SAndroid Build Coastguard Worker   // We can assume that each lane corresponds to one 32-bit register.
773*9880d681SAndroid Build Coastguard Worker   unsigned Count = countPopulation(getSubRegIndexLaneMask(SubIdx));
774*9880d681SAndroid Build Coastguard Worker   if (isSGPRClass(RC)) {
775*9880d681SAndroid Build Coastguard Worker     switch (Count) {
776*9880d681SAndroid Build Coastguard Worker     case 1:
777*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::SGPR_32RegClass;
778*9880d681SAndroid Build Coastguard Worker     case 2:
779*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::SReg_64RegClass;
780*9880d681SAndroid Build Coastguard Worker     case 4:
781*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::SReg_128RegClass;
782*9880d681SAndroid Build Coastguard Worker     case 8:
783*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::SReg_256RegClass;
784*9880d681SAndroid Build Coastguard Worker     case 16: /* fall-through */
785*9880d681SAndroid Build Coastguard Worker     default:
786*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid sub-register class size");
787*9880d681SAndroid Build Coastguard Worker     }
788*9880d681SAndroid Build Coastguard Worker   } else {
789*9880d681SAndroid Build Coastguard Worker     switch (Count) {
790*9880d681SAndroid Build Coastguard Worker     case 1:
791*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::VGPR_32RegClass;
792*9880d681SAndroid Build Coastguard Worker     case 2:
793*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::VReg_64RegClass;
794*9880d681SAndroid Build Coastguard Worker     case 3:
795*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::VReg_96RegClass;
796*9880d681SAndroid Build Coastguard Worker     case 4:
797*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::VReg_128RegClass;
798*9880d681SAndroid Build Coastguard Worker     case 8:
799*9880d681SAndroid Build Coastguard Worker       return &AMDGPU::VReg_256RegClass;
800*9880d681SAndroid Build Coastguard Worker     case 16: /* fall-through */
801*9880d681SAndroid Build Coastguard Worker     default:
802*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid sub-register class size");
803*9880d681SAndroid Build Coastguard Worker     }
804*9880d681SAndroid Build Coastguard Worker   }
805*9880d681SAndroid Build Coastguard Worker }
806*9880d681SAndroid Build Coastguard Worker 
shouldRewriteCopySrc(const TargetRegisterClass * DefRC,unsigned DefSubReg,const TargetRegisterClass * SrcRC,unsigned SrcSubReg) const807*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::shouldRewriteCopySrc(
808*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *DefRC,
809*9880d681SAndroid Build Coastguard Worker   unsigned DefSubReg,
810*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *SrcRC,
811*9880d681SAndroid Build Coastguard Worker   unsigned SrcSubReg) const {
812*9880d681SAndroid Build Coastguard Worker   // We want to prefer the smallest register class possible, so we don't want to
813*9880d681SAndroid Build Coastguard Worker   // stop and rewrite on anything that looks like a subregister
814*9880d681SAndroid Build Coastguard Worker   // extract. Operations mostly don't care about the super register class, so we
815*9880d681SAndroid Build Coastguard Worker   // only want to stop on the most basic of copies between the smae register
816*9880d681SAndroid Build Coastguard Worker   // class.
817*9880d681SAndroid Build Coastguard Worker   //
818*9880d681SAndroid Build Coastguard Worker   // e.g. if we have something like
819*9880d681SAndroid Build Coastguard Worker   // vreg0 = ...
820*9880d681SAndroid Build Coastguard Worker   // vreg1 = ...
821*9880d681SAndroid Build Coastguard Worker   // vreg2 = REG_SEQUENCE vreg0, sub0, vreg1, sub1, vreg2, sub2
822*9880d681SAndroid Build Coastguard Worker   // vreg3 = COPY vreg2, sub0
823*9880d681SAndroid Build Coastguard Worker   //
824*9880d681SAndroid Build Coastguard Worker   // We want to look through the COPY to find:
825*9880d681SAndroid Build Coastguard Worker   //  => vreg3 = COPY vreg0
826*9880d681SAndroid Build Coastguard Worker 
827*9880d681SAndroid Build Coastguard Worker   // Plain copy.
828*9880d681SAndroid Build Coastguard Worker   return getCommonSubClass(DefRC, SrcRC) != nullptr;
829*9880d681SAndroid Build Coastguard Worker }
830*9880d681SAndroid Build Coastguard Worker 
getPhysRegSubReg(unsigned Reg,const TargetRegisterClass * SubRC,unsigned Channel) const831*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::getPhysRegSubReg(unsigned Reg,
832*9880d681SAndroid Build Coastguard Worker                                           const TargetRegisterClass *SubRC,
833*9880d681SAndroid Build Coastguard Worker                                           unsigned Channel) const {
834*9880d681SAndroid Build Coastguard Worker 
835*9880d681SAndroid Build Coastguard Worker   switch (Reg) {
836*9880d681SAndroid Build Coastguard Worker     case AMDGPU::VCC:
837*9880d681SAndroid Build Coastguard Worker       switch(Channel) {
838*9880d681SAndroid Build Coastguard Worker         case 0: return AMDGPU::VCC_LO;
839*9880d681SAndroid Build Coastguard Worker         case 1: return AMDGPU::VCC_HI;
840*9880d681SAndroid Build Coastguard Worker         default: llvm_unreachable("Invalid SubIdx for VCC"); break;
841*9880d681SAndroid Build Coastguard Worker       }
842*9880d681SAndroid Build Coastguard Worker 
843*9880d681SAndroid Build Coastguard Worker     case AMDGPU::TBA:
844*9880d681SAndroid Build Coastguard Worker       switch(Channel) {
845*9880d681SAndroid Build Coastguard Worker         case 0: return AMDGPU::TBA_LO;
846*9880d681SAndroid Build Coastguard Worker         case 1: return AMDGPU::TBA_HI;
847*9880d681SAndroid Build Coastguard Worker         default: llvm_unreachable("Invalid SubIdx for TBA"); break;
848*9880d681SAndroid Build Coastguard Worker       }
849*9880d681SAndroid Build Coastguard Worker 
850*9880d681SAndroid Build Coastguard Worker     case AMDGPU::TMA:
851*9880d681SAndroid Build Coastguard Worker       switch(Channel) {
852*9880d681SAndroid Build Coastguard Worker         case 0: return AMDGPU::TMA_LO;
853*9880d681SAndroid Build Coastguard Worker         case 1: return AMDGPU::TMA_HI;
854*9880d681SAndroid Build Coastguard Worker         default: llvm_unreachable("Invalid SubIdx for TMA"); break;
855*9880d681SAndroid Build Coastguard Worker       }
856*9880d681SAndroid Build Coastguard Worker 
857*9880d681SAndroid Build Coastguard Worker   case AMDGPU::FLAT_SCR:
858*9880d681SAndroid Build Coastguard Worker     switch (Channel) {
859*9880d681SAndroid Build Coastguard Worker     case 0:
860*9880d681SAndroid Build Coastguard Worker       return AMDGPU::FLAT_SCR_LO;
861*9880d681SAndroid Build Coastguard Worker     case 1:
862*9880d681SAndroid Build Coastguard Worker       return AMDGPU::FLAT_SCR_HI;
863*9880d681SAndroid Build Coastguard Worker     default:
864*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid SubIdx for FLAT_SCR");
865*9880d681SAndroid Build Coastguard Worker     }
866*9880d681SAndroid Build Coastguard Worker     break;
867*9880d681SAndroid Build Coastguard Worker 
868*9880d681SAndroid Build Coastguard Worker   case AMDGPU::EXEC:
869*9880d681SAndroid Build Coastguard Worker     switch (Channel) {
870*9880d681SAndroid Build Coastguard Worker     case 0:
871*9880d681SAndroid Build Coastguard Worker       return AMDGPU::EXEC_LO;
872*9880d681SAndroid Build Coastguard Worker     case 1:
873*9880d681SAndroid Build Coastguard Worker       return AMDGPU::EXEC_HI;
874*9880d681SAndroid Build Coastguard Worker     default:
875*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid SubIdx for EXEC");
876*9880d681SAndroid Build Coastguard Worker     }
877*9880d681SAndroid Build Coastguard Worker     break;
878*9880d681SAndroid Build Coastguard Worker   }
879*9880d681SAndroid Build Coastguard Worker 
880*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = getPhysRegClass(Reg);
881*9880d681SAndroid Build Coastguard Worker   // 32-bit registers don't have sub-registers, so we can just return the
882*9880d681SAndroid Build Coastguard Worker   // Reg.  We need to have this check here, because the calculation below
883*9880d681SAndroid Build Coastguard Worker   // using getHWRegIndex() will fail with special 32-bit registers like
884*9880d681SAndroid Build Coastguard Worker   // VCC_LO, VCC_HI, EXEC_LO, EXEC_HI and M0.
885*9880d681SAndroid Build Coastguard Worker   if (RC->getSize() == 4) {
886*9880d681SAndroid Build Coastguard Worker     assert(Channel == 0);
887*9880d681SAndroid Build Coastguard Worker     return Reg;
888*9880d681SAndroid Build Coastguard Worker   }
889*9880d681SAndroid Build Coastguard Worker 
890*9880d681SAndroid Build Coastguard Worker   unsigned Index = getHWRegIndex(Reg);
891*9880d681SAndroid Build Coastguard Worker   return SubRC->getRegister(Index + Channel);
892*9880d681SAndroid Build Coastguard Worker }
893*9880d681SAndroid Build Coastguard Worker 
opCanUseLiteralConstant(unsigned OpType) const894*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::opCanUseLiteralConstant(unsigned OpType) const {
895*9880d681SAndroid Build Coastguard Worker   return OpType == AMDGPU::OPERAND_REG_IMM32;
896*9880d681SAndroid Build Coastguard Worker }
897*9880d681SAndroid Build Coastguard Worker 
opCanUseInlineConstant(unsigned OpType) const898*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::opCanUseInlineConstant(unsigned OpType) const {
899*9880d681SAndroid Build Coastguard Worker   if (opCanUseLiteralConstant(OpType))
900*9880d681SAndroid Build Coastguard Worker     return true;
901*9880d681SAndroid Build Coastguard Worker 
902*9880d681SAndroid Build Coastguard Worker   return OpType == AMDGPU::OPERAND_REG_INLINE_C;
903*9880d681SAndroid Build Coastguard Worker }
904*9880d681SAndroid Build Coastguard Worker 
905*9880d681SAndroid Build Coastguard Worker // FIXME: Most of these are flexible with HSA and we don't need to reserve them
906*9880d681SAndroid Build Coastguard Worker // as input registers if unused. Whether the dispatch ptr is necessary should be
907*9880d681SAndroid Build Coastguard Worker // easy to detect from used intrinsics. Scratch setup is harder to know.
getPreloadedValue(const MachineFunction & MF,enum PreloadedValue Value) const908*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::getPreloadedValue(const MachineFunction &MF,
909*9880d681SAndroid Build Coastguard Worker                                            enum PreloadedValue Value) const {
910*9880d681SAndroid Build Coastguard Worker 
911*9880d681SAndroid Build Coastguard Worker   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
912*9880d681SAndroid Build Coastguard Worker   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
913*9880d681SAndroid Build Coastguard Worker   (void)ST;
914*9880d681SAndroid Build Coastguard Worker   switch (Value) {
915*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKGROUP_ID_X:
916*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkGroupIDX());
917*9880d681SAndroid Build Coastguard Worker     return MFI->WorkGroupIDXSystemSGPR;
918*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKGROUP_ID_Y:
919*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkGroupIDY());
920*9880d681SAndroid Build Coastguard Worker     return MFI->WorkGroupIDYSystemSGPR;
921*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKGROUP_ID_Z:
922*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkGroupIDZ());
923*9880d681SAndroid Build Coastguard Worker     return MFI->WorkGroupIDZSystemSGPR;
924*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::PRIVATE_SEGMENT_WAVE_BYTE_OFFSET:
925*9880d681SAndroid Build Coastguard Worker     return MFI->PrivateSegmentWaveByteOffsetSystemSGPR;
926*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::PRIVATE_SEGMENT_BUFFER:
927*9880d681SAndroid Build Coastguard Worker     assert(ST.isAmdHsaOS() && "Non-HSA ABI currently uses relocations");
928*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasPrivateSegmentBuffer());
929*9880d681SAndroid Build Coastguard Worker     return MFI->PrivateSegmentBufferUserSGPR;
930*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::KERNARG_SEGMENT_PTR:
931*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasKernargSegmentPtr());
932*9880d681SAndroid Build Coastguard Worker     return MFI->KernargSegmentPtrUserSGPR;
933*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::DISPATCH_ID:
934*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unimplemented");
935*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::FLAT_SCRATCH_INIT:
936*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasFlatScratchInit());
937*9880d681SAndroid Build Coastguard Worker     return MFI->FlatScratchInitUserSGPR;
938*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::DISPATCH_PTR:
939*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasDispatchPtr());
940*9880d681SAndroid Build Coastguard Worker     return MFI->DispatchPtrUserSGPR;
941*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::QUEUE_PTR:
942*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasQueuePtr());
943*9880d681SAndroid Build Coastguard Worker     return MFI->QueuePtrUserSGPR;
944*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKITEM_ID_X:
945*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkItemIDX());
946*9880d681SAndroid Build Coastguard Worker     return AMDGPU::VGPR0;
947*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKITEM_ID_Y:
948*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkItemIDY());
949*9880d681SAndroid Build Coastguard Worker     return AMDGPU::VGPR1;
950*9880d681SAndroid Build Coastguard Worker   case SIRegisterInfo::WORKITEM_ID_Z:
951*9880d681SAndroid Build Coastguard Worker     assert(MFI->hasWorkItemIDZ());
952*9880d681SAndroid Build Coastguard Worker     return AMDGPU::VGPR2;
953*9880d681SAndroid Build Coastguard Worker   }
954*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("unexpected preloaded value type");
955*9880d681SAndroid Build Coastguard Worker }
956*9880d681SAndroid Build Coastguard Worker 
957*9880d681SAndroid Build Coastguard Worker /// \brief Returns a register that is not used at any point in the function.
958*9880d681SAndroid Build Coastguard Worker ///        If all registers are used, then this function will return
959*9880d681SAndroid Build Coastguard Worker //         AMDGPU::NoRegister.
findUnusedRegister(const MachineRegisterInfo & MRI,const TargetRegisterClass * RC) const960*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::findUnusedRegister(const MachineRegisterInfo &MRI,
961*9880d681SAndroid Build Coastguard Worker                                            const TargetRegisterClass *RC) const {
962*9880d681SAndroid Build Coastguard Worker   for (unsigned Reg : *RC)
963*9880d681SAndroid Build Coastguard Worker     if (!MRI.isPhysRegUsed(Reg))
964*9880d681SAndroid Build Coastguard Worker       return Reg;
965*9880d681SAndroid Build Coastguard Worker   return AMDGPU::NoRegister;
966*9880d681SAndroid Build Coastguard Worker }
967*9880d681SAndroid Build Coastguard Worker 
getNumVGPRsAllowed(unsigned WaveCount) const968*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::getNumVGPRsAllowed(unsigned WaveCount) const {
969*9880d681SAndroid Build Coastguard Worker   switch(WaveCount) {
970*9880d681SAndroid Build Coastguard Worker     case 10: return 24;
971*9880d681SAndroid Build Coastguard Worker     case 9:  return 28;
972*9880d681SAndroid Build Coastguard Worker     case 8:  return 32;
973*9880d681SAndroid Build Coastguard Worker     case 7:  return 36;
974*9880d681SAndroid Build Coastguard Worker     case 6:  return 40;
975*9880d681SAndroid Build Coastguard Worker     case 5:  return 48;
976*9880d681SAndroid Build Coastguard Worker     case 4:  return 64;
977*9880d681SAndroid Build Coastguard Worker     case 3:  return 84;
978*9880d681SAndroid Build Coastguard Worker     case 2:  return 128;
979*9880d681SAndroid Build Coastguard Worker     default: return 256;
980*9880d681SAndroid Build Coastguard Worker   }
981*9880d681SAndroid Build Coastguard Worker }
982*9880d681SAndroid Build Coastguard Worker 
getNumSGPRsAllowed(const SISubtarget & ST,unsigned WaveCount) const983*9880d681SAndroid Build Coastguard Worker unsigned SIRegisterInfo::getNumSGPRsAllowed(const SISubtarget &ST,
984*9880d681SAndroid Build Coastguard Worker                                             unsigned WaveCount) const {
985*9880d681SAndroid Build Coastguard Worker   if (ST.getGeneration() >= SISubtarget::VOLCANIC_ISLANDS) {
986*9880d681SAndroid Build Coastguard Worker     switch (WaveCount) {
987*9880d681SAndroid Build Coastguard Worker       case 10: return 80;
988*9880d681SAndroid Build Coastguard Worker       case 9:  return 80;
989*9880d681SAndroid Build Coastguard Worker       case 8:  return 96;
990*9880d681SAndroid Build Coastguard Worker       default: return 102;
991*9880d681SAndroid Build Coastguard Worker     }
992*9880d681SAndroid Build Coastguard Worker   } else {
993*9880d681SAndroid Build Coastguard Worker     switch(WaveCount) {
994*9880d681SAndroid Build Coastguard Worker       case 10: return 48;
995*9880d681SAndroid Build Coastguard Worker       case 9:  return 56;
996*9880d681SAndroid Build Coastguard Worker       case 8:  return 64;
997*9880d681SAndroid Build Coastguard Worker       case 7:  return 72;
998*9880d681SAndroid Build Coastguard Worker       case 6:  return 80;
999*9880d681SAndroid Build Coastguard Worker       case 5:  return 96;
1000*9880d681SAndroid Build Coastguard Worker       default: return 103;
1001*9880d681SAndroid Build Coastguard Worker     }
1002*9880d681SAndroid Build Coastguard Worker   }
1003*9880d681SAndroid Build Coastguard Worker }
1004*9880d681SAndroid Build Coastguard Worker 
isVGPR(const MachineRegisterInfo & MRI,unsigned Reg) const1005*9880d681SAndroid Build Coastguard Worker bool SIRegisterInfo::isVGPR(const MachineRegisterInfo &MRI,
1006*9880d681SAndroid Build Coastguard Worker                             unsigned Reg) const {
1007*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC;
1008*9880d681SAndroid Build Coastguard Worker   if (TargetRegisterInfo::isVirtualRegister(Reg))
1009*9880d681SAndroid Build Coastguard Worker     RC = MRI.getRegClass(Reg);
1010*9880d681SAndroid Build Coastguard Worker   else
1011*9880d681SAndroid Build Coastguard Worker     RC = getPhysRegClass(Reg);
1012*9880d681SAndroid Build Coastguard Worker 
1013*9880d681SAndroid Build Coastguard Worker   return hasVGPRs(RC);
1014*9880d681SAndroid Build Coastguard Worker }
1015