blob: f19b20ceb5da0d2a095623a3906b3b5a0949b6d8 [file] [log] [blame]
Eugene Zelenko59e12822017-08-08 00:47:13 +00001//==- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface --*- C++ -*-==//
Tom Stellard75aadc22012-12-11 21:25:42 +00002//
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
Tom Stellard75aadc22012-12-11 21:25:42 +00006//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10//
11//===----------------------------------------------------------------------===//
12
Matt Arsenault6b6a2c32016-03-11 08:00:27 +000013#ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H
14#define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H
Tom Stellard75aadc22012-12-11 21:25:42 +000015
Matt Arsenault8623e8d2017-08-03 23:00:29 +000016#include "AMDGPUArgumentUsageInfo.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000017#include "AMDGPUMachineFunction.h"
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +000018#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Tom Stellard44b30b42018-05-22 02:03:23 +000019#include "SIInstrInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "SIRegisterInfo.h"
Eugene Zelenko59e12822017-08-08 00:47:13 +000021#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/Optional.h"
Michael Liao80177ca2019-07-03 02:00:21 +000024#include "llvm/ADT/STLExtras.h"
Eugene Zelenko59e12822017-08-08 00:47:13 +000025#include "llvm/ADT/SmallVector.h"
Neil Henning0a30f332019-04-01 15:19:52 +000026#include "llvm/ADT/SparseBitVector.h"
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +000027#include "llvm/CodeGen/MIRYamlMapping.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000028#include "llvm/CodeGen/PseudoSourceValue.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000029#include "llvm/CodeGen/TargetInstrInfo.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000030#include "llvm/MC/MCRegisterInfo.h"
31#include "llvm/Support/ErrorHandling.h"
NAKAMURA Takumi5cbd41e2016-06-27 10:26:43 +000032#include <array>
Eugene Zelenko66203762017-01-21 00:53:49 +000033#include <cassert>
Eugene Zelenko66203762017-01-21 00:53:49 +000034#include <utility>
Eugene Zelenko59e12822017-08-08 00:47:13 +000035#include <vector>
Tom Stellard75aadc22012-12-11 21:25:42 +000036
37namespace llvm {
38
Eugene Zelenko59e12822017-08-08 00:47:13 +000039class MachineFrameInfo;
40class MachineFunction;
41class TargetRegisterClass;
42
Matt Arsenaulte683eba2019-06-17 13:52:15 +000043class AMDGPUPseudoSourceValue : public PseudoSourceValue {
Tom Stellard244891d2016-12-20 15:52:17 +000044public:
Matt Arsenaulte683eba2019-06-17 13:52:15 +000045 enum AMDGPUPSVKind : unsigned {
46 PSVBuffer = PseudoSourceValue::TargetCustom,
Matt Arsenault4d55d022019-06-19 19:55:27 +000047 PSVImage,
48 GWSResource
Matt Arsenaulte683eba2019-06-17 13:52:15 +000049 };
Tom Stellard244891d2016-12-20 15:52:17 +000050
Matt Arsenaulte683eba2019-06-17 13:52:15 +000051protected:
52 AMDGPUPseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII)
53 : PseudoSourceValue(Kind, TII) {}
54
55public:
Tom Stellard244891d2016-12-20 15:52:17 +000056 bool isConstant(const MachineFrameInfo *) const override {
57 // This should probably be true for most images, but we will start by being
58 // conservative.
59 return false;
60 }
61
62 bool isAliased(const MachineFrameInfo *) const override {
Tim Renouf75ced9d2018-01-12 22:57:24 +000063 return true;
Tom Stellard244891d2016-12-20 15:52:17 +000064 }
65
Eugene Zelenko59e12822017-08-08 00:47:13 +000066 bool mayAlias(const MachineFrameInfo *) const override {
Tim Renouf75ced9d2018-01-12 22:57:24 +000067 return true;
Tom Stellard244891d2016-12-20 15:52:17 +000068 }
69};
70
Matt Arsenaulte683eba2019-06-17 13:52:15 +000071class AMDGPUBufferPseudoSourceValue final : public AMDGPUPseudoSourceValue {
Tom Stellard6f9ef142016-12-20 17:19:44 +000072public:
Matt Arsenaulte683eba2019-06-17 13:52:15 +000073 explicit AMDGPUBufferPseudoSourceValue(const TargetInstrInfo &TII)
74 : AMDGPUPseudoSourceValue(PSVBuffer, TII) {}
Tom Stellard6f9ef142016-12-20 17:19:44 +000075
Matt Arsenaulte683eba2019-06-17 13:52:15 +000076 static bool classof(const PseudoSourceValue *V) {
77 return V->kind() == PSVBuffer;
Tom Stellard6f9ef142016-12-20 17:19:44 +000078 }
Matt Arsenaulte683eba2019-06-17 13:52:15 +000079};
Tom Stellard6f9ef142016-12-20 17:19:44 +000080
Matt Arsenaulte683eba2019-06-17 13:52:15 +000081class AMDGPUImagePseudoSourceValue final : public AMDGPUPseudoSourceValue {
82public:
83 // TODO: Is the img rsrc useful?
84 explicit AMDGPUImagePseudoSourceValue(const TargetInstrInfo &TII)
85 : AMDGPUPseudoSourceValue(PSVImage, TII) {}
Tom Stellard6f9ef142016-12-20 17:19:44 +000086
Matt Arsenaulte683eba2019-06-17 13:52:15 +000087 static bool classof(const PseudoSourceValue *V) {
88 return V->kind() == PSVImage;
Tom Stellard6f9ef142016-12-20 17:19:44 +000089 }
90};
Tom Stellard244891d2016-12-20 15:52:17 +000091
Matt Arsenault4d55d022019-06-19 19:55:27 +000092class AMDGPUGWSResourcePseudoSourceValue final : public AMDGPUPseudoSourceValue {
93public:
94 explicit AMDGPUGWSResourcePseudoSourceValue(const TargetInstrInfo &TII)
95 : AMDGPUPseudoSourceValue(GWSResource, TII) {}
96
97 static bool classof(const PseudoSourceValue *V) {
98 return V->kind() == GWSResource;
99 }
100
101 // These are inaccessible memory from IR.
102 bool isAliased(const MachineFrameInfo *) const override {
103 return false;
104 }
105
106 // These are inaccessible memory from IR.
107 bool mayAlias(const MachineFrameInfo *) const override {
108 return false;
109 }
110
111 void printCustom(raw_ostream &OS) const override {
112 OS << "GWSResource";
113 }
114};
115
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000116namespace yaml {
117
Michael Liao80177ca2019-07-03 02:00:21 +0000118struct SIArgument {
119 bool IsRegister;
120 union {
121 StringValue RegisterName;
122 unsigned StackOffset;
123 };
124 Optional<unsigned> Mask;
125
126 // Default constructor, which creates a stack argument.
127 SIArgument() : IsRegister(false), StackOffset(0) {}
128 SIArgument(const SIArgument &Other) {
129 IsRegister = Other.IsRegister;
130 if (IsRegister) {
131 ::new ((void *)std::addressof(RegisterName))
132 StringValue(Other.RegisterName);
133 } else
134 StackOffset = Other.StackOffset;
135 Mask = Other.Mask;
136 }
137 SIArgument &operator=(const SIArgument &Other) {
138 IsRegister = Other.IsRegister;
139 if (IsRegister) {
140 ::new ((void *)std::addressof(RegisterName))
141 StringValue(Other.RegisterName);
142 } else
143 StackOffset = Other.StackOffset;
144 Mask = Other.Mask;
145 return *this;
146 }
147 ~SIArgument() {
148 if (IsRegister)
149 RegisterName.~StringValue();
150 }
151
152 // Helper to create a register or stack argument.
153 static inline SIArgument createArgument(bool IsReg) {
154 if (IsReg)
155 return SIArgument(IsReg);
156 return SIArgument();
157 }
158
159private:
160 // Construct a register argument.
161 SIArgument(bool) : IsRegister(true), RegisterName() {}
162};
163
164template <> struct MappingTraits<SIArgument> {
165 static void mapping(IO &YamlIO, SIArgument &A) {
166 if (YamlIO.outputting()) {
167 if (A.IsRegister)
168 YamlIO.mapRequired("reg", A.RegisterName);
169 else
170 YamlIO.mapRequired("offset", A.StackOffset);
171 } else {
172 auto Keys = YamlIO.keys();
173 if (is_contained(Keys, "reg")) {
174 A = SIArgument::createArgument(true);
175 YamlIO.mapRequired("reg", A.RegisterName);
176 } else if (is_contained(Keys, "offset"))
177 YamlIO.mapRequired("offset", A.StackOffset);
178 else
179 YamlIO.setError("missing required key 'reg' or 'offset'");
180 }
181 YamlIO.mapOptional("mask", A.Mask);
182 }
183 static const bool flow = true;
184};
185
186struct SIArgumentInfo {
187 Optional<SIArgument> PrivateSegmentBuffer;
188 Optional<SIArgument> DispatchPtr;
189 Optional<SIArgument> QueuePtr;
190 Optional<SIArgument> KernargSegmentPtr;
191 Optional<SIArgument> DispatchID;
192 Optional<SIArgument> FlatScratchInit;
193 Optional<SIArgument> PrivateSegmentSize;
194
195 Optional<SIArgument> WorkGroupIDX;
196 Optional<SIArgument> WorkGroupIDY;
197 Optional<SIArgument> WorkGroupIDZ;
198 Optional<SIArgument> WorkGroupInfo;
199 Optional<SIArgument> PrivateSegmentWaveByteOffset;
200
201 Optional<SIArgument> ImplicitArgPtr;
202 Optional<SIArgument> ImplicitBufferPtr;
203
204 Optional<SIArgument> WorkItemIDX;
205 Optional<SIArgument> WorkItemIDY;
206 Optional<SIArgument> WorkItemIDZ;
207};
208
209template <> struct MappingTraits<SIArgumentInfo> {
210 static void mapping(IO &YamlIO, SIArgumentInfo &AI) {
211 YamlIO.mapOptional("privateSegmentBuffer", AI.PrivateSegmentBuffer);
212 YamlIO.mapOptional("dispatchPtr", AI.DispatchPtr);
213 YamlIO.mapOptional("queuePtr", AI.QueuePtr);
214 YamlIO.mapOptional("kernargSegmentPtr", AI.KernargSegmentPtr);
215 YamlIO.mapOptional("dispatchID", AI.DispatchID);
216 YamlIO.mapOptional("flatScratchInit", AI.FlatScratchInit);
217 YamlIO.mapOptional("privateSegmentSize", AI.PrivateSegmentSize);
218
219 YamlIO.mapOptional("workGroupIDX", AI.WorkGroupIDX);
220 YamlIO.mapOptional("workGroupIDY", AI.WorkGroupIDY);
221 YamlIO.mapOptional("workGroupIDZ", AI.WorkGroupIDZ);
222 YamlIO.mapOptional("workGroupInfo", AI.WorkGroupInfo);
223 YamlIO.mapOptional("privateSegmentWaveByteOffset",
224 AI.PrivateSegmentWaveByteOffset);
225
226 YamlIO.mapOptional("implicitArgPtr", AI.ImplicitArgPtr);
227 YamlIO.mapOptional("implicitBufferPtr", AI.ImplicitBufferPtr);
228
229 YamlIO.mapOptional("workItemIDX", AI.WorkItemIDX);
230 YamlIO.mapOptional("workItemIDY", AI.WorkItemIDY);
231 YamlIO.mapOptional("workItemIDZ", AI.WorkItemIDZ);
232 }
233};
234
Matt Arsenault58426a32019-07-10 16:09:26 +0000235// Default to default mode for default calling convention.
236struct SIMode {
237 bool IEEE = true;
238 bool DX10Clamp = true;
239
240 SIMode() = default;
241
242
243 SIMode(const AMDGPU::SIModeRegisterDefaults &Mode) {
244 IEEE = Mode.IEEE;
245 DX10Clamp = Mode.DX10Clamp;
246 }
247
248 bool operator ==(const SIMode Other) const {
249 return IEEE == Other.IEEE && DX10Clamp == Other.DX10Clamp;
250 }
251};
252
253template <> struct MappingTraits<SIMode> {
254 static void mapping(IO &YamlIO, SIMode &Mode) {
255 YamlIO.mapOptional("ieee", Mode.IEEE, true);
256 YamlIO.mapOptional("dx10-clamp", Mode.DX10Clamp, true);
257 }
258};
259
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000260struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo {
261 uint64_t ExplicitKernArgSize = 0;
262 unsigned MaxKernArgAlign = 0;
263 unsigned LDSSize = 0;
264 bool IsEntryFunction = false;
265 bool NoSignedZerosFPMath = false;
266 bool MemoryBound = false;
267 bool WaveLimiter = false;
268
269 StringValue ScratchRSrcReg = "$private_rsrc_reg";
270 StringValue ScratchWaveOffsetReg = "$scratch_wave_offset_reg";
271 StringValue FrameOffsetReg = "$fp_reg";
272 StringValue StackPtrOffsetReg = "$sp_reg";
273
Michael Liao80177ca2019-07-03 02:00:21 +0000274 Optional<SIArgumentInfo> ArgInfo;
Matt Arsenault58426a32019-07-10 16:09:26 +0000275 SIMode Mode;
Michael Liao80177ca2019-07-03 02:00:21 +0000276
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000277 SIMachineFunctionInfo() = default;
278 SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &,
279 const TargetRegisterInfo &TRI);
280
281 void mappingImpl(yaml::IO &YamlIO) override;
282 ~SIMachineFunctionInfo() = default;
283};
284
285template <> struct MappingTraits<SIMachineFunctionInfo> {
286 static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) {
287 YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize,
288 UINT64_C(0));
289 YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign, 0u);
290 YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u);
291 YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false);
292 YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false);
293 YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false);
294 YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false);
295 YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg,
296 StringValue("$private_rsrc_reg"));
297 YamlIO.mapOptional("scratchWaveOffsetReg", MFI.ScratchWaveOffsetReg,
298 StringValue("$scratch_wave_offset_reg"));
299 YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg,
300 StringValue("$fp_reg"));
301 YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg,
302 StringValue("$sp_reg"));
Michael Liao80177ca2019-07-03 02:00:21 +0000303 YamlIO.mapOptional("argumentInfo", MFI.ArgInfo);
Matt Arsenault58426a32019-07-10 16:09:26 +0000304 YamlIO.mapOptional("mode", MFI.Mode, SIMode());
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000305 }
306};
307
308} // end namespace yaml
309
Tom Stellard75aadc22012-12-11 21:25:42 +0000310/// This class keeps track of the SPI_SP_INPUT_ADDR config register, which
311/// tells the hardware which interpolation parameters to load.
Matt Arsenault6b6a2c32016-03-11 08:00:27 +0000312class SIMachineFunctionInfo final : public AMDGPUMachineFunction {
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000313 friend class GCNTargetMachine;
314
Eugene Zelenko59e12822017-08-08 00:47:13 +0000315 unsigned TIDReg = AMDGPU::NoRegister;
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000316
317 // Registers that may be reserved for spilling purposes. These may be the same
318 // as the input registers.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000319 unsigned ScratchRSrcReg = AMDGPU::PRIVATE_RSRC_REG;
320 unsigned ScratchWaveOffsetReg = AMDGPU::SCRATCH_WAVE_OFFSET_REG;
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000321
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000322 // This is the current function's incremented size from the kernel's scratch
323 // wave offset register. For an entry function, this is exactly the same as
324 // the ScratchWaveOffsetReg.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000325 unsigned FrameOffsetReg = AMDGPU::FP_REG;
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000326
327 // Top of the stack SGPR offset derived from the ScratchWaveOffsetReg.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000328 unsigned StackPtrOffsetReg = AMDGPU::SP_REG;
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000329
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000330 AMDGPUFunctionArgInfo ArgInfo;
Matt Arsenaulte15855d2017-07-17 22:35:50 +0000331
Matt Arsenault055e4dc2019-03-29 19:14:54 +0000332 // State of MODE register, assumed FP mode.
333 AMDGPU::SIModeRegisterDefaults Mode;
334
Marek Olsakfccabaf2016-01-13 11:45:36 +0000335 // Graphics info.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000336 unsigned PSInputAddr = 0;
337 unsigned PSInputEnable = 0;
Matt Arsenaulte622dc32017-04-11 22:29:24 +0000338
Matt Arsenault71bcbd42017-08-11 20:42:08 +0000339 /// Number of bytes of arguments this function has on the stack. If the callee
340 /// is expected to restore the argument stack this should be a multiple of 16,
341 /// all usable during a tail call.
342 ///
343 /// The alternative would forbid tail call optimisation in some cases: if we
344 /// want to transfer control from a function with 8-bytes of stack-argument
345 /// space to a function with 16-bytes then misalignment of this value would
346 /// make a stack adjustment necessary, which could not be undone by the
347 /// callee.
348 unsigned BytesInStackArgArea = 0;
349
Eugene Zelenko59e12822017-08-08 00:47:13 +0000350 bool ReturnsVoid = true;
Marek Olsakfccabaf2016-01-13 11:45:36 +0000351
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +0000352 // A pair of default/requested minimum/maximum flat work group sizes.
353 // Minimum - first, maximum - second.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000354 std::pair<unsigned, unsigned> FlatWorkGroupSizes = {0, 0};
Tom Stellard79a1fd72016-04-14 16:27:07 +0000355
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +0000356 // A pair of default/requested minimum/maximum number of waves per execution
357 // unit. Minimum - first, maximum - second.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000358 std::pair<unsigned, unsigned> WavesPerEU = {0, 0};
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +0000359
Matt Arsenaulte19bc2e2017-12-29 17:18:21 +0000360 DenseMap<const Value *,
361 std::unique_ptr<const AMDGPUBufferPseudoSourceValue>> BufferPSVs;
Matt Arsenault905f3512017-12-29 17:18:14 +0000362 DenseMap<const Value *,
363 std::unique_ptr<const AMDGPUImagePseudoSourceValue>> ImagePSVs;
Matt Arsenault4d55d022019-06-19 19:55:27 +0000364 std::unique_ptr<const AMDGPUGWSResourcePseudoSourceValue> GWSResourcePSV;
Matt Arsenault905f3512017-12-29 17:18:14 +0000365
Matt Arsenault161e2b42017-04-18 20:59:40 +0000366private:
Eugene Zelenko59e12822017-08-08 00:47:13 +0000367 unsigned LDSWaveSpillSize = 0;
Eugene Zelenko59e12822017-08-08 00:47:13 +0000368 unsigned NumUserSGPRs = 0;
369 unsigned NumSystemSGPRs = 0;
Matt Arsenault49affb82015-11-25 20:55:12 +0000370
Eugene Zelenko59e12822017-08-08 00:47:13 +0000371 bool HasSpilledSGPRs = false;
372 bool HasSpilledVGPRs = false;
373 bool HasNonSpillStackObjects = false;
Matt Arsenault03ae3992018-03-29 21:30:06 +0000374 bool IsStackRealigned = false;
Tom Stellard96468902014-09-24 01:33:17 +0000375
Eugene Zelenko59e12822017-08-08 00:47:13 +0000376 unsigned NumSpilledSGPRs = 0;
377 unsigned NumSpilledVGPRs = 0;
Marek Olsak0532c192016-07-13 17:35:15 +0000378
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000379 // Feature bits required for inputs passed in user SGPRs.
380 bool PrivateSegmentBuffer : 1;
Matt Arsenault49affb82015-11-25 20:55:12 +0000381 bool DispatchPtr : 1;
382 bool QueuePtr : 1;
Matt Arsenault49affb82015-11-25 20:55:12 +0000383 bool KernargSegmentPtr : 1;
Matt Arsenault8d718dc2016-07-22 17:01:30 +0000384 bool DispatchID : 1;
Matt Arsenault49affb82015-11-25 20:55:12 +0000385 bool FlatScratchInit : 1;
Tom Stellardc149dc02013-11-27 21:23:35 +0000386
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000387 // Feature bits required for inputs passed in system SGPRs.
Matt Arsenault49affb82015-11-25 20:55:12 +0000388 bool WorkGroupIDX : 1; // Always initialized.
389 bool WorkGroupIDY : 1;
390 bool WorkGroupIDZ : 1;
391 bool WorkGroupInfo : 1;
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000392 bool PrivateSegmentWaveByteOffset : 1;
Matt Arsenault49affb82015-11-25 20:55:12 +0000393
394 bool WorkItemIDX : 1; // Always initialized.
395 bool WorkItemIDY : 1;
396 bool WorkItemIDZ : 1;
397
Tom Stellard2f3f9852017-01-25 01:25:13 +0000398 // Private memory buffer
399 // Compute directly in sgpr[0:1]
400 // Other shaders indirect 64-bits at sgpr[0:1]
Matt Arsenault10fc0622017-06-26 03:01:31 +0000401 bool ImplicitBufferPtr : 1;
Tom Stellard2f3f9852017-01-25 01:25:13 +0000402
Matt Arsenault9166ce82017-07-28 15:52:08 +0000403 // Pointer to where the ABI inserts special kernel arguments separate from the
404 // user arguments. This is an offset from the KernargSegmentPtr.
405 bool ImplicitArgPtr : 1;
406
Tim Renouf13229152017-09-29 09:49:35 +0000407 // The hard-wired high half of the address of the global information table
408 // for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since
409 // current hardware only allows a 16 bit value.
410 unsigned GITPtrHigh;
411
Matt Arsenault923712b2018-02-09 16:57:57 +0000412 unsigned HighBitsOf32BitAddress;
Nicolai Haehnle4dc3b2b2019-07-01 17:17:45 +0000413 unsigned GDSSize;
Matt Arsenault923712b2018-02-09 16:57:57 +0000414
Stanislav Mekhanoshind4b500c2018-05-31 05:36:04 +0000415 // Current recorded maximum possible occupancy.
416 unsigned Occupancy;
417
Tom Stellard44b30b42018-05-22 02:03:23 +0000418 MCPhysReg getNextUserSGPR() const;
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000419
Tom Stellard44b30b42018-05-22 02:03:23 +0000420 MCPhysReg getNextSystemSGPR() const;
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000421
Matt Arsenault49affb82015-11-25 20:55:12 +0000422public:
Tom Stellardc149dc02013-11-27 21:23:35 +0000423 struct SpilledReg {
Tom Stellard44b30b42018-05-22 02:03:23 +0000424 unsigned VGPR = 0;
Eugene Zelenko66203762017-01-21 00:53:49 +0000425 int Lane = -1;
426
427 SpilledReg() = default;
Eugene Zelenko59e12822017-08-08 00:47:13 +0000428 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) {}
Eugene Zelenko66203762017-01-21 00:53:49 +0000429
Tom Stellardc149dc02013-11-27 21:23:35 +0000430 bool hasLane() { return Lane != -1;}
Tom Stellard44b30b42018-05-22 02:03:23 +0000431 bool hasReg() { return VGPR != 0;}
Tom Stellardc149dc02013-11-27 21:23:35 +0000432 };
433
Matt Arsenault8e8f8f42017-08-02 01:52:45 +0000434 struct SGPRSpillVGPRCSR {
435 // VGPR used for SGPR spills
436 unsigned VGPR;
437
438 // If the VGPR is a CSR, the stack slot used to save/restore it in the
439 // prolog/epilog.
440 Optional<int> FI;
441
Eugene Zelenko59e12822017-08-08 00:47:13 +0000442 SGPRSpillVGPRCSR(unsigned V, Optional<int> F) : VGPR(V), FI(F) {}
Matt Arsenault8e8f8f42017-08-02 01:52:45 +0000443 };
444
Stanislav Mekhanoshin937ff6e72019-07-11 21:54:13 +0000445 struct VGPRSpillToAGPR {
446 SmallVector<MCPhysReg, 32> Lanes;
447 bool FullyAllocated = false;
448 };
449
Neil Henning0a30f332019-04-01 15:19:52 +0000450 SparseBitVector<> WWMReservedRegs;
451
452 void ReserveWWMRegister(unsigned reg) { WWMReservedRegs.set(reg); }
453
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000454private:
455 // SGPR->VGPR spilling support.
Eugene Zelenko59e12822017-08-08 00:47:13 +0000456 using SpillRegMask = std::pair<unsigned, unsigned>;
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000457
458 // Track VGPR + wave index for each subregister of the SGPR spilled to
459 // frameindex key.
460 DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills;
461 unsigned NumVGPRSpillLanes = 0;
Matt Arsenault8e8f8f42017-08-02 01:52:45 +0000462 SmallVector<SGPRSpillVGPRCSR, 2> SpillVGPRs;
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000463
Stanislav Mekhanoshin937ff6e72019-07-11 21:54:13 +0000464 DenseMap<int, VGPRSpillToAGPR> VGPRToAGPRSpills;
465
466 // AGPRs used for VGPR spills.
467 SmallVector<MCPhysReg, 32> SpillAGPR;
468
469 // VGPRs used for AGPR spills.
470 SmallVector<MCPhysReg, 32> SpillVGPR;
471
Matt Arsenault71dfb7e2019-07-08 19:03:38 +0000472public: // FIXME
473 /// If this is set, an SGPR used for save/restore of the register used for the
474 /// frame pointer.
475 unsigned SGPRForFPSaveRestoreCopy = 0;
476 Optional<int> FramePointerSaveIndex;
477
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000478public:
Tom Stellard75aadc22012-12-11 21:25:42 +0000479 SIMachineFunctionInfo(const MachineFunction &MF);
Eugene Zelenko66203762017-01-21 00:53:49 +0000480
Matt Arsenaultbc6d07c2019-03-14 22:54:43 +0000481 bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI);
482
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000483 ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const {
484 auto I = SGPRToVGPRSpills.find(FrameIndex);
485 return (I == SGPRToVGPRSpills.end()) ?
486 ArrayRef<SpilledReg>() : makeArrayRef(I->second);
487 }
488
Matt Arsenault8e8f8f42017-08-02 01:52:45 +0000489 ArrayRef<SGPRSpillVGPRCSR> getSGPRSpillVGPRs() const {
490 return SpillVGPRs;
491 }
492
Stanislav Mekhanoshin937ff6e72019-07-11 21:54:13 +0000493 ArrayRef<MCPhysReg> getAGPRSpillVGPRs() const {
494 return SpillAGPR;
495 }
496
497 ArrayRef<MCPhysReg> getVGPRSpillAGPRs() const {
498 return SpillVGPR;
499 }
500
501 MCPhysReg getVGPRToAGPRSpill(int FrameIndex, unsigned Lane) const {
502 auto I = VGPRToAGPRSpills.find(FrameIndex);
503 return (I == VGPRToAGPRSpills.end()) ? (MCPhysReg)AMDGPU::NoRegister
504 : I->second.Lanes[Lane];
505 }
506
Matt Arsenault055e4dc2019-03-29 19:14:54 +0000507 AMDGPU::SIModeRegisterDefaults getMode() const {
508 return Mode;
509 }
510
Matt Arsenault71dfb7e2019-07-08 19:03:38 +0000511 bool haveFreeLanesForSGPRSpill(const MachineFunction &MF,
512 unsigned NumLane) const;
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000513 bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI);
Stanislav Mekhanoshin937ff6e72019-07-11 21:54:13 +0000514 bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR);
515 void removeDeadFrameIndices(MachineFrameInfo &MFI);
Matt Arsenaulte0bf7d02017-02-21 19:12:08 +0000516
Tom Stellard44b30b42018-05-22 02:03:23 +0000517 bool hasCalculatedTID() const { return TIDReg != 0; };
518 unsigned getTIDReg() const { return TIDReg; };
Tom Stellard96468902014-09-24 01:33:17 +0000519 void setTIDReg(unsigned Reg) { TIDReg = Reg; }
Matt Arsenault5b22dfa2015-11-05 05:27:10 +0000520
Matt Arsenault71bcbd42017-08-11 20:42:08 +0000521 unsigned getBytesInStackArgArea() const {
522 return BytesInStackArgArea;
523 }
524
525 void setBytesInStackArgArea(unsigned Bytes) {
526 BytesInStackArgArea = Bytes;
527 }
528
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000529 // Add user SGPRs.
530 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI);
531 unsigned addDispatchPtr(const SIRegisterInfo &TRI);
532 unsigned addQueuePtr(const SIRegisterInfo &TRI);
533 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI);
Matt Arsenault8d718dc2016-07-22 17:01:30 +0000534 unsigned addDispatchID(const SIRegisterInfo &TRI);
Matt Arsenault296b8492016-02-12 06:31:30 +0000535 unsigned addFlatScratchInit(const SIRegisterInfo &TRI);
Matt Arsenault10fc0622017-06-26 03:01:31 +0000536 unsigned addImplicitBufferPtr(const SIRegisterInfo &TRI);
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000537
538 // Add system SGPRs.
539 unsigned addWorkGroupIDX() {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000540 ArgInfo.WorkGroupIDX = ArgDescriptor::createRegister(getNextSystemSGPR());
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000541 NumSystemSGPRs += 1;
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000542 return ArgInfo.WorkGroupIDX.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000543 }
544
545 unsigned addWorkGroupIDY() {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000546 ArgInfo.WorkGroupIDY = ArgDescriptor::createRegister(getNextSystemSGPR());
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000547 NumSystemSGPRs += 1;
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000548 return ArgInfo.WorkGroupIDY.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000549 }
550
551 unsigned addWorkGroupIDZ() {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000552 ArgInfo.WorkGroupIDZ = ArgDescriptor::createRegister(getNextSystemSGPR());
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000553 NumSystemSGPRs += 1;
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000554 return ArgInfo.WorkGroupIDZ.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000555 }
556
557 unsigned addWorkGroupInfo() {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000558 ArgInfo.WorkGroupInfo = ArgDescriptor::createRegister(getNextSystemSGPR());
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000559 NumSystemSGPRs += 1;
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000560 return ArgInfo.WorkGroupInfo.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000561 }
562
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000563 // Add special VGPR inputs
564 void setWorkItemIDX(ArgDescriptor Arg) {
565 ArgInfo.WorkItemIDX = Arg;
566 }
567
568 void setWorkItemIDY(ArgDescriptor Arg) {
569 ArgInfo.WorkItemIDY = Arg;
570 }
571
572 void setWorkItemIDZ(ArgDescriptor Arg) {
573 ArgInfo.WorkItemIDZ = Arg;
574 }
575
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000576 unsigned addPrivateSegmentWaveByteOffset() {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000577 ArgInfo.PrivateSegmentWaveByteOffset
578 = ArgDescriptor::createRegister(getNextSystemSGPR());
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000579 NumSystemSGPRs += 1;
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000580 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000581 }
582
Tom Stellardf110f8f2016-04-14 16:27:03 +0000583 void setPrivateSegmentWaveByteOffset(unsigned Reg) {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000584 ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg);
Tom Stellardf110f8f2016-04-14 16:27:03 +0000585 }
586
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000587 bool hasPrivateSegmentBuffer() const {
588 return PrivateSegmentBuffer;
589 }
590
Matt Arsenault49affb82015-11-25 20:55:12 +0000591 bool hasDispatchPtr() const {
592 return DispatchPtr;
593 }
594
595 bool hasQueuePtr() const {
596 return QueuePtr;
597 }
598
Matt Arsenault49affb82015-11-25 20:55:12 +0000599 bool hasKernargSegmentPtr() const {
600 return KernargSegmentPtr;
601 }
602
Matt Arsenault8d718dc2016-07-22 17:01:30 +0000603 bool hasDispatchID() const {
604 return DispatchID;
605 }
606
Matt Arsenault49affb82015-11-25 20:55:12 +0000607 bool hasFlatScratchInit() const {
608 return FlatScratchInit;
609 }
610
Matt Arsenault49affb82015-11-25 20:55:12 +0000611 bool hasWorkGroupIDX() const {
612 return WorkGroupIDX;
613 }
614
615 bool hasWorkGroupIDY() const {
616 return WorkGroupIDY;
617 }
618
619 bool hasWorkGroupIDZ() const {
620 return WorkGroupIDZ;
621 }
622
623 bool hasWorkGroupInfo() const {
624 return WorkGroupInfo;
625 }
626
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000627 bool hasPrivateSegmentWaveByteOffset() const {
628 return PrivateSegmentWaveByteOffset;
629 }
630
Matt Arsenault49affb82015-11-25 20:55:12 +0000631 bool hasWorkItemIDX() const {
632 return WorkItemIDX;
633 }
634
635 bool hasWorkItemIDY() const {
636 return WorkItemIDY;
637 }
638
639 bool hasWorkItemIDZ() const {
640 return WorkItemIDZ;
641 }
642
Matt Arsenault9166ce82017-07-28 15:52:08 +0000643 bool hasImplicitArgPtr() const {
644 return ImplicitArgPtr;
645 }
646
Matt Arsenault10fc0622017-06-26 03:01:31 +0000647 bool hasImplicitBufferPtr() const {
648 return ImplicitBufferPtr;
Tom Stellard2f3f9852017-01-25 01:25:13 +0000649 }
650
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000651 AMDGPUFunctionArgInfo &getArgInfo() {
652 return ArgInfo;
653 }
654
655 const AMDGPUFunctionArgInfo &getArgInfo() const {
656 return ArgInfo;
657 }
658
659 std::pair<const ArgDescriptor *, const TargetRegisterClass *>
660 getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const {
661 return ArgInfo.getPreloadedValue(Value);
662 }
663
Matt Arsenault1b317682019-07-01 13:44:46 +0000664 Register getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const {
Matt Arsenaultb812b7a2019-06-05 22:20:47 +0000665 auto Arg = ArgInfo.getPreloadedValue(Value).first;
Matt Arsenault1b317682019-07-01 13:44:46 +0000666 return Arg ? Arg->getRegister() : Register();
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000667 }
668
Tim Renouf13229152017-09-29 09:49:35 +0000669 unsigned getGITPtrHigh() const {
670 return GITPtrHigh;
671 }
672
Matt Arsenault923712b2018-02-09 16:57:57 +0000673 unsigned get32BitAddressHighBits() const {
674 return HighBitsOf32BitAddress;
675 }
676
Nicolai Haehnle4dc3b2b2019-07-01 17:17:45 +0000677 unsigned getGDSSize() const {
678 return GDSSize;
679 }
680
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000681 unsigned getNumUserSGPRs() const {
682 return NumUserSGPRs;
683 }
684
685 unsigned getNumPreloadedSGPRs() const {
686 return NumUserSGPRs + NumSystemSGPRs;
687 }
688
689 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000690 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister();
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000691 }
692
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000693 /// Returns the physical register reserved for use as the resource
Matt Arsenault49affb82015-11-25 20:55:12 +0000694 /// descriptor for scratch accesses.
695 unsigned getScratchRSrcReg() const {
696 return ScratchRSrcReg;
697 }
698
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000699 void setScratchRSrcReg(unsigned Reg) {
Tom Stellard44b30b42018-05-22 02:03:23 +0000700 assert(Reg != 0 && "Should never be unset");
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000701 ScratchRSrcReg = Reg;
702 }
703
704 unsigned getScratchWaveOffsetReg() const {
705 return ScratchWaveOffsetReg;
706 }
707
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000708 unsigned getFrameOffsetReg() const {
709 return FrameOffsetReg;
710 }
711
Matt Arsenaultb812b7a2019-06-05 22:20:47 +0000712 void setFrameOffsetReg(unsigned Reg) {
713 assert(Reg != 0 && "Should never be unset");
714 FrameOffsetReg = Reg;
715 }
716
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000717 void setStackPtrOffsetReg(unsigned Reg) {
Tom Stellard44b30b42018-05-22 02:03:23 +0000718 assert(Reg != 0 && "Should never be unset");
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000719 StackPtrOffsetReg = Reg;
720 }
721
Matt Arsenault1cc47f82017-07-18 16:44:56 +0000722 // Note the unset value for this is AMDGPU::SP_REG rather than
723 // NoRegister. This is mostly a workaround for MIR tests where state that
724 // can't be directly computed from the function is not preserved in serialized
725 // MIR.
Matt Arsenault1c0ae392017-04-24 18:05:16 +0000726 unsigned getStackPtrOffsetReg() const {
727 return StackPtrOffsetReg;
728 }
729
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000730 void setScratchWaveOffsetReg(unsigned Reg) {
Tom Stellard44b30b42018-05-22 02:03:23 +0000731 assert(Reg != 0 && "Should never be unset");
Matt Arsenault26f8f3d2015-11-30 21:16:03 +0000732 ScratchWaveOffsetReg = Reg;
733 }
Matt Arsenault49affb82015-11-25 20:55:12 +0000734
Matt Arsenault99c14522016-04-25 19:27:24 +0000735 unsigned getQueuePtrUserSGPR() const {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000736 return ArgInfo.QueuePtr.getRegister();
Matt Arsenault99c14522016-04-25 19:27:24 +0000737 }
738
Matt Arsenault10fc0622017-06-26 03:01:31 +0000739 unsigned getImplicitBufferPtrUserSGPR() const {
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000740 return ArgInfo.ImplicitBufferPtr.getRegister();
Tom Stellard2f3f9852017-01-25 01:25:13 +0000741 }
742
Matt Arsenault5b22dfa2015-11-05 05:27:10 +0000743 bool hasSpilledSGPRs() const {
744 return HasSpilledSGPRs;
745 }
746
747 void setHasSpilledSGPRs(bool Spill = true) {
748 HasSpilledSGPRs = Spill;
749 }
750
751 bool hasSpilledVGPRs() const {
752 return HasSpilledVGPRs;
753 }
754
755 void setHasSpilledVGPRs(bool Spill = true) {
756 HasSpilledVGPRs = Spill;
757 }
Tom Stellard96468902014-09-24 01:33:17 +0000758
Matt Arsenault296b8492016-02-12 06:31:30 +0000759 bool hasNonSpillStackObjects() const {
760 return HasNonSpillStackObjects;
761 }
762
763 void setHasNonSpillStackObjects(bool StackObject = true) {
764 HasNonSpillStackObjects = StackObject;
765 }
766
Matt Arsenault03ae3992018-03-29 21:30:06 +0000767 bool isStackRealigned() const {
768 return IsStackRealigned;
769 }
770
771 void setIsStackRealigned(bool Realigned = true) {
772 IsStackRealigned = Realigned;
773 }
774
Marek Olsak0532c192016-07-13 17:35:15 +0000775 unsigned getNumSpilledSGPRs() const {
776 return NumSpilledSGPRs;
777 }
778
779 unsigned getNumSpilledVGPRs() const {
780 return NumSpilledVGPRs;
781 }
782
783 void addToSpilledSGPRs(unsigned num) {
784 NumSpilledSGPRs += num;
785 }
786
787 void addToSpilledVGPRs(unsigned num) {
788 NumSpilledVGPRs += num;
789 }
790
Marek Olsakfccabaf2016-01-13 11:45:36 +0000791 unsigned getPSInputAddr() const {
792 return PSInputAddr;
793 }
794
Matt Arsenaulte622dc32017-04-11 22:29:24 +0000795 unsigned getPSInputEnable() const {
796 return PSInputEnable;
797 }
798
Marek Olsakfccabaf2016-01-13 11:45:36 +0000799 bool isPSInputAllocated(unsigned Index) const {
800 return PSInputAddr & (1 << Index);
801 }
802
803 void markPSInputAllocated(unsigned Index) {
804 PSInputAddr |= 1 << Index;
805 }
806
Matt Arsenaulte622dc32017-04-11 22:29:24 +0000807 void markPSInputEnabled(unsigned Index) {
808 PSInputEnable |= 1 << Index;
809 }
810
Marek Olsak8e9cc632016-01-13 17:23:09 +0000811 bool returnsVoid() const {
812 return ReturnsVoid;
813 }
814
815 void setIfReturnsVoid(bool Value) {
816 ReturnsVoid = Value;
817 }
818
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +0000819 /// \returns A pair of default/requested minimum/maximum flat work group sizes
820 /// for this function.
821 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const {
822 return FlatWorkGroupSizes;
823 }
824
825 /// \returns Default/requested minimum flat work group size for this function.
826 unsigned getMinFlatWorkGroupSize() const {
827 return FlatWorkGroupSizes.first;
828 }
829
830 /// \returns Default/requested maximum flat work group size for this function.
831 unsigned getMaxFlatWorkGroupSize() const {
832 return FlatWorkGroupSizes.second;
833 }
834
835 /// \returns A pair of default/requested minimum/maximum number of waves per
836 /// execution unit.
837 std::pair<unsigned, unsigned> getWavesPerEU() const {
838 return WavesPerEU;
839 }
840
841 /// \returns Default/requested minimum number of waves per execution unit.
842 unsigned getMinWavesPerEU() const {
843 return WavesPerEU.first;
844 }
845
846 /// \returns Default/requested maximum number of waves per execution unit.
847 unsigned getMaxWavesPerEU() const {
848 return WavesPerEU.second;
Konstantin Zhuravlyov71515e52016-04-26 17:24:40 +0000849 }
850
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000851 /// \returns SGPR used for \p Dim's work group ID.
852 unsigned getWorkGroupIDSGPR(unsigned Dim) const {
853 switch (Dim) {
854 case 0:
855 assert(hasWorkGroupIDX());
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000856 return ArgInfo.WorkGroupIDX.getRegister();
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000857 case 1:
858 assert(hasWorkGroupIDY());
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000859 return ArgInfo.WorkGroupIDY.getRegister();
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000860 case 2:
861 assert(hasWorkGroupIDZ());
Matt Arsenault8623e8d2017-08-03 23:00:29 +0000862 return ArgInfo.WorkGroupIDZ.getRegister();
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000863 }
864 llvm_unreachable("unexpected dimension");
865 }
866
Matt Arsenault161e2b42017-04-18 20:59:40 +0000867 unsigned getLDSWaveSpillSize() const {
868 return LDSWaveSpillSize;
869 }
870
Matt Arsenaulte19bc2e2017-12-29 17:18:21 +0000871 const AMDGPUBufferPseudoSourceValue *getBufferPSV(const SIInstrInfo &TII,
872 const Value *BufferRsrc) {
873 assert(BufferRsrc);
874 auto PSV = BufferPSVs.try_emplace(
875 BufferRsrc,
876 llvm::make_unique<AMDGPUBufferPseudoSourceValue>(TII));
877 return PSV.first->second.get();
Tom Stellard6f9ef142016-12-20 17:19:44 +0000878 }
879
Matt Arsenault905f3512017-12-29 17:18:14 +0000880 const AMDGPUImagePseudoSourceValue *getImagePSV(const SIInstrInfo &TII,
881 const Value *ImgRsrc) {
882 assert(ImgRsrc);
883 auto PSV = ImagePSVs.try_emplace(
884 ImgRsrc,
885 llvm::make_unique<AMDGPUImagePseudoSourceValue>(TII));
886 return PSV.first->second.get();
Tom Stellard244891d2016-12-20 15:52:17 +0000887 }
Stanislav Mekhanoshind4b500c2018-05-31 05:36:04 +0000888
Matt Arsenault4d55d022019-06-19 19:55:27 +0000889 const AMDGPUGWSResourcePseudoSourceValue *getGWSPSV(const SIInstrInfo &TII) {
890 if (!GWSResourcePSV) {
891 GWSResourcePSV =
892 llvm::make_unique<AMDGPUGWSResourcePseudoSourceValue>(TII);
893 }
894
895 return GWSResourcePSV.get();
896 }
897
Stanislav Mekhanoshind4b500c2018-05-31 05:36:04 +0000898 unsigned getOccupancy() const {
899 return Occupancy;
900 }
901
902 unsigned getMinAllowedOccupancy() const {
903 if (!isMemoryBound() && !needsWaveLimiter())
904 return Occupancy;
905 return (Occupancy < 4) ? Occupancy : 4;
906 }
907
908 void limitOccupancy(const MachineFunction &MF);
909
910 void limitOccupancy(unsigned Limit) {
911 if (Occupancy > Limit)
912 Occupancy = Limit;
913 }
914
915 void increaseOccupancy(const MachineFunction &MF, unsigned Limit) {
916 if (Occupancy < Limit)
917 Occupancy = Limit;
918 limitOccupancy(MF);
919 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000920};
921
Eugene Zelenko66203762017-01-21 00:53:49 +0000922} // end namespace llvm
Tom Stellard75aadc22012-12-11 21:25:42 +0000923
Eugene Zelenko66203762017-01-21 00:53:49 +0000924#endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H