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 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 27 /// tells the hardware which interpolation parameters to load. 28 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 29 // FIXME: This should be removed and getPreloadedValue moved here. 30 friend struct SIRegisterInfo; 31 void anchor() override; 32 33 unsigned TIDReg; 34 35 // Registers that may be reserved for spilling purposes. These may be the same 36 // as the input registers. 37 unsigned ScratchRSrcReg; 38 unsigned ScratchWaveOffsetReg; 39 40 // Input registers setup for the HSA ABI. 41 // User SGPRs in allocation order. 42 unsigned PrivateSegmentBufferUserSGPR; 43 unsigned DispatchPtrUserSGPR; 44 unsigned QueuePtrUserSGPR; 45 unsigned KernargSegmentPtrUserSGPR; 46 unsigned DispatchIDUserSGPR; 47 unsigned FlatScratchInitUserSGPR; 48 unsigned PrivateSegmentSizeUserSGPR; 49 unsigned GridWorkGroupCountXUserSGPR; 50 unsigned GridWorkGroupCountYUserSGPR; 51 unsigned GridWorkGroupCountZUserSGPR; 52 53 // System SGPRs in allocation order. 54 unsigned WorkGroupIDXSystemSGPR; 55 unsigned WorkGroupIDYSystemSGPR; 56 unsigned WorkGroupIDZSystemSGPR; 57 unsigned WorkGroupInfoSystemSGPR; 58 unsigned PrivateSegmentWaveByteOffsetSystemSGPR; 59 60 // Graphics info. 61 unsigned PSInputAddr; 62 bool ReturnsVoid; 63 64 unsigned MaximumWorkGroupSize; 65 66 // Number of reserved VGPRs for debugger usage. 67 unsigned DebuggerReservedVGPRCount; 68 // Stack object indices for work group IDs. 69 std::array<int, 3> DebuggerWorkGroupIDStackObjectIndices; 70 // Stack object indices for work item IDs. 71 std::array<int, 3> DebuggerWorkItemIDStackObjectIndices; 72 73 public: 74 // FIXME: Make private 75 unsigned LDSWaveSpillSize; 76 unsigned PSInputEna; 77 std::map<unsigned, unsigned> LaneVGPRs; 78 unsigned ScratchOffsetReg; 79 unsigned NumUserSGPRs; 80 unsigned NumSystemSGPRs; 81 82 private: 83 bool HasSpilledSGPRs; 84 bool HasSpilledVGPRs; 85 bool HasNonSpillStackObjects; 86 bool HasFlatInstructions; 87 88 // Feature bits required for inputs passed in user SGPRs. 89 bool PrivateSegmentBuffer : 1; 90 bool DispatchPtr : 1; 91 bool QueuePtr : 1; 92 bool DispatchID : 1; 93 bool KernargSegmentPtr : 1; 94 bool FlatScratchInit : 1; 95 bool GridWorkgroupCountX : 1; 96 bool GridWorkgroupCountY : 1; 97 bool GridWorkgroupCountZ : 1; 98 99 // Feature bits required for inputs passed in system SGPRs. 100 bool WorkGroupIDX : 1; // Always initialized. 101 bool WorkGroupIDY : 1; 102 bool WorkGroupIDZ : 1; 103 bool WorkGroupInfo : 1; 104 bool PrivateSegmentWaveByteOffset : 1; 105 106 bool WorkItemIDX : 1; // Always initialized. 107 bool WorkItemIDY : 1; 108 bool WorkItemIDZ : 1; 109 110 MCPhysReg getNextUserSGPR() const { 111 assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs"); 112 return AMDGPU::SGPR0 + NumUserSGPRs; 113 } 114 115 MCPhysReg getNextSystemSGPR() const { 116 return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs; 117 } 118 119 public: 120 struct SpilledReg { 121 unsigned VGPR; 122 int Lane; 123 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) { } 124 SpilledReg() : VGPR(AMDGPU::NoRegister), Lane(-1) { } 125 bool hasLane() { return Lane != -1;} 126 bool hasReg() { return VGPR != AMDGPU::NoRegister;} 127 }; 128 129 // SIMachineFunctionInfo definition 130 131 SIMachineFunctionInfo(const MachineFunction &MF); 132 SpilledReg getSpilledReg(MachineFunction *MF, unsigned FrameIndex, 133 unsigned SubIdx); 134 bool hasCalculatedTID() const { return TIDReg != AMDGPU::NoRegister; }; 135 unsigned getTIDReg() const { return TIDReg; }; 136 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 137 138 // Add user SGPRs. 139 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 140 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 141 unsigned addQueuePtr(const SIRegisterInfo &TRI); 142 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 143 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 144 145 // Add system SGPRs. 146 unsigned addWorkGroupIDX() { 147 WorkGroupIDXSystemSGPR = getNextSystemSGPR(); 148 NumSystemSGPRs += 1; 149 return WorkGroupIDXSystemSGPR; 150 } 151 152 unsigned addWorkGroupIDY() { 153 WorkGroupIDYSystemSGPR = getNextSystemSGPR(); 154 NumSystemSGPRs += 1; 155 return WorkGroupIDYSystemSGPR; 156 } 157 158 unsigned addWorkGroupIDZ() { 159 WorkGroupIDZSystemSGPR = getNextSystemSGPR(); 160 NumSystemSGPRs += 1; 161 return WorkGroupIDZSystemSGPR; 162 } 163 164 unsigned addWorkGroupInfo() { 165 WorkGroupInfoSystemSGPR = getNextSystemSGPR(); 166 NumSystemSGPRs += 1; 167 return WorkGroupInfoSystemSGPR; 168 } 169 170 unsigned addPrivateSegmentWaveByteOffset() { 171 PrivateSegmentWaveByteOffsetSystemSGPR = getNextSystemSGPR(); 172 NumSystemSGPRs += 1; 173 return PrivateSegmentWaveByteOffsetSystemSGPR; 174 } 175 176 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 177 PrivateSegmentWaveByteOffsetSystemSGPR = Reg; 178 } 179 180 bool hasPrivateSegmentBuffer() const { 181 return PrivateSegmentBuffer; 182 } 183 184 bool hasDispatchPtr() const { 185 return DispatchPtr; 186 } 187 188 bool hasQueuePtr() const { 189 return QueuePtr; 190 } 191 192 bool hasDispatchID() const { 193 return DispatchID; 194 } 195 196 bool hasKernargSegmentPtr() const { 197 return KernargSegmentPtr; 198 } 199 200 bool hasFlatScratchInit() const { 201 return FlatScratchInit; 202 } 203 204 bool hasGridWorkgroupCountX() const { 205 return GridWorkgroupCountX; 206 } 207 208 bool hasGridWorkgroupCountY() const { 209 return GridWorkgroupCountY; 210 } 211 212 bool hasGridWorkgroupCountZ() const { 213 return GridWorkgroupCountZ; 214 } 215 216 bool hasWorkGroupIDX() const { 217 return WorkGroupIDX; 218 } 219 220 bool hasWorkGroupIDY() const { 221 return WorkGroupIDY; 222 } 223 224 bool hasWorkGroupIDZ() const { 225 return WorkGroupIDZ; 226 } 227 228 bool hasWorkGroupInfo() const { 229 return WorkGroupInfo; 230 } 231 232 bool hasPrivateSegmentWaveByteOffset() const { 233 return PrivateSegmentWaveByteOffset; 234 } 235 236 bool hasWorkItemIDX() const { 237 return WorkItemIDX; 238 } 239 240 bool hasWorkItemIDY() const { 241 return WorkItemIDY; 242 } 243 244 bool hasWorkItemIDZ() const { 245 return WorkItemIDZ; 246 } 247 248 unsigned getNumUserSGPRs() const { 249 return NumUserSGPRs; 250 } 251 252 unsigned getNumPreloadedSGPRs() const { 253 return NumUserSGPRs + NumSystemSGPRs; 254 } 255 256 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 257 return PrivateSegmentWaveByteOffsetSystemSGPR; 258 } 259 260 /// \brief Returns the physical register reserved for use as the resource 261 /// descriptor for scratch accesses. 262 unsigned getScratchRSrcReg() const { 263 return ScratchRSrcReg; 264 } 265 266 void setScratchRSrcReg(unsigned Reg) { 267 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 268 ScratchRSrcReg = Reg; 269 } 270 271 unsigned getScratchWaveOffsetReg() const { 272 return ScratchWaveOffsetReg; 273 } 274 275 void setScratchWaveOffsetReg(unsigned Reg) { 276 assert(Reg != AMDGPU::NoRegister && "Should never be unset"); 277 ScratchWaveOffsetReg = Reg; 278 } 279 280 unsigned getQueuePtrUserSGPR() const { 281 return QueuePtrUserSGPR; 282 } 283 284 bool hasSpilledSGPRs() const { 285 return HasSpilledSGPRs; 286 } 287 288 void setHasSpilledSGPRs(bool Spill = true) { 289 HasSpilledSGPRs = Spill; 290 } 291 292 bool hasSpilledVGPRs() const { 293 return HasSpilledVGPRs; 294 } 295 296 void setHasSpilledVGPRs(bool Spill = true) { 297 HasSpilledVGPRs = Spill; 298 } 299 300 bool hasNonSpillStackObjects() const { 301 return HasNonSpillStackObjects; 302 } 303 304 void setHasNonSpillStackObjects(bool StackObject = true) { 305 HasNonSpillStackObjects = StackObject; 306 } 307 308 bool hasFlatInstructions() const { 309 return HasFlatInstructions; 310 } 311 312 void setHasFlatInstructions(bool UseFlat = true) { 313 HasFlatInstructions = UseFlat; 314 } 315 316 unsigned getPSInputAddr() const { 317 return PSInputAddr; 318 } 319 320 bool isPSInputAllocated(unsigned Index) const { 321 return PSInputAddr & (1 << Index); 322 } 323 324 void markPSInputAllocated(unsigned Index) { 325 PSInputAddr |= 1 << Index; 326 } 327 328 bool returnsVoid() const { 329 return ReturnsVoid; 330 } 331 332 void setIfReturnsVoid(bool Value) { 333 ReturnsVoid = Value; 334 } 335 336 /// \returns Number of reserved VGPRs for debugger usage. 337 unsigned getDebuggerReservedVGPRCount() const { 338 return DebuggerReservedVGPRCount; 339 } 340 341 /// \returns Stack object index for \p Dim's work group ID. 342 int getDebuggerWorkGroupIDStackObjectIndex(unsigned Dim) const { 343 assert(Dim < 3); 344 return DebuggerWorkGroupIDStackObjectIndices[Dim]; 345 } 346 347 /// \brief Sets stack object index for \p Dim's work group ID to \p ObjectIdx. 348 void setDebuggerWorkGroupIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 349 assert(Dim < 3); 350 DebuggerWorkGroupIDStackObjectIndices[Dim] = ObjectIdx; 351 } 352 353 /// \returns Stack object index for \p Dim's work item ID. 354 int getDebuggerWorkItemIDStackObjectIndex(unsigned Dim) const { 355 assert(Dim < 3); 356 return DebuggerWorkItemIDStackObjectIndices[Dim]; 357 } 358 359 /// \brief Sets stack object index for \p Dim's work item ID to \p ObjectIdx. 360 void setDebuggerWorkItemIDStackObjectIndex(unsigned Dim, int ObjectIdx) { 361 assert(Dim < 3); 362 DebuggerWorkItemIDStackObjectIndices[Dim] = ObjectIdx; 363 } 364 365 /// \returns SGPR used for \p Dim's work group ID. 366 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 367 switch (Dim) { 368 case 0: 369 assert(hasWorkGroupIDX()); 370 return WorkGroupIDXSystemSGPR; 371 case 1: 372 assert(hasWorkGroupIDY()); 373 return WorkGroupIDYSystemSGPR; 374 case 2: 375 assert(hasWorkGroupIDZ()); 376 return WorkGroupIDZSystemSGPR; 377 } 378 llvm_unreachable("unexpected dimension"); 379 } 380 381 /// \returns VGPR used for \p Dim' work item ID. 382 unsigned getWorkItemIDVGPR(unsigned Dim) const { 383 switch (Dim) { 384 case 0: 385 assert(hasWorkItemIDX()); 386 return AMDGPU::VGPR0; 387 case 1: 388 assert(hasWorkItemIDY()); 389 return AMDGPU::VGPR1; 390 case 2: 391 assert(hasWorkItemIDZ()); 392 return AMDGPU::VGPR2; 393 } 394 llvm_unreachable("unexpected dimension"); 395 } 396 397 unsigned getMaximumWorkGroupSize(const MachineFunction &MF) const; 398 }; 399 400 } // End namespace llvm 401 402 #endif 403