xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUReserveWWMRegs.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===-- AMDGPUReserveWWMRegs.cpp - Add WWM Regs to reserved regs list -----===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric /// \file
10*700637cbSDimitry Andric /// This pass should be invoked at the end of wwm-regalloc pipeline.
11*700637cbSDimitry Andric /// It identifies the WWM regs allocated during this pipeline and add
12*700637cbSDimitry Andric /// them to the list of reserved registers so that they won't be available for
13*700637cbSDimitry Andric /// per-thread VGPR allocation in the subsequent regalloc pipeline.
14*700637cbSDimitry Andric //
15*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
16*700637cbSDimitry Andric 
17*700637cbSDimitry Andric #include "AMDGPUReserveWWMRegs.h"
18*700637cbSDimitry Andric #include "AMDGPU.h"
19*700637cbSDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
20*700637cbSDimitry Andric #include "SIMachineFunctionInfo.h"
21*700637cbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
22*700637cbSDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric using namespace llvm;
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric #define DEBUG_TYPE "amdgpu-reserve-wwm-regs"
27*700637cbSDimitry Andric 
28*700637cbSDimitry Andric namespace {
29*700637cbSDimitry Andric 
30*700637cbSDimitry Andric class AMDGPUReserveWWMRegsLegacy : public MachineFunctionPass {
31*700637cbSDimitry Andric public:
32*700637cbSDimitry Andric   static char ID;
33*700637cbSDimitry Andric 
AMDGPUReserveWWMRegsLegacy()34*700637cbSDimitry Andric   AMDGPUReserveWWMRegsLegacy() : MachineFunctionPass(ID) {}
35*700637cbSDimitry Andric 
36*700637cbSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
37*700637cbSDimitry Andric 
getPassName() const38*700637cbSDimitry Andric   StringRef getPassName() const override {
39*700637cbSDimitry Andric     return "AMDGPU Reserve WWM Registers";
40*700637cbSDimitry Andric   }
41*700637cbSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const42*700637cbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
43*700637cbSDimitry Andric     AU.setPreservesAll();
44*700637cbSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
45*700637cbSDimitry Andric   }
46*700637cbSDimitry Andric };
47*700637cbSDimitry Andric 
48*700637cbSDimitry Andric class AMDGPUReserveWWMRegs {
49*700637cbSDimitry Andric public:
50*700637cbSDimitry Andric   bool run(MachineFunction &MF);
51*700637cbSDimitry Andric };
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric } // End anonymous namespace.
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric INITIALIZE_PASS(AMDGPUReserveWWMRegsLegacy, DEBUG_TYPE,
56*700637cbSDimitry Andric                 "AMDGPU Reserve WWM Registers", false, false)
57*700637cbSDimitry Andric 
58*700637cbSDimitry Andric char AMDGPUReserveWWMRegsLegacy::ID = 0;
59*700637cbSDimitry Andric 
60*700637cbSDimitry Andric char &llvm::AMDGPUReserveWWMRegsLegacyID = AMDGPUReserveWWMRegsLegacy::ID;
61*700637cbSDimitry Andric 
runOnMachineFunction(MachineFunction & MF)62*700637cbSDimitry Andric bool AMDGPUReserveWWMRegsLegacy::runOnMachineFunction(MachineFunction &MF) {
63*700637cbSDimitry Andric   return AMDGPUReserveWWMRegs().run(MF);
64*700637cbSDimitry Andric }
65*700637cbSDimitry Andric 
66*700637cbSDimitry Andric PreservedAnalyses
run(MachineFunction & MF,MachineFunctionAnalysisManager &)67*700637cbSDimitry Andric AMDGPUReserveWWMRegsPass::run(MachineFunction &MF,
68*700637cbSDimitry Andric                               MachineFunctionAnalysisManager &) {
69*700637cbSDimitry Andric   AMDGPUReserveWWMRegs().run(MF);
70*700637cbSDimitry Andric   // TODO: This should abandon RegisterClassInfo once it is turned into an
71*700637cbSDimitry Andric   // analysis.
72*700637cbSDimitry Andric   return PreservedAnalyses::all();
73*700637cbSDimitry Andric }
74*700637cbSDimitry Andric 
run(MachineFunction & MF)75*700637cbSDimitry Andric bool AMDGPUReserveWWMRegs::run(MachineFunction &MF) {
76*700637cbSDimitry Andric   SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric   bool Changed = false;
79*700637cbSDimitry Andric   for (MachineBasicBlock &MBB : MF) {
80*700637cbSDimitry Andric     for (MachineInstr &MI : MBB) {
81*700637cbSDimitry Andric       unsigned Opc = MI.getOpcode();
82*700637cbSDimitry Andric       if (Opc != AMDGPU::SI_SPILL_S32_TO_VGPR &&
83*700637cbSDimitry Andric           Opc != AMDGPU::SI_RESTORE_S32_FROM_VGPR)
84*700637cbSDimitry Andric         continue;
85*700637cbSDimitry Andric 
86*700637cbSDimitry Andric       Register Reg = Opc == AMDGPU::SI_SPILL_S32_TO_VGPR
87*700637cbSDimitry Andric                          ? MI.getOperand(0).getReg()
88*700637cbSDimitry Andric                          : MI.getOperand(1).getReg();
89*700637cbSDimitry Andric 
90*700637cbSDimitry Andric       assert(Reg.isPhysical() &&
91*700637cbSDimitry Andric              "All WWM registers should have been allocated by now.");
92*700637cbSDimitry Andric 
93*700637cbSDimitry Andric       MFI->reserveWWMRegister(Reg);
94*700637cbSDimitry Andric       Changed |= true;
95*700637cbSDimitry Andric     }
96*700637cbSDimitry Andric   }
97*700637cbSDimitry Andric 
98*700637cbSDimitry Andric   // The renamable flag can't be set for reserved registers. Reset the flag for
99*700637cbSDimitry Andric   // MOs involving wwm-regs as they will be reserved during vgpr-regalloc
100*700637cbSDimitry Andric   // pipeline.
101*700637cbSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
102*700637cbSDimitry Andric   for (Register Reg : MFI->getWWMReservedRegs()) {
103*700637cbSDimitry Andric     for (MachineOperand &MO : MRI.reg_operands(Reg))
104*700637cbSDimitry Andric       MO.setIsRenamable(false);
105*700637cbSDimitry Andric   }
106*700637cbSDimitry Andric 
107*700637cbSDimitry Andric   // Now clear the NonWWMRegMask earlier set during wwm-regalloc.
108*700637cbSDimitry Andric   MFI->clearNonWWMRegAllocMask();
109*700637cbSDimitry Andric 
110*700637cbSDimitry Andric   return Changed;
111*700637cbSDimitry Andric }
112