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