Define a statistic for the number of slots that were filled with useful
[oota-llvm.git] / lib / Target / Mips / MipsDelaySlotFiller.cpp
1 //===-- DelaySlotFiller.cpp - Mips delay slot filler ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Simple pass to fills delay slots with useful instructions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "delay-slot-filler"
15
16 #include "Mips.h"
17 #include "MipsTargetMachine.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Target/TargetMachine.h"
22 #include "llvm/Target/TargetInstrInfo.h"
23 #include "llvm/Target/TargetRegisterInfo.h"
24 #include "llvm/ADT/SmallSet.h"
25 #include "llvm/ADT/Statistic.h"
26
27 using namespace llvm;
28
29 STATISTIC(FilledSlots, "Number of delay slots filled");
30 STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
31                        "are not NOP.");
32
33 static cl::opt<bool> EnableDelaySlotFiller(
34   "enable-mips-delay-filler",
35   cl::init(false),
36   cl::desc("Fill the Mips delay slots useful instructions."),
37   cl::Hidden);
38
39 namespace {
40   struct Filler : public MachineFunctionPass {
41
42     TargetMachine &TM;
43     const TargetInstrInfo *TII;
44
45     static char ID;
46     Filler(TargetMachine &tm)
47       : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { }
48
49     virtual const char *getPassName() const {
50       return "Mips Delay Slot Filler";
51     }
52
53     bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
54     bool runOnMachineFunction(MachineFunction &F) {
55       bool Changed = false;
56       for (MachineFunction::iterator FI = F.begin(), FE = F.end();
57            FI != FE; ++FI)
58         Changed |= runOnMachineBasicBlock(*FI);
59       return Changed;
60     }
61
62     bool isDelayFiller(MachineBasicBlock &MBB,
63                        MachineBasicBlock::iterator candidate);
64
65     void insertCallUses(MachineBasicBlock::iterator MI,
66                         SmallSet<unsigned, 32>& RegDefs,
67                         SmallSet<unsigned, 32>& RegUses);
68
69     void insertDefsUses(MachineBasicBlock::iterator MI,
70                         SmallSet<unsigned, 32>& RegDefs,
71                         SmallSet<unsigned, 32>& RegUses);
72
73     bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
74                     unsigned Reg);
75
76     bool delayHasHazard(MachineBasicBlock::iterator candidate,
77                         bool &sawLoad, bool &sawStore,
78                         SmallSet<unsigned, 32> &RegDefs,
79                         SmallSet<unsigned, 32> &RegUses);
80
81     MachineBasicBlock::iterator
82     findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot);
83
84
85   };
86   char Filler::ID = 0;
87 } // end of anonymous namespace
88
89 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
90 /// We assume there is only one delay slot per delayed instruction.
91 bool Filler::
92 runOnMachineBasicBlock(MachineBasicBlock &MBB) {
93   bool Changed = false;
94   for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
95     if (I->getDesc().hasDelaySlot()) {
96       MachineBasicBlock::iterator D = MBB.end();
97       MachineBasicBlock::iterator J = I;
98
99       if (EnableDelaySlotFiller)
100         D = findDelayInstr(MBB, I);
101
102       ++FilledSlots;
103       Changed = true;
104
105       if (D == MBB.end())
106         BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(Mips::NOP));
107       else
108         MBB.splice(++J, &MBB, D);
109      }
110   return Changed;
111
112 }
113
114 /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
115 /// slots in Mips MachineFunctions
116 FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) {
117   return new Filler(tm);
118 }
119
120 MachineBasicBlock::iterator
121 Filler::findDelayInstr(MachineBasicBlock &MBB,
122                        MachineBasicBlock::iterator slot) {
123   SmallSet<unsigned, 32> RegDefs;
124   SmallSet<unsigned, 32> RegUses;
125   bool sawLoad = false;
126   bool sawStore = false;
127
128   MachineBasicBlock::iterator I = slot;
129
130   // Call's delay filler can def some of call's uses.
131   if (slot->getDesc().isCall())
132     insertCallUses(slot, RegDefs, RegUses);
133   else
134     insertDefsUses(slot, RegDefs, RegUses);
135
136   bool done = false;
137
138   while (!done) {
139     done = (I == MBB.begin());
140
141     if (!done)
142       --I;
143
144     // skip debug value
145     if (I->isDebugValue())
146       continue;
147
148     if (I->hasUnmodeledSideEffects()
149         || I->isInlineAsm()
150         || I->isLabel()
151         || isDelayFiller(MBB, I)
152         || I->getDesc().isPseudo()
153         //
154         // Should not allow:
155         // ERET, DERET or WAIT, PAUSE. Need to add these to instruction
156         // list. TBD.
157         )
158       break;
159
160     if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
161       insertDefsUses(I, RegDefs, RegUses);
162       continue;
163     }
164
165     return I;
166   }
167   return MBB.end();
168 }
169
170 bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
171                             bool &sawLoad,
172                             bool &sawStore,
173                             SmallSet<unsigned, 32> &RegDefs,
174                             SmallSet<unsigned, 32> &RegUses) {
175   if (candidate->isImplicitDef() || candidate->isKill())
176     return true;
177
178   // Loads or stores cannot be moved past a store to the delay slot
179   // and stores cannot be moved past a load. 
180   if (candidate->getDesc().mayLoad()) {
181     if (sawStore)
182       return true;
183     sawLoad = true;
184   }
185
186   if (candidate->getDesc().mayStore()) {
187     if (sawStore)
188       return true;
189     sawStore = true;
190     if (sawLoad)
191       return true;
192   }
193
194   for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
195     const MachineOperand &MO = candidate->getOperand(i);
196     if (!MO.isReg())
197       continue; // skip
198
199     unsigned Reg = MO.getReg();
200
201     if (MO.isDef()) {
202       // check whether Reg is defined or used before delay slot.
203       if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
204         return true;
205     }
206     if (MO.isUse()) {
207       // check whether Reg is defined before delay slot.
208       if (IsRegInSet(RegDefs, Reg))
209         return true;
210     }
211   }
212   return false;
213 }
214
215 void Filler::insertCallUses(MachineBasicBlock::iterator MI,
216                             SmallSet<unsigned, 32>& RegDefs,
217                             SmallSet<unsigned, 32>& RegUses) {
218   switch(MI->getOpcode()) {
219   default: llvm_unreachable("Unknown opcode.");
220   case Mips::JAL:
221     RegDefs.insert(31);
222     break;
223   case Mips::JALR:
224     assert(MI->getNumOperands() >= 1);
225     const MachineOperand &Reg = MI->getOperand(0);
226     assert(Reg.isReg() && "JALR first operand is not a register.");
227     RegUses.insert(Reg.getReg());
228     RegDefs.insert(31);
229     break;
230   }
231 }
232
233 // Insert Defs and Uses of MI into the sets RegDefs and RegUses.
234 void Filler::insertDefsUses(MachineBasicBlock::iterator MI,
235                             SmallSet<unsigned, 32>& RegDefs,
236                             SmallSet<unsigned, 32>& RegUses) {
237   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
238     const MachineOperand &MO = MI->getOperand(i);
239     if (!MO.isReg())
240       continue;
241
242     unsigned Reg = MO.getReg();
243     if (Reg == 0)
244       continue;
245     if (MO.isDef())
246       RegDefs.insert(Reg);
247     if (MO.isUse())
248       RegUses.insert(Reg);
249   }
250 }
251
252 //returns true if the Reg or its alias is in the RegSet.
253 bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg) {
254   if (RegSet.count(Reg))
255     return true;
256   // check Aliased Registers
257   for (const unsigned *Alias = TM.getRegisterInfo()->getAliasSet(Reg);
258        *Alias; ++Alias)
259     if (RegSet.count(*Alias))
260       return true;
261
262   return false;
263 }
264
265 // return true if the candidate is a delay filler.
266 bool Filler::isDelayFiller(MachineBasicBlock &MBB,
267                            MachineBasicBlock::iterator candidate) {
268   if (candidate == MBB.begin())
269     return false;
270   const MCInstrDesc &prevdesc = (--candidate)->getDesc();
271   return prevdesc.hasDelaySlot();
272 }