1*0fca6ea1SDimitry Andric //=== LoongArchDeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg ===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===---------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This pass rewrites Rd to r0 for instrs whose return values are unused. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===---------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "LoongArch.h" 14*0fca6ea1SDimitry Andric #include "LoongArchInstrInfo.h" 15*0fca6ea1SDimitry Andric #include "LoongArchSubtarget.h" 16*0fca6ea1SDimitry Andric #include "llvm/ADT/Statistic.h" 17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveDebugVariables.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 19*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveStacks.h" 20*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 22*0fca6ea1SDimitry Andric 23*0fca6ea1SDimitry Andric using namespace llvm; 24*0fca6ea1SDimitry Andric #define DEBUG_TYPE "loongarch-dead-defs" 25*0fca6ea1SDimitry Andric #define LoongArch_DEAD_REG_DEF_NAME "LoongArch Dead register definitions" 26*0fca6ea1SDimitry Andric 27*0fca6ea1SDimitry Andric STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced"); 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric namespace { 30*0fca6ea1SDimitry Andric class LoongArchDeadRegisterDefinitions : public MachineFunctionPass { 31*0fca6ea1SDimitry Andric public: 32*0fca6ea1SDimitry Andric static char ID; 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric LoongArchDeadRegisterDefinitions() : MachineFunctionPass(ID) {} 35*0fca6ea1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 36*0fca6ea1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 37*0fca6ea1SDimitry Andric AU.setPreservesCFG(); 38*0fca6ea1SDimitry Andric AU.addRequired<LiveIntervalsWrapperPass>(); 39*0fca6ea1SDimitry Andric AU.addPreserved<LiveIntervalsWrapperPass>(); 40*0fca6ea1SDimitry Andric AU.addRequired<LiveIntervalsWrapperPass>(); 41*0fca6ea1SDimitry Andric AU.addPreserved<SlotIndexesWrapperPass>(); 42*0fca6ea1SDimitry Andric AU.addPreserved<LiveDebugVariables>(); 43*0fca6ea1SDimitry Andric AU.addPreserved<LiveStacks>(); 44*0fca6ea1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 45*0fca6ea1SDimitry Andric } 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric StringRef getPassName() const override { return LoongArch_DEAD_REG_DEF_NAME; } 48*0fca6ea1SDimitry Andric }; 49*0fca6ea1SDimitry Andric } // end anonymous namespace 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric char LoongArchDeadRegisterDefinitions::ID = 0; 52*0fca6ea1SDimitry Andric INITIALIZE_PASS(LoongArchDeadRegisterDefinitions, DEBUG_TYPE, 53*0fca6ea1SDimitry Andric LoongArch_DEAD_REG_DEF_NAME, false, false) 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric FunctionPass *llvm::createLoongArchDeadRegisterDefinitionsPass() { 56*0fca6ea1SDimitry Andric return new LoongArchDeadRegisterDefinitions(); 57*0fca6ea1SDimitry Andric } 58*0fca6ea1SDimitry Andric 59*0fca6ea1SDimitry Andric bool LoongArchDeadRegisterDefinitions::runOnMachineFunction( 60*0fca6ea1SDimitry Andric MachineFunction &MF) { 61*0fca6ea1SDimitry Andric if (skipFunction(MF.getFunction())) 62*0fca6ea1SDimitry Andric return false; 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 65*0fca6ea1SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 66*0fca6ea1SDimitry Andric LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS(); 67*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "***** LoongArchDeadRegisterDefinitions *****\n"); 68*0fca6ea1SDimitry Andric 69*0fca6ea1SDimitry Andric bool MadeChange = false; 70*0fca6ea1SDimitry Andric for (MachineBasicBlock &MBB : MF) { 71*0fca6ea1SDimitry Andric for (MachineInstr &MI : MBB) { 72*0fca6ea1SDimitry Andric // We only handle non-computational instructions. 73*0fca6ea1SDimitry Andric const MCInstrDesc &Desc = MI.getDesc(); 74*0fca6ea1SDimitry Andric if (!Desc.mayLoad() && !Desc.mayStore() && 75*0fca6ea1SDimitry Andric !Desc.hasUnmodeledSideEffects()) 76*0fca6ea1SDimitry Andric continue; 77*0fca6ea1SDimitry Andric for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) { 78*0fca6ea1SDimitry Andric MachineOperand &MO = MI.getOperand(I); 79*0fca6ea1SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.isEarlyClobber()) 80*0fca6ea1SDimitry Andric continue; 81*0fca6ea1SDimitry Andric // Be careful not to change the register if it's a tied operand. 82*0fca6ea1SDimitry Andric if (MI.isRegTiedToUseOperand(I)) { 83*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " Ignoring, def is tied operand.\n"); 84*0fca6ea1SDimitry Andric continue; 85*0fca6ea1SDimitry Andric } 86*0fca6ea1SDimitry Andric Register Reg = MO.getReg(); 87*0fca6ea1SDimitry Andric if (!Reg.isVirtual() || !MO.isDead()) 88*0fca6ea1SDimitry Andric continue; 89*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " Dead def operand #" << I << " in:\n "; 90*0fca6ea1SDimitry Andric MI.print(dbgs())); 91*0fca6ea1SDimitry Andric const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF); 92*0fca6ea1SDimitry Andric if (!(RC && RC->contains(LoongArch::R0))) { 93*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n"); 94*0fca6ea1SDimitry Andric continue; 95*0fca6ea1SDimitry Andric } 96*0fca6ea1SDimitry Andric assert(LIS.hasInterval(Reg)); 97*0fca6ea1SDimitry Andric LIS.removeInterval(Reg); 98*0fca6ea1SDimitry Andric MO.setReg(LoongArch::R0); 99*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " Replacing with zero register. New:\n "; 100*0fca6ea1SDimitry Andric MI.print(dbgs())); 101*0fca6ea1SDimitry Andric ++NumDeadDefsReplaced; 102*0fca6ea1SDimitry Andric MadeChange = true; 103*0fca6ea1SDimitry Andric } 104*0fca6ea1SDimitry Andric } 105*0fca6ea1SDimitry Andric } 106*0fca6ea1SDimitry Andric 107*0fca6ea1SDimitry Andric return MadeChange; 108*0fca6ea1SDimitry Andric } 109