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