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