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 struct SIRegisterInfo;
31   void anchor() override;
32 
33   unsigned TIDReg;
34 
35   // Registers that may be reserved for spilling purposes. These may be the same
36   // as the input registers.
37   unsigned ScratchRSrcReg;
38   unsigned ScratchWaveOffsetReg;
39 
40   // Input registers setup for the HSA ABI.
41   // User SGPRs in allocation order.
42   unsigned PrivateSegmentBufferUserSGPR;
43   unsigned DispatchPtrUserSGPR;
44   unsigned QueuePtrUserSGPR;
45   unsigned KernargSegmentPtrUserSGPR;
46   unsigned DispatchIDUserSGPR;
47   unsigned FlatScratchInitUserSGPR;
48   unsigned PrivateSegmentSizeUserSGPR;
49   unsigned GridWorkGroupCountXUserSGPR;
50   unsigned GridWorkGroupCountYUserSGPR;
51   unsigned GridWorkGroupCountZUserSGPR;
52 
53   // System SGPRs in allocation order.
54   unsigned WorkGroupIDXSystemSGPR;
55   unsigned WorkGroupIDYSystemSGPR;
56   unsigned WorkGroupIDZSystemSGPR;
57   unsigned WorkGroupInfoSystemSGPR;
58   unsigned PrivateSegmentWaveByteOffsetSystemSGPR;
59 
60   // Graphics info.
61   unsigned PSInputAddr;
62   bool ReturnsVoid;
63 
64   unsigned MaximumWorkGroupSize;
65 
66   // Number of reserved VGPRs for debugger usage.
67   unsigned DebuggerReservedVGPRCount;
68   // Stack object indices for work group IDs.
69   std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices;
70   // Stack object indices for work item IDs.
71   std::array<int, 3> DebuggerWorkItemIDStackObjectIndices;
72 
73 public:
74   // FIXME: Make private
75   unsigned LDSWaveSpillSize;
76   unsigned PSInputEna;
77   std::map<unsigned, unsigned> LaneVGPRs;
78   unsigned ScratchOffsetReg;
79   unsigned NumUserSGPRs;
80   unsigned NumSystemSGPRs;
81 
82 private:
83   bool HasSpilledSGPRs;
84   bool HasSpilledVGPRs;
85   bool HasNonSpillStackObjects;
86   bool HasFlatInstructions;
87 
88   // Feature bits required for inputs passed in user SGPRs.
89   bool PrivateSegmentBuffer : 1;
90   bool DispatchPtr : 1;
91   bool QueuePtr : 1;
92   bool DispatchID : 1;
93   bool KernargSegmentPtr : 1;
94   bool FlatScratchInit : 1;
95   bool GridWorkgroupCountX : 1;
96   bool GridWorkgroupCountY : 1;
97   bool GridWorkgroupCountZ : 1;
98 
99   // Feature bits required for inputs passed in system SGPRs.
100   bool WorkGroupIDX : 1; // Always initialized.
101   bool WorkGroupIDY : 1;
102   bool WorkGroupIDZ : 1;
103   bool WorkGroupInfo : 1;
104   bool PrivateSegmentWaveByteOffset : 1;
105 
106   bool WorkItemIDX : 1; // Always initialized.
107   bool WorkItemIDY : 1;
108   bool WorkItemIDZ : 1;
109 
110   MCPhysReg getNextUserSGPR() const {
111     assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
112     return AMDGPU::SGPR0 + NumUserSGPRs;
113   }
114 
115   MCPhysReg getNextSystemSGPR() const {
116     return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
117   }
118 
119 public:
120   struct SpilledReg {
121     unsigned VGPR;
122     int Lane;
123     SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { }
124     SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { }
125     bool hasLane() { return Lane != -1;}
126     bool hasReg() { return VGPR != AMDGPU::NoRegister;}
127   };
128 
129   // SIMachineFunctionInfo definition
130 
131   SIMachineFunctionInfo(const MachineFunction &MF);
132   SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex,
133                            unsigned SubIdx);
134   bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; };
135   unsigned getTIDReg() const { return TIDReg; };
136   void setTIDReg(unsigned Reg) { TIDReg = Reg; }
137 
138   // Add user SGPRs.
139   unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI);
140   unsigned addDispatchPtr(const SIRegisterInfo &TRI);
141   unsigned addQueuePtr(const SIRegisterInfo &TRI);
142   unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI);
143   unsigned addFlatScratchInit(const SIRegisterInfo &TRI);
144 
145   // Add system SGPRs.
146   unsigned addWorkGroupIDX() {
147     WorkGroupIDXSystemSGPR = getNextSystemSGPR();
148     NumSystemSGPRs += 1;
149     return WorkGroupIDXSystemSGPR;
150   }
151 
152   unsigned addWorkGroupIDY() {
153     WorkGroupIDYSystemSGPR = getNextSystemSGPR();
154     NumSystemSGPRs += 1;
155     return WorkGroupIDYSystemSGPR;
156   }
157 
158   unsigned addWorkGroupIDZ() {
159     WorkGroupIDZSystemSGPR = getNextSystemSGPR();
160     NumSystemSGPRs += 1;
161     return WorkGroupIDZSystemSGPR;
162   }
163 
164   unsigned addWorkGroupInfo() {
165     WorkGroupInfoSystemSGPR = getNextSystemSGPR();
166     NumSystemSGPRs += 1;
167     return WorkGroupInfoSystemSGPR;
168   }
169 
170   unsigned addPrivateSegmentWaveByteOffset() {
171     PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR();
172     NumSystemSGPRs += 1;
173     return PrivateSegmentWaveByteOffsetSystemSGPR;
174   }
175 
176   void setPrivateSegmentWaveByteOffset(unsigned Reg) {
177     PrivateSegmentWaveByteOffsetSystemSGPR = Reg;
178   }
179 
180   bool hasPrivateSegmentBuffer() const {
181     return PrivateSegmentBuffer;
182   }
183 
184   bool hasDispatchPtr() const {
185     return DispatchPtr;
186   }
187 
188   bool hasQueuePtr() const {
189     return QueuePtr;
190   }
191 
192   bool hasDispatchID() const {
193     return DispatchID;
194   }
195 
196   bool hasKernargSegmentPtr() const {
197     return KernargSegmentPtr;
198   }
199 
200   bool hasFlatScratchInit() const {
201     return FlatScratchInit;
202   }
203 
204   bool hasGridWorkgroupCountX() const {
205     return GridWorkgroupCountX;
206   }
207 
208   bool hasGridWorkgroupCountY() const {
209     return GridWorkgroupCountY;
210   }
211 
212   bool hasGridWorkgroupCountZ() const {
213     return GridWorkgroupCountZ;
214   }
215 
216   bool hasWorkGroupIDX() const {
217     return WorkGroupIDX;
218   }
219 
220   bool hasWorkGroupIDY() const {
221     return WorkGroupIDY;
222   }
223 
224   bool hasWorkGroupIDZ() const {
225     return WorkGroupIDZ;
226   }
227 
228   bool hasWorkGroupInfo() const {
229     return WorkGroupInfo;
230   }
231 
232   bool hasPrivateSegmentWaveByteOffset() const {
233     return PrivateSegmentWaveByteOffset;
234   }
235 
236   bool hasWorkItemIDX() const {
237     return WorkItemIDX;
238   }
239 
240   bool hasWorkItemIDY() const {
241     return WorkItemIDY;
242   }
243 
244   bool hasWorkItemIDZ() const {
245     return WorkItemIDZ;
246   }
247 
248   unsigned getNumUserSGPRs() const {
249     return NumUserSGPRs;
250   }
251 
252   unsigned getNumPreloadedSGPRs() const {
253     return NumUserSGPRs + NumSystemSGPRs;
254   }
255 
256   unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const {
257     return PrivateSegmentWaveByteOffsetSystemSGPR;
258   }
259 
260   /// \brief Returns the physical register reserved for use as the resource
261   /// descriptor for scratch accesses.
262   unsigned getScratchRSrcReg() const {
263     return ScratchRSrcReg;
264   }
265 
266   void setScratchRSrcReg(unsigned Reg) {
267     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
268     ScratchRSrcReg = Reg;
269   }
270 
271   unsigned getScratchWaveOffsetReg() const {
272     return ScratchWaveOffsetReg;
273   }
274 
275   void setScratchWaveOffsetReg(unsigned Reg) {
276     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
277     ScratchWaveOffsetReg = Reg;
278   }
279 
280   unsigned getQueuePtrUserSGPR() const {
281     return QueuePtrUserSGPR;
282   }
283 
284   bool hasSpilledSGPRs() const {
285     return HasSpilledSGPRs;
286   }
287 
288   void setHasSpilledSGPRs(bool Spill = true) {
289     HasSpilledSGPRs = Spill;
290   }
291 
292   bool hasSpilledVGPRs() const {
293     return HasSpilledVGPRs;
294   }
295 
296   void setHasSpilledVGPRs(bool Spill = true) {
297     HasSpilledVGPRs = Spill;
298   }
299 
300   bool hasNonSpillStackObjects() const {
301     return HasNonSpillStackObjects;
302   }
303 
304   void setHasNonSpillStackObjects(bool StackObject = true) {
305     HasNonSpillStackObjects = StackObject;
306   }
307 
308   bool hasFlatInstructions() const {
309     return HasFlatInstructions;
310   }
311 
312   void setHasFlatInstructions(bool UseFlat = true) {
313     HasFlatInstructions = UseFlat;
314   }
315 
316   unsigned getPSInputAddr() const {
317     return PSInputAddr;
318   }
319 
320   bool isPSInputAllocated(unsigned Index) const {
321     return PSInputAddr & (1 << Index);
322   }
323 
324   void markPSInputAllocated(unsigned Index) {
325     PSInputAddr |= 1 << Index;
326   }
327 
328   bool returnsVoid() const {
329     return ReturnsVoid;
330   }
331 
332   void setIfReturnsVoid(bool Value) {
333     ReturnsVoid = Value;
334   }
335 
336   /// \returns Number of reserved VGPRs for debugger usage.
337   unsigned getDebuggerReservedVGPRCount() const {
338     return DebuggerReservedVGPRCount;
339   }
340 
341   /// \returns Stack object index for \p Dim's work group ID.
342   int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const {
343     assert(Dim < 3);
344     return DebuggerWorkGroupIDStackObjectIndices[Dim];
345   }
346 
347   /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx.
348   void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
349     assert(Dim < 3);
350     DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx;
351   }
352 
353   /// \returns Stack object index for \p Dim's work item ID.
354   int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const {
355     assert(Dim < 3);
356     return DebuggerWorkItemIDStackObjectIndices[Dim];
357   }
358 
359   /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx.
360   void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
361     assert(Dim < 3);
362     DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx;
363   }
364 
365   /// \returns SGPR used for \p Dim's work group ID.
366   unsigned getWorkGroupIDSGPR(unsigned Dim) const {
367     switch (Dim) {
368     case 0:
369       assert(hasWorkGroupIDX());
370       return WorkGroupIDXSystemSGPR;
371     case 1:
372       assert(hasWorkGroupIDY());
373       return WorkGroupIDYSystemSGPR;
374     case 2:
375       assert(hasWorkGroupIDZ());
376       return WorkGroupIDZSystemSGPR;
377     }
378     llvm_unreachable("unexpected dimension");
379   }
380 
381   /// \returns VGPR used for \p Dim' work item ID.
382   unsigned getWorkItemIDVGPR(unsigned Dim) const {
383     switch (Dim) {
384     case 0:
385       assert(hasWorkItemIDX());
386       return AMDGPU::VGPR0;
387     case 1:
388       assert(hasWorkItemIDY());
389       return AMDGPU::VGPR1;
390     case 2:
391       assert(hasWorkItemIDZ());
392       return AMDGPU::VGPR2;
393     }
394     llvm_unreachable("unexpected dimension");
395   }
396 
397   unsigned getMaximumWorkGroupSize(const MachineFunction &MF) const;
398 };
399 
400 } // End namespace llvm
401 
402 #endif
403