LLVM 24.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"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "si-pre-allocate-wwm-regs"
33
34static cl::opt<bool>
35 EnablePreallocateSGPRSpillVGPRs("amdgpu-prealloc-sgpr-spill-vgprs",
36 cl::init(false), cl::Hidden);
37
40 MF.getFunction().hasFnAttribute("amdgpu-prealloc-sgpr-spill-vgprs");
41}
42
43namespace {
44
45class SIPreAllocateWWMRegs {
46private:
47 const SIInstrInfo *TII;
48 const SIRegisterInfo *TRI;
50 LiveIntervals *LIS;
52 VirtRegMap *VRM;
53 const RegisterClassInfo &RegClassInfo;
54
55 std::vector<unsigned> RegsToRewrite;
56#ifndef NDEBUG
57 void printWWMInfo(const MachineInstr &MI);
58#endif
59 bool processDef(MachineOperand &MO);
60 void rewriteRegs(MachineFunction &MF);
61
62public:
63 SIPreAllocateWWMRegs(LiveIntervals *LIS, LiveRegMatrix *Matrix,
64 VirtRegMap *VRM, const RegisterClassInfo &RCI)
65 : LIS(LIS), Matrix(Matrix), VRM(VRM), RegClassInfo(RCI) {}
66 bool run(MachineFunction &MF);
67};
68
69class SIPreAllocateWWMRegsLegacy : public MachineFunctionPass {
70public:
71 static char ID;
72
73 SIPreAllocateWWMRegsLegacy() : MachineFunctionPass(ID) {}
74
75 bool runOnMachineFunction(MachineFunction &MF) override;
76
77 void getAnalysisUsage(AnalysisUsage &AU) const override {
78 AU.addRequired<LiveIntervalsWrapperPass>();
79 AU.addRequired<VirtRegMapWrapperLegacy>();
80 AU.addRequired<LiveRegMatrixWrapperLegacy>();
81 // TODO: Update RCI with the additional reserved registers the pass sets.
82 AU.addRequired<MachineRegisterClassInfoWrapperPass>();
83 AU.setPreservesCFG();
84 AU.addPreserved<LiveIntervalsWrapperPass>();
85 AU.addPreserved<SlotIndexesWrapperPass>();
86 AU.addPreserved<VirtRegMapWrapperLegacy>();
87 AU.addPreserved<LiveRegMatrixWrapperLegacy>();
88 AU.addPreserved<LiveDebugVariablesWrapperLegacy>();
90 }
91};
92
93} // End anonymous namespace.
94
95INITIALIZE_PASS_BEGIN(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
96 "SI Pre-allocate WWM Registers", false, false)
101INITIALIZE_PASS_END(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
102 "SI Pre-allocate WWM Registers", false, false)
103
104char SIPreAllocateWWMRegsLegacy::ID = 0;
105
106char &llvm::SIPreAllocateWWMRegsLegacyID = SIPreAllocateWWMRegsLegacy::ID;
107
109 return new SIPreAllocateWWMRegsLegacy();
110}
111
112bool SIPreAllocateWWMRegs::processDef(MachineOperand &MO) {
113 Register Reg = MO.getReg();
114 if (Reg.isPhysical())
115 return false;
116
118 return false;
119
120 if (VRM->hasPhys(Reg))
121 return false;
122
123 LiveInterval &LI = LIS->getInterval(Reg);
124
125 for (MCRegister PhysReg : RegClassInfo.getOrder(MRI->getRegClass(Reg))) {
126 if (!MRI->isPhysRegUsed(PhysReg, /*SkipRegMaskTest=*/true) &&
127 Matrix->checkInterference(LI, PhysReg) == LiveRegMatrix::IK_Free) {
128 Matrix->assign(LI, PhysReg);
129 assert(PhysReg != 0);
130 RegsToRewrite.push_back(Reg);
131 return true;
132 }
133 }
134
135 llvm_unreachable("physreg not found for WWM expression");
136}
137
138void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
139 for (MachineBasicBlock &MBB : MF) {
140 for (MachineInstr &MI : MBB) {
141 for (MachineOperand &MO : MI.operands()) {
142 if (!MO.isReg())
143 continue;
144
145 const Register VirtReg = MO.getReg();
146 if (VirtReg.isPhysical())
147 continue;
148
149 if (!VirtReg.isValid())
150 continue;
151
152 if (!VRM->hasPhys(VirtReg))
153 continue;
154
155 Register PhysReg = VRM->getPhys(VirtReg);
156 const unsigned SubReg = MO.getSubReg();
157 if (SubReg != 0) {
158 PhysReg = TRI->getSubReg(PhysReg, SubReg);
159 MO.setSubReg(0);
160 }
161
162 MO.setReg(PhysReg);
163 MO.setIsRenamable(false);
164 }
165 }
166 }
167
168 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
169
170 for (unsigned Reg : RegsToRewrite) {
171 const Register PhysReg = VRM->getPhys(Reg);
172 assert(PhysReg != 0);
173
174 LiveInterval &LI = LIS->getInterval(Reg);
175 Matrix->unassign(LI, /*ClearAllReferencingSegments=*/true);
176 LIS->removeInterval(Reg);
177
178 MFI->reserveWWMRegister(PhysReg);
179 }
180
181 RegsToRewrite.clear();
182
183 // Update the set of reserved registers to include WWM ones.
184 MRI->freezeReservedRegs();
185}
186
187#ifndef NDEBUG
189SIPreAllocateWWMRegs::printWWMInfo(const MachineInstr &MI) {
190
191 unsigned Opc = MI.getOpcode();
192
193 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::ENTER_STRICT_WQM) {
194 dbgs() << "Entering ";
195 } else {
196 assert(Opc == AMDGPU::EXIT_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WQM);
197 dbgs() << "Exiting ";
198 }
199
200 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WWM) {
201 dbgs() << "Strict WWM ";
202 } else {
203 assert(Opc == AMDGPU::ENTER_STRICT_WQM || Opc == AMDGPU::EXIT_STRICT_WQM);
204 dbgs() << "Strict WQM ";
205 }
206
207 dbgs() << "region: " << MI;
208}
209
210#endif
211
212bool SIPreAllocateWWMRegsLegacy::runOnMachineFunction(MachineFunction &MF) {
213 auto *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
214 auto *Matrix = &getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
215 auto *VRM = &getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
216 const auto &RCI = getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
217 return SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
218}
219
220bool SIPreAllocateWWMRegs::run(MachineFunction &MF) {
221 LLVM_DEBUG(dbgs() << "SIPreAllocateWWMRegs: function " << MF.getName() << "\n");
222
223 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
224
225 TII = ST.getInstrInfo();
226 TRI = &TII->getRegisterInfo();
227 MRI = &MF.getRegInfo();
228
229 bool PreallocateSGPRSpillVGPRs = isPreallocateSGPRSpillVGPRsEnabled(MF);
230
231 bool RegsAssigned = false;
232
233 // We use a reverse post-order traversal of the control-flow graph to
234 // guarantee that we visit definitions in dominance order. Since WWM
235 // expressions are guaranteed to never involve phi nodes, and we can only
236 // escape WWM through the special WWM instruction, this means that this is a
237 // perfect elimination order, so we can never do any better.
238 ReversePostOrderTraversal<MachineFunction*> RPOT(&MF);
239
240 for (MachineBasicBlock *MBB : RPOT) {
241 bool InWWM = false;
242 for (MachineInstr &MI : *MBB) {
243 if (MI.getOpcode() == AMDGPU::SI_SPILL_S32_TO_VGPR) {
244 if (PreallocateSGPRSpillVGPRs)
245 RegsAssigned |= processDef(MI.getOperand(0));
246 continue;
247 }
248
249 if (MI.getOpcode() == AMDGPU::ENTER_STRICT_WWM ||
250 MI.getOpcode() == AMDGPU::ENTER_STRICT_WQM) {
251 LLVM_DEBUG(printWWMInfo(MI));
252 InWWM = true;
253 continue;
254 }
255
256 if (MI.getOpcode() == AMDGPU::EXIT_STRICT_WWM ||
257 MI.getOpcode() == AMDGPU::EXIT_STRICT_WQM) {
258 LLVM_DEBUG(printWWMInfo(MI));
259 InWWM = false;
260 }
261
262 if (!InWWM)
263 continue;
264
265 LLVM_DEBUG(dbgs() << "Processing " << MI);
266
267 for (MachineOperand &DefOpnd : MI.defs()) {
268 RegsAssigned |= processDef(DefOpnd);
269 }
270 }
271 }
272
273 if (!RegsAssigned)
274 return false;
275
276 rewriteRegs(MF);
277 return true;
278}
279
280PreservedAnalyses
283 auto *LIS = &MFAM.getResult<LiveIntervalsAnalysis>(MF);
284 auto *Matrix = &MFAM.getResult<LiveRegMatrixAnalysis>(MF);
285 auto *VRM = &MFAM.getResult<VirtRegMapAnalysis>(MF);
286 const auto &RCI = MFAM.getResult<MachineRegisterClassAnalysis>(MF);
287 SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
288 // The pass reserves WWM registers, invalidating RegisterClassInfo's
289 // allocation order, so it cannot be preserved (see the legacy
290 // getAnalysisUsage above).
293 return PA;
294}
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:678
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Live Register Matrix
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#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.
static cl::opt< bool > EnablePreallocateSGPRSpillVGPRs("amdgpu-prealloc-sgpr-spill-vgprs", cl::init(false), cl::Hidden)
#define LLVM_DEBUG(...)
Definition Debug.h:119
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
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
const HexagonRegisterInfo & getRegisterInfo() const
LiveInterval - This class represents the liveness of a register, or stack slot.
LiveInterval & getInterval(Register Reg)
void removeInterval(Register Reg)
Interval removal.
@ IK_Free
No interference, go ahead and assign.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
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.
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.
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.
Result run(MachineFunction &, MachineFunctionAnalysisManager &)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
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
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Definition Analysis.h:171
ArrayRef< MCPhysReg > getOrder(const TargetRegisterClass *RC) const
getOrder - Returns the preferred allocation order for RC.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static bool hasVGPRs(const TargetRegisterClass *RC)
MCRegister getPhys(Register virtReg) const
returns the physical register mapped to the specified virtual register
Definition VirtRegMap.h:91
bool hasPhys(Register virtReg) const
returns true if the specified virtual register is mapped to a physical register
Definition VirtRegMap.h:87
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
This is an optimization pass for GlobalISel generic memory operations.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
FunctionPass * createSIPreAllocateWWMRegsLegacyPass()
char & SIPreAllocateWWMRegsLegacyID
bool isPreallocateSGPRSpillVGPRsEnabled(const MachineFunction &MF)