1 //==- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface --*- C++ -*-==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 14 #define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 15 16 #include "AMDGPUArgumentUsageInfo.h" 17 #include "AMDGPUMachineFunction.h" 18 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 19 #include "SIInstrInfo.h" 20 #include "SIRegisterInfo.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/Optional.h" 24 #include "llvm/ADT/SmallVector.h" 25 #include "llvm/CodeGen/MIRYamlMapping.h" 26 #include "llvm/CodeGen/PseudoSourceValue.h" 27 #include "llvm/CodeGen/TargetInstrInfo.h" 28 #include "llvm/MC/MCRegisterInfo.h" 29 #include "llvm/Support/ErrorHandling.h" 30 #include <array> 31 #include <cassert> 32 #include <utility> 33 #include <vector> 34 35 namespace llvm { 36 37 class MachineFrameInfo; 38 class MachineFunction; 39 class TargetRegisterClass; 40 41 class AMDGPUImagePseudoSourceValue : public PseudoSourceValue { 42 public: 43 // TODO: Is the img rsrc useful? 44 explicit AMDGPUImagePseudoSourceValue(const TargetInstrInfo &TII) : 45 PseudoSourceValue(PseudoSourceValue::TargetCustom, TII) {} 46 47 bool isConstant(const MachineFrameInfo *) const override { 48 // This should probably be true for most images, but we will start by being 49 // conservative. 50 return false; 51 } 52 53 bool isAliased(const MachineFrameInfo *) const override { 54 return true; 55 } 56 57 bool mayAlias(const MachineFrameInfo *) const override { 58 return true; 59 } 60 }; 61 62 class AMDGPUBufferPseudoSourceValue : public PseudoSourceValue { 63 public: 64 explicit AMDGPUBufferPseudoSourceValue(const TargetInstrInfo &TII) : 65 PseudoSourceValue(PseudoSourceValue::TargetCustom, TII) { } 66 67 bool isConstant(const MachineFrameInfo *) const override { 68 // This should probably be true for most images, but we will start by being 69 // conservative. 70 return false; 71 } 72 73 bool isAliased(const MachineFrameInfo *) const override { 74 return true; 75 } 76 77 bool mayAlias(const MachineFrameInfo *) const override { 78 return true; 79 } 80 }; 81 82 namespace yaml { 83 84 struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo { 85 uint64_t ExplicitKernArgSize = 0; 86 unsigned MaxKernArgAlign = 0; 87 unsigned LDSSize = 0; 88 bool IsEntryFunction = false; 89 bool NoSignedZerosFPMath = false; 90 bool MemoryBound = false; 91 bool WaveLimiter = false; 92 93 StringValue ScratchRSrcReg = "$private_rsrc_reg"; 94 StringValue ScratchWaveOffsetReg = "$scratch_wave_offset_reg"; 95 StringValue FrameOffsetReg = "$fp_reg"; 96 StringValue StackPtrOffsetReg = "$sp_reg"; 97 98 SIMachineFunctionInfo() = default; 99 SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &, 100 const TargetRegisterInfo &TRI); 101 102 void mappingImpl(yaml::IO &YamlIO) override; 103 ~SIMachineFunctionInfo() = default; 104 }; 105 106 template <> struct MappingTraits<SIMachineFunctionInfo> { 107 static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) { 108 YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize, 109 UINT64_C(0)); 110 YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign, 0u); 111 YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u); 112 YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false); 113 YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false); 114 YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false); 115 YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false); 116 YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg, 117 StringValue("$private_rsrc_reg")); 118 YamlIO.mapOptional("scratchWaveOffsetReg", MFI.ScratchWaveOffsetReg, 119 StringValue("$scratch_wave_offset_reg")); 120 YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg, 121 StringValue("$fp_reg")); 122 YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg, 123 StringValue("$sp_reg")); 124 } 125 }; 126 127 } // end namespace yaml 128 129 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 130 /// tells the hardware which interpolation parameters to load. 131 class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 132 friend class GCNTargetMachine; 133 134 unsigned TIDReg = AMDGPU::NoRegister; 135 136 // Registers that may be reserved for spilling purposes. These may be the same 137 // as the input registers. 138 unsigned ScratchRSrcReg = AMDGPU::PRIVATE_RSRC_REG; 139 unsigned ScratchWaveOffsetReg = AMDGPU::SCRATCH_WAVE_OFFSET_REG; 140 141 // This is the current function's incremented size from the kernel's scratch 142 // wave offset register. For an entry function, this is exactly the same as 143 // the ScratchWaveOffsetReg. 144 unsigned FrameOffsetReg = AMDGPU::FP_REG; 145 146 // Top of the stack SGPR offset derived from the ScratchWaveOffsetReg. 147 unsigned StackPtrOffsetReg = AMDGPU::SP_REG; 148 149 AMDGPUFunctionArgInfo ArgInfo; 150 151 // Graphics info. 152 unsigned PSInputAddr = 0; 153 unsigned PSInputEnable = 0; 154 155 /// Number of bytes of arguments this function has on the stack. If the callee 156 /// is expected to restore the argument stack this should be a multiple of 16, 157 /// all usable during a tail call. 158 /// 159 /// The alternative would forbid tail call optimisation in some cases: if we 160 /// want to transfer control from a function with 8-bytes of stack-argument 161 /// space to a function with 16-bytes then misalignment of this value would 162 /// make a stack adjustment necessary, which could not be undone by the 163 /// callee. 164 unsigned BytesInStackArgArea = 0; 165 166 bool ReturnsVoid = true; 167 168 // A pair of default/requested minimum/maximum flat work group sizes. 169 // Minimum - first, maximum - second. 170 std::pair<unsigned, unsigned> FlatWorkGroupSizes = {0, 0}; 171 172 // A pair of default/requested minimum/maximum number of waves per execution 173 // unit. Minimum - first, maximum - second. 174 std::pair<unsigned, unsigned> WavesPerEU = {0, 0}; 175 176 DenseMap<const Value *, 177 std::unique_ptr<const AMDGPUBufferPseudoSourceValue>> BufferPSVs; 178 DenseMap<const Value *, 179 std::unique_ptr<const AMDGPUImagePseudoSourceValue>> ImagePSVs; 180 181 private: 182 unsigned LDSWaveSpillSize = 0; 183 unsigned NumUserSGPRs = 0; 184 unsigned NumSystemSGPRs = 0; 185 186 bool HasSpilledSGPRs = false; 187 bool HasSpilledVGPRs = false; 188 bool HasNonSpillStackObjects = false; 189 bool IsStackRealigned = false; 190 191 unsigned NumSpilledSGPRs = 0; 192 unsigned NumSpilledVGPRs = 0; 193 194 // Feature bits required for inputs passed in user SGPRs. 195 bool PrivateSegmentBuffer : 1; 196 bool DispatchPtr : 1; 197 bool QueuePtr : 1; 198 bool KernargSegmentPtr : 1; 199 bool DispatchID : 1; 200 bool FlatScratchInit : 1; 201 202 // Feature bits required for inputs passed in system SGPRs. 203 bool WorkGroupIDX : 1; // Always initialized. 204 bool WorkGroupIDY : 1; 205 bool WorkGroupIDZ : 1; 206 bool WorkGroupInfo : 1; 207 bool PrivateSegmentWaveByteOffset : 1; 208 209 bool WorkItemIDX : 1; // Always initialized. 210 bool WorkItemIDY : 1; 211 bool WorkItemIDZ : 1; 212 213 // Private memory buffer 214 // Compute directly in sgpr[0:1] 215 // Other shaders indirect 64-bits at sgpr[0:1] 216 bool ImplicitBufferPtr : 1; 217 218 // Pointer to where the ABI inserts special kernel arguments separate from the 219 // user arguments. This is an offset from the KernargSegmentPtr. 220 bool ImplicitArgPtr : 1; 221 222 // The hard-wired high half of the address of the global information table 223 // for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since 224 // current hardware only allows a 16 bit value. 225 unsigned GITPtrHigh; 226 227 unsigned HighBitsOf32BitAddress; 228 229 // Current recorded maximum possible occupancy. 230 unsigned Occupancy; 231 232 MCPhysReg getNextUserSGPR() const; 233 234 MCPhysReg getNextSystemSGPR() const; 235 236 public: 237 struct SpilledReg { 238 unsigned VGPR = 0; 239 int Lane = -1; 240 241 SpilledReg() = default; 242 SpilledReg(unsigned R, int L) : VGPR (R), Lane (L) {} 243 244 bool hasLane() { return Lane != -1;} 245 bool hasReg() { return VGPR != 0;} 246 }; 247 248 struct SGPRSpillVGPRCSR { 249 // VGPR used for SGPR spills 250 unsigned VGPR; 251 252 // If the VGPR is a CSR, the stack slot used to save/restore it in the 253 // prolog/epilog. 254 Optional<int> FI; 255 256 SGPRSpillVGPRCSR(unsigned V, Optional<int> F) : VGPR(V), FI(F) {} 257 }; 258 259 private: 260 // SGPR->VGPR spilling support. 261 using SpillRegMask = std::pair<unsigned, unsigned>; 262 263 // Track VGPR + wave index for each subregister of the SGPR spilled to 264 // frameindex key. 265 DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills; 266 unsigned NumVGPRSpillLanes = 0; 267 SmallVector<SGPRSpillVGPRCSR, 2> SpillVGPRs; 268 269 public: 270 SIMachineFunctionInfo(const MachineFunction &MF); 271 272 bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI); 273 274 ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const { 275 auto I = SGPRToVGPRSpills.find(FrameIndex); 276 return (I == SGPRToVGPRSpills.end()) ? 277 ArrayRef<SpilledReg>() : makeArrayRef(I->second); 278 } 279 280 ArrayRef<SGPRSpillVGPRCSR> getSGPRSpillVGPRs() const { 281 return SpillVGPRs; 282 } 283 284 bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI); 285 void removeSGPRToVGPRFrameIndices(MachineFrameInfo &MFI); 286 287 bool hasCalculatedTID() const { return TIDReg != 0; }; 288 unsigned getTIDReg() const { return TIDReg; }; 289 void setTIDReg(unsigned Reg) { TIDReg = Reg; } 290 291 unsigned getBytesInStackArgArea() const { 292 return BytesInStackArgArea; 293 } 294 295 void setBytesInStackArgArea(unsigned Bytes) { 296 BytesInStackArgArea = Bytes; 297 } 298 299 // Add user SGPRs. 300 unsigned addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 301 unsigned addDispatchPtr(const SIRegisterInfo &TRI); 302 unsigned addQueuePtr(const SIRegisterInfo &TRI); 303 unsigned addKernargSegmentPtr(const SIRegisterInfo &TRI); 304 unsigned addDispatchID(const SIRegisterInfo &TRI); 305 unsigned addFlatScratchInit(const SIRegisterInfo &TRI); 306 unsigned addImplicitBufferPtr(const SIRegisterInfo &TRI); 307 308 // Add system SGPRs. 309 unsigned addWorkGroupIDX() { 310 ArgInfo.WorkGroupIDX = ArgDescriptor::createRegister(getNextSystemSGPR()); 311 NumSystemSGPRs += 1; 312 return ArgInfo.WorkGroupIDX.getRegister(); 313 } 314 315 unsigned addWorkGroupIDY() { 316 ArgInfo.WorkGroupIDY = ArgDescriptor::createRegister(getNextSystemSGPR()); 317 NumSystemSGPRs += 1; 318 return ArgInfo.WorkGroupIDY.getRegister(); 319 } 320 321 unsigned addWorkGroupIDZ() { 322 ArgInfo.WorkGroupIDZ = ArgDescriptor::createRegister(getNextSystemSGPR()); 323 NumSystemSGPRs += 1; 324 return ArgInfo.WorkGroupIDZ.getRegister(); 325 } 326 327 unsigned addWorkGroupInfo() { 328 ArgInfo.WorkGroupInfo = ArgDescriptor::createRegister(getNextSystemSGPR()); 329 NumSystemSGPRs += 1; 330 return ArgInfo.WorkGroupInfo.getRegister(); 331 } 332 333 // Add special VGPR inputs 334 void setWorkItemIDX(ArgDescriptor Arg) { 335 ArgInfo.WorkItemIDX = Arg; 336 } 337 338 void setWorkItemIDY(ArgDescriptor Arg) { 339 ArgInfo.WorkItemIDY = Arg; 340 } 341 342 void setWorkItemIDZ(ArgDescriptor Arg) { 343 ArgInfo.WorkItemIDZ = Arg; 344 } 345 346 unsigned addPrivateSegmentWaveByteOffset() { 347 ArgInfo.PrivateSegmentWaveByteOffset 348 = ArgDescriptor::createRegister(getNextSystemSGPR()); 349 NumSystemSGPRs += 1; 350 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 351 } 352 353 void setPrivateSegmentWaveByteOffset(unsigned Reg) { 354 ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg); 355 } 356 357 bool hasPrivateSegmentBuffer() const { 358 return PrivateSegmentBuffer; 359 } 360 361 bool hasDispatchPtr() const { 362 return DispatchPtr; 363 } 364 365 bool hasQueuePtr() const { 366 return QueuePtr; 367 } 368 369 bool hasKernargSegmentPtr() const { 370 return KernargSegmentPtr; 371 } 372 373 bool hasDispatchID() const { 374 return DispatchID; 375 } 376 377 bool hasFlatScratchInit() const { 378 return FlatScratchInit; 379 } 380 381 bool hasWorkGroupIDX() const { 382 return WorkGroupIDX; 383 } 384 385 bool hasWorkGroupIDY() const { 386 return WorkGroupIDY; 387 } 388 389 bool hasWorkGroupIDZ() const { 390 return WorkGroupIDZ; 391 } 392 393 bool hasWorkGroupInfo() const { 394 return WorkGroupInfo; 395 } 396 397 bool hasPrivateSegmentWaveByteOffset() const { 398 return PrivateSegmentWaveByteOffset; 399 } 400 401 bool hasWorkItemIDX() const { 402 return WorkItemIDX; 403 } 404 405 bool hasWorkItemIDY() const { 406 return WorkItemIDY; 407 } 408 409 bool hasWorkItemIDZ() const { 410 return WorkItemIDZ; 411 } 412 413 bool hasImplicitArgPtr() const { 414 return ImplicitArgPtr; 415 } 416 417 bool hasImplicitBufferPtr() const { 418 return ImplicitBufferPtr; 419 } 420 421 AMDGPUFunctionArgInfo &getArgInfo() { 422 return ArgInfo; 423 } 424 425 const AMDGPUFunctionArgInfo &getArgInfo() const { 426 return ArgInfo; 427 } 428 429 std::pair<const ArgDescriptor *, const TargetRegisterClass *> 430 getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 431 return ArgInfo.getPreloadedValue(Value); 432 } 433 434 unsigned getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 435 return ArgInfo.getPreloadedValue(Value).first->getRegister(); 436 } 437 438 unsigned getGITPtrHigh() const { 439 return GITPtrHigh; 440 } 441 442 unsigned get32BitAddressHighBits() const { 443 return HighBitsOf32BitAddress; 444 } 445 446 unsigned getNumUserSGPRs() const { 447 return NumUserSGPRs; 448 } 449 450 unsigned getNumPreloadedSGPRs() const { 451 return NumUserSGPRs + NumSystemSGPRs; 452 } 453 454 unsigned getPrivateSegmentWaveByteOffsetSystemSGPR() const { 455 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 456 } 457 458 /// Returns the physical register reserved for use as the resource 459 /// descriptor for scratch accesses. 460 unsigned getScratchRSrcReg() const { 461 return ScratchRSrcReg; 462 } 463 464 void setScratchRSrcReg(unsigned Reg) { 465 assert(Reg != 0 && "Should never be unset"); 466 ScratchRSrcReg = Reg; 467 } 468 469 unsigned getScratchWaveOffsetReg() const { 470 return ScratchWaveOffsetReg; 471 } 472 473 unsigned getFrameOffsetReg() const { 474 return FrameOffsetReg; 475 } 476 477 void setStackPtrOffsetReg(unsigned Reg) { 478 assert(Reg != 0 && "Should never be unset"); 479 StackPtrOffsetReg = Reg; 480 } 481 482 // Note the unset value for this is AMDGPU::SP_REG rather than 483 // NoRegister. This is mostly a workaround for MIR tests where state that 484 // can't be directly computed from the function is not preserved in serialized 485 // MIR. 486 unsigned getStackPtrOffsetReg() const { 487 return StackPtrOffsetReg; 488 } 489 490 void setScratchWaveOffsetReg(unsigned Reg) { 491 assert(Reg != 0 && "Should never be unset"); 492 ScratchWaveOffsetReg = Reg; 493 if (isEntryFunction()) 494 FrameOffsetReg = ScratchWaveOffsetReg; 495 } 496 497 unsigned getQueuePtrUserSGPR() const { 498 return ArgInfo.QueuePtr.getRegister(); 499 } 500 501 unsigned getImplicitBufferPtrUserSGPR() const { 502 return ArgInfo.ImplicitBufferPtr.getRegister(); 503 } 504 505 bool hasSpilledSGPRs() const { 506 return HasSpilledSGPRs; 507 } 508 509 void setHasSpilledSGPRs(bool Spill = true) { 510 HasSpilledSGPRs = Spill; 511 } 512 513 bool hasSpilledVGPRs() const { 514 return HasSpilledVGPRs; 515 } 516 517 void setHasSpilledVGPRs(bool Spill = true) { 518 HasSpilledVGPRs = Spill; 519 } 520 521 bool hasNonSpillStackObjects() const { 522 return HasNonSpillStackObjects; 523 } 524 525 void setHasNonSpillStackObjects(bool StackObject = true) { 526 HasNonSpillStackObjects = StackObject; 527 } 528 529 bool isStackRealigned() const { 530 return IsStackRealigned; 531 } 532 533 void setIsStackRealigned(bool Realigned = true) { 534 IsStackRealigned = Realigned; 535 } 536 537 unsigned getNumSpilledSGPRs() const { 538 return NumSpilledSGPRs; 539 } 540 541 unsigned getNumSpilledVGPRs() const { 542 return NumSpilledVGPRs; 543 } 544 545 void addToSpilledSGPRs(unsigned num) { 546 NumSpilledSGPRs += num; 547 } 548 549 void addToSpilledVGPRs(unsigned num) { 550 NumSpilledVGPRs += num; 551 } 552 553 unsigned getPSInputAddr() const { 554 return PSInputAddr; 555 } 556 557 unsigned getPSInputEnable() const { 558 return PSInputEnable; 559 } 560 561 bool isPSInputAllocated(unsigned Index) const { 562 return PSInputAddr & (1 << Index); 563 } 564 565 void markPSInputAllocated(unsigned Index) { 566 PSInputAddr |= 1 << Index; 567 } 568 569 void markPSInputEnabled(unsigned Index) { 570 PSInputEnable |= 1 << Index; 571 } 572 573 bool returnsVoid() const { 574 return ReturnsVoid; 575 } 576 577 void setIfReturnsVoid(bool Value) { 578 ReturnsVoid = Value; 579 } 580 581 /// \returns A pair of default/requested minimum/maximum flat work group sizes 582 /// for this function. 583 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 584 return FlatWorkGroupSizes; 585 } 586 587 /// \returns Default/requested minimum flat work group size for this function. 588 unsigned getMinFlatWorkGroupSize() const { 589 return FlatWorkGroupSizes.first; 590 } 591 592 /// \returns Default/requested maximum flat work group size for this function. 593 unsigned getMaxFlatWorkGroupSize() const { 594 return FlatWorkGroupSizes.second; 595 } 596 597 /// \returns A pair of default/requested minimum/maximum number of waves per 598 /// execution unit. 599 std::pair<unsigned, unsigned> getWavesPerEU() const { 600 return WavesPerEU; 601 } 602 603 /// \returns Default/requested minimum number of waves per execution unit. 604 unsigned getMinWavesPerEU() const { 605 return WavesPerEU.first; 606 } 607 608 /// \returns Default/requested maximum number of waves per execution unit. 609 unsigned getMaxWavesPerEU() const { 610 return WavesPerEU.second; 611 } 612 613 /// \returns SGPR used for \p Dim's work group ID. 614 unsigned getWorkGroupIDSGPR(unsigned Dim) const { 615 switch (Dim) { 616 case 0: 617 assert(hasWorkGroupIDX()); 618 return ArgInfo.WorkGroupIDX.getRegister(); 619 case 1: 620 assert(hasWorkGroupIDY()); 621 return ArgInfo.WorkGroupIDY.getRegister(); 622 case 2: 623 assert(hasWorkGroupIDZ()); 624 return ArgInfo.WorkGroupIDZ.getRegister(); 625 } 626 llvm_unreachable("unexpected dimension"); 627 } 628 629 /// \returns VGPR used for \p Dim' work item ID. 630 unsigned getWorkItemIDVGPR(unsigned Dim) const; 631 632 unsigned getLDSWaveSpillSize() const { 633 return LDSWaveSpillSize; 634 } 635 636 const AMDGPUBufferPseudoSourceValue *getBufferPSV(const SIInstrInfo &TII, 637 const Value *BufferRsrc) { 638 assert(BufferRsrc); 639 auto PSV = BufferPSVs.try_emplace( 640 BufferRsrc, 641 llvm::make_unique<AMDGPUBufferPseudoSourceValue>(TII)); 642 return PSV.first->second.get(); 643 } 644 645 const AMDGPUImagePseudoSourceValue *getImagePSV(const SIInstrInfo &TII, 646 const Value *ImgRsrc) { 647 assert(ImgRsrc); 648 auto PSV = ImagePSVs.try_emplace( 649 ImgRsrc, 650 llvm::make_unique<AMDGPUImagePseudoSourceValue>(TII)); 651 return PSV.first->second.get(); 652 } 653 654 unsigned getOccupancy() const { 655 return Occupancy; 656 } 657 658 unsigned getMinAllowedOccupancy() const { 659 if (!isMemoryBound() && !needsWaveLimiter()) 660 return Occupancy; 661 return (Occupancy < 4) ? Occupancy : 4; 662 } 663 664 void limitOccupancy(const MachineFunction &MF); 665 666 void limitOccupancy(unsigned Limit) { 667 if (Occupancy > Limit) 668 Occupancy = Limit; 669 } 670 671 void increaseOccupancy(const MachineFunction &MF, unsigned Limit) { 672 if (Occupancy < Limit) 673 Occupancy = Limit; 674 limitOccupancy(MF); 675 } 676 }; 677 678 } // end namespace llvm 679 680 #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 681