1 //===- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface -*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H
15 #define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H
16 
17 #include "AMDGPUMachineFunction.h"
18 #include "SIRegisterInfo.h"
19 #include <map>
20 
21 namespace llvm {
22 
23 class MachineRegisterInfo;
24 
25 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which
26 /// tells the hardware which interpolation parameters to load.
27 class SIMachineFunctionInfo final : public AMDGPUMachineFunction {
28   // FIXME: This should be removed and getPreloadedValue moved here.
29   friend struct SIRegisterInfo;
30   void anchor() override;
31 
32   unsigned TIDReg;
33 
34   // Registers that may be reserved for spilling purposes. These may be the same
35   // as the input registers.
36   unsigned ScratchRSrcReg;
37   unsigned ScratchWaveOffsetReg;
38 
39   // Input registers setup for the HSA ABI.
40   // User SGPRs in allocation order.
41   unsigned PrivateSegmentBufferUserSGPR;
42   unsigned DispatchPtrUserSGPR;
43   unsigned QueuePtrUserSGPR;
44   unsigned KernargSegmentPtrUserSGPR;
45   unsigned DispatchIDUserSGPR;
46   unsigned FlatScratchInitUserSGPR;
47   unsigned PrivateSegmentSizeUserSGPR;
48   unsigned GridWorkGroupCountXUserSGPR;
49   unsigned GridWorkGroupCountYUserSGPR;
50   unsigned GridWorkGroupCountZUserSGPR;
51 
52   // System SGPRs in allocation order.
53   unsigned WorkGroupIDXSystemSGPR;
54   unsigned WorkGroupIDYSystemSGPR;
55   unsigned WorkGroupIDZSystemSGPR;
56   unsigned WorkGroupInfoSystemSGPR;
57   unsigned PrivateSegmentWaveByteOffsetSystemSGPR;
58 
59   // Graphics info.
60   unsigned PSInputAddr;
61   bool ReturnsVoid;
62 
63 public:
64   // FIXME: Make private
65   unsigned LDSWaveSpillSize;
66   unsigned PSInputEna;
67   std::map<unsigned, unsigned> LaneVGPRs;
68   unsigned ScratchOffsetReg;
69   unsigned NumUserSGPRs;
70   unsigned NumSystemSGPRs;
71 
72 private:
73   bool HasSpilledSGPRs;
74   bool HasSpilledVGPRs;
75   bool HasNonSpillStackObjects;
76   bool HasFlatInstructions;
77 
78   // Feature bits required for inputs passed in user SGPRs.
79   bool PrivateSegmentBuffer : 1;
80   bool DispatchPtr : 1;
81   bool QueuePtr : 1;
82   bool DispatchID : 1;
83   bool KernargSegmentPtr : 1;
84   bool FlatScratchInit : 1;
85   bool GridWorkgroupCountX : 1;
86   bool GridWorkgroupCountY : 1;
87   bool GridWorkgroupCountZ : 1;
88 
89   // Feature bits required for inputs passed in system SGPRs.
90   bool WorkGroupIDX : 1; // Always initialized.
91   bool WorkGroupIDY : 1;
92   bool WorkGroupIDZ : 1;
93   bool WorkGroupInfo : 1;
94   bool PrivateSegmentWaveByteOffset : 1;
95 
96   bool WorkItemIDX : 1; // Always initialized.
97   bool WorkItemIDY : 1;
98   bool WorkItemIDZ : 1;
99 
100 
101   MCPhysReg getNextUserSGPR() const {
102     assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
103     return AMDGPU::SGPR0 + NumUserSGPRs;
104   }
105 
106   MCPhysReg getNextSystemSGPR() const {
107     return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
108   }
109 
110 public:
111   struct SpilledReg {
112     unsigned VGPR;
113     int Lane;
114     SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { }
115     SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { }
116     bool hasLane() { return Lane != -1;}
117     bool hasReg() { return VGPR != AMDGPU::NoRegister;}
118   };
119 
120   // SIMachineFunctionInfo definition
121 
122   SIMachineFunctionInfo(const MachineFunction &MF);
123   SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex,
124                            unsigned SubIdx);
125   bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; };
126   unsigned getTIDReg() const { return TIDReg; };
127   void setTIDReg(unsigned Reg) { TIDReg = Reg; }
128 
129   // Add user SGPRs.
130   unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI);
131   unsigned addDispatchPtr(const SIRegisterInfo &TRI);
132   unsigned addQueuePtr(const SIRegisterInfo &TRI);
133   unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI);
134   unsigned addFlatScratchInit(const SIRegisterInfo &TRI);
135 
136   // Add system SGPRs.
137   unsigned addWorkGroupIDX() {
138     WorkGroupIDXSystemSGPR = getNextSystemSGPR();
139     NumSystemSGPRs += 1;
140     return WorkGroupIDXSystemSGPR;
141   }
142 
143   unsigned addWorkGroupIDY() {
144     WorkGroupIDYSystemSGPR = getNextSystemSGPR();
145     NumSystemSGPRs += 1;
146     return WorkGroupIDYSystemSGPR;
147   }
148 
149   unsigned addWorkGroupIDZ() {
150     WorkGroupIDZSystemSGPR = getNextSystemSGPR();
151     NumSystemSGPRs += 1;
152     return WorkGroupIDZSystemSGPR;
153   }
154 
155   unsigned addWorkGroupInfo() {
156     WorkGroupInfoSystemSGPR = getNextSystemSGPR();
157     NumSystemSGPRs += 1;
158     return WorkGroupInfoSystemSGPR;
159   }
160 
161   unsigned addPrivateSegmentWaveByteOffset() {
162     PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR();
163     NumSystemSGPRs += 1;
164     return PrivateSegmentWaveByteOffsetSystemSGPR;
165   }
166 
167   bool hasPrivateSegmentBuffer() const {
168     return PrivateSegmentBuffer;
169   }
170 
171   bool hasDispatchPtr() const {
172     return DispatchPtr;
173   }
174 
175   bool hasQueuePtr() const {
176     return QueuePtr;
177   }
178 
179   bool hasDispatchID() const {
180     return DispatchID;
181   }
182 
183   bool hasKernargSegmentPtr() const {
184     return KernargSegmentPtr;
185   }
186 
187   bool hasFlatScratchInit() const {
188     return FlatScratchInit;
189   }
190 
191   bool hasGridWorkgroupCountX() const {
192     return GridWorkgroupCountX;
193   }
194 
195   bool hasGridWorkgroupCountY() const {
196     return GridWorkgroupCountY;
197   }
198 
199   bool hasGridWorkgroupCountZ() const {
200     return GridWorkgroupCountZ;
201   }
202 
203   bool hasWorkGroupIDX() const {
204     return WorkGroupIDX;
205   }
206 
207   bool hasWorkGroupIDY() const {
208     return WorkGroupIDY;
209   }
210 
211   bool hasWorkGroupIDZ() const {
212     return WorkGroupIDZ;
213   }
214 
215   bool hasWorkGroupInfo() const {
216     return WorkGroupInfo;
217   }
218 
219   bool hasPrivateSegmentWaveByteOffset() const {
220     return PrivateSegmentWaveByteOffset;
221   }
222 
223   bool hasWorkItemIDX() const {
224     return WorkItemIDX;
225   }
226 
227   bool hasWorkItemIDY() const {
228     return WorkItemIDY;
229   }
230 
231   bool hasWorkItemIDZ() const {
232     return WorkItemIDZ;
233   }
234 
235   unsigned getNumUserSGPRs() const {
236     return NumUserSGPRs;
237   }
238 
239   unsigned getNumPreloadedSGPRs() const {
240     return NumUserSGPRs + NumSystemSGPRs;
241   }
242 
243   unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const {
244     return PrivateSegmentWaveByteOffsetSystemSGPR;
245   }
246 
247   /// \brief Returns the physical register reserved for use as the resource
248   /// descriptor for scratch accesses.
249   unsigned getScratchRSrcReg() const {
250     return ScratchRSrcReg;
251   }
252 
253   void setScratchRSrcReg(unsigned Reg) {
254     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
255     ScratchRSrcReg = Reg;
256   }
257 
258   unsigned getScratchWaveOffsetReg() const {
259     return ScratchWaveOffsetReg;
260   }
261 
262   void setScratchWaveOffsetReg(unsigned Reg) {
263     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
264     ScratchWaveOffsetReg = Reg;
265   }
266 
267   bool hasSpilledSGPRs() const {
268     return HasSpilledSGPRs;
269   }
270 
271   void setHasSpilledSGPRs(bool Spill = true) {
272     HasSpilledSGPRs = Spill;
273   }
274 
275   bool hasSpilledVGPRs() const {
276     return HasSpilledVGPRs;
277   }
278 
279   void setHasSpilledVGPRs(bool Spill = true) {
280     HasSpilledVGPRs = Spill;
281   }
282 
283   bool hasNonSpillStackObjects() const {
284     return HasNonSpillStackObjects;
285   }
286 
287   void setHasNonSpillStackObjects(bool StackObject = true) {
288     HasNonSpillStackObjects = StackObject;
289   }
290 
291   bool hasFlatInstructions() const {
292     return HasFlatInstructions;
293   }
294 
295   void setHasFlatInstructions(bool UseFlat = true) {
296     HasFlatInstructions = UseFlat;
297   }
298 
299   unsigned getPSInputAddr() const {
300     return PSInputAddr;
301   }
302 
303   bool isPSInputAllocated(unsigned Index) const {
304     return PSInputAddr & (1 << Index);
305   }
306 
307   void markPSInputAllocated(unsigned Index) {
308     PSInputAddr |= 1 << Index;
309   }
310 
311   bool returnsVoid() const {
312     return ReturnsVoid;
313   }
314 
315   void setIfReturnsVoid(bool Value) {
316     ReturnsVoid = Value;
317   }
318 
319   unsigned getMaximumWorkGroupSize(const MachineFunction &MF) const;
320 };
321 
322 } // End namespace llvm
323 
324 #endif
325