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