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 "MCTargetDesc/AMDGPUMCTargetDesc.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 // Input registers for non-HSA ABI 92 unsigned PrivateMemoryPtrUserSGPR; 93 94 // Input registers setup for the HSA ABI. 95 // User SGPRs in allocation order. 96 unsigned PrivateSegmentBufferUserSGPR; 97 unsigned DispatchPtrUserSGPR; 98 unsigned QueuePtrUserSGPR; 99 unsigned KernargSegmentPtrUserSGPR; 100 unsigned DispatchIDUserSGPR; 101 unsigned FlatScratchInitUserSGPR; 102 unsigned PrivateSegmentSizeUserSGPR; 103 unsigned GridWorkGroupCountXUserSGPR; 104 unsigned GridWorkGroupCountYUserSGPR; 105 unsigned GridWorkGroupCountZUserSGPR; 106 107 // System SGPRs in allocation order. 108 unsigned WorkGroupIDXSystemSGPR; 109 unsigned WorkGroupIDYSystemSGPR; 110 unsigned WorkGroupIDZSystemSGPR; 111 unsigned WorkGroupInfoSystemSGPR; 112 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 113 114 // Graphics info. 115 unsigned PSInputAddr; 116 unsigned PSInputEnable; 117 118 bool ReturnsVoid; 119 120 // A pair of default/requested minimum/maximum flat work group sizes. 121 // Minimum - first, maximum - second. 122 std::pair<unsigned, unsigned> FlatWorkGroupSizes; 123 124 // A pair of default/requested minimum/maximum number of waves per execution 125 // unit. Minimum - first, maximum - second. 126 std::pair<unsigned, unsigned> WavesPerEU; 127 128 // Stack object indices for work group IDs. 129 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 130 // Stack object indices for work item IDs. 131 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 132 133 AMDGPUBufferPseudoSourceValue BufferPSV; 134 AMDGPUImagePseudoSourceValue ImagePSV; 135 136 public: 137 // FIXME: Make private 138 unsigned LDSWaveSpillSize; 139 unsigned ScratchOffsetReg; 140 unsigned NumUserSGPRs; 141 unsigned NumSystemSGPRs; 142 143 private: 144 bool HasSpilledSGPRs; 145 bool HasSpilledVGPRs; 146 bool HasNonSpillStackObjects; 147 148 unsigned NumSpilledSGPRs; 149 unsigned NumSpilledVGPRs; 150 151 // Feature bits required for inputs passed in user SGPRs. 152 bool PrivateSegmentBuffer : 1; 153 bool DispatchPtr : 1; 154 bool QueuePtr : 1; 155 bool KernargSegmentPtr : 1; 156 bool DispatchID : 1; 157 bool FlatScratchInit : 1; 158 bool GridWorkgroupCountX : 1; 159 bool GridWorkgroupCountY : 1; 160 bool GridWorkgroupCountZ : 1; 161 162 // Feature bits required for inputs passed in system SGPRs. 163 bool WorkGroupIDX : 1; // Always initialized. 164 bool WorkGroupIDY : 1; 165 bool WorkGroupIDZ : 1; 166 bool WorkGroupInfo : 1; 167 bool PrivateSegmentWaveByteOffset : 1; 168 169 bool WorkItemIDX : 1; // Always initialized. 170 bool WorkItemIDY : 1; 171 bool WorkItemIDZ : 1; 172 173 // Private memory buffer 174 // Compute directly in sgpr[0:1] 175 // Other shaders indirect 64-bits at sgpr[0:1] 176 bool PrivateMemoryInputPtr : 1; 177 178 MCPhysReg getNextUserSGPR() const { 179 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs"); 180 return AMDGPU::SGPR0 + NumUserSGPRs; 181 } 182 183 MCPhysReg getNextSystemSGPR() const { 184 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs; 185 } 186 187 public: 188 struct SpilledReg { 189 unsigned VGPR = AMDGPU::NoRegister; 190 int Lane = -1; 191 192 SpilledReg() = default; 193 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { } 194 195 bool hasLane() { return Lane != -1;} 196 bool hasReg() { return VGPR != AMDGPU::NoRegister;} 197 }; 198 199 private: 200 // SGPR->VGPR spilling support. 201 typedef std::pair<unsigned, unsigned> SpillRegMask; 202 203 // Track VGPR + wave index for each subregister of the SGPR spilled to 204 // frameindex key. 205 DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills; 206 unsigned NumVGPRSpillLanes = 0; 207 SmallVector<unsigned, 2> SpillVGPRs; 208 209 public: 210 211 SIMachineFunctionInfo(const MachineFunction &MF); 212 213 ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const { 214 auto I = SGPRToVGPRSpills.find(FrameIndex); 215 return (I == SGPRToVGPRSpills.end()) ? 216 ArrayRef<SpilledReg>() : makeArrayRef(I->second); 217 } 218 219 bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI); 220 void removeSGPRToVGPRFrameIndices(MachineFrameInfo &MFI); 221 222 bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; }; 223 unsigned getTIDReg() const { return TIDReg; }; 224 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 225 226 // Add user SGPRs. 227 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 228 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 229 unsigned addQueuePtr(const SIRegisterInfo &TRI); 230 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 231 unsigned addDispatchID(const SIRegisterInfo &TRI); 232 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 233 unsigned addPrivateMemoryPtr(const SIRegisterInfo &TRI); 234 235 // Add system SGPRs. 236 unsigned addWorkGroupIDX() { 237 WorkGroupIDXSystemSGPR = getNextSystemSGPR(); 238 NumSystemSGPRs += 1; 239 return WorkGroupIDXSystemSGPR; 240 } 241 242 unsigned addWorkGroupIDY() { 243 WorkGroupIDYSystemSGPR = getNextSystemSGPR(); 244 NumSystemSGPRs += 1; 245 return WorkGroupIDYSystemSGPR; 246 } 247 248 unsigned addWorkGroupIDZ() { 249 WorkGroupIDZSystemSGPR = getNextSystemSGPR(); 250 NumSystemSGPRs += 1; 251 return WorkGroupIDZSystemSGPR; 252 } 253 254 unsigned addWorkGroupInfo() { 255 WorkGroupInfoSystemSGPR = getNextSystemSGPR(); 256 NumSystemSGPRs += 1; 257 return WorkGroupInfoSystemSGPR; 258 } 259 260 unsigned addPrivateSegmentWaveByteOffset() { 261 PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR(); 262 NumSystemSGPRs += 1; 263 return PrivateSegmentWaveByteOffsetSystemSGPR; 264 } 265 266 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 267 PrivateSegmentWaveByteOffsetSystemSGPR = Reg; 268 } 269 270 bool hasPrivateSegmentBuffer() const { 271 return PrivateSegmentBuffer; 272 } 273 274 bool hasDispatchPtr() const { 275 return DispatchPtr; 276 } 277 278 bool hasQueuePtr() const { 279 return QueuePtr; 280 } 281 282 bool hasKernargSegmentPtr() const { 283 return KernargSegmentPtr; 284 } 285 286 bool hasDispatchID() const { 287 return DispatchID; 288 } 289 290 bool hasFlatScratchInit() const { 291 return FlatScratchInit; 292 } 293 294 bool hasGridWorkgroupCountX() const { 295 return GridWorkgroupCountX; 296 } 297 298 bool hasGridWorkgroupCountY() const { 299 return GridWorkgroupCountY; 300 } 301 302 bool hasGridWorkgroupCountZ() const { 303 return GridWorkgroupCountZ; 304 } 305 306 bool hasWorkGroupIDX() const { 307 return WorkGroupIDX; 308 } 309 310 bool hasWorkGroupIDY() const { 311 return WorkGroupIDY; 312 } 313 314 bool hasWorkGroupIDZ() const { 315 return WorkGroupIDZ; 316 } 317 318 bool hasWorkGroupInfo() const { 319 return WorkGroupInfo; 320 } 321 322 bool hasPrivateSegmentWaveByteOffset() const { 323 return PrivateSegmentWaveByteOffset; 324 } 325 326 bool hasWorkItemIDX() const { 327 return WorkItemIDX; 328 } 329 330 bool hasWorkItemIDY() const { 331 return WorkItemIDY; 332 } 333 334 bool hasWorkItemIDZ() const { 335 return WorkItemIDZ; 336 } 337 338 bool hasPrivateMemoryInputPtr() const { 339 return PrivateMemoryInputPtr; 340 } 341 342 unsigned getNumUserSGPRs() const { 343 return NumUserSGPRs; 344 } 345 346 unsigned getNumPreloadedSGPRs() const { 347 return NumUserSGPRs + NumSystemSGPRs; 348 } 349 350 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 351 return PrivateSegmentWaveByteOffsetSystemSGPR; 352 } 353 354 /// \brief Returns the physical register reserved for use as the resource 355 /// descriptor for scratch accesses. 356 unsigned getScratchRSrcReg() const { 357 return ScratchRSrcReg; 358 } 359 360 void setScratchRSrcReg(unsigned Reg) { 361 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 362 ScratchRSrcReg = Reg; 363 } 364 365 unsigned getScratchWaveOffsetReg() const { 366 return ScratchWaveOffsetReg; 367 } 368 369 void setScratchWaveOffsetReg(unsigned Reg) { 370 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 371 ScratchWaveOffsetReg = Reg; 372 } 373 374 unsigned getQueuePtrUserSGPR() const { 375 return QueuePtrUserSGPR; 376 } 377 378 unsigned getPrivateMemoryPtrUserSGPR() const { 379 return PrivateMemoryPtrUserSGPR; 380 } 381 382 bool hasSpilledSGPRs() const { 383 return HasSpilledSGPRs; 384 } 385 386 void setHasSpilledSGPRs(bool Spill = true) { 387 HasSpilledSGPRs = Spill; 388 } 389 390 bool hasSpilledVGPRs() const { 391 return HasSpilledVGPRs; 392 } 393 394 void setHasSpilledVGPRs(bool Spill = true) { 395 HasSpilledVGPRs = Spill; 396 } 397 398 bool hasNonSpillStackObjects() const { 399 return HasNonSpillStackObjects; 400 } 401 402 void setHasNonSpillStackObjects(bool StackObject = true) { 403 HasNonSpillStackObjects = StackObject; 404 } 405 406 unsigned getNumSpilledSGPRs() const { 407 return NumSpilledSGPRs; 408 } 409 410 unsigned getNumSpilledVGPRs() const { 411 return NumSpilledVGPRs; 412 } 413 414 void addToSpilledSGPRs(unsigned num) { 415 NumSpilledSGPRs += num; 416 } 417 418 void addToSpilledVGPRs(unsigned num) { 419 NumSpilledVGPRs += num; 420 } 421 422 unsigned getPSInputAddr() const { 423 return PSInputAddr; 424 } 425 426 unsigned getPSInputEnable() const { 427 return PSInputEnable; 428 } 429 430 bool isPSInputAllocated(unsigned Index) const { 431 return PSInputAddr & (1 << Index); 432 } 433 434 void markPSInputAllocated(unsigned Index) { 435 PSInputAddr |= 1 << Index; 436 } 437 438 void markPSInputEnabled(unsigned Index) { 439 PSInputEnable |= 1 << Index; 440 } 441 442 bool returnsVoid() const { 443 return ReturnsVoid; 444 } 445 446 void setIfReturnsVoid(bool Value) { 447 ReturnsVoid = Value; 448 } 449 450 /// \returns A pair of default/requested minimum/maximum flat work group sizes 451 /// for this function. 452 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 453 return FlatWorkGroupSizes; 454 } 455 456 /// \returns Default/requested minimum flat work group size for this function. 457 unsigned getMinFlatWorkGroupSize() const { 458 return FlatWorkGroupSizes.first; 459 } 460 461 /// \returns Default/requested maximum flat work group size for this function. 462 unsigned getMaxFlatWorkGroupSize() const { 463 return FlatWorkGroupSizes.second; 464 } 465 466 /// \returns A pair of default/requested minimum/maximum number of waves per 467 /// execution unit. 468 std::pair<unsigned, unsigned> getWavesPerEU() const { 469 return WavesPerEU; 470 } 471 472 /// \returns Default/requested minimum number of waves per execution unit. 473 unsigned getMinWavesPerEU() const { 474 return WavesPerEU.first; 475 } 476 477 /// \returns Default/requested maximum number of waves per execution unit. 478 unsigned getMaxWavesPerEU() const { 479 return WavesPerEU.second; 480 } 481 482 /// \returns Stack object index for \p Dim's work group ID. 483 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 484 assert(Dim < 3); 485 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 486 } 487 488 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 489 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 490 assert(Dim < 3); 491 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 492 } 493 494 /// \returns Stack object index for \p Dim's work item ID. 495 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 496 assert(Dim < 3); 497 return DebuggerWorkItemIDStackObjectIndices[Dim]; 498 } 499 500 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 501 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 502 assert(Dim < 3); 503 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 504 } 505 506 /// \returns SGPR used for \p Dim's work group ID. 507 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 508 switch (Dim) { 509 case 0: 510 assert(hasWorkGroupIDX()); 511 return WorkGroupIDXSystemSGPR; 512 case 1: 513 assert(hasWorkGroupIDY()); 514 return WorkGroupIDYSystemSGPR; 515 case 2: 516 assert(hasWorkGroupIDZ()); 517 return WorkGroupIDZSystemSGPR; 518 } 519 llvm_unreachable("unexpected dimension"); 520 } 521 522 /// \returns VGPR used for \p Dim' work item ID. 523 unsigned getWorkItemIDVGPR(unsigned Dim) const { 524 switch (Dim) { 525 case 0: 526 assert(hasWorkItemIDX()); 527 return AMDGPU::VGPR0; 528 case 1: 529 assert(hasWorkItemIDY()); 530 return AMDGPU::VGPR1; 531 case 2: 532 assert(hasWorkItemIDZ()); 533 return AMDGPU::VGPR2; 534 } 535 llvm_unreachable("unexpected dimension"); 536 } 537 538 const AMDGPUBufferPseudoSourceValue *getBufferPSV() const { 539 return &BufferPSV; 540 } 541 542 const AMDGPUImagePseudoSourceValue *getImagePSV() const { 543 return &ImagePSV; 544 } 545 }; 546 547 } // end namespace llvm 548 549 #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 550