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"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "si-pre-allocate-wwm-regs"
30
31static cl::opt<bool>
32 EnablePreallocateSGPRSpillVGPRs("amdgpu-prealloc-sgpr-spill-vgprs",
33 cl::init(false), cl::Hidden);
34
37 MF.getFunction().hasFnAttribute("amdgpu-prealloc-sgpr-spill-vgprs");
38}
39
40namespace {
41
42class SIPreAllocateWWMRegs {
43private:
44 const SIInstrInfo *TII;
45 const SIRegisterInfo *TRI;
47 LiveIntervals *LIS;
49 VirtRegMap *VRM;
51
52 std::vector<unsigned> RegsToRewrite;
53#ifndef NDEBUG
54 void printWWMInfo(const MachineInstr &MI);
55#endif
56 bool processDef(MachineOperand &MO);
57 void rewriteRegs(MachineFunction &MF);
58
59public:
60 SIPreAllocateWWMRegs(LiveIntervals *LIS, LiveRegMatrix *Matrix,
62 : LIS(LIS), Matrix(Matrix), VRM(VRM), RCI(RCI) {}
63 bool run(MachineFunction &MF);
64};
65
66class SIPreAllocateWWMRegsLegacy : public MachineFunctionPass {
67public:
68 static char ID;
69
70 SIPreAllocateWWMRegsLegacy() : MachineFunctionPass(ID) {}
71
72 bool runOnMachineFunction(MachineFunction &MF) override;
73
74 void getAnalysisUsage(AnalysisUsage &AU) const override {
75 AU.addRequired<LiveIntervalsWrapperPass>();
76 AU.addRequired<VirtRegMapWrapperLegacy>();
77 AU.addRequired<LiveRegMatrixWrapperLegacy>();
78 AU.addRequired<MachineRegisterClassInfoWrapperPass>();
79 AU.setPreservesAll();
81 }
82};
83
84} // End anonymous namespace.
85
86INITIALIZE_PASS_BEGIN(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
87 "SI Pre-allocate WWM Registers", false, false)
92INITIALIZE_PASS_END(SIPreAllocateWWMRegsLegacy, DEBUG_TYPE,
93 "SI Pre-allocate WWM Registers", false, false)
94
95char SIPreAllocateWWMRegsLegacy::ID = 0;
96
97char &llvm::SIPreAllocateWWMRegsLegacyID = SIPreAllocateWWMRegsLegacy::ID;
98
99bool SIPreAllocateWWMRegs::processDef(MachineOperand &MO) {
100 Register Reg = MO.getReg();
101 if (Reg.isPhysical())
102 return false;
103
104 if (!SIRegisterInfo::hasVGPRs(MRI->getRegClass(Reg)))
105 return false;
106
107 if (VRM->hasPhys(Reg))
108 return false;
109
110 LiveInterval &LI = LIS->getInterval(Reg);
111
112 for (MCRegister PhysReg : RCI.getOrder(MRI->getRegClass(Reg))) {
113 if (!MRI->isPhysRegUsed(PhysReg, /*SkipRegMaskTest=*/true) &&
114 Matrix->checkInterference(LI, PhysReg) == LiveRegMatrix::IK_Free) {
115 Matrix->assign(LI, PhysReg);
116 assert(PhysReg != 0);
117 RegsToRewrite.push_back(Reg);
118 return true;
119 }
120 }
121
122 llvm_unreachable("physreg not found for WWM expression");
123}
124
125void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) {
126 for (MachineBasicBlock &MBB : MF) {
127 for (MachineInstr &MI : MBB) {
128 for (MachineOperand &MO : MI.operands()) {
129 if (!MO.isReg())
130 continue;
131
132 const Register VirtReg = MO.getReg();
133 if (VirtReg.isPhysical())
134 continue;
135
136 if (!VirtReg.isValid())
137 continue;
138
139 if (!VRM->hasPhys(VirtReg))
140 continue;
141
142 Register PhysReg = VRM->getPhys(VirtReg);
143 const unsigned SubReg = MO.getSubReg();
144 if (SubReg != 0) {
145 PhysReg = TRI->getSubReg(PhysReg, SubReg);
146 MO.setSubReg(0);
147 }
148
149 MO.setReg(PhysReg);
150 MO.setIsRenamable(false);
151 }
152 }
153 }
154
155 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
156
157 for (unsigned Reg : RegsToRewrite) {
158 const Register PhysReg = VRM->getPhys(Reg);
159 assert(PhysReg != 0);
160
161 LiveInterval &LI = LIS->getInterval(Reg);
162 Matrix->unassign(LI, /*ClearAllReferencingSegments=*/true);
163 LIS->removeInterval(Reg);
164
165 MFI->reserveWWMRegister(PhysReg);
166 }
167
168 RegsToRewrite.clear();
169
170 // Update the set of reserved registers to include WWM ones
171 // without unnecessarily invalidating RegClassInfo.
172 MRI->freezeReservedRegs();
174}
175
176#ifndef NDEBUG
178SIPreAllocateWWMRegs::printWWMInfo(const MachineInstr &MI) {
179
180 unsigned Opc = MI.getOpcode();
181
182 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::ENTER_STRICT_WQM) {
183 dbgs() << "Entering ";
184 } else {
185 assert(Opc == AMDGPU::EXIT_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WQM);
186 dbgs() << "Exiting ";
187 }
188
189 if (Opc == AMDGPU::ENTER_STRICT_WWM || Opc == AMDGPU::EXIT_STRICT_WWM) {
190 dbgs() << "Strict WWM ";
191 } else {
192 assert(Opc == AMDGPU::ENTER_STRICT_WQM || Opc == AMDGPU::EXIT_STRICT_WQM);
193 dbgs() << "Strict WQM ";
194 }
195
196 dbgs() << "region: " << MI;
197}
198
199#endif
200
201bool SIPreAllocateWWMRegsLegacy::runOnMachineFunction(MachineFunction &MF) {
202 auto *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
203 auto *Matrix = &getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
204 auto *VRM = &getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
205 auto &RCI = getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
206 return SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
207}
208
209bool SIPreAllocateWWMRegs::run(MachineFunction &MF) {
210 LLVM_DEBUG(dbgs() << "SIPreAllocateWWMRegs: function " << MF.getName() << "\n");
211
212 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
213
214 TII = ST.getInstrInfo();
215 TRI = &TII->getRegisterInfo();
216 MRI = &MF.getRegInfo();
217
218 bool PreallocateSGPRSpillVGPRs = isPreallocateSGPRSpillVGPRsEnabled(MF);
219
220 bool RegsAssigned = false;
221
222 // We use a reverse post-order traversal of the control-flow graph to
223 // guarantee that we visit definitions in dominance order. Since WWM
224 // expressions are guaranteed to never involve phi nodes, and we can only
225 // escape WWM through the special WWM instruction, this means that this is a
226 // perfect elimination order, so we can never do any better.
227 ReversePostOrderTraversal<MachineFunction*> RPOT(&MF);
228
229 for (MachineBasicBlock *MBB : RPOT) {
230 bool InWWM = false;
231 for (MachineInstr &MI : *MBB) {
232 if (MI.getOpcode() == AMDGPU::SI_SPILL_S32_TO_VGPR) {
233 if (PreallocateSGPRSpillVGPRs)
234 RegsAssigned |= processDef(MI.getOperand(0));
235 continue;
236 }
237
238 if (MI.getOpcode() == AMDGPU::ENTER_STRICT_WWM ||
239 MI.getOpcode() == AMDGPU::ENTER_STRICT_WQM) {
240 LLVM_DEBUG(printWWMInfo(MI));
241 InWWM = true;
242 continue;
243 }
244
245 if (MI.getOpcode() == AMDGPU::EXIT_STRICT_WWM ||
246 MI.getOpcode() == AMDGPU::EXIT_STRICT_WQM) {
247 LLVM_DEBUG(printWWMInfo(MI));
248 InWWM = false;
249 }
250
251 if (!InWWM)
252 continue;
253
254 LLVM_DEBUG(dbgs() << "Processing " << MI);
255
256 for (MachineOperand &DefOpnd : MI.defs()) {
257 RegsAssigned |= processDef(DefOpnd);
258 }
259 }
260 }
261
262 if (!RegsAssigned)
263 return false;
264
265 rewriteRegs(MF);
266 return true;
267}
268
269PreservedAnalyses
272 auto *LIS = &MFAM.getResult<LiveIntervalsAnalysis>(MF);
273 auto *Matrix = &MFAM.getResult<LiveRegMatrixAnalysis>(MF);
274 auto *VRM = &MFAM.getResult<VirtRegMapAnalysis>(MF);
275 auto &RCI = MFAM.getResult<MachineRegisterClassAnalysis>(MF);
276 SIPreAllocateWWMRegs(LIS, Matrix, VRM, RCI).run(MF);
277 return PreservedAnalyses::all();
278}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:686
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
if(PassOpts->AAPipeline)
#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()
void setPreservesAll()
Set by analyses that do not transform their input at all.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:734
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.
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.
LLVM_ABI 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 BitVector & getReservedRegs() const
getReservedRegs - Returns a reference to the frozen set of reserved registers.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
LLVM_ABI void updateReservedRegs(const BitVector &ReservedInput)
Update cached register class information using ReservedInput, MRI's current reserved-register set.
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)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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
char & SIPreAllocateWWMRegsLegacyID
bool isPreallocateSGPRSpillVGPRsEnabled(const MachineFunction &MF)