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