LLVM  16.0.0git
AMDGPUReleaseVGPRs.cpp
Go to the documentation of this file.
1 //===- AMDGPUReleaseVGPRs.cpp - Automatically release vgprs on GFX11+ -----===//
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 /// Insert S_SENDMSG instructions to release vgprs on GFX11+.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AMDGPU.h"
15 #include "AMDGPUSubtarget.h"
16 #include "GCNSubtarget.h"
18 #include "SIDefines.h"
22 #include <optional>
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "release-vgprs"
26 
27 namespace {
28 
29 class AMDGPUReleaseVGPRs : public MachineFunctionPass {
30 public:
31  static char ID;
32 
33  AMDGPUReleaseVGPRs() : MachineFunctionPass(ID) {}
34 
35  void getAnalysisUsage(AnalysisUsage &AU) const override {
36  AU.setPreservesAll();
38  }
39 
40  // Track if the last instruction referencing a vgpr in a MBB is a VMEM
41  // store. Because this pass is late in the pipeline, it is expected that the
42  // last vgpr use will likely be one of vmem store, ds, exp.
43  // Loads and others vgpr operations would have been
44  // deleted by this point, except for complex control flow involving loops.
45  // This is why we are just testing the type of instructions rather
46  // than the operands.
47  class LastVGPRUseIsVMEMStore {
48  BitVector BlockVMEMStore;
49 
50  static std::optional<bool>
51  lastVGPRUseIsStore(const MachineBasicBlock &MBB) {
52  for (auto &MI : reverse(MBB.instrs())) {
53  // If it's a VMEM store, a VGPR will be used, return true.
55  MI.mayStore())
56  return true;
57 
58  // If it's referencing a VGPR but is not a VMEM store, return false.
62  return false;
63  }
64  // Wait until the values are propagated from the predecessors
65  return std::nullopt;
66  }
67 
68  public:
69  LastVGPRUseIsVMEMStore(const MachineFunction &MF)
70  : BlockVMEMStore(MF.getNumBlockIDs()) {
71 
73  SmallVector<const MachineBasicBlock *> EndWithVMEMStoreBlocks;
74 
75  for (const auto &MBB : MF) {
76  auto LastUseIsStore = lastVGPRUseIsStore(MBB);
77  if (!LastUseIsStore.has_value())
78  continue;
79 
80  if (*LastUseIsStore) {
81  EndWithVMEMStoreBlocks.push_back(&MBB);
82  } else {
83  Visited.insert(&MBB);
84  }
85  }
86 
87  for (const auto *MBB : EndWithVMEMStoreBlocks) {
88  for (const auto *Succ : depth_first_ext(MBB, Visited)) {
89  BlockVMEMStore[Succ->getNumber()] = true;
90  }
91  }
92  }
93 
94  // Return true if the last instruction referencing a vgpr in this MBB
95  // is a VMEM store, otherwise return false.
96  bool isLastVGPRUseVMEMStore(const MachineBasicBlock &MBB) const {
97  return BlockVMEMStore[MBB.getNumber()];
98  }
99  };
100 
101  static bool
102  runOnMachineBasicBlock(MachineBasicBlock &MBB, const SIInstrInfo *SII,
103  const LastVGPRUseIsVMEMStore &BlockVMEMStore) {
104 
105  bool Changed = false;
106 
107  for (auto &MI : MBB.terminators()) {
108  // Look for S_ENDPGM instructions
109  if (MI.getOpcode() == AMDGPU::S_ENDPGM ||
110  MI.getOpcode() == AMDGPU::S_ENDPGM_SAVED) {
111  // If the last instruction using a VGPR in the block is a VMEM store,
112  // release VGPRs. The VGPRs release will be placed just before ending
113  // the program
114  if (BlockVMEMStore.isLastVGPRUseVMEMStore(MBB)) {
115  BuildMI(MBB, MI, DebugLoc(), SII->get(AMDGPU::S_SENDMSG))
117  Changed = true;
118  }
119  }
120  }
121 
122  return Changed;
123  }
124 
125  bool runOnMachineFunction(MachineFunction &MF) override {
126  Function &F = MF.getFunction();
127  if (skipFunction(F) || !AMDGPU::isEntryFunctionCC(F.getCallingConv()))
128  return false;
129 
130  // This pass only runs on GFX11+
131  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
132  if (ST.getGeneration() < AMDGPUSubtarget::GFX11)
133  return false;
134 
135  LLVM_DEBUG(dbgs() << "AMDGPUReleaseVGPRs running on " << MF.getName()
136  << "\n");
137 
138  const SIInstrInfo *SII = ST.getInstrInfo();
139  LastVGPRUseIsVMEMStore BlockVMEMStore(MF);
140 
141  bool Changed = false;
142  for (auto &MBB : MF) {
143  Changed |= runOnMachineBasicBlock(MBB, SII, BlockVMEMStore);
144  }
145 
146  return Changed;
147  }
148 };
149 
150 } // namespace
151 
152 char AMDGPUReleaseVGPRs::ID = 0;
153 
155 
156 INITIALIZE_PASS(AMDGPUReleaseVGPRs, DEBUG_TYPE, "Release VGPRs", false, false)
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:109
llvm::MachineInstrBuilder::addImm
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Definition: MachineInstrBuilder.h:131
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:818
llvm::Function
Definition: Function.h:60
llvm::MachineBasicBlock::instrs
instr_range instrs()
Definition: MachineBasicBlock.h:300
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::SIInstrInfo::isEXP
static bool isEXP(const MachineInstr &MI)
Definition: SIInstrInfo.h:554
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
MachineBasicBlock.h
llvm::MachineFunction::getNumBlockIDs
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
Definition: MachineFunction.h:799
llvm::GCNSubtarget
Definition: GCNSubtarget.h:31
llvm::AMDGPUReleaseVGPRsID
char & AMDGPUReleaseVGPRsID
Definition: AMDGPUReleaseVGPRs.cpp:154
llvm::MachineBasicBlock::terminators
iterator_range< iterator > terminators()
Definition: MachineBasicBlock.h:325
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:167
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
DepthFirstIterator.h
llvm::AMDGPUSubtarget::GFX11
@ GFX11
Definition: AMDGPUSubtarget.h:42
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::AMDGPU::SendMsg::ID_DEALLOC_VGPRS_GFX11Plus
@ ID_DEALLOC_VGPRS_GFX11Plus
Definition: SIDefines.h:325
DEBUG_TYPE
#define DEBUG_TYPE
Definition: AMDGPUReleaseVGPRs.cpp:25
GCNSubtarget.h
INITIALIZE_PASS
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:37
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
AMDGPUSubtarget.h
llvm::depth_first_ext
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
Definition: DepthFirstIterator.h:252
llvm::BitVector
Definition: BitVector.h:75
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
llvm::AMDGPU::isEntryFunctionCC
bool isEntryFunctionCC(CallingConv::ID CC)
Definition: AMDGPUBaseInfo.cpp:1831
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:657
AMDGPUMCTargetDesc.h
llvm::ARM_MB::ST
@ ST
Definition: ARMBaseInfo.h:73
llvm::SIInstrInfo::isDS
static bool isDS(const MachineInstr &MI)
Definition: SIInstrInfo.h:491
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:567
llvm::df_iterator_default_set::insert
std::pair< iterator, bool > insert(NodeRef N)
Definition: DepthFirstIterator.h:74
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::df_iterator_default_set
Definition: DepthFirstIterator.h:70
llvm::MachineBasicBlock::getNumber
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Definition: MachineBasicBlock.h:1115
AMDGPU.h
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:623
llvm::AnalysisUsage::setPreservesAll
void setPreservesAll()
Set by analyses that do not transform their input at all.
Definition: PassAnalysisSupport.h:130
SIDefines.h
llvm::SIInstrInfo::isVMEM
static bool isVMEM(const MachineInstr &MI)
Definition: SIInstrInfo.h:369
llvm::SIInstrInfo
Definition: SIInstrInfo.h:44
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:357
llvm::SIInstrInfo::isVALU
static bool isVALU(const MachineInstr &MI)
Definition: SIInstrInfo.h:361
llvm::reverse
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:485
MachineOperand.h
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::SIInstrInfo::isFLAT
static bool isFLAT(const MachineInstr &MI)
Definition: SIInstrInfo.h:517