1*9880d681SAndroid Build Coastguard Worker //===-- SIMachineFunctionInfo.cpp -------- SI Machine Function Info -------===//
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 #include "SIMachineFunctionInfo.h"
11*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
12*9880d681SAndroid Build Coastguard Worker #include "SIInstrInfo.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker #define MAX_LANES 64
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableSpillSGPRToVGPR(
24*9880d681SAndroid Build Coastguard Worker "amdgpu-spill-sgpr-to-vgpr",
25*9880d681SAndroid Build Coastguard Worker cl::desc("Enable spilling VGPRs to SGPRs"),
26*9880d681SAndroid Build Coastguard Worker cl::ReallyHidden,
27*9880d681SAndroid Build Coastguard Worker cl::init(true));
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker // Pin the vtable to this file.
anchor()30*9880d681SAndroid Build Coastguard Worker void SIMachineFunctionInfo::anchor() {}
31*9880d681SAndroid Build Coastguard Worker
SIMachineFunctionInfo(const MachineFunction & MF)32*9880d681SAndroid Build Coastguard Worker SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
33*9880d681SAndroid Build Coastguard Worker : AMDGPUMachineFunction(MF),
34*9880d681SAndroid Build Coastguard Worker TIDReg(AMDGPU::NoRegister),
35*9880d681SAndroid Build Coastguard Worker ScratchRSrcReg(AMDGPU::NoRegister),
36*9880d681SAndroid Build Coastguard Worker ScratchWaveOffsetReg(AMDGPU::NoRegister),
37*9880d681SAndroid Build Coastguard Worker PrivateSegmentBufferUserSGPR(AMDGPU::NoRegister),
38*9880d681SAndroid Build Coastguard Worker DispatchPtrUserSGPR(AMDGPU::NoRegister),
39*9880d681SAndroid Build Coastguard Worker QueuePtrUserSGPR(AMDGPU::NoRegister),
40*9880d681SAndroid Build Coastguard Worker KernargSegmentPtrUserSGPR(AMDGPU::NoRegister),
41*9880d681SAndroid Build Coastguard Worker DispatchIDUserSGPR(AMDGPU::NoRegister),
42*9880d681SAndroid Build Coastguard Worker FlatScratchInitUserSGPR(AMDGPU::NoRegister),
43*9880d681SAndroid Build Coastguard Worker PrivateSegmentSizeUserSGPR(AMDGPU::NoRegister),
44*9880d681SAndroid Build Coastguard Worker GridWorkGroupCountXUserSGPR(AMDGPU::NoRegister),
45*9880d681SAndroid Build Coastguard Worker GridWorkGroupCountYUserSGPR(AMDGPU::NoRegister),
46*9880d681SAndroid Build Coastguard Worker GridWorkGroupCountZUserSGPR(AMDGPU::NoRegister),
47*9880d681SAndroid Build Coastguard Worker WorkGroupIDXSystemSGPR(AMDGPU::NoRegister),
48*9880d681SAndroid Build Coastguard Worker WorkGroupIDYSystemSGPR(AMDGPU::NoRegister),
49*9880d681SAndroid Build Coastguard Worker WorkGroupIDZSystemSGPR(AMDGPU::NoRegister),
50*9880d681SAndroid Build Coastguard Worker WorkGroupInfoSystemSGPR(AMDGPU::NoRegister),
51*9880d681SAndroid Build Coastguard Worker PrivateSegmentWaveByteOffsetSystemSGPR(AMDGPU::NoRegister),
52*9880d681SAndroid Build Coastguard Worker PSInputAddr(0),
53*9880d681SAndroid Build Coastguard Worker ReturnsVoid(true),
54*9880d681SAndroid Build Coastguard Worker MaximumWorkGroupSize(0),
55*9880d681SAndroid Build Coastguard Worker DebuggerReservedVGPRCount(0),
56*9880d681SAndroid Build Coastguard Worker DebuggerWorkGroupIDStackObjectIndices({{0, 0, 0}}),
57*9880d681SAndroid Build Coastguard Worker DebuggerWorkItemIDStackObjectIndices({{0, 0, 0}}),
58*9880d681SAndroid Build Coastguard Worker LDSWaveSpillSize(0),
59*9880d681SAndroid Build Coastguard Worker PSInputEna(0),
60*9880d681SAndroid Build Coastguard Worker NumUserSGPRs(0),
61*9880d681SAndroid Build Coastguard Worker NumSystemSGPRs(0),
62*9880d681SAndroid Build Coastguard Worker HasSpilledSGPRs(false),
63*9880d681SAndroid Build Coastguard Worker HasSpilledVGPRs(false),
64*9880d681SAndroid Build Coastguard Worker HasNonSpillStackObjects(false),
65*9880d681SAndroid Build Coastguard Worker HasFlatInstructions(false),
66*9880d681SAndroid Build Coastguard Worker NumSpilledSGPRs(0),
67*9880d681SAndroid Build Coastguard Worker NumSpilledVGPRs(0),
68*9880d681SAndroid Build Coastguard Worker PrivateSegmentBuffer(false),
69*9880d681SAndroid Build Coastguard Worker DispatchPtr(false),
70*9880d681SAndroid Build Coastguard Worker QueuePtr(false),
71*9880d681SAndroid Build Coastguard Worker DispatchID(false),
72*9880d681SAndroid Build Coastguard Worker KernargSegmentPtr(false),
73*9880d681SAndroid Build Coastguard Worker FlatScratchInit(false),
74*9880d681SAndroid Build Coastguard Worker GridWorkgroupCountX(false),
75*9880d681SAndroid Build Coastguard Worker GridWorkgroupCountY(false),
76*9880d681SAndroid Build Coastguard Worker GridWorkgroupCountZ(false),
77*9880d681SAndroid Build Coastguard Worker WorkGroupIDX(false),
78*9880d681SAndroid Build Coastguard Worker WorkGroupIDY(false),
79*9880d681SAndroid Build Coastguard Worker WorkGroupIDZ(false),
80*9880d681SAndroid Build Coastguard Worker WorkGroupInfo(false),
81*9880d681SAndroid Build Coastguard Worker PrivateSegmentWaveByteOffset(false),
82*9880d681SAndroid Build Coastguard Worker WorkItemIDX(false),
83*9880d681SAndroid Build Coastguard Worker WorkItemIDY(false),
84*9880d681SAndroid Build Coastguard Worker WorkItemIDZ(false) {
85*9880d681SAndroid Build Coastguard Worker const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
86*9880d681SAndroid Build Coastguard Worker const Function *F = MF.getFunction();
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker PSInputAddr = AMDGPU::getInitialPSInputAddr(*F);
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo *FrameInfo = MF.getFrameInfo();
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker if (!AMDGPU::isShader(F->getCallingConv())) {
93*9880d681SAndroid Build Coastguard Worker KernargSegmentPtr = true;
94*9880d681SAndroid Build Coastguard Worker WorkGroupIDX = true;
95*9880d681SAndroid Build Coastguard Worker WorkItemIDX = true;
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-work-group-id-y") || ST.debuggerEmitPrologue())
99*9880d681SAndroid Build Coastguard Worker WorkGroupIDY = true;
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-work-group-id-z") || ST.debuggerEmitPrologue())
102*9880d681SAndroid Build Coastguard Worker WorkGroupIDZ = true;
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-work-item-id-y") || ST.debuggerEmitPrologue())
105*9880d681SAndroid Build Coastguard Worker WorkItemIDY = true;
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-work-item-id-z") || ST.debuggerEmitPrologue())
108*9880d681SAndroid Build Coastguard Worker WorkItemIDZ = true;
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker // X, XY, and XYZ are the only supported combinations, so make sure Y is
111*9880d681SAndroid Build Coastguard Worker // enabled if Z is.
112*9880d681SAndroid Build Coastguard Worker if (WorkItemIDZ)
113*9880d681SAndroid Build Coastguard Worker WorkItemIDY = true;
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker bool MaySpill = ST.isVGPRSpillingEnabled(*F);
116*9880d681SAndroid Build Coastguard Worker bool HasStackObjects = FrameInfo->hasStackObjects();
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker if (HasStackObjects || MaySpill)
119*9880d681SAndroid Build Coastguard Worker PrivateSegmentWaveByteOffset = true;
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker if (ST.isAmdHsaOS()) {
122*9880d681SAndroid Build Coastguard Worker if (HasStackObjects || MaySpill)
123*9880d681SAndroid Build Coastguard Worker PrivateSegmentBuffer = true;
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-dispatch-ptr"))
126*9880d681SAndroid Build Coastguard Worker DispatchPtr = true;
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker if (F->hasFnAttribute("amdgpu-queue-ptr"))
129*9880d681SAndroid Build Coastguard Worker QueuePtr = true;
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker
132*9880d681SAndroid Build Coastguard Worker // We don't need to worry about accessing spills with flat instructions.
133*9880d681SAndroid Build Coastguard Worker // TODO: On VI where we must use flat for global, we should be able to omit
134*9880d681SAndroid Build Coastguard Worker // this if it is never used for generic access.
135*9880d681SAndroid Build Coastguard Worker if (HasStackObjects && ST.getGeneration() >= SISubtarget::SEA_ISLANDS &&
136*9880d681SAndroid Build Coastguard Worker ST.isAmdHsaOS())
137*9880d681SAndroid Build Coastguard Worker FlatScratchInit = true;
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker if (AMDGPU::isCompute(F->getCallingConv()))
140*9880d681SAndroid Build Coastguard Worker MaximumWorkGroupSize = AMDGPU::getMaximumWorkGroupSize(*F);
141*9880d681SAndroid Build Coastguard Worker else
142*9880d681SAndroid Build Coastguard Worker MaximumWorkGroupSize = ST.getWavefrontSize();
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker if (ST.debuggerReserveRegs())
145*9880d681SAndroid Build Coastguard Worker DebuggerReservedVGPRCount = 4;
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker
addPrivateSegmentBuffer(const SIRegisterInfo & TRI)148*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::addPrivateSegmentBuffer(
149*9880d681SAndroid Build Coastguard Worker const SIRegisterInfo &TRI) {
150*9880d681SAndroid Build Coastguard Worker PrivateSegmentBufferUserSGPR = TRI.getMatchingSuperReg(
151*9880d681SAndroid Build Coastguard Worker getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_128RegClass);
152*9880d681SAndroid Build Coastguard Worker NumUserSGPRs += 4;
153*9880d681SAndroid Build Coastguard Worker return PrivateSegmentBufferUserSGPR;
154*9880d681SAndroid Build Coastguard Worker }
155*9880d681SAndroid Build Coastguard Worker
addDispatchPtr(const SIRegisterInfo & TRI)156*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::addDispatchPtr(const SIRegisterInfo &TRI) {
157*9880d681SAndroid Build Coastguard Worker DispatchPtrUserSGPR = TRI.getMatchingSuperReg(
158*9880d681SAndroid Build Coastguard Worker getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass);
159*9880d681SAndroid Build Coastguard Worker NumUserSGPRs += 2;
160*9880d681SAndroid Build Coastguard Worker return DispatchPtrUserSGPR;
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
addQueuePtr(const SIRegisterInfo & TRI)163*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::addQueuePtr(const SIRegisterInfo &TRI) {
164*9880d681SAndroid Build Coastguard Worker QueuePtrUserSGPR = TRI.getMatchingSuperReg(
165*9880d681SAndroid Build Coastguard Worker getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass);
166*9880d681SAndroid Build Coastguard Worker NumUserSGPRs += 2;
167*9880d681SAndroid Build Coastguard Worker return QueuePtrUserSGPR;
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker
addKernargSegmentPtr(const SIRegisterInfo & TRI)170*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::addKernargSegmentPtr(const SIRegisterInfo &TRI) {
171*9880d681SAndroid Build Coastguard Worker KernargSegmentPtrUserSGPR = TRI.getMatchingSuperReg(
172*9880d681SAndroid Build Coastguard Worker getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass);
173*9880d681SAndroid Build Coastguard Worker NumUserSGPRs += 2;
174*9880d681SAndroid Build Coastguard Worker return KernargSegmentPtrUserSGPR;
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker
addFlatScratchInit(const SIRegisterInfo & TRI)177*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::addFlatScratchInit(const SIRegisterInfo &TRI) {
178*9880d681SAndroid Build Coastguard Worker FlatScratchInitUserSGPR = TRI.getMatchingSuperReg(
179*9880d681SAndroid Build Coastguard Worker getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass);
180*9880d681SAndroid Build Coastguard Worker NumUserSGPRs += 2;
181*9880d681SAndroid Build Coastguard Worker return FlatScratchInitUserSGPR;
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
getSpilledReg(MachineFunction * MF,unsigned FrameIndex,unsigned SubIdx)184*9880d681SAndroid Build Coastguard Worker SIMachineFunctionInfo::SpilledReg SIMachineFunctionInfo::getSpilledReg (
185*9880d681SAndroid Build Coastguard Worker MachineFunction *MF,
186*9880d681SAndroid Build Coastguard Worker unsigned FrameIndex,
187*9880d681SAndroid Build Coastguard Worker unsigned SubIdx) {
188*9880d681SAndroid Build Coastguard Worker if (!EnableSpillSGPRToVGPR)
189*9880d681SAndroid Build Coastguard Worker return SpilledReg();
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker const SISubtarget &ST = MF->getSubtarget<SISubtarget>();
192*9880d681SAndroid Build Coastguard Worker const SIRegisterInfo *TRI = ST.getRegisterInfo();
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *FrameInfo = MF->getFrameInfo();
195*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF->getRegInfo();
196*9880d681SAndroid Build Coastguard Worker int64_t Offset = FrameInfo->getObjectOffset(FrameIndex);
197*9880d681SAndroid Build Coastguard Worker Offset += SubIdx * 4;
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker unsigned LaneVGPRIdx = Offset / (64 * 4);
200*9880d681SAndroid Build Coastguard Worker unsigned Lane = (Offset / 4) % 64;
201*9880d681SAndroid Build Coastguard Worker
202*9880d681SAndroid Build Coastguard Worker struct SpilledReg Spill;
203*9880d681SAndroid Build Coastguard Worker Spill.Lane = Lane;
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker if (!LaneVGPRs.count(LaneVGPRIdx)) {
206*9880d681SAndroid Build Coastguard Worker unsigned LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass);
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker if (LaneVGPR == AMDGPU::NoRegister)
209*9880d681SAndroid Build Coastguard Worker // We have no VGPRs left for spilling SGPRs.
210*9880d681SAndroid Build Coastguard Worker return Spill;
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker LaneVGPRs[LaneVGPRIdx] = LaneVGPR;
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard Worker // Add this register as live-in to all blocks to avoid machine verifer
215*9880d681SAndroid Build Coastguard Worker // complaining about use of an undefined physical register.
216*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator BI = MF->begin(), BE = MF->end();
217*9880d681SAndroid Build Coastguard Worker BI != BE; ++BI) {
218*9880d681SAndroid Build Coastguard Worker BI->addLiveIn(LaneVGPR);
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker }
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker Spill.VGPR = LaneVGPRs[LaneVGPRIdx];
223*9880d681SAndroid Build Coastguard Worker return Spill;
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker
getMaximumWorkGroupSize(const MachineFunction & MF) const226*9880d681SAndroid Build Coastguard Worker unsigned SIMachineFunctionInfo::getMaximumWorkGroupSize(
227*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF) const {
228*9880d681SAndroid Build Coastguard Worker return MaximumWorkGroupSize;
229*9880d681SAndroid Build Coastguard Worker }
230