xref: /llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp (revision 073401e59c8c0e03e06be1d516fe8ea821146d2f)
1 //===- ReduceRegisterDefs.cpp - Specialized Delta Pass --------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting register uses from the MachineFunction.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ReduceRegisterDefs.h"
15 #include "llvm/CodeGen/MachineFunction.h"
16 #include "llvm/CodeGen/MachineModuleInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/TargetInstrInfo.h"
19 
20 using namespace llvm;
21 
removeDefsFromFunction(Oracle & O,MachineFunction & MF)22 static void removeDefsFromFunction(Oracle &O, MachineFunction &MF) {
23   MachineRegisterInfo &MRI = MF.getRegInfo();
24   const TargetSubtargetInfo &STI = MF.getSubtarget();
25   const TargetInstrInfo *TII = STI.getInstrInfo();
26 
27   DenseSet<MachineOperand *> KeepDefs;
28   DenseSet<TargetInstrInfo::RegSubRegPair> DeleteDefs;
29 
30   for (MachineBasicBlock &MBB : MF) {
31     for (MachineBasicBlock::iterator It = MBB.begin(),
32                                      E = MBB.getFirstTerminator();
33          It != E;) {
34       MachineBasicBlock::iterator InsPt = It;
35       MachineInstr &MI = *It;
36       ++It;
37 
38       KeepDefs.clear();
39       DeleteDefs.clear();
40 
41       int NumOperands = MI.getNumOperands();
42       int NumRequiredOps = MI.getNumExplicitOperands() +
43                            MI.getDesc().implicit_defs().size() +
44                            MI.getDesc().implicit_uses().size();
45 
46       bool HaveDelete = false;
47       // Do an initial scan in case the instruction defines the same register
48       // multiple times.
49       for (int I = NumOperands - 1; I >= 0; --I) {
50         MachineOperand &MO = MI.getOperand(I);
51         if (!MO.isReg() || !MO.isDef())
52           continue;
53 
54         TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg());
55         if (!RegPair.Reg.isVirtual())
56           continue;
57 
58         if (O.shouldKeep())
59           KeepDefs.insert(&MO);
60         else
61           HaveDelete = true;
62       }
63 
64       if (!HaveDelete)
65         continue;
66 
67       bool HaveKeptDef = !KeepDefs.empty();
68       for (int I = NumOperands - 1; I >= 0; --I) {
69         MachineOperand &MO = MI.getOperand(I);
70         if (!MO.isReg() || !MO.isDef())
71           continue;
72 
73         if (KeepDefs.count(&MO))
74           continue;
75 
76         TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg());
77         if (!RegPair.Reg.isVirtual())
78           continue;
79 
80         if (!DeleteDefs.insert(RegPair).second)
81           continue;
82 
83         if (MRI.use_empty(RegPair.Reg)) {
84           if (I >= NumRequiredOps) {
85             // Delete implicit def operands that aren't part of the instruction
86             // definition
87             MI.removeOperand(I);
88           }
89 
90           continue;
91         }
92 
93         // If we aren't going to delete the instruction, replace it with a dead
94         // def.
95         if (HaveKeptDef)
96           MO.setReg(MRI.cloneVirtualRegister(MO.getReg()));
97 
98         bool IsGeneric = MRI.getRegClassOrNull(RegPair.Reg) == nullptr;
99         unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
100                                     : TargetOpcode::IMPLICIT_DEF;
101 
102         unsigned OpFlags = getRegState(MO) & ~RegState::Implicit;
103         InsPt = BuildMI(MBB, InsPt, DebugLoc(), TII->get(ImpDef))
104           .addReg(RegPair.Reg, OpFlags, RegPair.SubReg);
105       }
106 
107       if (!HaveKeptDef)
108         MI.eraseFromParent();
109     }
110   }
111 }
112 
removeDefsFromModule(Oracle & O,ReducerWorkItem & WorkItem)113 static void removeDefsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
114   for (const Function &F : WorkItem.getModule()) {
115     if (auto *MF = WorkItem.MMI->getMachineFunction(F))
116       removeDefsFromFunction(O, *MF);
117   }
118 }
119 
reduceRegisterDefsMIRDeltaPass(TestRunner & Test)120 void llvm::reduceRegisterDefsMIRDeltaPass(TestRunner &Test) {
121   runDeltaPass(Test, removeDefsFromModule, "Reducing register defs");
122 }
123