1 //===- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface -*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 15 #define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 16 17 #include "AMDGPUMachineFunction.h" 18 #include "SIRegisterInfo.h" 19 #include <array> 20 #include <map> 21 22 namespace llvm { 23 24 class MachineRegisterInfo; 25 26 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 27 /// tells the hardware which interpolation parameters to load. 28 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 29 // FIXME: This should be removed and getPreloadedValue moved here. 30 friend struct SIRegisterInfo; 31 void anchor() override; 32 33 unsigned TIDReg; 34 35 // Registers that may be reserved for spilling purposes. These may be the same 36 // as the input registers. 37 unsigned ScratchRSrcReg; 38 unsigned ScratchWaveOffsetReg; 39 40 // Input registers setup for the HSA ABI. 41 // User SGPRs in allocation order. 42 unsigned PrivateSegmentBufferUserSGPR; 43 unsigned DispatchPtrUserSGPR; 44 unsigned QueuePtrUserSGPR; 45 unsigned KernargSegmentPtrUserSGPR; 46 unsigned DispatchIDUserSGPR; 47 unsigned FlatScratchInitUserSGPR; 48 unsigned PrivateSegmentSizeUserSGPR; 49 unsigned GridWorkGroupCountXUserSGPR; 50 unsigned GridWorkGroupCountYUserSGPR; 51 unsigned GridWorkGroupCountZUserSGPR; 52 53 // System SGPRs in allocation order. 54 unsigned WorkGroupIDXSystemSGPR; 55 unsigned WorkGroupIDYSystemSGPR; 56 unsigned WorkGroupIDZSystemSGPR; 57 unsigned WorkGroupInfoSystemSGPR; 58 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 59 60 // Graphics info. 61 unsigned PSInputAddr; 62 bool ReturnsVoid; 63 64 unsigned MaximumWorkGroupSize; 65 66 // Number of reserved VGPRs for debugger usage. 67 unsigned DebuggerReservedVGPRCount; 68 // Stack object indices for work group IDs. 69 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 70 // Stack object indices for work item IDs. 71 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 72 73 public: 74 // FIXME: Make private 75 unsigned LDSWaveSpillSize; 76 unsigned PSInputEna; 77 std::map<unsigned, unsigned> LaneVGPRs; 78 unsigned ScratchOffsetReg; 79 unsigned NumUserSGPRs; 80 unsigned NumSystemSGPRs; 81 82 private: 83 bool HasSpilledSGPRs; 84 bool HasSpilledVGPRs; 85 bool HasNonSpillStackObjects; 86 bool HasFlatInstructions; 87 88 unsigned NumSpilledSGPRs; 89 unsigned NumSpilledVGPRs; 90 91 // Feature bits required for inputs passed in user SGPRs. 92 bool PrivateSegmentBuffer : 1; 93 bool DispatchPtr : 1; 94 bool QueuePtr : 1; 95 bool DispatchID : 1; 96 bool KernargSegmentPtr : 1; 97 bool FlatScratchInit : 1; 98 bool GridWorkgroupCountX : 1; 99 bool GridWorkgroupCountY : 1; 100 bool GridWorkgroupCountZ : 1; 101 102 // Feature bits required for inputs passed in system SGPRs. 103 bool WorkGroupIDX : 1; // Always initialized. 104 bool WorkGroupIDY : 1; 105 bool WorkGroupIDZ : 1; 106 bool WorkGroupInfo : 1; 107 bool PrivateSegmentWaveByteOffset : 1; 108 109 bool WorkItemIDX : 1; // Always initialized. 110 bool WorkItemIDY : 1; 111 bool WorkItemIDZ : 1; 112 113 MCPhysReg getNextUserSGPR() const { 114 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs"); 115 return AMDGPU::SGPR0 + NumUserSGPRs; 116 } 117 118 MCPhysReg getNextSystemSGPR() const { 119 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs; 120 } 121 122 public: 123 struct SpilledReg { 124 unsigned VGPR; 125 int Lane; 126 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { } 127 SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { } 128 bool hasLane() { return Lane != -1;} 129 bool hasReg() { return VGPR != AMDGPU::NoRegister;} 130 }; 131 132 // SIMachineFunctionInfo definition 133 134 SIMachineFunctionInfo(const MachineFunction &MF); 135 SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex, 136 unsigned SubIdx); 137 bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; }; 138 unsigned getTIDReg() const { return TIDReg; }; 139 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 140 141 // Add user SGPRs. 142 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 143 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 144 unsigned addQueuePtr(const SIRegisterInfo &TRI); 145 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 146 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 147 148 // Add system SGPRs. 149 unsigned addWorkGroupIDX() { 150 WorkGroupIDXSystemSGPR = getNextSystemSGPR(); 151 NumSystemSGPRs += 1; 152 return WorkGroupIDXSystemSGPR; 153 } 154 155 unsigned addWorkGroupIDY() { 156 WorkGroupIDYSystemSGPR = getNextSystemSGPR(); 157 NumSystemSGPRs += 1; 158 return WorkGroupIDYSystemSGPR; 159 } 160 161 unsigned addWorkGroupIDZ() { 162 WorkGroupIDZSystemSGPR = getNextSystemSGPR(); 163 NumSystemSGPRs += 1; 164 return WorkGroupIDZSystemSGPR; 165 } 166 167 unsigned addWorkGroupInfo() { 168 WorkGroupInfoSystemSGPR = getNextSystemSGPR(); 169 NumSystemSGPRs += 1; 170 return WorkGroupInfoSystemSGPR; 171 } 172 173 unsigned addPrivateSegmentWaveByteOffset() { 174 PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR(); 175 NumSystemSGPRs += 1; 176 return PrivateSegmentWaveByteOffsetSystemSGPR; 177 } 178 179 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 180 PrivateSegmentWaveByteOffsetSystemSGPR = Reg; 181 } 182 183 bool hasPrivateSegmentBuffer() const { 184 return PrivateSegmentBuffer; 185 } 186 187 bool hasDispatchPtr() const { 188 return DispatchPtr; 189 } 190 191 bool hasQueuePtr() const { 192 return QueuePtr; 193 } 194 195 bool hasDispatchID() const { 196 return DispatchID; 197 } 198 199 bool hasKernargSegmentPtr() const { 200 return KernargSegmentPtr; 201 } 202 203 bool hasFlatScratchInit() const { 204 return FlatScratchInit; 205 } 206 207 bool hasGridWorkgroupCountX() const { 208 return GridWorkgroupCountX; 209 } 210 211 bool hasGridWorkgroupCountY() const { 212 return GridWorkgroupCountY; 213 } 214 215 bool hasGridWorkgroupCountZ() const { 216 return GridWorkgroupCountZ; 217 } 218 219 bool hasWorkGroupIDX() const { 220 return WorkGroupIDX; 221 } 222 223 bool hasWorkGroupIDY() const { 224 return WorkGroupIDY; 225 } 226 227 bool hasWorkGroupIDZ() const { 228 return WorkGroupIDZ; 229 } 230 231 bool hasWorkGroupInfo() const { 232 return WorkGroupInfo; 233 } 234 235 bool hasPrivateSegmentWaveByteOffset() const { 236 return PrivateSegmentWaveByteOffset; 237 } 238 239 bool hasWorkItemIDX() const { 240 return WorkItemIDX; 241 } 242 243 bool hasWorkItemIDY() const { 244 return WorkItemIDY; 245 } 246 247 bool hasWorkItemIDZ() const { 248 return WorkItemIDZ; 249 } 250 251 unsigned getNumUserSGPRs() const { 252 return NumUserSGPRs; 253 } 254 255 unsigned getNumPreloadedSGPRs() const { 256 return NumUserSGPRs + NumSystemSGPRs; 257 } 258 259 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 260 return PrivateSegmentWaveByteOffsetSystemSGPR; 261 } 262 263 /// \brief Returns the physical register reserved for use as the resource 264 /// descriptor for scratch accesses. 265 unsigned getScratchRSrcReg() const { 266 return ScratchRSrcReg; 267 } 268 269 void setScratchRSrcReg(unsigned Reg) { 270 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 271 ScratchRSrcReg = Reg; 272 } 273 274 unsigned getScratchWaveOffsetReg() const { 275 return ScratchWaveOffsetReg; 276 } 277 278 void setScratchWaveOffsetReg(unsigned Reg) { 279 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 280 ScratchWaveOffsetReg = Reg; 281 } 282 283 unsigned getQueuePtrUserSGPR() const { 284 return QueuePtrUserSGPR; 285 } 286 287 bool hasSpilledSGPRs() const { 288 return HasSpilledSGPRs; 289 } 290 291 void setHasSpilledSGPRs(bool Spill = true) { 292 HasSpilledSGPRs = Spill; 293 } 294 295 bool hasSpilledVGPRs() const { 296 return HasSpilledVGPRs; 297 } 298 299 void setHasSpilledVGPRs(bool Spill = true) { 300 HasSpilledVGPRs = Spill; 301 } 302 303 bool hasNonSpillStackObjects() const { 304 return HasNonSpillStackObjects; 305 } 306 307 void setHasNonSpillStackObjects(bool StackObject = true) { 308 HasNonSpillStackObjects = StackObject; 309 } 310 311 bool hasFlatInstructions() const { 312 return HasFlatInstructions; 313 } 314 315 void setHasFlatInstructions(bool UseFlat = true) { 316 HasFlatInstructions = UseFlat; 317 } 318 319 unsigned getNumSpilledSGPRs() const { 320 return NumSpilledSGPRs; 321 } 322 323 unsigned getNumSpilledVGPRs() const { 324 return NumSpilledVGPRs; 325 } 326 327 void addToSpilledSGPRs(unsigned num) { 328 NumSpilledSGPRs += num; 329 } 330 331 void addToSpilledVGPRs(unsigned num) { 332 NumSpilledVGPRs += num; 333 } 334 335 unsigned getPSInputAddr() const { 336 return PSInputAddr; 337 } 338 339 bool isPSInputAllocated(unsigned Index) const { 340 return PSInputAddr & (1 << Index); 341 } 342 343 void markPSInputAllocated(unsigned Index) { 344 PSInputAddr |= 1 << Index; 345 } 346 347 bool returnsVoid() const { 348 return ReturnsVoid; 349 } 350 351 void setIfReturnsVoid(bool Value) { 352 ReturnsVoid = Value; 353 } 354 355 /// \returns Number of reserved VGPRs for debugger usage. 356 unsigned getDebuggerReservedVGPRCount() const { 357 return DebuggerReservedVGPRCount; 358 } 359 360 /// \returns Stack object index for \p Dim's work group ID. 361 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 362 assert(Dim < 3); 363 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 364 } 365 366 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 367 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 368 assert(Dim < 3); 369 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 370 } 371 372 /// \returns Stack object index for \p Dim's work item ID. 373 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 374 assert(Dim < 3); 375 return DebuggerWorkItemIDStackObjectIndices[Dim]; 376 } 377 378 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 379 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 380 assert(Dim < 3); 381 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 382 } 383 384 /// \returns SGPR used for \p Dim's work group ID. 385 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 386 switch (Dim) { 387 case 0: 388 assert(hasWorkGroupIDX()); 389 return WorkGroupIDXSystemSGPR; 390 case 1: 391 assert(hasWorkGroupIDY()); 392 return WorkGroupIDYSystemSGPR; 393 case 2: 394 assert(hasWorkGroupIDZ()); 395 return WorkGroupIDZSystemSGPR; 396 } 397 llvm_unreachable("unexpected dimension"); 398 } 399 400 /// \returns VGPR used for \p Dim' work item ID. 401 unsigned getWorkItemIDVGPR(unsigned Dim) const { 402 switch (Dim) { 403 case 0: 404 assert(hasWorkItemIDX()); 405 return AMDGPU::VGPR0; 406 case 1: 407 assert(hasWorkItemIDY()); 408 return AMDGPU::VGPR1; 409 case 2: 410 assert(hasWorkItemIDZ()); 411 return AMDGPU::VGPR2; 412 } 413 llvm_unreachable("unexpected dimension"); 414 } 415 416 unsigned getMaximumWorkGroupSize(const MachineFunction &MF) const; 417 }; 418 419 } // End namespace llvm 420 421 #endif 422