LLVM 22.0.0git
SIPreAllocateWWMRegs.cpp
Go to the documentation of this file.
1//===- SIPreAllocateWWMRegs.cpp - WWM Register Pre-allocation -------------===//
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/// Pass to pre-allocated WWM registers
11//
12//===----------------------------------------------------------------------===//
13
15#include "AMDGPU.h"
16#include "GCNSubtarget.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "si-pre-allocate-wwm-regs"
31
32static cl::opt<bool>
33 EnablePreallocateSGPRSpillVGPRs("amdgpu-prealloc-sgpr-spill-vgprs",
34 cl::init(false), cl::Hidden);
35
36namespace {
37
38class SIPreAllocateWWMRegs {
39private:
40 const SIInstrInfo *TII;
41 const SIRegisterInfo *TRI;
43 LiveIntervals *LIS;
45 VirtRegMap *VRM;
46 RegisterClassInfo RegClassInfo;
47
48 std::vector<unsigned> RegsToRewrite;
49#ifndef NDEBUG
50 void printWWMInfo(const MachineInstr &MI);
51#endif
52 bool processDef(MachineOperand &MO);
53 void rewriteRegs(MachineFunction &MF);
54
55public:
56 SIPreAllocateWWMRegs(LiveIntervals *LIS, LiveRegMatrix *Matrix,
57 VirtRegMap *VRM)
58 : LIS(LIS), Matrix(Matrix), VRM(VRM) {}
59 bool run(MachineFunction &MF);
60};
61
62class SIPreAllocateWWMRegsLegacy : public MachineFunctionPass {
63public:
64 static char ID;
65
66 SIPreAllocateWWMRegsLegacy() : MachineFunctionPass(ID) {}
67
68 bool runOnMachineFunction(MachineFunction &MF) override;
69
70 void getAnalysisUsage(AnalysisUsage &AU) const override {
74 AU.setPreservesAll();
76 }
77};
78
79} // End anonymous namespace.
80
81INITIALIZE_PASS_BEGIN(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
82 "SI Pre-allocate WWM Registers", false, false)
86INITIALIZE_PASS_END(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
87 "SI Pre-allocate WWM Registers", false, false)
88
89char SIPreAllocateWWMRegsLegacy::ID = 0;
90
91char &llvm::SIPreAllocateWWMRegsLegacyID = SIPreAllocateWWMRegsLegacy::ID;
92
94 return new SIPreAllocateWWMRegsLegacy();
95}
96
97bool SIPreAllocateWWMRegs::processDef(MachineOperand &MO) {
98 Register Reg = MO.getReg();
99 if (Reg.isPhysical())
100 return false;
101
102 if (!TRI->isVGPR(*MRI, Reg))
103 return false;
104
105 if (VRM->hasPhys(Reg))
106 return false;
107
108 LiveInterval &LI = LIS->getInterval(Reg);
109
110 for (MCRegister PhysReg : RegClassInfo.getOrder(MRI->getRegClass(Reg))) {
111 if (!MRI->isPhysRegUsed(PhysReg, /*SkipRegMaskTest=*/true) &&
112 Matrix->checkInterference(LI, PhysReg) == LiveRegMatrix::IK_Free) {
113 Matrix->assign(LI, PhysReg);
114 assert(PhysReg != 0);
115 RegsToRewrite.push_back(Reg);
116 return true;
117 }
118 }
119
120 llvm_unreachable("physreg not found for WWM expression");
121}
122
123void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
124 for (MachineBasicBlock &MBB : MF) {
125 for (MachineInstr &MI : MBB) {
126 for (MachineOperand &MO : MI.operands()) {
127 if (!MO.isReg())
128 continue;
129
130 const Register VirtReg = MO.getReg();
131 if (VirtReg.isPhysical())
132 continue;
133
134 if (!VirtReg.isValid())
135 continue;
136
137 if (!VRM->hasPhys(VirtReg))
138 continue;
139
140 Register PhysReg = VRM->getPhys(VirtReg);
141 const unsigned SubReg = MO.getSubReg();
142 if (SubReg != 0) {
143 PhysReg = TRI->getSubReg(PhysReg, SubReg);
144 MO.setSubReg(0);
145 }
146
147 MO.setReg(PhysReg);
148 MO.setIsRenamable(false);
149 }
150 }
151 }
152
153 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
154
155 for (unsigned Reg : RegsToRewrite) {
156 LIS->removeInterval(Reg);
157
158 const Register PhysReg = VRM->getPhys(Reg);
159 assert(PhysReg != 0);
160
161 MFI->reserveWWMRegister(PhysReg);
162 }
163
164 RegsToRewrite.clear();
165
166 // Update the set of reserved registers to include WWM ones.
167 MRI->freezeReservedRegs();
168}
169
170#ifndef NDEBUG
172SIPreAllocateWWMRegs::printWWMInfo(const MachineInstr &MI) {
173
174 unsigned Opc = MI.getOpcode();
175
176 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::ENTER_STRICT_WQM) {
177 dbgs() << "Entering ";
178 } else {
179 assert(Opc == AMDGPU::EXIT_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WQM);
180 dbgs() << "Exiting ";
181 }
182
183 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WWM) {
184 dbgs() << "Strict WWM ";
185 } else {
186 assert(Opc == AMDGPU::ENTER_STRICT_WQM || Opc == AMDGPU::EXIT_STRICT_WQM);
187 dbgs() << "Strict WQM ";
188 }
189
190 dbgs() << "region: " << MI;
191}
192
193#endif
194
195bool SIPreAllocateWWMRegsLegacy::runOnMachineFunction(MachineFunction &MF) {
196 auto *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
197 auto *Matrix = &getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
198 auto *VRM = &getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
199 return SIPreAllocateWWMRegs(LIS, Matrix, VRM).run(MF);
200}
201
202bool SIPreAllocateWWMRegs::run(MachineFunction &MF) {
203 LLVM_DEBUG(dbgs() << "SIPreAllocateWWMRegs: function " << MF.getName() << "\n");
204
206
207 TII = ST.getInstrInfo();
208 TRI = &TII->getRegisterInfo();
209 MRI = &MF.getRegInfo();
210
211 RegClassInfo.runOnMachineFunction(MF);
212
213 bool PreallocateSGPRSpillVGPRs =
215 MF.getFunction().hasFnAttribute("amdgpu-prealloc-sgpr-spill-vgprs");
216
217 bool RegsAssigned = false;
218
219 // We use a reverse post-order traversal of the control-flow graph to
220 // guarantee that we visit definitions in dominance order. Since WWM
221 // expressions are guaranteed to never involve phi nodes, and we can only
222 // escape WWM through the special WWM instruction, this means that this is a
223 // perfect elimination order, so we can never do any better.
225
226 for (MachineBasicBlock *MBB : RPOT) {
227 bool InWWM = false;
228 for (MachineInstr &MI : *MBB) {
229 if (MI.getOpcode() == AMDGPU::SI_SPILL_S32_TO_VGPR) {
230 if (PreallocateSGPRSpillVGPRs)
231 RegsAssigned |= processDef(MI.getOperand(0));
232 continue;
233 }
234
235 if (MI.getOpcode() == AMDGPU::ENTER_STRICT_WWM ||
236 MI.getOpcode() == AMDGPU::ENTER_STRICT_WQM) {
237 LLVM_DEBUG(printWWMInfo(MI));
238 InWWM = true;
239 continue;
240 }
241
242 if (MI.getOpcode() == AMDGPU::EXIT_STRICT_WWM ||
243 MI.getOpcode() == AMDGPU::EXIT_STRICT_WQM) {
244 LLVM_DEBUG(printWWMInfo(MI));
245 InWWM = false;
246 }
247
248 if (!InWWM)
249 continue;
250
251 LLVM_DEBUG(dbgs() << "Processing " << MI);
252
253 for (MachineOperand &DefOpnd : MI.defs()) {
254 RegsAssigned |= processDef(DefOpnd);
255 }
256 }
257 }
258
259 if (!RegsAssigned)
260 return false;
261
262 rewriteRegs(MF);
263 return true;
264}
265
269 auto *LIS = &MFAM.getResult<LiveIntervalsAnalysis>(MF);
270 auto *Matrix = &MFAM.getResult<LiveRegMatrixAnalysis>(MF);
271 auto *VRM = &MFAM.getResult<VirtRegMapAnalysis>(MF);
272 SIPreAllocateWWMRegs(LIS, Matrix, VRM).run(MF);
273 return PreservedAnalyses::all();
274}
unsigned SubReg
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
MachineBasicBlock & MBB
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:638
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Live Register Matrix
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:39
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
SI Pre allocate WWM Registers
#define DEBUG_TYPE
static cl::opt< bool > EnablePreallocateSGPRSpillVGPRs("amdgpu-prealloc-sgpr-spill-vgprs", cl::init(false), cl::Hidden)
#define LLVM_DEBUG(...)
Definition: Debug.h:119
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:727
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:690
@ IK_Free
No interference, go ahead and assign.
Definition: LiveRegMatrix.h:86
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:72
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:107
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:78
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI VirtRegMap run(MachineFunction &MF, MachineFunctionAnalysisManager &MAM)
Definition: VirtRegMap.cpp:182
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
FunctionPass * createSIPreAllocateWWMRegsLegacyPass()
char & SIPreAllocateWWMRegsLegacyID