blob: 097730441ed8d5248b67a6aa1524c7e8ceff3e01 [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"
Matt Arsenault1b317682019-07-01 13:44:46 +000013#include "llvm/CodeGen/Register.h"
Matt Arsenault7016f132017-08-03 22:30:46 +000014#include "llvm/IR/Function.h"
15#include "llvm/Pass.h"
16
17namespace llvm {
18
19class Function;
20class raw_ostream;
Tom Stellard5bfbae52018-07-11 20:59:01 +000021class GCNSubtarget;
Matt Arsenault7016f132017-08-03 22:30:46 +000022class TargetMachine;
23class TargetRegisterClass;
24class TargetRegisterInfo;
25
26struct ArgDescriptor {
27private:
28 friend struct AMDGPUFunctionArgInfo;
Florian Gross2feb1052017-08-04 10:53:07 +000029 friend class AMDGPUArgumentUsageInfo;
Matt Arsenault7016f132017-08-03 22:30:46 +000030
31 union {
Matt Arsenault1b317682019-07-01 13:44:46 +000032 Register Reg;
Matt Arsenault7016f132017-08-03 22:30:46 +000033 unsigned StackOffset;
34 };
35
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000036 // Bitmask to locate argument within the register.
37 unsigned Mask;
38
Matt Arsenault7016f132017-08-03 22:30:46 +000039 bool IsStack : 1;
40 bool IsSet : 1;
41
Matt Arsenault7016f132017-08-03 22:30:46 +000042public:
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000043 ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u,
44 bool IsStack = false, bool IsSet = false)
Matt Arsenault1b317682019-07-01 13:44:46 +000045 : Reg(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {}
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000046
Matt Arsenault1b317682019-07-01 13:44:46 +000047 static ArgDescriptor createRegister(Register Reg, unsigned Mask = ~0u) {
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000048 return ArgDescriptor(Reg, Mask, false, true);
Matt Arsenault7016f132017-08-03 22:30:46 +000049 }
50
Matt Arsenault1b317682019-07-01 13:44:46 +000051 static ArgDescriptor createStack(Register Reg, unsigned Mask = ~0u) {
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000052 return ArgDescriptor(Reg, Mask, true, true);
53 }
54
55 static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask) {
Matt Arsenault1b317682019-07-01 13:44:46 +000056 return ArgDescriptor(Arg.Reg, Mask, Arg.IsStack, Arg.IsSet);
Matt Arsenault7016f132017-08-03 22:30:46 +000057 }
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
Matt Arsenault1b317682019-07-01 13:44:46 +000071 Register getRegister() const {
Matt Arsenault7016f132017-08-03 22:30:46 +000072 assert(!IsStack);
Matt Arsenault1b317682019-07-01 13:44:46 +000073 return Reg;
Matt Arsenault7016f132017-08-03 22:30:46 +000074 }
75
76 unsigned getStackOffset() const {
77 assert(IsStack);
78 return StackOffset;
79 }
80
Stanislav Mekhanoshin07fd88d2019-06-28 01:52:13 +000081 unsigned getMask() const {
82 return Mask;
83 }
84
85 bool isMasked() const {
86 return Mask != ~0u;
87 }
88
Matt Arsenault7016f132017-08-03 22:30:46 +000089 void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
90};
91
92inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
93 Arg.print(OS);
94 return OS;
95}
96
97struct 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 WORKGROUP_ID_X = 10,
107 WORKGROUP_ID_Y = 11,
108 WORKGROUP_ID_Z = 12,
109 PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
110 IMPLICIT_BUFFER_PTR = 15,
Matt Arsenault817c2532017-08-03 23:12:44 +0000111 IMPLICIT_ARG_PTR = 16,
Matt Arsenault7016f132017-08-03 22:30:46 +0000112
113 // VGPRS:
Matt Arsenault817c2532017-08-03 23:12:44 +0000114 WORKITEM_ID_X = 17,
115 WORKITEM_ID_Y = 18,
116 WORKITEM_ID_Z = 19,
117 FIRST_VGPR_VALUE = WORKITEM_ID_X
Matt Arsenault7016f132017-08-03 22:30:46 +0000118 };
119
120 // Kernel input registers setup for the HSA ABI in allocation order.
121
122 // User SGPRs in kernels
123 // XXX - Can these require argument spills?
124 ArgDescriptor PrivateSegmentBuffer;
125 ArgDescriptor DispatchPtr;
126 ArgDescriptor QueuePtr;
127 ArgDescriptor KernargSegmentPtr;
128 ArgDescriptor DispatchID;
129 ArgDescriptor FlatScratchInit;
130 ArgDescriptor PrivateSegmentSize;
Matt Arsenault7016f132017-08-03 22:30:46 +0000131
132 // System SGPRs in kernels.
133 ArgDescriptor WorkGroupIDX;
134 ArgDescriptor WorkGroupIDY;
135 ArgDescriptor WorkGroupIDZ;
136 ArgDescriptor WorkGroupInfo;
137 ArgDescriptor PrivateSegmentWaveByteOffset;
138
Matt Arsenault817c2532017-08-03 23:12:44 +0000139 // Pointer with offset from kernargsegmentptr to where special ABI arguments
140 // are passed to callable functions.
141 ArgDescriptor ImplicitArgPtr;
142
Matt Arsenault7016f132017-08-03 22:30:46 +0000143 // Input registers for non-HSA ABI
144 ArgDescriptor ImplicitBufferPtr = 0;
145
146 // VGPRs inputs. These are always v0, v1 and v2 for entry functions.
147 ArgDescriptor WorkItemIDX;
148 ArgDescriptor WorkItemIDY;
149 ArgDescriptor WorkItemIDZ;
150
151 std::pair<const ArgDescriptor *, const TargetRegisterClass *>
152 getPreloadedValue(PreloadedValue Value) const;
153};
154
155class AMDGPUArgumentUsageInfo : public ImmutablePass {
156private:
157 static const AMDGPUFunctionArgInfo ExternFunctionInfo;
158 DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
159
160public:
161 static char ID;
162
163 AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
164
165 void getAnalysisUsage(AnalysisUsage &AU) const override {
166 AU.setPreservesAll();
167 }
168
169 bool doInitialization(Module &M) override;
170 bool doFinalization(Module &M) override;
171
172 void print(raw_ostream &OS, const Module *M = nullptr) const override;
173
174 void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
175 ArgInfoMap[&F] = ArgInfo;
176 }
177
178 const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const {
179 auto I = ArgInfoMap.find(&F);
180 if (I == ArgInfoMap.end()) {
181 assert(F.isDeclaration());
182 return ExternFunctionInfo;
183 }
184
185 return I->second;
186 }
187};
188
189} // end namespace llvm
190
191#endif