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 <array>
20 #include <map>
21 
22 namespace llvm {
23 
24 class MachineRegisterInfo;
25 
26 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which
27 /// tells the hardware which interpolation parameters to load.
28 class SIMachineFunctionInfo final : public AMDGPUMachineFunction {
29   // FIXME: This should be removed and getPreloadedValue moved here.
30   friend class SIRegisterInfo;
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   // A pair of default/requested minimum/maximum flat work group sizes.
64   // Minimum - first, maximum - second.
65   std::pair<unsigned, unsigned> FlatWorkGroupSizes;
66 
67   // A pair of default/requested minimum/maximum number of waves per execution
68   // unit. Minimum - first, maximum - second.
69   std::pair<unsigned, unsigned> WavesPerEU;
70 
71   // Stack object indices for work group IDs.
72   std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices;
73   // Stack object indices for work item IDs.
74   std::array<int, 3> DebuggerWorkItemIDStackObjectIndices;
75 
76 public:
77   // FIXME: Make private
78   unsigned LDSWaveSpillSize;
79   unsigned PSInputEna;
80   std::map<unsigned, unsigned> LaneVGPRs;
81   unsigned ScratchOffsetReg;
82   unsigned NumUserSGPRs;
83   unsigned NumSystemSGPRs;
84 
85 private:
86   bool HasSpilledSGPRs;
87   bool HasSpilledVGPRs;
88   bool HasNonSpillStackObjects;
89 
90   unsigned NumSpilledSGPRs;
91   unsigned NumSpilledVGPRs;
92 
93   // Feature bits required for inputs passed in user SGPRs.
94   bool PrivateSegmentBuffer : 1;
95   bool DispatchPtr : 1;
96   bool QueuePtr : 1;
97   bool KernargSegmentPtr : 1;
98   bool DispatchID : 1;
99   bool FlatScratchInit : 1;
100   bool GridWorkgroupCountX : 1;
101   bool GridWorkgroupCountY : 1;
102   bool GridWorkgroupCountZ : 1;
103 
104   // Feature bits required for inputs passed in system SGPRs.
105   bool WorkGroupIDX : 1; // Always initialized.
106   bool WorkGroupIDY : 1;
107   bool WorkGroupIDZ : 1;
108   bool WorkGroupInfo : 1;
109   bool PrivateSegmentWaveByteOffset : 1;
110 
111   bool WorkItemIDX : 1; // Always initialized.
112   bool WorkItemIDY : 1;
113   bool WorkItemIDZ : 1;
114 
115   MCPhysReg getNextUserSGPR() const {
116     assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
117     return AMDGPU::SGPR0 + NumUserSGPRs;
118   }
119 
120   MCPhysReg getNextSystemSGPR() const {
121     return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
122   }
123 
124 public:
125   struct SpilledReg {
126     unsigned VGPR;
127     int Lane;
128     SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { }
129     SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { }
130     bool hasLane() { return Lane != -1;}
131     bool hasReg() { return VGPR != AMDGPU::NoRegister;}
132   };
133 
134   // SIMachineFunctionInfo definition
135 
136   SIMachineFunctionInfo(const MachineFunction &MF);
137   SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex,
138                            unsigned SubIdx);
139   bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; };
140   unsigned getTIDReg() const { return TIDReg; };
141   void setTIDReg(unsigned Reg) { TIDReg = Reg; }
142 
143   // Add user SGPRs.
144   unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI);
145   unsigned addDispatchPtr(const SIRegisterInfo &TRI);
146   unsigned addQueuePtr(const SIRegisterInfo &TRI);
147   unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI);
148   unsigned addDispatchID(const SIRegisterInfo &TRI);
149   unsigned addFlatScratchInit(const SIRegisterInfo &TRI);
150 
151   // Add system SGPRs.
152   unsigned addWorkGroupIDX() {
153     WorkGroupIDXSystemSGPR = getNextSystemSGPR();
154     NumSystemSGPRs += 1;
155     return WorkGroupIDXSystemSGPR;
156   }
157 
158   unsigned addWorkGroupIDY() {
159     WorkGroupIDYSystemSGPR = getNextSystemSGPR();
160     NumSystemSGPRs += 1;
161     return WorkGroupIDYSystemSGPR;
162   }
163 
164   unsigned addWorkGroupIDZ() {
165     WorkGroupIDZSystemSGPR = getNextSystemSGPR();
166     NumSystemSGPRs += 1;
167     return WorkGroupIDZSystemSGPR;
168   }
169 
170   unsigned addWorkGroupInfo() {
171     WorkGroupInfoSystemSGPR = getNextSystemSGPR();
172     NumSystemSGPRs += 1;
173     return WorkGroupInfoSystemSGPR;
174   }
175 
176   unsigned addPrivateSegmentWaveByteOffset() {
177     PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR();
178     NumSystemSGPRs += 1;
179     return PrivateSegmentWaveByteOffsetSystemSGPR;
180   }
181 
182   void setPrivateSegmentWaveByteOffset(unsigned Reg) {
183     PrivateSegmentWaveByteOffsetSystemSGPR = Reg;
184   }
185 
186   bool hasPrivateSegmentBuffer() const {
187     return PrivateSegmentBuffer;
188   }
189 
190   bool hasDispatchPtr() const {
191     return DispatchPtr;
192   }
193 
194   bool hasQueuePtr() const {
195     return QueuePtr;
196   }
197 
198   bool hasKernargSegmentPtr() const {
199     return KernargSegmentPtr;
200   }
201 
202   bool hasDispatchID() const {
203     return DispatchID;
204   }
205 
206   bool hasFlatScratchInit() const {
207     return FlatScratchInit;
208   }
209 
210   bool hasGridWorkgroupCountX() const {
211     return GridWorkgroupCountX;
212   }
213 
214   bool hasGridWorkgroupCountY() const {
215     return GridWorkgroupCountY;
216   }
217 
218   bool hasGridWorkgroupCountZ() const {
219     return GridWorkgroupCountZ;
220   }
221 
222   bool hasWorkGroupIDX() const {
223     return WorkGroupIDX;
224   }
225 
226   bool hasWorkGroupIDY() const {
227     return WorkGroupIDY;
228   }
229 
230   bool hasWorkGroupIDZ() const {
231     return WorkGroupIDZ;
232   }
233 
234   bool hasWorkGroupInfo() const {
235     return WorkGroupInfo;
236   }
237 
238   bool hasPrivateSegmentWaveByteOffset() const {
239     return PrivateSegmentWaveByteOffset;
240   }
241 
242   bool hasWorkItemIDX() const {
243     return WorkItemIDX;
244   }
245 
246   bool hasWorkItemIDY() const {
247     return WorkItemIDY;
248   }
249 
250   bool hasWorkItemIDZ() const {
251     return WorkItemIDZ;
252   }
253 
254   unsigned getNumUserSGPRs() const {
255     return NumUserSGPRs;
256   }
257 
258   unsigned getNumPreloadedSGPRs() const {
259     return NumUserSGPRs + NumSystemSGPRs;
260   }
261 
262   unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const {
263     return PrivateSegmentWaveByteOffsetSystemSGPR;
264   }
265 
266   /// \brief Returns the physical register reserved for use as the resource
267   /// descriptor for scratch accesses.
268   unsigned getScratchRSrcReg() const {
269     return ScratchRSrcReg;
270   }
271 
272   void setScratchRSrcReg(unsigned Reg) {
273     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
274     ScratchRSrcReg = Reg;
275   }
276 
277   unsigned getScratchWaveOffsetReg() const {
278     return ScratchWaveOffsetReg;
279   }
280 
281   void setScratchWaveOffsetReg(unsigned Reg) {
282     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
283     ScratchWaveOffsetReg = Reg;
284   }
285 
286   unsigned getQueuePtrUserSGPR() const {
287     return QueuePtrUserSGPR;
288   }
289 
290   bool hasSpilledSGPRs() const {
291     return HasSpilledSGPRs;
292   }
293 
294   void setHasSpilledSGPRs(bool Spill = true) {
295     HasSpilledSGPRs = Spill;
296   }
297 
298   bool hasSpilledVGPRs() const {
299     return HasSpilledVGPRs;
300   }
301 
302   void setHasSpilledVGPRs(bool Spill = true) {
303     HasSpilledVGPRs = Spill;
304   }
305 
306   bool hasNonSpillStackObjects() const {
307     return HasNonSpillStackObjects;
308   }
309 
310   void setHasNonSpillStackObjects(bool StackObject = true) {
311     HasNonSpillStackObjects = StackObject;
312   }
313 
314   unsigned getNumSpilledSGPRs() const {
315     return NumSpilledSGPRs;
316   }
317 
318   unsigned getNumSpilledVGPRs() const {
319     return NumSpilledVGPRs;
320   }
321 
322   void addToSpilledSGPRs(unsigned num) {
323     NumSpilledSGPRs += num;
324   }
325 
326   void addToSpilledVGPRs(unsigned num) {
327     NumSpilledVGPRs += num;
328   }
329 
330   unsigned getPSInputAddr() const {
331     return PSInputAddr;
332   }
333 
334   bool isPSInputAllocated(unsigned Index) const {
335     return PSInputAddr & (1 << Index);
336   }
337 
338   void markPSInputAllocated(unsigned Index) {
339     PSInputAddr |= 1 << Index;
340   }
341 
342   bool returnsVoid() const {
343     return ReturnsVoid;
344   }
345 
346   void setIfReturnsVoid(bool Value) {
347     ReturnsVoid = Value;
348   }
349 
350   /// \returns A pair of default/requested minimum/maximum flat work group sizes
351   /// for this function.
352   std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const {
353     return FlatWorkGroupSizes;
354   }
355 
356   /// \returns Default/requested minimum flat work group size for this function.
357   unsigned getMinFlatWorkGroupSize() const {
358     return FlatWorkGroupSizes.first;
359   }
360 
361   /// \returns Default/requested maximum flat work group size for this function.
362   unsigned getMaxFlatWorkGroupSize() const {
363     return FlatWorkGroupSizes.second;
364   }
365 
366   /// \returns A pair of default/requested minimum/maximum number of waves per
367   /// execution unit.
368   std::pair<unsigned, unsigned> getWavesPerEU() const {
369     return WavesPerEU;
370   }
371 
372   /// \returns Default/requested minimum number of waves per execution unit.
373   unsigned getMinWavesPerEU() const {
374     return WavesPerEU.first;
375   }
376 
377   /// \returns Default/requested maximum number of waves per execution unit.
378   unsigned getMaxWavesPerEU() const {
379     return WavesPerEU.second;
380   }
381 
382   /// \returns Stack object index for \p Dim's work group ID.
383   int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const {
384     assert(Dim < 3);
385     return DebuggerWorkGroupIDStackObjectIndices[Dim];
386   }
387 
388   /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx.
389   void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
390     assert(Dim < 3);
391     DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx;
392   }
393 
394   /// \returns Stack object index for \p Dim's work item ID.
395   int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const {
396     assert(Dim < 3);
397     return DebuggerWorkItemIDStackObjectIndices[Dim];
398   }
399 
400   /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx.
401   void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
402     assert(Dim < 3);
403     DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx;
404   }
405 
406   /// \returns SGPR used for \p Dim's work group ID.
407   unsigned getWorkGroupIDSGPR(unsigned Dim) const {
408     switch (Dim) {
409     case 0:
410       assert(hasWorkGroupIDX());
411       return WorkGroupIDXSystemSGPR;
412     case 1:
413       assert(hasWorkGroupIDY());
414       return WorkGroupIDYSystemSGPR;
415     case 2:
416       assert(hasWorkGroupIDZ());
417       return WorkGroupIDZSystemSGPR;
418     }
419     llvm_unreachable("unexpected dimension");
420   }
421 
422   /// \returns VGPR used for \p Dim' work item ID.
423   unsigned getWorkItemIDVGPR(unsigned Dim) const {
424     switch (Dim) {
425     case 0:
426       assert(hasWorkItemIDX());
427       return AMDGPU::VGPR0;
428     case 1:
429       assert(hasWorkItemIDY());
430       return AMDGPU::VGPR1;
431     case 2:
432       assert(hasWorkItemIDZ());
433       return AMDGPU::VGPR2;
434     }
435     llvm_unreachable("unexpected dimension");
436   }
437 };
438 
439 } // End namespace llvm
440 
441 #endif
442