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 "llvm/CodeGen/PseudoSourceValue.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/Support/ErrorHandling.h" 22 #include <array> 23 #include <cassert> 24 #include <map> 25 #include <utility> 26 27 namespace llvm { 28 29 class AMDGPUImagePseudoSourceValue : public PseudoSourceValue { 30 public: 31 explicit AMDGPUImagePseudoSourceValue() : 32 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 33 34 bool isConstant(const MachineFrameInfo *) const override { 35 // This should probably be true for most images, but we will start by being 36 // conservative. 37 return false; 38 } 39 40 bool isAliased(const MachineFrameInfo *) const override { 41 // FIXME: If we ever change image intrinsics to accept fat pointers, then 42 // this could be true for some cases. 43 return false; 44 } 45 46 bool mayAlias(const MachineFrameInfo*) const override { 47 // FIXME: If we ever change image intrinsics to accept fat pointers, then 48 // this could be true for some cases. 49 return false; 50 } 51 }; 52 53 class AMDGPUBufferPseudoSourceValue : public PseudoSourceValue { 54 public: 55 explicit AMDGPUBufferPseudoSourceValue() : 56 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 57 58 bool isConstant(const MachineFrameInfo *) const override { 59 // This should probably be true for most images, but we will start by being 60 // conservative. 61 return false; 62 } 63 64 bool isAliased(const MachineFrameInfo *) const override { 65 // FIXME: If we ever change image intrinsics to accept fat pointers, then 66 // this could be true for some cases. 67 return false; 68 } 69 70 bool mayAlias(const MachineFrameInfo*) const override { 71 // FIXME: If we ever change image intrinsics to accept fat pointers, then 72 // this could be true for some cases. 73 return false; 74 } 75 }; 76 77 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 78 /// tells the hardware which interpolation parameters to load. 79 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 80 // FIXME: This should be removed and getPreloadedValue moved here. 81 friend class SIRegisterInfo; 82 83 unsigned TIDReg; 84 85 // Registers that may be reserved for spilling purposes. These may be the same 86 // as the input registers. 87 unsigned ScratchRSrcReg; 88 unsigned ScratchWaveOffsetReg; 89 90 // Input registers for non-HSA ABI 91 unsigned PrivateMemoryPtrUserSGPR; 92 93 // Input registers setup for the HSA ABI. 94 // User SGPRs in allocation order. 95 unsigned PrivateSegmentBufferUserSGPR; 96 unsigned DispatchPtrUserSGPR; 97 unsigned QueuePtrUserSGPR; 98 unsigned KernargSegmentPtrUserSGPR; 99 unsigned DispatchIDUserSGPR; 100 unsigned FlatScratchInitUserSGPR; 101 unsigned PrivateSegmentSizeUserSGPR; 102 unsigned GridWorkGroupCountXUserSGPR; 103 unsigned GridWorkGroupCountYUserSGPR; 104 unsigned GridWorkGroupCountZUserSGPR; 105 106 // System SGPRs in allocation order. 107 unsigned WorkGroupIDXSystemSGPR; 108 unsigned WorkGroupIDYSystemSGPR; 109 unsigned WorkGroupIDZSystemSGPR; 110 unsigned WorkGroupInfoSystemSGPR; 111 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 112 113 // Graphics info. 114 unsigned PSInputAddr; 115 bool ReturnsVoid; 116 117 // A pair of default/requested minimum/maximum flat work group sizes. 118 // Minimum - first, maximum - second. 119 std::pair<unsigned, unsigned> FlatWorkGroupSizes; 120 121 // A pair of default/requested minimum/maximum number of waves per execution 122 // unit. Minimum - first, maximum - second. 123 std::pair<unsigned, unsigned> WavesPerEU; 124 125 // Stack object indices for work group IDs. 126 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 127 // Stack object indices for work item IDs. 128 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 129 130 AMDGPUBufferPseudoSourceValue BufferPSV; 131 AMDGPUImagePseudoSourceValue ImagePSV; 132 133 public: 134 // FIXME: Make private 135 unsigned LDSWaveSpillSize; 136 unsigned PSInputEna; 137 138 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 bool isPSInputAllocated(unsigned Index) const { 427 return PSInputAddr & (1 << Index); 428 } 429 430 void markPSInputAllocated(unsigned Index) { 431 PSInputAddr |= 1 << Index; 432 } 433 434 bool returnsVoid() const { 435 return ReturnsVoid; 436 } 437 438 void setIfReturnsVoid(bool Value) { 439 ReturnsVoid = Value; 440 } 441 442 /// \returns A pair of default/requested minimum/maximum flat work group sizes 443 /// for this function. 444 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 445 return FlatWorkGroupSizes; 446 } 447 448 /// \returns Default/requested minimum flat work group size for this function. 449 unsigned getMinFlatWorkGroupSize() const { 450 return FlatWorkGroupSizes.first; 451 } 452 453 /// \returns Default/requested maximum flat work group size for this function. 454 unsigned getMaxFlatWorkGroupSize() const { 455 return FlatWorkGroupSizes.second; 456 } 457 458 /// \returns A pair of default/requested minimum/maximum number of waves per 459 /// execution unit. 460 std::pair<unsigned, unsigned> getWavesPerEU() const { 461 return WavesPerEU; 462 } 463 464 /// \returns Default/requested minimum number of waves per execution unit. 465 unsigned getMinWavesPerEU() const { 466 return WavesPerEU.first; 467 } 468 469 /// \returns Default/requested maximum number of waves per execution unit. 470 unsigned getMaxWavesPerEU() const { 471 return WavesPerEU.second; 472 } 473 474 /// \returns Stack object index for \p Dim's work group ID. 475 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 476 assert(Dim < 3); 477 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 478 } 479 480 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 481 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 482 assert(Dim < 3); 483 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 484 } 485 486 /// \returns Stack object index for \p Dim's work item ID. 487 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 488 assert(Dim < 3); 489 return DebuggerWorkItemIDStackObjectIndices[Dim]; 490 } 491 492 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 493 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 494 assert(Dim < 3); 495 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 496 } 497 498 /// \returns SGPR used for \p Dim's work group ID. 499 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 500 switch (Dim) { 501 case 0: 502 assert(hasWorkGroupIDX()); 503 return WorkGroupIDXSystemSGPR; 504 case 1: 505 assert(hasWorkGroupIDY()); 506 return WorkGroupIDYSystemSGPR; 507 case 2: 508 assert(hasWorkGroupIDZ()); 509 return WorkGroupIDZSystemSGPR; 510 } 511 llvm_unreachable("unexpected dimension"); 512 } 513 514 /// \returns VGPR used for \p Dim' work item ID. 515 unsigned getWorkItemIDVGPR(unsigned Dim) const { 516 switch (Dim) { 517 case 0: 518 assert(hasWorkItemIDX()); 519 return AMDGPU::VGPR0; 520 case 1: 521 assert(hasWorkItemIDY()); 522 return AMDGPU::VGPR1; 523 case 2: 524 assert(hasWorkItemIDZ()); 525 return AMDGPU::VGPR2; 526 } 527 llvm_unreachable("unexpected dimension"); 528 } 529 530 const AMDGPUBufferPseudoSourceValue *getBufferPSV() const { 531 return &BufferPSV; 532 } 533 534 const AMDGPUImagePseudoSourceValue *getImagePSV() const { 535 return &ImagePSV; 536 } 537 }; 538 539 } // end namespace llvm 540 541 #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 542