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