1 //==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
10 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
11 
12 #include "llvm/CodeGen/Register.h"
13 #include "llvm/Pass.h"
14 
15 namespace llvm {
16 
17 class Function;
18 class LLT;
19 class raw_ostream;
20 class TargetRegisterClass;
21 class TargetRegisterInfo;
22 
23 struct ArgDescriptor {
24 private:
25   friend struct AMDGPUFunctionArgInfo;
26   friend class AMDGPUArgumentUsageInfo;
27 
28   union {
29     MCRegister Reg;
30     unsigned StackOffset;
31   };
32 
33   // Bitmask to locate argument within the register.
34   unsigned Mask;
35 
36   bool IsStack : 1;
37   bool IsSet : 1;
38 
39 public:
40   constexpr ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u,
41                 bool IsStack = false, bool IsSet = false)
42     : Reg(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {}
43 
44   static constexpr ArgDescriptor createRegister(Register Reg,
45                                                 unsigned Mask = ~0u) {
46     return ArgDescriptor(Reg, Mask, false, true);
47   }
48 
49   static constexpr ArgDescriptor createStack(unsigned Offset,
50                                              unsigned Mask = ~0u) {
51     return ArgDescriptor(Offset, Mask, true, true);
52   }
53 
54   static constexpr ArgDescriptor createArg(const ArgDescriptor &Arg,
55                                            unsigned Mask) {
56     return ArgDescriptor(Arg.Reg, Mask, Arg.IsStack, Arg.IsSet);
57   }
58 
59   bool isSet() const {
60     return IsSet;
61   }
62 
63   explicit operator bool() const {
64     return isSet();
65   }
66 
67   bool isRegister() const {
68     return !IsStack;
69   }
70 
71   MCRegister getRegister() const {
72     assert(!IsStack);
73     return Reg;
74   }
75 
76   unsigned getStackOffset() const {
77     assert(IsStack);
78     return StackOffset;
79   }
80 
81   unsigned getMask() const {
82     return Mask;
83   }
84 
85   bool isMasked() const {
86     return Mask != ~0u;
87   }
88 
89   void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
90 };
91 
92 inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
93   Arg.print(OS);
94   return OS;
95 }
96 
97 struct AMDGPUFunctionArgInfo {
98   enum PreloadedValue {
99     // SGPRS:
100     PRIVATE_SEGMENT_BUFFER = 0,
101     DISPATCH_PTR        =  1,
102     QUEUE_PTR           =  2,
103     KERNARG_SEGMENT_PTR =  3,
104     DISPATCH_ID         =  4,
105     FLAT_SCRATCH_INIT   =  5,
106     LDS_KERNEL_ID       =  6, // LLVM internal, not part of the ABI
107     WORKGROUP_ID_X      = 10,
108     WORKGROUP_ID_Y      = 11,
109     WORKGROUP_ID_Z      = 12,
110     PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
111     IMPLICIT_BUFFER_PTR = 15,
112     IMPLICIT_ARG_PTR = 16,
113 
114     // VGPRS:
115     WORKITEM_ID_X       = 17,
116     WORKITEM_ID_Y       = 18,
117     WORKITEM_ID_Z       = 19,
118     FIRST_VGPR_VALUE    = WORKITEM_ID_X
119   };
120 
121   // Kernel input registers setup for the HSA ABI in allocation order.
122 
123   // User SGPRs in kernels
124   // XXX - Can these require argument spills?
125   ArgDescriptor PrivateSegmentBuffer;
126   ArgDescriptor DispatchPtr;
127   ArgDescriptor QueuePtr;
128   ArgDescriptor KernargSegmentPtr;
129   ArgDescriptor DispatchID;
130   ArgDescriptor FlatScratchInit;
131   ArgDescriptor PrivateSegmentSize;
132   ArgDescriptor LDSKernelId;
133 
134   // System SGPRs in kernels.
135   ArgDescriptor WorkGroupIDX;
136   ArgDescriptor WorkGroupIDY;
137   ArgDescriptor WorkGroupIDZ;
138   ArgDescriptor WorkGroupInfo;
139   ArgDescriptor PrivateSegmentWaveByteOffset;
140 
141   // Pointer with offset from kernargsegmentptr to where special ABI arguments
142   // are passed to callable functions.
143   ArgDescriptor ImplicitArgPtr;
144 
145   // Input registers for non-HSA ABI
146   ArgDescriptor ImplicitBufferPtr;
147 
148   // VGPRs inputs. For entry functions these are either v0, v1 and v2 or packed
149   // into v0, 10 bits per dimension if packed-tid is set.
150   ArgDescriptor WorkItemIDX;
151   ArgDescriptor WorkItemIDY;
152   ArgDescriptor WorkItemIDZ;
153 
154   std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT>
155   getPreloadedValue(PreloadedValue Value) const;
156 
157   static constexpr AMDGPUFunctionArgInfo fixedABILayout();
158 };
159 
160 class AMDGPUArgumentUsageInfo : public ImmutablePass {
161 private:
162   DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
163 
164 public:
165   static char ID;
166 
167   static const AMDGPUFunctionArgInfo ExternFunctionInfo;
168   static const AMDGPUFunctionArgInfo FixedABIFunctionInfo;
169 
170   AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
171 
172   void getAnalysisUsage(AnalysisUsage &AU) const override {
173     AU.setPreservesAll();
174   }
175 
176   bool doInitialization(Module &M) override;
177   bool doFinalization(Module &M) override;
178 
179   void print(raw_ostream &OS, const Module *M = nullptr) const override;
180 
181   void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
182     ArgInfoMap[&F] = ArgInfo;
183   }
184 
185   const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const;
186 };
187 
188 } // end namespace llvm
189 
190 #endif
191