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 "MCTargetDesc/AMDGPUMCTargetDesc.h" 19 #include "SIRegisterInfo.h" 20 #include "llvm/CodeGen/PseudoSourceValue.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include <array> 24 #include <cassert> 25 #include <map> 26 #include <utility> 27 28 namespace llvm { 29 30 class AMDGPUImagePseudoSourceValue : public PseudoSourceValue { 31 public: 32 explicit AMDGPUImagePseudoSourceValue() : 33 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 34 35 bool isConstant(const MachineFrameInfo *) const override { 36 // This should probably be true for most images, but we will start by being 37 // conservative. 38 return false; 39 } 40 41 bool isAliased(const MachineFrameInfo *) const override { 42 // FIXME: If we ever change image intrinsics to accept fat pointers, then 43 // this could be true for some cases. 44 return false; 45 } 46 47 bool mayAlias(const MachineFrameInfo*) const override { 48 // FIXME: If we ever change image intrinsics to accept fat pointers, then 49 // this could be true for some cases. 50 return false; 51 } 52 }; 53 54 class AMDGPUBufferPseudoSourceValue : public PseudoSourceValue { 55 public: 56 explicit AMDGPUBufferPseudoSourceValue() : 57 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 58 59 bool isConstant(const MachineFrameInfo *) const override { 60 // This should probably be true for most images, but we will start by being 61 // conservative. 62 return false; 63 } 64 65 bool isAliased(const MachineFrameInfo *) const override { 66 // FIXME: If we ever change image intrinsics to accept fat pointers, then 67 // this could be true for some cases. 68 return false; 69 } 70 71 bool mayAlias(const MachineFrameInfo*) const override { 72 // FIXME: If we ever change image intrinsics to accept fat pointers, then 73 // this could be true for some cases. 74 return false; 75 } 76 }; 77 78 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 79 /// tells the hardware which interpolation parameters to load. 80 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 81 // FIXME: This should be removed and getPreloadedValue moved here. 82 friend class SIRegisterInfo; 83 84 unsigned TIDReg; 85 86 // Registers that may be reserved for spilling purposes. These may be the same 87 // as the input registers. 88 unsigned ScratchRSrcReg; 89 unsigned ScratchWaveOffsetReg; 90 91 // This is the current function's incremented size from the kernel's scratch 92 // wave offset register. For an entry function, this is exactly the same as 93 // the ScratchWaveOffsetReg. 94 unsigned FrameOffsetReg; 95 96 // Top of the stack SGPR offset derived from the ScratchWaveOffsetReg. 97 unsigned StackPtrOffsetReg; 98 99 // Input registers for non-HSA ABI 100 unsigned ImplicitBufferPtrUserSGPR; 101 102 // Input registers setup for the HSA ABI. 103 // User SGPRs in allocation order. 104 unsigned PrivateSegmentBufferUserSGPR; 105 unsigned DispatchPtrUserSGPR; 106 unsigned QueuePtrUserSGPR; 107 unsigned KernargSegmentPtrUserSGPR; 108 unsigned DispatchIDUserSGPR; 109 unsigned FlatScratchInitUserSGPR; 110 unsigned PrivateSegmentSizeUserSGPR; 111 unsigned GridWorkGroupCountXUserSGPR; 112 unsigned GridWorkGroupCountYUserSGPR; 113 unsigned GridWorkGroupCountZUserSGPR; 114 115 // System SGPRs in allocation order. 116 unsigned WorkGroupIDXSystemSGPR; 117 unsigned WorkGroupIDYSystemSGPR; 118 unsigned WorkGroupIDZSystemSGPR; 119 unsigned WorkGroupInfoSystemSGPR; 120 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 121 122 // VGPR inputs. These are always v0, v1 and v2 for entry functions. 123 unsigned WorkItemIDXVGPR; 124 unsigned WorkItemIDYVGPR; 125 unsigned WorkItemIDZVGPR; 126 127 // Graphics info. 128 unsigned PSInputAddr; 129 unsigned PSInputEnable; 130 131 bool ReturnsVoid; 132 133 // A pair of default/requested minimum/maximum flat work group sizes. 134 // Minimum - first, maximum - second. 135 std::pair<unsigned, unsigned> FlatWorkGroupSizes; 136 137 // A pair of default/requested minimum/maximum number of waves per execution 138 // unit. Minimum - first, maximum - second. 139 std::pair<unsigned, unsigned> WavesPerEU; 140 141 // Stack object indices for work group IDs. 142 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 143 // Stack object indices for work item IDs. 144 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 145 146 AMDGPUBufferPseudoSourceValue BufferPSV; 147 AMDGPUImagePseudoSourceValue ImagePSV; 148 149 private: 150 unsigned LDSWaveSpillSize; 151 unsigned ScratchOffsetReg; 152 unsigned NumUserSGPRs; 153 unsigned NumSystemSGPRs; 154 155 bool HasSpilledSGPRs; 156 bool HasSpilledVGPRs; 157 bool HasNonSpillStackObjects; 158 159 unsigned NumSpilledSGPRs; 160 unsigned NumSpilledVGPRs; 161 162 // Feature bits required for inputs passed in user SGPRs. 163 bool PrivateSegmentBuffer : 1; 164 bool DispatchPtr : 1; 165 bool QueuePtr : 1; 166 bool KernargSegmentPtr : 1; 167 bool DispatchID : 1; 168 bool FlatScratchInit : 1; 169 bool GridWorkgroupCountX : 1; 170 bool GridWorkgroupCountY : 1; 171 bool GridWorkgroupCountZ : 1; 172 173 // Feature bits required for inputs passed in system SGPRs. 174 bool WorkGroupIDX : 1; // Always initialized. 175 bool WorkGroupIDY : 1; 176 bool WorkGroupIDZ : 1; 177 bool WorkGroupInfo : 1; 178 bool PrivateSegmentWaveByteOffset : 1; 179 180 bool WorkItemIDX : 1; // Always initialized. 181 bool WorkItemIDY : 1; 182 bool WorkItemIDZ : 1; 183 184 // Private memory buffer 185 // Compute directly in sgpr[0:1] 186 // Other shaders indirect 64-bits at sgpr[0:1] 187 bool ImplicitBufferPtr : 1; 188 189 // Pointer to where the ABI inserts special kernel arguments separate from the 190 // user arguments. This is an offset from the KernargSegmentPtr. 191 bool ImplicitArgPtr : 1; 192 193 MCPhysReg getNextUserSGPR() const { 194 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs"); 195 return AMDGPU::SGPR0 + NumUserSGPRs; 196 } 197 198 MCPhysReg getNextSystemSGPR() const { 199 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs; 200 } 201 202 public: 203 struct SpilledReg { 204 unsigned VGPR = AMDGPU::NoRegister; 205 int Lane = -1; 206 207 SpilledReg() = default; 208 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { } 209 210 bool hasLane() { return Lane != -1;} 211 bool hasReg() { return VGPR != AMDGPU::NoRegister;} 212 }; 213 214 private: 215 // SGPR->VGPR spilling support. 216 typedef std::pair<unsigned, unsigned> SpillRegMask; 217 218 // Track VGPR + wave index for each subregister of the SGPR spilled to 219 // frameindex key. 220 DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills; 221 unsigned NumVGPRSpillLanes = 0; 222 SmallVector<unsigned, 2> SpillVGPRs; 223 224 public: 225 226 SIMachineFunctionInfo(const MachineFunction &MF); 227 228 ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const { 229 auto I = SGPRToVGPRSpills.find(FrameIndex); 230 return (I == SGPRToVGPRSpills.end()) ? 231 ArrayRef<SpilledReg>() : makeArrayRef(I->second); 232 } 233 234 bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI); 235 void removeSGPRToVGPRFrameIndices(MachineFrameInfo &MFI); 236 237 bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; }; 238 unsigned getTIDReg() const { return TIDReg; }; 239 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 240 241 // Add user SGPRs. 242 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 243 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 244 unsigned addQueuePtr(const SIRegisterInfo &TRI); 245 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 246 unsigned addDispatchID(const SIRegisterInfo &TRI); 247 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 248 unsigned addImplicitBufferPtr(const SIRegisterInfo &TRI); 249 250 // Add system SGPRs. 251 unsigned addWorkGroupIDX() { 252 WorkGroupIDXSystemSGPR = getNextSystemSGPR(); 253 NumSystemSGPRs += 1; 254 return WorkGroupIDXSystemSGPR; 255 } 256 257 unsigned addWorkGroupIDY() { 258 WorkGroupIDYSystemSGPR = getNextSystemSGPR(); 259 NumSystemSGPRs += 1; 260 return WorkGroupIDYSystemSGPR; 261 } 262 263 unsigned addWorkGroupIDZ() { 264 WorkGroupIDZSystemSGPR = getNextSystemSGPR(); 265 NumSystemSGPRs += 1; 266 return WorkGroupIDZSystemSGPR; 267 } 268 269 unsigned addWorkGroupInfo() { 270 WorkGroupInfoSystemSGPR = getNextSystemSGPR(); 271 NumSystemSGPRs += 1; 272 return WorkGroupInfoSystemSGPR; 273 } 274 275 unsigned addPrivateSegmentWaveByteOffset() { 276 PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR(); 277 NumSystemSGPRs += 1; 278 return PrivateSegmentWaveByteOffsetSystemSGPR; 279 } 280 281 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 282 PrivateSegmentWaveByteOffsetSystemSGPR = Reg; 283 } 284 285 bool hasPrivateSegmentBuffer() const { 286 return PrivateSegmentBuffer; 287 } 288 289 bool hasDispatchPtr() const { 290 return DispatchPtr; 291 } 292 293 bool hasQueuePtr() const { 294 return QueuePtr; 295 } 296 297 bool hasKernargSegmentPtr() const { 298 return KernargSegmentPtr; 299 } 300 301 bool hasDispatchID() const { 302 return DispatchID; 303 } 304 305 bool hasFlatScratchInit() const { 306 return FlatScratchInit; 307 } 308 309 bool hasGridWorkgroupCountX() const { 310 return GridWorkgroupCountX; 311 } 312 313 bool hasGridWorkgroupCountY() const { 314 return GridWorkgroupCountY; 315 } 316 317 bool hasGridWorkgroupCountZ() const { 318 return GridWorkgroupCountZ; 319 } 320 321 bool hasWorkGroupIDX() const { 322 return WorkGroupIDX; 323 } 324 325 bool hasWorkGroupIDY() const { 326 return WorkGroupIDY; 327 } 328 329 bool hasWorkGroupIDZ() const { 330 return WorkGroupIDZ; 331 } 332 333 bool hasWorkGroupInfo() const { 334 return WorkGroupInfo; 335 } 336 337 bool hasPrivateSegmentWaveByteOffset() const { 338 return PrivateSegmentWaveByteOffset; 339 } 340 341 bool hasWorkItemIDX() const { 342 return WorkItemIDX; 343 } 344 345 bool hasWorkItemIDY() const { 346 return WorkItemIDY; 347 } 348 349 bool hasWorkItemIDZ() const { 350 return WorkItemIDZ; 351 } 352 353 bool hasImplicitArgPtr() const { 354 return ImplicitArgPtr; 355 } 356 357 bool hasImplicitBufferPtr() const { 358 return ImplicitBufferPtr; 359 } 360 361 unsigned getNumUserSGPRs() const { 362 return NumUserSGPRs; 363 } 364 365 unsigned getNumPreloadedSGPRs() const { 366 return NumUserSGPRs + NumSystemSGPRs; 367 } 368 369 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 370 return PrivateSegmentWaveByteOffsetSystemSGPR; 371 } 372 373 /// \brief Returns the physical register reserved for use as the resource 374 /// descriptor for scratch accesses. 375 unsigned getScratchRSrcReg() const { 376 return ScratchRSrcReg; 377 } 378 379 void setScratchRSrcReg(unsigned Reg) { 380 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 381 ScratchRSrcReg = Reg; 382 } 383 384 unsigned getScratchWaveOffsetReg() const { 385 return ScratchWaveOffsetReg; 386 } 387 388 unsigned getFrameOffsetReg() const { 389 return FrameOffsetReg; 390 } 391 392 void setStackPtrOffsetReg(unsigned Reg) { 393 StackPtrOffsetReg = Reg; 394 } 395 396 // Note the unset value for this is AMDGPU::SP_REG rather than 397 // NoRegister. This is mostly a workaround for MIR tests where state that 398 // can't be directly computed from the function is not preserved in serialized 399 // MIR. 400 unsigned getStackPtrOffsetReg() const { 401 return StackPtrOffsetReg; 402 } 403 404 void setScratchWaveOffsetReg(unsigned Reg) { 405 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 406 ScratchWaveOffsetReg = Reg; 407 if (isEntryFunction()) 408 FrameOffsetReg = ScratchWaveOffsetReg; 409 } 410 411 unsigned getQueuePtrUserSGPR() const { 412 return QueuePtrUserSGPR; 413 } 414 415 unsigned getImplicitBufferPtrUserSGPR() const { 416 return ImplicitBufferPtrUserSGPR; 417 } 418 419 bool hasSpilledSGPRs() const { 420 return HasSpilledSGPRs; 421 } 422 423 void setHasSpilledSGPRs(bool Spill = true) { 424 HasSpilledSGPRs = Spill; 425 } 426 427 bool hasSpilledVGPRs() const { 428 return HasSpilledVGPRs; 429 } 430 431 void setHasSpilledVGPRs(bool Spill = true) { 432 HasSpilledVGPRs = Spill; 433 } 434 435 bool hasNonSpillStackObjects() const { 436 return HasNonSpillStackObjects; 437 } 438 439 void setHasNonSpillStackObjects(bool StackObject = true) { 440 HasNonSpillStackObjects = StackObject; 441 } 442 443 unsigned getNumSpilledSGPRs() const { 444 return NumSpilledSGPRs; 445 } 446 447 unsigned getNumSpilledVGPRs() const { 448 return NumSpilledVGPRs; 449 } 450 451 void addToSpilledSGPRs(unsigned num) { 452 NumSpilledSGPRs += num; 453 } 454 455 void addToSpilledVGPRs(unsigned num) { 456 NumSpilledVGPRs += num; 457 } 458 459 unsigned getPSInputAddr() const { 460 return PSInputAddr; 461 } 462 463 unsigned getPSInputEnable() const { 464 return PSInputEnable; 465 } 466 467 bool isPSInputAllocated(unsigned Index) const { 468 return PSInputAddr & (1 << Index); 469 } 470 471 void markPSInputAllocated(unsigned Index) { 472 PSInputAddr |= 1 << Index; 473 } 474 475 void markPSInputEnabled(unsigned Index) { 476 PSInputEnable |= 1 << Index; 477 } 478 479 bool returnsVoid() const { 480 return ReturnsVoid; 481 } 482 483 void setIfReturnsVoid(bool Value) { 484 ReturnsVoid = Value; 485 } 486 487 /// \returns A pair of default/requested minimum/maximum flat work group sizes 488 /// for this function. 489 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 490 return FlatWorkGroupSizes; 491 } 492 493 /// \returns Default/requested minimum flat work group size for this function. 494 unsigned getMinFlatWorkGroupSize() const { 495 return FlatWorkGroupSizes.first; 496 } 497 498 /// \returns Default/requested maximum flat work group size for this function. 499 unsigned getMaxFlatWorkGroupSize() const { 500 return FlatWorkGroupSizes.second; 501 } 502 503 /// \returns A pair of default/requested minimum/maximum number of waves per 504 /// execution unit. 505 std::pair<unsigned, unsigned> getWavesPerEU() const { 506 return WavesPerEU; 507 } 508 509 /// \returns Default/requested minimum number of waves per execution unit. 510 unsigned getMinWavesPerEU() const { 511 return WavesPerEU.first; 512 } 513 514 /// \returns Default/requested maximum number of waves per execution unit. 515 unsigned getMaxWavesPerEU() const { 516 return WavesPerEU.second; 517 } 518 519 /// \returns Stack object index for \p Dim's work group ID. 520 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 521 assert(Dim < 3); 522 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 523 } 524 525 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 526 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 527 assert(Dim < 3); 528 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 529 } 530 531 /// \returns Stack object index for \p Dim's work item ID. 532 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 533 assert(Dim < 3); 534 return DebuggerWorkItemIDStackObjectIndices[Dim]; 535 } 536 537 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 538 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 539 assert(Dim < 3); 540 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 541 } 542 543 /// \returns SGPR used for \p Dim's work group ID. 544 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 545 switch (Dim) { 546 case 0: 547 assert(hasWorkGroupIDX()); 548 return WorkGroupIDXSystemSGPR; 549 case 1: 550 assert(hasWorkGroupIDY()); 551 return WorkGroupIDYSystemSGPR; 552 case 2: 553 assert(hasWorkGroupIDZ()); 554 return WorkGroupIDZSystemSGPR; 555 } 556 llvm_unreachable("unexpected dimension"); 557 } 558 559 /// \returns VGPR used for \p Dim' work item ID. 560 unsigned getWorkItemIDVGPR(unsigned Dim) const { 561 switch (Dim) { 562 case 0: 563 assert(hasWorkItemIDX()); 564 return AMDGPU::VGPR0; 565 case 1: 566 assert(hasWorkItemIDY()); 567 return AMDGPU::VGPR1; 568 case 2: 569 assert(hasWorkItemIDZ()); 570 return AMDGPU::VGPR2; 571 } 572 llvm_unreachable("unexpected dimension"); 573 } 574 575 unsigned getLDSWaveSpillSize() const { 576 return LDSWaveSpillSize; 577 } 578 579 const AMDGPUBufferPseudoSourceValue *getBufferPSV() const { 580 return &BufferPSV; 581 } 582 583 const AMDGPUImagePseudoSourceValue *getImagePSV() const { 584 return &ImagePSV; 585 } 586 }; 587 588 } // end namespace llvm 589 590 #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 591