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