blob: ab0024b50be18c1937c0c726f3b73a4c90f829e2 [file] [log] [blame]
Matt Arsenault7016f132017-08-03 22:30:46 +00001//==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- C++ -*-==//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Matt Arsenault7016f132017-08-03 22:30:46 +00006//
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/IR/Function.h"
14#include "llvm/Pass.h"
15
16namespace llvm {
17
18class Function;
19class raw_ostream;
Tom Stellard5bfbae52018-07-11 20:59:01 +000020class GCNSubtarget;
Matt Arsenault7016f132017-08-03 22:30:46 +000021class TargetMachine;
22class TargetRegisterClass;
23class TargetRegisterInfo;
24
25struct ArgDescriptor {
26private:
27 friend struct AMDGPUFunctionArgInfo;
Florian Gross2feb1052017-08-04 10:53:07 +000028 friend class AMDGPUArgumentUsageInfo;
Matt Arsenault7016f132017-08-03 22:30:46 +000029
30 union {
31 unsigned Register;
32 unsigned StackOffset;
33 };
34
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000035 // Bitmask to locate argument within the register.
36 unsigned Mask;
37
Matt Arsenault7016f132017-08-03 22:30:46 +000038 bool IsStack : 1;
39 bool IsSet : 1;
40
Matt Arsenault7016f132017-08-03 22:30:46 +000041public:
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000042 ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u,
43 bool IsStack = false, bool IsSet = false)
44 : Register(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {}
45
46 static ArgDescriptor createRegister(unsigned Reg, unsigned Mask = ~0u) {
47 return ArgDescriptor(Reg, Mask, false, true);
Matt Arsenault7016f132017-08-03 22:30:46 +000048 }
49
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000050 static ArgDescriptor createStack(unsigned Reg, unsigned Mask = ~0u) {
51 return ArgDescriptor(Reg, Mask, true, true);
52 }
53
54 static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask) {
55 return ArgDescriptor(Arg.Register, Mask, Arg.IsStack, Arg.IsSet);
Matt Arsenault7016f132017-08-03 22:30:46 +000056 }
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 unsigned getRegister() const {
71 assert(!IsStack);
72 return Register;
73 }
74
75 unsigned getStackOffset() const {
76 assert(IsStack);
77 return StackOffset;
78 }
79
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000080 unsigned getMask() const {
81 return Mask;
82 }
83
84 bool isMasked() const {
85 return Mask != ~0u;
86 }
87
Matt Arsenault7016f132017-08-03 22:30:46 +000088 void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
89};
90
91inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
92 Arg.print(OS);
93 return OS;
94}
95
96struct AMDGPUFunctionArgInfo {
97 enum PreloadedValue {
98 // SGPRS:
99 PRIVATE_SEGMENT_BUFFER = 0,
100 DISPATCH_PTR = 1,
101 QUEUE_PTR = 2,
102 KERNARG_SEGMENT_PTR = 3,
103 DISPATCH_ID = 4,
104 FLAT_SCRATCH_INIT = 5,
105 WORKGROUP_ID_X = 10,
106 WORKGROUP_ID_Y = 11,
107 WORKGROUP_ID_Z = 12,
108 PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
109 IMPLICIT_BUFFER_PTR = 15,
Matt Arsenault817c2532017-08-03 23:12:44 +0000110 IMPLICIT_ARG_PTR = 16,
Matt Arsenault7016f132017-08-03 22:30:46 +0000111
112 // VGPRS:
Matt Arsenault817c2532017-08-03 23:12:44 +0000113 WORKITEM_ID_X = 17,
114 WORKITEM_ID_Y = 18,
115 WORKITEM_ID_Z = 19,
116 FIRST_VGPR_VALUE = WORKITEM_ID_X
Matt Arsenault7016f132017-08-03 22:30:46 +0000117 };
118
119 // Kernel input registers setup for the HSA ABI in allocation order.
120
121 // User SGPRs in kernels
122 // XXX - Can these require argument spills?
123 ArgDescriptor PrivateSegmentBuffer;
124 ArgDescriptor DispatchPtr;
125 ArgDescriptor QueuePtr;
126 ArgDescriptor KernargSegmentPtr;
127 ArgDescriptor DispatchID;
128 ArgDescriptor FlatScratchInit;
129 ArgDescriptor PrivateSegmentSize;
Matt Arsenault7016f132017-08-03 22:30:46 +0000130
131 // System SGPRs in kernels.
132 ArgDescriptor WorkGroupIDX;
133 ArgDescriptor WorkGroupIDY;
134 ArgDescriptor WorkGroupIDZ;
135 ArgDescriptor WorkGroupInfo;
136 ArgDescriptor PrivateSegmentWaveByteOffset;
137
Matt Arsenault817c2532017-08-03 23:12:44 +0000138 // Pointer with offset from kernargsegmentptr to where special ABI arguments
139 // are passed to callable functions.
140 ArgDescriptor ImplicitArgPtr;
141
Matt Arsenault7016f132017-08-03 22:30:46 +0000142 // Input registers for non-HSA ABI
143 ArgDescriptor ImplicitBufferPtr = 0;
144
145 // VGPRs inputs. These are always v0, v1 and v2 for entry functions.
146 ArgDescriptor WorkItemIDX;
147 ArgDescriptor WorkItemIDY;
148 ArgDescriptor WorkItemIDZ;
149
150 std::pair<const ArgDescriptor *, const TargetRegisterClass *>
151 getPreloadedValue(PreloadedValue Value) const;
152};
153
154class AMDGPUArgumentUsageInfo : public ImmutablePass {
155private:
156 static const AMDGPUFunctionArgInfo ExternFunctionInfo;
157 DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
158
159public:
160 static char ID;
161
162 AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
163
164 void getAnalysisUsage(AnalysisUsage &AU) const override {
165 AU.setPreservesAll();
166 }
167
168 bool doInitialization(Module &M) override;
169 bool doFinalization(Module &M) override;
170
171 void print(raw_ostream &OS, const Module *M = nullptr) const override;
172
173 void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
174 ArgInfoMap[&F] = ArgInfo;
175 }
176
177 const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const {
178 auto I = ArgInfoMap.find(&F);
179 if (I == ArgInfoMap.end()) {
180 assert(F.isDeclaration());
181 return ExternFunctionInfo;
182 }
183
184 return I->second;
185 }
186};
187
188} // end namespace llvm
189
190#endif