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