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