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 <array> 20 #include <map> 21 22 namespace llvm { 23 24 class MachineRegisterInfo; 25 26 class AMDGPUImagePseudoSourceValue : public PseudoSourceValue { 27 public: 28 explicit AMDGPUImagePseudoSourceValue() : 29 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 30 31 bool isConstant(const MachineFrameInfo *) const override { 32 // This should probably be true for most images, but we will start by being 33 // conservative. 34 return false; 35 } 36 37 bool isAliased(const MachineFrameInfo *) const override { 38 // FIXME: If we ever change image intrinsics to accept fat pointers, then 39 // this could be true for some cases. 40 return false; 41 } 42 43 bool mayAlias(const MachineFrameInfo*) const override { 44 // FIXME: If we ever change image intrinsics to accept fat pointers, then 45 // this could be true for some cases. 46 return false; 47 } 48 }; 49 50 class AMDGPUBufferPseudoSourceValue : public PseudoSourceValue { 51 public: 52 explicit AMDGPUBufferPseudoSourceValue() : 53 PseudoSourceValue(PseudoSourceValue::TargetCustom) { } 54 55 bool isConstant(const MachineFrameInfo *) const override { 56 // This should probably be true for most images, but we will start by being 57 // conservative. 58 return false; 59 } 60 61 bool isAliased(const MachineFrameInfo *) const override { 62 // FIXME: If we ever change image intrinsics to accept fat pointers, then 63 // this could be true for some cases. 64 return false; 65 } 66 67 bool mayAlias(const MachineFrameInfo*) const override { 68 // FIXME: If we ever change image intrinsics to accept fat pointers, then 69 // this could be true for some cases. 70 return false; 71 } 72 }; 73 74 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 75 /// tells the hardware which interpolation parameters to load. 76 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 77 // FIXME: This should be removed and getPreloadedValue moved here. 78 friend class SIRegisterInfo; 79 80 unsigned TIDReg; 81 82 // Registers that may be reserved for spilling purposes. These may be the same 83 // as the input registers. 84 unsigned ScratchRSrcReg; 85 unsigned ScratchWaveOffsetReg; 86 87 // Input registers for non-HSA ABI 88 unsigned PrivateMemoryPtrUserSGPR; 89 90 // Input registers setup for the HSA ABI. 91 // User SGPRs in allocation order. 92 unsigned PrivateSegmentBufferUserSGPR; 93 unsigned DispatchPtrUserSGPR; 94 unsigned QueuePtrUserSGPR; 95 unsigned KernargSegmentPtrUserSGPR; 96 unsigned DispatchIDUserSGPR; 97 unsigned FlatScratchInitUserSGPR; 98 unsigned PrivateSegmentSizeUserSGPR; 99 unsigned GridWorkGroupCountXUserSGPR; 100 unsigned GridWorkGroupCountYUserSGPR; 101 unsigned GridWorkGroupCountZUserSGPR; 102 103 // System SGPRs in allocation order. 104 unsigned WorkGroupIDXSystemSGPR; 105 unsigned WorkGroupIDYSystemSGPR; 106 unsigned WorkGroupIDZSystemSGPR; 107 unsigned WorkGroupInfoSystemSGPR; 108 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 109 110 // Graphics info. 111 unsigned PSInputAddr; 112 bool ReturnsVoid; 113 114 // A pair of default/requested minimum/maximum flat work group sizes. 115 // Minimum - first, maximum - second. 116 std::pair<unsigned, unsigned> FlatWorkGroupSizes; 117 118 // A pair of default/requested minimum/maximum number of waves per execution 119 // unit. Minimum - first, maximum - second. 120 std::pair<unsigned, unsigned> WavesPerEU; 121 122 // Stack object indices for work group IDs. 123 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 124 // Stack object indices for work item IDs. 125 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 126 127 AMDGPUBufferPseudoSourceValue BufferPSV; 128 AMDGPUImagePseudoSourceValue ImagePSV; 129 130 public: 131 // FIXME: Make private 132 unsigned LDSWaveSpillSize; 133 unsigned PSInputEna; 134 std::map<unsigned, unsigned> LaneVGPRs; 135 unsigned ScratchOffsetReg; 136 unsigned NumUserSGPRs; 137 unsigned NumSystemSGPRs; 138 139 private: 140 bool HasSpilledSGPRs; 141 bool HasSpilledVGPRs; 142 bool HasNonSpillStackObjects; 143 144 unsigned NumSpilledSGPRs; 145 unsigned NumSpilledVGPRs; 146 147 // Feature bits required for inputs passed in user SGPRs. 148 bool PrivateSegmentBuffer : 1; 149 bool DispatchPtr : 1; 150 bool QueuePtr : 1; 151 bool KernargSegmentPtr : 1; 152 bool DispatchID : 1; 153 bool FlatScratchInit : 1; 154 bool GridWorkgroupCountX : 1; 155 bool GridWorkgroupCountY : 1; 156 bool GridWorkgroupCountZ : 1; 157 158 // Feature bits required for inputs passed in system SGPRs. 159 bool WorkGroupIDX : 1; // Always initialized. 160 bool WorkGroupIDY : 1; 161 bool WorkGroupIDZ : 1; 162 bool WorkGroupInfo : 1; 163 bool PrivateSegmentWaveByteOffset : 1; 164 165 bool WorkItemIDX : 1; // Always initialized. 166 bool WorkItemIDY : 1; 167 bool WorkItemIDZ : 1; 168 169 // Private memory buffer 170 // Compute directly in sgpr[0:1] 171 // Other shaders indirect 64-bits at sgpr[0:1] 172 bool PrivateMemoryInputPtr : 1; 173 174 MCPhysReg getNextUserSGPR() const { 175 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs"); 176 return AMDGPU::SGPR0 + NumUserSGPRs; 177 } 178 179 MCPhysReg getNextSystemSGPR() const { 180 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs; 181 } 182 183 public: 184 struct SpilledReg { 185 unsigned VGPR; 186 int Lane; 187 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { } 188 SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { } 189 bool hasLane() { return Lane != -1;} 190 bool hasReg() { return VGPR != AMDGPU::NoRegister;} 191 }; 192 193 // SIMachineFunctionInfo definition 194 195 SIMachineFunctionInfo(const MachineFunction &MF); 196 SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex, 197 unsigned SubIdx); 198 bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; }; 199 unsigned getTIDReg() const { return TIDReg; }; 200 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 201 202 // Add user SGPRs. 203 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 204 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 205 unsigned addQueuePtr(const SIRegisterInfo &TRI); 206 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 207 unsigned addDispatchID(const SIRegisterInfo &TRI); 208 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 209 unsigned addPrivateMemoryPtr(const SIRegisterInfo &TRI); 210 211 // Add system SGPRs. 212 unsigned addWorkGroupIDX() { 213 WorkGroupIDXSystemSGPR = getNextSystemSGPR(); 214 NumSystemSGPRs += 1; 215 return WorkGroupIDXSystemSGPR; 216 } 217 218 unsigned addWorkGroupIDY() { 219 WorkGroupIDYSystemSGPR = getNextSystemSGPR(); 220 NumSystemSGPRs += 1; 221 return WorkGroupIDYSystemSGPR; 222 } 223 224 unsigned addWorkGroupIDZ() { 225 WorkGroupIDZSystemSGPR = getNextSystemSGPR(); 226 NumSystemSGPRs += 1; 227 return WorkGroupIDZSystemSGPR; 228 } 229 230 unsigned addWorkGroupInfo() { 231 WorkGroupInfoSystemSGPR = getNextSystemSGPR(); 232 NumSystemSGPRs += 1; 233 return WorkGroupInfoSystemSGPR; 234 } 235 236 unsigned addPrivateSegmentWaveByteOffset() { 237 PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR(); 238 NumSystemSGPRs += 1; 239 return PrivateSegmentWaveByteOffsetSystemSGPR; 240 } 241 242 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 243 PrivateSegmentWaveByteOffsetSystemSGPR = Reg; 244 } 245 246 bool hasPrivateSegmentBuffer() const { 247 return PrivateSegmentBuffer; 248 } 249 250 bool hasDispatchPtr() const { 251 return DispatchPtr; 252 } 253 254 bool hasQueuePtr() const { 255 return QueuePtr; 256 } 257 258 bool hasKernargSegmentPtr() const { 259 return KernargSegmentPtr; 260 } 261 262 bool hasDispatchID() const { 263 return DispatchID; 264 } 265 266 bool hasFlatScratchInit() const { 267 return FlatScratchInit; 268 } 269 270 bool hasGridWorkgroupCountX() const { 271 return GridWorkgroupCountX; 272 } 273 274 bool hasGridWorkgroupCountY() const { 275 return GridWorkgroupCountY; 276 } 277 278 bool hasGridWorkgroupCountZ() const { 279 return GridWorkgroupCountZ; 280 } 281 282 bool hasWorkGroupIDX() const { 283 return WorkGroupIDX; 284 } 285 286 bool hasWorkGroupIDY() const { 287 return WorkGroupIDY; 288 } 289 290 bool hasWorkGroupIDZ() const { 291 return WorkGroupIDZ; 292 } 293 294 bool hasWorkGroupInfo() const { 295 return WorkGroupInfo; 296 } 297 298 bool hasPrivateSegmentWaveByteOffset() const { 299 return PrivateSegmentWaveByteOffset; 300 } 301 302 bool hasWorkItemIDX() const { 303 return WorkItemIDX; 304 } 305 306 bool hasWorkItemIDY() const { 307 return WorkItemIDY; 308 } 309 310 bool hasWorkItemIDZ() const { 311 return WorkItemIDZ; 312 } 313 314 bool hasPrivateMemoryInputPtr() const { 315 return PrivateMemoryInputPtr; 316 } 317 318 unsigned getNumUserSGPRs() const { 319 return NumUserSGPRs; 320 } 321 322 unsigned getNumPreloadedSGPRs() const { 323 return NumUserSGPRs + NumSystemSGPRs; 324 } 325 326 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 327 return PrivateSegmentWaveByteOffsetSystemSGPR; 328 } 329 330 /// \brief Returns the physical register reserved for use as the resource 331 /// descriptor for scratch accesses. 332 unsigned getScratchRSrcReg() const { 333 return ScratchRSrcReg; 334 } 335 336 void setScratchRSrcReg(unsigned Reg) { 337 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 338 ScratchRSrcReg = Reg; 339 } 340 341 unsigned getScratchWaveOffsetReg() const { 342 return ScratchWaveOffsetReg; 343 } 344 345 void setScratchWaveOffsetReg(unsigned Reg) { 346 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 347 ScratchWaveOffsetReg = Reg; 348 } 349 350 unsigned getQueuePtrUserSGPR() const { 351 return QueuePtrUserSGPR; 352 } 353 354 unsigned getPrivateMemoryPtrUserSGPR() const { 355 return PrivateMemoryPtrUserSGPR; 356 } 357 358 bool hasSpilledSGPRs() const { 359 return HasSpilledSGPRs; 360 } 361 362 void setHasSpilledSGPRs(bool Spill = true) { 363 HasSpilledSGPRs = Spill; 364 } 365 366 bool hasSpilledVGPRs() const { 367 return HasSpilledVGPRs; 368 } 369 370 void setHasSpilledVGPRs(bool Spill = true) { 371 HasSpilledVGPRs = Spill; 372 } 373 374 bool hasNonSpillStackObjects() const { 375 return HasNonSpillStackObjects; 376 } 377 378 void setHasNonSpillStackObjects(bool StackObject = true) { 379 HasNonSpillStackObjects = StackObject; 380 } 381 382 unsigned getNumSpilledSGPRs() const { 383 return NumSpilledSGPRs; 384 } 385 386 unsigned getNumSpilledVGPRs() const { 387 return NumSpilledVGPRs; 388 } 389 390 void addToSpilledSGPRs(unsigned num) { 391 NumSpilledSGPRs += num; 392 } 393 394 void addToSpilledVGPRs(unsigned num) { 395 NumSpilledVGPRs += num; 396 } 397 398 unsigned getPSInputAddr() const { 399 return PSInputAddr; 400 } 401 402 bool isPSInputAllocated(unsigned Index) const { 403 return PSInputAddr & (1 << Index); 404 } 405 406 void markPSInputAllocated(unsigned Index) { 407 PSInputAddr |= 1 << Index; 408 } 409 410 bool returnsVoid() const { 411 return ReturnsVoid; 412 } 413 414 void setIfReturnsVoid(bool Value) { 415 ReturnsVoid = Value; 416 } 417 418 /// \returns A pair of default/requested minimum/maximum flat work group sizes 419 /// for this function. 420 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 421 return FlatWorkGroupSizes; 422 } 423 424 /// \returns Default/requested minimum flat work group size for this function. 425 unsigned getMinFlatWorkGroupSize() const { 426 return FlatWorkGroupSizes.first; 427 } 428 429 /// \returns Default/requested maximum flat work group size for this function. 430 unsigned getMaxFlatWorkGroupSize() const { 431 return FlatWorkGroupSizes.second; 432 } 433 434 /// \returns A pair of default/requested minimum/maximum number of waves per 435 /// execution unit. 436 std::pair<unsigned, unsigned> getWavesPerEU() const { 437 return WavesPerEU; 438 } 439 440 /// \returns Default/requested minimum number of waves per execution unit. 441 unsigned getMinWavesPerEU() const { 442 return WavesPerEU.first; 443 } 444 445 /// \returns Default/requested maximum number of waves per execution unit. 446 unsigned getMaxWavesPerEU() const { 447 return WavesPerEU.second; 448 } 449 450 /// \returns Stack object index for \p Dim's work group ID. 451 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 452 assert(Dim < 3); 453 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 454 } 455 456 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 457 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 458 assert(Dim < 3); 459 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 460 } 461 462 /// \returns Stack object index for \p Dim's work item ID. 463 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 464 assert(Dim < 3); 465 return DebuggerWorkItemIDStackObjectIndices[Dim]; 466 } 467 468 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 469 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 470 assert(Dim < 3); 471 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 472 } 473 474 /// \returns SGPR used for \p Dim's work group ID. 475 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 476 switch (Dim) { 477 case 0: 478 assert(hasWorkGroupIDX()); 479 return WorkGroupIDXSystemSGPR; 480 case 1: 481 assert(hasWorkGroupIDY()); 482 return WorkGroupIDYSystemSGPR; 483 case 2: 484 assert(hasWorkGroupIDZ()); 485 return WorkGroupIDZSystemSGPR; 486 } 487 llvm_unreachable("unexpected dimension"); 488 } 489 490 /// \returns VGPR used for \p Dim' work item ID. 491 unsigned getWorkItemIDVGPR(unsigned Dim) const { 492 switch (Dim) { 493 case 0: 494 assert(hasWorkItemIDX()); 495 return AMDGPU::VGPR0; 496 case 1: 497 assert(hasWorkItemIDY()); 498 return AMDGPU::VGPR1; 499 case 2: 500 assert(hasWorkItemIDZ()); 501 return AMDGPU::VGPR2; 502 } 503 llvm_unreachable("unexpected dimension"); 504 } 505 506 const AMDGPUBufferPseudoSourceValue *getBufferPSV() const { 507 return &BufferPSV; 508 } 509 510 const AMDGPUImagePseudoSourceValue *getImagePSV() const { 511 return &ImagePSV; 512 } 513 }; 514 515 } // End namespace llvm 516 517 #endif 518