1 //==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- 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 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
11 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
12 
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/Pass.h"
16 
17 namespace llvm {
18 
19 class Function;
20 class raw_ostream;
21 class SISubtarget;
22 class TargetMachine;
23 class TargetRegisterClass;
24 class TargetRegisterInfo;
25 
26 struct ArgDescriptor {
27 private:
28   friend struct AMDGPUFunctionArgInfo;
29   friend class AMDGPUArgumentUsageInfo;
30 
31   union {
32     unsigned Register;
33     unsigned StackOffset;
34   };
35 
36   bool IsStack : 1;
37   bool IsSet : 1;
38 
39   ArgDescriptor(unsigned Val = 0, bool IsStack = false, bool IsSet = false)
40     : Register(Val), IsStack(IsStack), IsSet(IsSet) {}
41 public:
42   static ArgDescriptor createRegister(unsigned Reg) {
43     return ArgDescriptor(Reg, false, true);
44   }
45 
46   static ArgDescriptor createStack(unsigned Reg) {
47     return ArgDescriptor(Reg, true, true);
48   }
49 
50   bool isSet() const {
51     return IsSet;
52   }
53 
54   explicit operator bool() const {
55     return isSet();
56   }
57 
58   bool isRegister() const {
59     return !IsStack;
60   }
61 
62   unsigned getRegister() const {
63     assert(!IsStack);
64     return Register;
65   }
66 
67   unsigned getStackOffset() const {
68     assert(IsStack);
69     return StackOffset;
70   }
71 
72   void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
73 };
74 
75 inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
76   Arg.print(OS);
77   return OS;
78 }
79 
80 struct AMDGPUFunctionArgInfo {
81   enum PreloadedValue {
82     // SGPRS:
83     PRIVATE_SEGMENT_BUFFER = 0,
84     DISPATCH_PTR        =  1,
85     QUEUE_PTR           =  2,
86     KERNARG_SEGMENT_PTR =  3,
87     DISPATCH_ID         =  4,
88     FLAT_SCRATCH_INIT   =  5,
89     WORKGROUP_ID_X      = 10,
90     WORKGROUP_ID_Y      = 11,
91     WORKGROUP_ID_Z      = 12,
92     PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
93     IMPLICIT_BUFFER_PTR = 15,
94     IMPLICIT_ARG_PTR = 16,
95 
96     // VGPRS:
97     WORKITEM_ID_X       = 17,
98     WORKITEM_ID_Y       = 18,
99     WORKITEM_ID_Z       = 19,
100     FIRST_VGPR_VALUE    = WORKITEM_ID_X
101   };
102 
103   // Kernel input registers setup for the HSA ABI in allocation order.
104 
105   // User SGPRs in kernels
106   // XXX - Can these require argument spills?
107   ArgDescriptor PrivateSegmentBuffer;
108   ArgDescriptor DispatchPtr;
109   ArgDescriptor QueuePtr;
110   ArgDescriptor KernargSegmentPtr;
111   ArgDescriptor DispatchID;
112   ArgDescriptor FlatScratchInit;
113   ArgDescriptor PrivateSegmentSize;
114   ArgDescriptor GridWorkGroupCountX;
115   ArgDescriptor GridWorkGroupCountY;
116   ArgDescriptor GridWorkGroupCountZ;
117 
118   // System SGPRs in kernels.
119   ArgDescriptor WorkGroupIDX;
120   ArgDescriptor WorkGroupIDY;
121   ArgDescriptor WorkGroupIDZ;
122   ArgDescriptor WorkGroupInfo;
123   ArgDescriptor PrivateSegmentWaveByteOffset;
124 
125   // Pointer with offset from kernargsegmentptr to where special ABI arguments
126   // are passed to callable functions.
127   ArgDescriptor ImplicitArgPtr;
128 
129   // Input registers for non-HSA ABI
130   ArgDescriptor ImplicitBufferPtr = 0;
131 
132   // VGPRs inputs. These are always v0, v1 and v2 for entry functions.
133   ArgDescriptor WorkItemIDX;
134   ArgDescriptor WorkItemIDY;
135   ArgDescriptor WorkItemIDZ;
136 
137   std::pair<const ArgDescriptor *, const TargetRegisterClass *>
138   getPreloadedValue(PreloadedValue Value) const;
139 };
140 
141 class AMDGPUArgumentUsageInfo : public ImmutablePass {
142 private:
143   static const AMDGPUFunctionArgInfo ExternFunctionInfo;
144   DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
145 
146 public:
147   static char ID;
148 
149   AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
150 
151   void getAnalysisUsage(AnalysisUsage &AU) const override {
152     AU.setPreservesAll();
153   }
154 
155   bool doInitialization(Module &M) override;
156   bool doFinalization(Module &M) override;
157 
158   void print(raw_ostream &OS, const Module *M = nullptr) const override;
159 
160   void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
161     ArgInfoMap[&F] = ArgInfo;
162   }
163 
164   const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const {
165     auto I = ArgInfoMap.find(&F);
166     if (I == ArgInfoMap.end()) {
167       assert(F.isDeclaration());
168       return ExternFunctionInfo;
169     }
170 
171     return I->second;
172   }
173 };
174 
175 } // end namespace llvm
176 
177 #endif
178