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
20using namespace llvm;
21
22static 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: 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(V: &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: I);
70 if (!MO.isReg() || !MO.isDef())
71 continue;
72
73 if (KeepDefs.count(V: &MO))
74 continue;
75
76 TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg());
77 if (!RegPair.Reg.isVirtual())
78 continue;
79
80 if (!DeleteDefs.insert(V: RegPair).second)
81 continue;
82
83 if (MRI.use_empty(RegNo: RegPair.Reg)) {
84 if (I >= NumRequiredOps) {
85 // Delete implicit def operands that aren't part of the instruction
86 // definition
87 MI.removeOperand(OpNo: 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(VReg: MO.getReg()));
97
98 bool IsGeneric = MRI.getRegClassOrNull(Reg: RegPair.Reg) == nullptr;
99 unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
100 : TargetOpcode::IMPLICIT_DEF;
101
102 RegState OpFlags = getRegState(RegOp: MO) & ~RegState::Implicit;
103 InsPt = BuildMI(BB&: MBB, I: InsPt, MIMD: DebugLoc(), MCID: TII->get(Opcode: ImpDef))
104 .addReg(RegNo: RegPair.Reg, Flags: OpFlags, SubReg: RegPair.SubReg);
105 }
106
107 if (!HaveKeptDef)
108 MI.eraseFromParent();
109 }
110 }
111}
112
113void llvm::reduceRegisterDefsMIRDeltaPass(Oracle &O,
114 ReducerWorkItem &WorkItem) {
115 for (const Function &F : WorkItem.getModule()) {
116 if (auto *MF = WorkItem.MMI->getMachineFunction(F))
117 removeDefsFromFunction(O, MF&: *MF);
118 }
119}
120