xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchDeadRegisterDefinitions.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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