1 //===- SIPreAllocateWWMRegs.cpp - WWM Register Pre-allocation -------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// Pass to pre-allocated WWM registers
12 //===----------------------------------------------------------------------===//
15 #include "GCNSubtarget.h"
16 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
17 #include "SIMachineFunctionInfo.h"
18 #include "llvm/ADT/PostOrderIterator.h"
19 #include "llvm/CodeGen/LiveIntervals.h"
20 #include "llvm/CodeGen/LiveRegMatrix.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/InitializePasses.h"
26 #define DEBUG_TYPE "si-pre-allocate-wwm-regs"
30 class SIPreAllocateWWMRegs
: public MachineFunctionPass
{
32 const SIInstrInfo
*TII
;
33 const SIRegisterInfo
*TRI
;
34 MachineRegisterInfo
*MRI
;
36 LiveRegMatrix
*Matrix
;
38 RegisterClassInfo RegClassInfo
;
40 std::vector
<unsigned> RegsToRewrite
;
42 void printWWMInfo(const MachineInstr
&MI
);
48 SIPreAllocateWWMRegs() : MachineFunctionPass(ID
) {
49 initializeSIPreAllocateWWMRegsPass(*PassRegistry::getPassRegistry());
52 bool runOnMachineFunction(MachineFunction
&MF
) override
;
54 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
55 AU
.addRequired
<LiveIntervals
>();
56 AU
.addPreserved
<LiveIntervals
>();
57 AU
.addRequired
<VirtRegMap
>();
58 AU
.addRequired
<LiveRegMatrix
>();
59 AU
.addPreserved
<SlotIndexes
>();
61 MachineFunctionPass::getAnalysisUsage(AU
);
65 bool processDef(MachineOperand
&MO
);
66 void rewriteRegs(MachineFunction
&MF
);
69 } // End anonymous namespace.
71 INITIALIZE_PASS_BEGIN(SIPreAllocateWWMRegs
, DEBUG_TYPE
,
72 "SI Pre-allocate WWM Registers", false, false)
73 INITIALIZE_PASS_DEPENDENCY(LiveIntervals
)
74 INITIALIZE_PASS_DEPENDENCY(VirtRegMap
)
75 INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix
)
76 INITIALIZE_PASS_END(SIPreAllocateWWMRegs
, DEBUG_TYPE
,
77 "SI Pre-allocate WWM Registers", false, false)
79 char SIPreAllocateWWMRegs::ID
= 0;
81 char &llvm::SIPreAllocateWWMRegsID
= SIPreAllocateWWMRegs::ID
;
83 FunctionPass
*llvm::createSIPreAllocateWWMRegsPass() {
84 return new SIPreAllocateWWMRegs();
87 bool SIPreAllocateWWMRegs::processDef(MachineOperand
&MO
) {
91 Register Reg
= MO
.getReg();
95 if (!TRI
->isVGPR(*MRI
, Reg
))
98 if (VRM
->hasPhys(Reg
))
101 LiveInterval
&LI
= LIS
->getInterval(Reg
);
103 for (MCRegister PhysReg
: RegClassInfo
.getOrder(MRI
->getRegClass(Reg
))) {
104 if (!MRI
->isPhysRegUsed(PhysReg
) &&
105 Matrix
->checkInterference(LI
, PhysReg
) == LiveRegMatrix::IK_Free
) {
106 Matrix
->assign(LI
, PhysReg
);
107 assert(PhysReg
!= 0);
108 RegsToRewrite
.push_back(Reg
);
113 llvm_unreachable("physreg not found for WWM expression");
117 void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction
&MF
) {
118 for (MachineBasicBlock
&MBB
: MF
) {
119 for (MachineInstr
&MI
: MBB
) {
120 for (MachineOperand
&MO
: MI
.operands()) {
124 const Register VirtReg
= MO
.getReg();
125 if (VirtReg
.isPhysical())
128 if (!VRM
->hasPhys(VirtReg
))
131 Register PhysReg
= VRM
->getPhys(VirtReg
);
132 const unsigned SubReg
= MO
.getSubReg();
134 PhysReg
= TRI
->getSubReg(PhysReg
, SubReg
);
139 MO
.setIsRenamable(false);
144 SIMachineFunctionInfo
*MFI
= MF
.getInfo
<SIMachineFunctionInfo
>();
145 MachineFrameInfo
&FrameInfo
= MF
.getFrameInfo();
147 for (unsigned Reg
: RegsToRewrite
) {
148 LIS
->removeInterval(Reg
);
150 const Register PhysReg
= VRM
->getPhys(Reg
);
151 assert(PhysReg
!= 0);
153 // Check if PhysReg is already reserved
154 if (!MFI
->WWMReservedRegs
.count(PhysReg
)) {
156 if (!MFI
->isEntryFunction()) {
157 // Create a stack object for a possible spill in the function prologue.
158 // Note: Non-CSR VGPR also need this as we may overwrite inactive lanes.
159 const TargetRegisterClass
*RC
= TRI
->getPhysRegClass(PhysReg
);
160 FI
= FrameInfo
.CreateSpillStackObject(TRI
->getSpillSize(*RC
),
161 TRI
->getSpillAlign(*RC
));
163 MFI
->reserveWWMRegister(PhysReg
, FI
);
167 RegsToRewrite
.clear();
169 // Update the set of reserved registers to include WWM ones.
170 MRI
->freezeReservedRegs(MF
);
174 LLVM_DUMP_METHOD
void
175 SIPreAllocateWWMRegs::printWWMInfo(const MachineInstr
&MI
) {
177 unsigned Opc
= MI
.getOpcode();
179 if (Opc
== AMDGPU::ENTER_STRICT_WWM
|| Opc
== AMDGPU::ENTER_STRICT_WQM
) {
180 dbgs() << "Entering ";
182 assert(Opc
== AMDGPU::EXIT_STRICT_WWM
|| Opc
== AMDGPU::EXIT_STRICT_WQM
);
183 dbgs() << "Exiting ";
186 if (Opc
== AMDGPU::ENTER_STRICT_WWM
|| Opc
== AMDGPU::EXIT_STRICT_WWM
) {
187 dbgs() << "Strict WWM ";
189 assert(Opc
== AMDGPU::ENTER_STRICT_WQM
|| Opc
== AMDGPU::EXIT_STRICT_WQM
);
190 dbgs() << "Strict WQM ";
193 dbgs() << "region: " << MI
;
198 bool SIPreAllocateWWMRegs::runOnMachineFunction(MachineFunction
&MF
) {
199 LLVM_DEBUG(dbgs() << "SIPreAllocateWWMRegs: function " << MF
.getName() << "\n");
201 const GCNSubtarget
&ST
= MF
.getSubtarget
<GCNSubtarget
>();
203 TII
= ST
.getInstrInfo();
204 TRI
= &TII
->getRegisterInfo();
205 MRI
= &MF
.getRegInfo();
207 LIS
= &getAnalysis
<LiveIntervals
>();
208 Matrix
= &getAnalysis
<LiveRegMatrix
>();
209 VRM
= &getAnalysis
<VirtRegMap
>();
211 RegClassInfo
.runOnMachineFunction(MF
);
213 bool RegsAssigned
= false;
215 // We use a reverse post-order traversal of the control-flow graph to
216 // guarantee that we visit definitions in dominance order. Since WWM
217 // expressions are guaranteed to never involve phi nodes, and we can only
218 // escape WWM through the special WWM instruction, this means that this is a
219 // perfect elimination order, so we can never do any better.
220 ReversePostOrderTraversal
<MachineFunction
*> RPOT(&MF
);
222 for (MachineBasicBlock
*MBB
: RPOT
) {
224 for (MachineInstr
&MI
: *MBB
) {
225 if (MI
.getOpcode() == AMDGPU::V_SET_INACTIVE_B32
||
226 MI
.getOpcode() == AMDGPU::V_SET_INACTIVE_B64
)
227 RegsAssigned
|= processDef(MI
.getOperand(0));
229 if (MI
.getOpcode() == AMDGPU::ENTER_STRICT_WWM
||
230 MI
.getOpcode() == AMDGPU::ENTER_STRICT_WQM
) {
231 LLVM_DEBUG(printWWMInfo(MI
));
236 if (MI
.getOpcode() == AMDGPU::EXIT_STRICT_WWM
||
237 MI
.getOpcode() == AMDGPU::EXIT_STRICT_WQM
) {
238 LLVM_DEBUG(printWWMInfo(MI
));
245 LLVM_DEBUG(dbgs() << "Processing " << MI
);
247 for (MachineOperand
&DefOpnd
: MI
.defs()) {
248 RegsAssigned
|= processDef(DefOpnd
);