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