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 "MCTargetDesc/AMDGPUMCTargetDesc.h"
20 #include "llvm/CodeGen/PseudoSourceValue.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include <array>
24 #include <cassert>
25 #include <map>
26 #include <utility>
27 
28 namespace llvm {
29 
30 class AMDGPUImagePseudoSourceValue : public PseudoSourceValue {
31 public:
32   explicit AMDGPUImagePseudoSourceValue() :
33     PseudoSourceValue(PseudoSourceValue::TargetCustom) { }
34 
35   bool isConstant(const MachineFrameInfo *) const override {
36     // This should probably be true for most images, but we will start by being
37     // conservative.
38     return false;
39   }
40 
41   bool isAliased(const MachineFrameInfo *) const override {
42     // FIXME: If we ever change image intrinsics to accept fat pointers, then
43     // this could be true for some cases.
44     return false;
45   }
46 
47   bool mayAlias(const MachineFrameInfo*) const override {
48     // FIXME: If we ever change image intrinsics to accept fat pointers, then
49     // this could be true for some cases.
50     return false;
51   }
52 };
53 
54 class AMDGPUBufferPseudoSourceValue : public PseudoSourceValue {
55 public:
56   explicit AMDGPUBufferPseudoSourceValue() :
57     PseudoSourceValue(PseudoSourceValue::TargetCustom) { }
58 
59   bool isConstant(const MachineFrameInfo *) const override {
60     // This should probably be true for most images, but we will start by being
61     // conservative.
62     return false;
63   }
64 
65   bool isAliased(const MachineFrameInfo *) const override {
66     // FIXME: If we ever change image intrinsics to accept fat pointers, then
67     // this could be true for some cases.
68     return false;
69   }
70 
71   bool mayAlias(const MachineFrameInfo*) const override {
72     // FIXME: If we ever change image intrinsics to accept fat pointers, then
73     // this could be true for some cases.
74     return false;
75   }
76 };
77 
78 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which
79 /// tells the hardware which interpolation parameters to load.
80 class SIMachineFunctionInfo final : public AMDGPUMachineFunction {
81   // FIXME: This should be removed and getPreloadedValue moved here.
82   friend class SIRegisterInfo;
83 
84   unsigned TIDReg;
85 
86   // Registers that may be reserved for spilling purposes. These may be the same
87   // as the input registers.
88   unsigned ScratchRSrcReg;
89   unsigned ScratchWaveOffsetReg;
90 
91   // Input registers for non-HSA ABI
92   unsigned PrivateMemoryPtrUserSGPR;
93 
94   // Input registers setup for the HSA ABI.
95   // User SGPRs in allocation order.
96   unsigned PrivateSegmentBufferUserSGPR;
97   unsigned DispatchPtrUserSGPR;
98   unsigned QueuePtrUserSGPR;
99   unsigned KernargSegmentPtrUserSGPR;
100   unsigned DispatchIDUserSGPR;
101   unsigned FlatScratchInitUserSGPR;
102   unsigned PrivateSegmentSizeUserSGPR;
103   unsigned GridWorkGroupCountXUserSGPR;
104   unsigned GridWorkGroupCountYUserSGPR;
105   unsigned GridWorkGroupCountZUserSGPR;
106 
107   // System SGPRs in allocation order.
108   unsigned WorkGroupIDXSystemSGPR;
109   unsigned WorkGroupIDYSystemSGPR;
110   unsigned WorkGroupIDZSystemSGPR;
111   unsigned WorkGroupInfoSystemSGPR;
112   unsigned PrivateSegmentWaveByteOffsetSystemSGPR;
113 
114   // Graphics info.
115   unsigned PSInputAddr;
116   unsigned PSInputEnable;
117 
118   bool ReturnsVoid;
119 
120   // A pair of default/requested minimum/maximum flat work group sizes.
121   // Minimum - first, maximum - second.
122   std::pair<unsigned, unsigned> FlatWorkGroupSizes;
123 
124   // A pair of default/requested minimum/maximum number of waves per execution
125   // unit. Minimum - first, maximum - second.
126   std::pair<unsigned, unsigned> WavesPerEU;
127 
128   // Stack object indices for work group IDs.
129   std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices;
130   // Stack object indices for work item IDs.
131   std::array<int, 3> DebuggerWorkItemIDStackObjectIndices;
132 
133   AMDGPUBufferPseudoSourceValue BufferPSV;
134   AMDGPUImagePseudoSourceValue ImagePSV;
135 
136 private:
137   unsigned LDSWaveSpillSize;
138   unsigned ScratchOffsetReg;
139   unsigned NumUserSGPRs;
140   unsigned NumSystemSGPRs;
141 
142   bool HasSpilledSGPRs;
143   bool HasSpilledVGPRs;
144   bool HasNonSpillStackObjects;
145 
146   unsigned NumSpilledSGPRs;
147   unsigned NumSpilledVGPRs;
148 
149   // Feature bits required for inputs passed in user SGPRs.
150   bool PrivateSegmentBuffer : 1;
151   bool DispatchPtr : 1;
152   bool QueuePtr : 1;
153   bool KernargSegmentPtr : 1;
154   bool DispatchID : 1;
155   bool FlatScratchInit : 1;
156   bool GridWorkgroupCountX : 1;
157   bool GridWorkgroupCountY : 1;
158   bool GridWorkgroupCountZ : 1;
159 
160   // Feature bits required for inputs passed in system SGPRs.
161   bool WorkGroupIDX : 1; // Always initialized.
162   bool WorkGroupIDY : 1;
163   bool WorkGroupIDZ : 1;
164   bool WorkGroupInfo : 1;
165   bool PrivateSegmentWaveByteOffset : 1;
166 
167   bool WorkItemIDX : 1; // Always initialized.
168   bool WorkItemIDY : 1;
169   bool WorkItemIDZ : 1;
170 
171   // Private memory buffer
172   // Compute directly in sgpr[0:1]
173   // Other shaders indirect 64-bits at sgpr[0:1]
174   bool PrivateMemoryInputPtr : 1;
175 
176   MCPhysReg getNextUserSGPR() const {
177     assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
178     return AMDGPU::SGPR0 + NumUserSGPRs;
179   }
180 
181   MCPhysReg getNextSystemSGPR() const {
182     return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
183   }
184 
185 public:
186   struct SpilledReg {
187     unsigned VGPR = AMDGPU::NoRegister;
188     int Lane = -1;
189 
190     SpilledReg() = default;
191     SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { }
192 
193     bool hasLane() { return Lane != -1;}
194     bool hasReg() { return VGPR != AMDGPU::NoRegister;}
195   };
196 
197 private:
198   // SGPR->VGPR spilling support.
199   typedef std::pair<unsigned, unsigned> SpillRegMask;
200 
201   // Track VGPR + wave index for each subregister of the SGPR spilled to
202   // frameindex key.
203   DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills;
204   unsigned NumVGPRSpillLanes = 0;
205   SmallVector<unsigned, 2> SpillVGPRs;
206 
207 public:
208 
209   SIMachineFunctionInfo(const MachineFunction &MF);
210 
211   ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const {
212     auto I = SGPRToVGPRSpills.find(FrameIndex);
213     return (I == SGPRToVGPRSpills.end()) ?
214       ArrayRef<SpilledReg>() : makeArrayRef(I->second);
215   }
216 
217   bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI);
218   void removeSGPRToVGPRFrameIndices(MachineFrameInfo &MFI);
219 
220   bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; };
221   unsigned getTIDReg() const { return TIDReg; };
222   void setTIDReg(unsigned Reg) { TIDReg = Reg; }
223 
224   // Add user SGPRs.
225   unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI);
226   unsigned addDispatchPtr(const SIRegisterInfo &TRI);
227   unsigned addQueuePtr(const SIRegisterInfo &TRI);
228   unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI);
229   unsigned addDispatchID(const SIRegisterInfo &TRI);
230   unsigned addFlatScratchInit(const SIRegisterInfo &TRI);
231   unsigned addPrivateMemoryPtr(const SIRegisterInfo &TRI);
232 
233   // Add system SGPRs.
234   unsigned addWorkGroupIDX() {
235     WorkGroupIDXSystemSGPR = getNextSystemSGPR();
236     NumSystemSGPRs += 1;
237     return WorkGroupIDXSystemSGPR;
238   }
239 
240   unsigned addWorkGroupIDY() {
241     WorkGroupIDYSystemSGPR = getNextSystemSGPR();
242     NumSystemSGPRs += 1;
243     return WorkGroupIDYSystemSGPR;
244   }
245 
246   unsigned addWorkGroupIDZ() {
247     WorkGroupIDZSystemSGPR = getNextSystemSGPR();
248     NumSystemSGPRs += 1;
249     return WorkGroupIDZSystemSGPR;
250   }
251 
252   unsigned addWorkGroupInfo() {
253     WorkGroupInfoSystemSGPR = getNextSystemSGPR();
254     NumSystemSGPRs += 1;
255     return WorkGroupInfoSystemSGPR;
256   }
257 
258   unsigned addPrivateSegmentWaveByteOffset() {
259     PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR();
260     NumSystemSGPRs += 1;
261     return PrivateSegmentWaveByteOffsetSystemSGPR;
262   }
263 
264   void setPrivateSegmentWaveByteOffset(unsigned Reg) {
265     PrivateSegmentWaveByteOffsetSystemSGPR = Reg;
266   }
267 
268   bool hasPrivateSegmentBuffer() const {
269     return PrivateSegmentBuffer;
270   }
271 
272   bool hasDispatchPtr() const {
273     return DispatchPtr;
274   }
275 
276   bool hasQueuePtr() const {
277     return QueuePtr;
278   }
279 
280   bool hasKernargSegmentPtr() const {
281     return KernargSegmentPtr;
282   }
283 
284   bool hasDispatchID() const {
285     return DispatchID;
286   }
287 
288   bool hasFlatScratchInit() const {
289     return FlatScratchInit;
290   }
291 
292   bool hasGridWorkgroupCountX() const {
293     return GridWorkgroupCountX;
294   }
295 
296   bool hasGridWorkgroupCountY() const {
297     return GridWorkgroupCountY;
298   }
299 
300   bool hasGridWorkgroupCountZ() const {
301     return GridWorkgroupCountZ;
302   }
303 
304   bool hasWorkGroupIDX() const {
305     return WorkGroupIDX;
306   }
307 
308   bool hasWorkGroupIDY() const {
309     return WorkGroupIDY;
310   }
311 
312   bool hasWorkGroupIDZ() const {
313     return WorkGroupIDZ;
314   }
315 
316   bool hasWorkGroupInfo() const {
317     return WorkGroupInfo;
318   }
319 
320   bool hasPrivateSegmentWaveByteOffset() const {
321     return PrivateSegmentWaveByteOffset;
322   }
323 
324   bool hasWorkItemIDX() const {
325     return WorkItemIDX;
326   }
327 
328   bool hasWorkItemIDY() const {
329     return WorkItemIDY;
330   }
331 
332   bool hasWorkItemIDZ() const {
333     return WorkItemIDZ;
334   }
335 
336   bool hasPrivateMemoryInputPtr() const {
337     return PrivateMemoryInputPtr;
338   }
339 
340   unsigned getNumUserSGPRs() const {
341     return NumUserSGPRs;
342   }
343 
344   unsigned getNumPreloadedSGPRs() const {
345     return NumUserSGPRs + NumSystemSGPRs;
346   }
347 
348   unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const {
349     return PrivateSegmentWaveByteOffsetSystemSGPR;
350   }
351 
352   /// \brief Returns the physical register reserved for use as the resource
353   /// descriptor for scratch accesses.
354   unsigned getScratchRSrcReg() const {
355     return ScratchRSrcReg;
356   }
357 
358   void setScratchRSrcReg(unsigned Reg) {
359     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
360     ScratchRSrcReg = Reg;
361   }
362 
363   unsigned getScratchWaveOffsetReg() const {
364     return ScratchWaveOffsetReg;
365   }
366 
367   void setScratchWaveOffsetReg(unsigned Reg) {
368     assert(Reg != AMDGPU::NoRegister && "Should never be unset");
369     ScratchWaveOffsetReg = Reg;
370   }
371 
372   unsigned getQueuePtrUserSGPR() const {
373     return QueuePtrUserSGPR;
374   }
375 
376   unsigned getPrivateMemoryPtrUserSGPR() const {
377     return PrivateMemoryPtrUserSGPR;
378   }
379 
380   bool hasSpilledSGPRs() const {
381     return HasSpilledSGPRs;
382   }
383 
384   void setHasSpilledSGPRs(bool Spill = true) {
385     HasSpilledSGPRs = Spill;
386   }
387 
388   bool hasSpilledVGPRs() const {
389     return HasSpilledVGPRs;
390   }
391 
392   void setHasSpilledVGPRs(bool Spill = true) {
393     HasSpilledVGPRs = Spill;
394   }
395 
396   bool hasNonSpillStackObjects() const {
397     return HasNonSpillStackObjects;
398   }
399 
400   void setHasNonSpillStackObjects(bool StackObject = true) {
401     HasNonSpillStackObjects = StackObject;
402   }
403 
404   unsigned getNumSpilledSGPRs() const {
405     return NumSpilledSGPRs;
406   }
407 
408   unsigned getNumSpilledVGPRs() const {
409     return NumSpilledVGPRs;
410   }
411 
412   void addToSpilledSGPRs(unsigned num) {
413     NumSpilledSGPRs += num;
414   }
415 
416   void addToSpilledVGPRs(unsigned num) {
417     NumSpilledVGPRs += num;
418   }
419 
420   unsigned getPSInputAddr() const {
421     return PSInputAddr;
422   }
423 
424   unsigned getPSInputEnable() const {
425     return PSInputEnable;
426   }
427 
428   bool isPSInputAllocated(unsigned Index) const {
429     return PSInputAddr & (1 << Index);
430   }
431 
432   void markPSInputAllocated(unsigned Index) {
433     PSInputAddr |= 1 << Index;
434   }
435 
436   void markPSInputEnabled(unsigned Index) {
437     PSInputEnable |= 1 << Index;
438   }
439 
440   bool returnsVoid() const {
441     return ReturnsVoid;
442   }
443 
444   void setIfReturnsVoid(bool Value) {
445     ReturnsVoid = Value;
446   }
447 
448   /// \returns A pair of default/requested minimum/maximum flat work group sizes
449   /// for this function.
450   std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const {
451     return FlatWorkGroupSizes;
452   }
453 
454   /// \returns Default/requested minimum flat work group size for this function.
455   unsigned getMinFlatWorkGroupSize() const {
456     return FlatWorkGroupSizes.first;
457   }
458 
459   /// \returns Default/requested maximum flat work group size for this function.
460   unsigned getMaxFlatWorkGroupSize() const {
461     return FlatWorkGroupSizes.second;
462   }
463 
464   /// \returns A pair of default/requested minimum/maximum number of waves per
465   /// execution unit.
466   std::pair<unsigned, unsigned> getWavesPerEU() const {
467     return WavesPerEU;
468   }
469 
470   /// \returns Default/requested minimum number of waves per execution unit.
471   unsigned getMinWavesPerEU() const {
472     return WavesPerEU.first;
473   }
474 
475   /// \returns Default/requested maximum number of waves per execution unit.
476   unsigned getMaxWavesPerEU() const {
477     return WavesPerEU.second;
478   }
479 
480   /// \returns Stack object index for \p Dim's work group ID.
481   int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const {
482     assert(Dim < 3);
483     return DebuggerWorkGroupIDStackObjectIndices[Dim];
484   }
485 
486   /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx.
487   void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
488     assert(Dim < 3);
489     DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx;
490   }
491 
492   /// \returns Stack object index for \p Dim's work item ID.
493   int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const {
494     assert(Dim < 3);
495     return DebuggerWorkItemIDStackObjectIndices[Dim];
496   }
497 
498   /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx.
499   void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) {
500     assert(Dim < 3);
501     DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx;
502   }
503 
504   /// \returns SGPR used for \p Dim's work group ID.
505   unsigned getWorkGroupIDSGPR(unsigned Dim) const {
506     switch (Dim) {
507     case 0:
508       assert(hasWorkGroupIDX());
509       return WorkGroupIDXSystemSGPR;
510     case 1:
511       assert(hasWorkGroupIDY());
512       return WorkGroupIDYSystemSGPR;
513     case 2:
514       assert(hasWorkGroupIDZ());
515       return WorkGroupIDZSystemSGPR;
516     }
517     llvm_unreachable("unexpected dimension");
518   }
519 
520   /// \returns VGPR used for \p Dim' work item ID.
521   unsigned getWorkItemIDVGPR(unsigned Dim) const {
522     switch (Dim) {
523     case 0:
524       assert(hasWorkItemIDX());
525       return AMDGPU::VGPR0;
526     case 1:
527       assert(hasWorkItemIDY());
528       return AMDGPU::VGPR1;
529     case 2:
530       assert(hasWorkItemIDZ());
531       return AMDGPU::VGPR2;
532     }
533     llvm_unreachable("unexpected dimension");
534   }
535 
536   unsigned getLDSWaveSpillSize() const {
537     return LDSWaveSpillSize;
538   }
539 
540   const AMDGPUBufferPseudoSourceValue *getBufferPSV() const {
541     return &BufferPSV;
542   }
543 
544   const AMDGPUImagePseudoSourceValue *getImagePSV() const {
545     return &ImagePSV;
546   }
547 };
548 
549 } // end namespace llvm
550 
551 #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H
552