MipsDelaySlotFiller.cpp revision cd7319dc5f91ac81ab9d8505f34937e91bfcf65d
1//===-- MipsDelaySlotFiller.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 fill 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/ADT/BitVector.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/CodeGen/MachineFunctionPass.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Target/TargetInstrInfo.h"
24#include "llvm/Target/TargetMachine.h"
25#include "llvm/Target/TargetRegisterInfo.h"
26
27using namespace llvm;
28
29STATISTIC(FilledSlots, "Number of delay slots filled");
30STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
31                       " are not NOP.");
32
33static cl::opt<bool> DisableDelaySlotFiller(
34  "disable-mips-delay-filler",
35  cl::init(false),
36  cl::desc("Fill all delay slots with NOPs."),
37  cl::Hidden);
38
39// This option can be used to silence complaints by machine verifier passes.
40static cl::opt<bool> SkipDelaySlotFiller(
41  "skip-mips-delay-filler",
42  cl::init(false),
43  cl::desc("Skip MIPS' delay slot filling pass."),
44  cl::Hidden);
45
46namespace {
47  class Filler : public MachineFunctionPass {
48  public:
49    Filler(TargetMachine &tm)
50      : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { }
51
52    virtual const char *getPassName() const {
53      return "Mips Delay Slot Filler";
54    }
55
56    bool runOnMachineFunction(MachineFunction &F) {
57      if (SkipDelaySlotFiller)
58        return false;
59
60      bool Changed = false;
61      for (MachineFunction::iterator FI = F.begin(), FE = F.end();
62           FI != FE; ++FI)
63        Changed |= runOnMachineBasicBlock(*FI);
64      return Changed;
65    }
66
67  private:
68    typedef MachineBasicBlock::iterator Iter;
69    typedef MachineBasicBlock::reverse_iterator ReverseIter;
70
71    bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
72
73    /// Initialize RegDefs and RegUses.
74    void initRegDefsUses(const MachineInstr &MI, BitVector &RegDefs,
75                         BitVector &RegUses) const;
76
77    bool isRegInSet(const BitVector &RegSet, unsigned Reg) const;
78
79    bool checkRegDefsUses(const BitVector &RegDefs, const BitVector &RegUses,
80                          BitVector &NewDefs, BitVector &NewUses,
81                          unsigned Reg, bool IsDef) const;
82
83    bool checkRegDefsUses(BitVector &RegDefs, BitVector &RegUses,
84                          const MachineInstr &MI, unsigned Begin,
85                          unsigned End) const;
86
87    /// This function checks if it is valid to move Candidate to the delay slot
88    /// and returns true if it isn't. It also updates load and store flags and
89    /// register defs and uses.
90    bool delayHasHazard(const MachineInstr &Candidate, bool &SawLoad,
91                        bool &SawStore, BitVector &RegDefs,
92                        BitVector &RegUses) const;
93
94    bool findDelayInstr(MachineBasicBlock &MBB, Iter slot, Iter &Filler) const;
95
96    bool terminateSearch(const MachineInstr &Candidate) const;
97
98    TargetMachine &TM;
99    const TargetInstrInfo *TII;
100
101    static char ID;
102  };
103  char Filler::ID = 0;
104} // end of anonymous namespace
105
106/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
107/// We assume there is only one delay slot per delayed instruction.
108bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
109  bool Changed = false;
110
111  for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
112    if (!I->hasDelaySlot())
113      continue;
114
115    ++FilledSlots;
116    Changed = true;
117    Iter D;
118
119    // Delay slot filling is disabled at -O0.
120    if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None) &&
121        findDelayInstr(MBB, I, D)) {
122      MBB.splice(llvm::next(I), &MBB, D);
123      ++UsefulSlots;
124    } else
125      BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
126
127    // Bundle the delay slot filler to the instruction with the delay slot.
128    MIBundleBuilder(MBB, I, llvm::next(llvm::next(I)));
129  }
130
131  return Changed;
132}
133
134/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
135/// slots in Mips MachineFunctions
136FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) {
137  return new Filler(tm);
138}
139
140bool Filler::findDelayInstr(MachineBasicBlock &MBB, Iter Slot,
141                            Iter &Filler) const {
142  unsigned NumRegs = TM.getRegisterInfo()->getNumRegs();
143  BitVector RegDefs(NumRegs), RegUses(NumRegs);
144
145  initRegDefsUses(*Slot, RegDefs, RegUses);
146
147  bool SawLoad = false;
148  bool SawStore = false;
149
150  for (ReverseIter I(Slot); I != MBB.rend(); ++I) {
151    // skip debug value
152    if (I->isDebugValue())
153      continue;
154
155    if (terminateSearch(*I))
156      break;
157
158    if (delayHasHazard(*I, SawLoad, SawStore, RegDefs, RegUses))
159      continue;
160
161    Filler = llvm::next(I).base();
162    return true;
163  }
164
165  return false;
166}
167
168bool Filler::checkRegDefsUses(const BitVector &RegDefs,
169                              const BitVector &RegUses,
170                              BitVector &NewDefs, BitVector &NewUses,
171                              unsigned Reg, bool IsDef) const {
172  if (IsDef) {
173    NewDefs.set(Reg);
174    // check whether Reg has already been defined or used.
175    return (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg));
176  }
177
178  NewUses.set(Reg);
179  // check whether Reg has already been defined.
180  return isRegInSet(RegDefs, Reg);
181}
182
183bool Filler::checkRegDefsUses(BitVector &RegDefs, BitVector &RegUses,
184                              const MachineInstr &MI, unsigned Begin,
185                              unsigned End) const {
186  unsigned NumRegs = TM.getRegisterInfo()->getNumRegs();
187  BitVector NewDefs(NumRegs), NewUses(NumRegs);
188  bool HasHazard = false;
189
190  for (unsigned I = Begin; I != End; ++I) {
191    const MachineOperand &MO = MI.getOperand(I);
192
193    if (MO.isReg() && MO.getReg())
194      HasHazard |= checkRegDefsUses(RegDefs, RegUses, NewDefs, NewUses,
195                                    MO.getReg(), MO.isDef());
196  }
197
198  RegDefs |= NewDefs;
199  RegUses |= NewUses;
200
201  return HasHazard;
202}
203
204bool Filler::delayHasHazard(const MachineInstr &Candidate, bool &SawLoad,
205                            bool &SawStore, BitVector &RegDefs,
206                            BitVector &RegUses) const {
207  bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill());
208
209  // Loads or stores cannot be moved past a store to the delay slot
210  // and stores cannot be moved past a load.
211  if (Candidate.mayStore()) {
212    HasHazard |= SawStore | SawLoad;
213    SawStore = true;
214  } else if (Candidate.mayLoad()) {
215    HasHazard |= SawStore;
216    SawLoad = true;
217  }
218
219  assert((!Candidate.isCall() && !Candidate.isReturn()) &&
220         "Cannot put calls or returns in delay slot.");
221
222  HasHazard |= checkRegDefsUses(RegDefs, RegUses, Candidate, 0,
223                                Candidate.getNumOperands());
224
225  return HasHazard;
226}
227
228void Filler::initRegDefsUses(const MachineInstr &MI, BitVector &RegDefs,
229                             BitVector &RegUses) const {
230  // Add all register operands which are explicit and non-variadic.
231  checkRegDefsUses(RegDefs, RegUses, MI, 0, MI.getDesc().getNumOperands());
232
233  // If MI is a call, add RA to RegDefs to prevent users of RA from going into
234  // delay slot.
235  if (MI.isCall())
236    RegDefs.set(Mips::RA);
237
238  // Add all implicit register operands of branch instructions except
239  // register AT.
240  if (MI.isBranch()) {
241    checkRegDefsUses(RegDefs, RegUses, MI, MI.getDesc().getNumOperands(),
242                     MI.getNumOperands());
243    RegDefs.reset(Mips::AT);
244  }
245}
246
247//returns true if the Reg or its alias is in the RegSet.
248bool Filler::isRegInSet(const BitVector &RegSet, unsigned Reg) const {
249  // Check Reg and all aliased Registers.
250  for (MCRegAliasIterator AI(Reg, TM.getRegisterInfo(), true);
251       AI.isValid(); ++AI)
252    if (RegSet.test(*AI))
253      return true;
254  return false;
255}
256
257bool Filler::terminateSearch(const MachineInstr &Candidate) const {
258  return (Candidate.isTerminator() || Candidate.isCall() ||
259          Candidate.isLabel() || Candidate.isInlineAsm() ||
260          Candidate.hasUnmodeledSideEffects());
261}
262