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