1 //===- ReduceInstructionsMIR.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 MachineInstr from the MachineFunction.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ReduceInstructionsMIR.h"
15 #include "Delta.h"
16 
17 #include "llvm/ADT/SetVector.h"
18 #include "llvm/CodeGen/MachineDominators.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/CodeGen/TargetInstrInfo.h"
23 
24 using namespace llvm;
25 
getPrevDefOfRCInMBB(MachineBasicBlock & MBB,MachineBasicBlock::reverse_iterator & RI,const RegClassOrRegBank & RC,LLT Ty,SetVector<MachineInstr * > & ExcludeMIs)26 static Register getPrevDefOfRCInMBB(MachineBasicBlock &MBB,
27                                     MachineBasicBlock::reverse_iterator &RI,
28                                     const RegClassOrRegBank &RC, LLT Ty,
29                                     SetVector<MachineInstr *> &ExcludeMIs) {
30   auto MRI = &MBB.getParent()->getRegInfo();
31   for (MachineBasicBlock::reverse_instr_iterator E = MBB.instr_rend(); RI != E;
32        ++RI) {
33     auto &MI = *RI;
34     // All Def operands explicit and implicit.
35     for (auto &MO : MI.operands()) {
36       if (!MO.isReg() || !MO.isDef())
37         continue;
38       auto Reg = MO.getReg();
39       if (Register::isPhysicalRegister(Reg))
40         continue;
41 
42       if (MRI->getRegClassOrRegBank(Reg) == RC && MRI->getType(Reg) == Ty &&
43           !ExcludeMIs.count(MO.getParent()))
44         return Reg;
45     }
46   }
47   return 0;
48 }
49 
shouldNotRemoveInstruction(const TargetInstrInfo & TII,const MachineInstr & MI)50 static bool shouldNotRemoveInstruction(const TargetInstrInfo &TII,
51                                        const MachineInstr &MI) {
52   if (MI.isTerminator())
53     return true;
54 
55   // The MIR is almost certainly going to be invalid if frame instructions are
56   // deleted individually since they need to come in balanced pairs, so don't
57   // try to delete them.
58   if (MI.getOpcode() == TII.getCallFrameSetupOpcode() ||
59       MI.getOpcode() == TII.getCallFrameDestroyOpcode())
60     return true;
61 
62   return false;
63 }
64 
extractInstrFromFunction(Oracle & O,MachineFunction & MF)65 static void extractInstrFromFunction(Oracle &O, MachineFunction &MF) {
66   MachineDominatorTree MDT;
67   MDT.runOnMachineFunction(MF);
68 
69   auto MRI = &MF.getRegInfo();
70   SetVector<MachineInstr *> ToDelete;
71 
72   const TargetSubtargetInfo &STI = MF.getSubtarget();
73   const TargetInstrInfo *TII = STI.getInstrInfo();
74   MachineBasicBlock *EntryMBB = &*MF.begin();
75   MachineBasicBlock::iterator EntryInsPt =
76       EntryMBB->SkipPHIsLabelsAndDebug(EntryMBB->begin());
77 
78   // Mark MIs for deletion according to some criteria.
79   for (auto &MBB : MF) {
80     for (auto &MI : MBB) {
81       if (shouldNotRemoveInstruction(*TII, MI))
82         continue;
83       if (!O.shouldKeep())
84         ToDelete.insert(&MI);
85     }
86   }
87 
88   // For each MI to be deleted update users of regs defined by that MI to use
89   // some other dominating definition (that is not to be deleted).
90   for (auto *MI : ToDelete) {
91     for (auto &MO : MI->operands()) {
92       if (!MO.isReg() || !MO.isDef())
93         continue;
94       auto Reg = MO.getReg();
95       if (Register::isPhysicalRegister(Reg))
96         continue;
97       auto UI = MRI->use_begin(Reg);
98       auto UE = MRI->use_end();
99 
100       const auto &RegRC = MRI->getRegClassOrRegBank(Reg);
101       LLT RegTy = MRI->getType(Reg);
102 
103       Register NewReg = 0;
104       // If this is not a physical register and there are some uses.
105       if (UI != UE) {
106         MachineBasicBlock::reverse_iterator RI(*MI);
107         MachineBasicBlock *BB = MI->getParent();
108         ++RI;
109 
110         if (MDT.isReachableFromEntry(BB)) {
111           while (NewReg == 0 && BB) {
112             NewReg = getPrevDefOfRCInMBB(*BB, RI, RegRC, RegTy, ToDelete);
113             // Prepare for idom(BB).
114             if (auto *IDM = MDT.getNode(BB)->getIDom()) {
115               BB = IDM->getBlock();
116               RI = BB->rbegin();
117             } else {
118               BB = nullptr;
119             }
120           }
121         }
122       }
123 
124       // If no dominating definition was found then add an implicit def to the
125       // top of the entry block.
126       if (!NewReg) {
127         NewReg = MRI->cloneVirtualRegister(Reg);
128         bool IsGeneric = MRI->getRegClassOrNull(Reg) == nullptr;
129         unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
130                                     : TargetOpcode::IMPLICIT_DEF;
131         BuildMI(*EntryMBB, EntryInsPt, DebugLoc(), TII->get(ImpDef))
132           .addReg(NewReg, getRegState(MO), MO.getSubReg());
133       }
134 
135       // Update all uses.
136       while (UI != UE) {
137         auto &UMO = *UI++;
138         UMO.setReg(NewReg);
139       }
140     }
141   }
142 
143   // Finally delete the MIs.
144   for (auto *MI : ToDelete)
145     MI->eraseFromParent();
146 }
147 
extractInstrFromModule(Oracle & O,ReducerWorkItem & WorkItem)148 static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
149   for (const Function &F : WorkItem.getModule()) {
150     if (MachineFunction *MF = WorkItem.MMI->getMachineFunction(F))
151       extractInstrFromFunction(O, *MF);
152   }
153 }
154 
reduceInstructionsMIRDeltaPass(TestRunner & Test)155 void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) {
156   outs() << "*** Reducing Instructions...\n";
157   runDeltaPass(Test, extractInstrFromModule);
158 }
159