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 Andricbool 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 AndricAMDGPUReserveWWMRegsPass::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 Andricbool 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