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