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