MipsDelaySlotFiller.cpp revision 49d58723d2f8d4578c07b37cf636a81b8b8a24a5
1a5b9332418f25338f118358e27303cd510d54107Chandler Carruth//===-- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler ------------------===//
2a5b9332418f25338f118358e27303cd510d54107Chandler Carruth//
3a5b9332418f25338f118358e27303cd510d54107Chandler Carruth//                     The LLVM Compiler Infrastructure
4a5b9332418f25338f118358e27303cd510d54107Chandler Carruth//
5a5b9332418f25338f118358e27303cd510d54107Chandler Carruth// This file is distributed under the University of Illinois Open Source
6a5b9332418f25338f118358e27303cd510d54107Chandler Carruth// License. See LICENSE.TXT for details.
7a5b9332418f25338f118358e27303cd510d54107Chandler Carruth//
8be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie//===----------------------------------------------------------------------===//
9be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie//
10be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie// Simple pass to fill delay slots with useful instructions.
11be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie//
12be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie//===----------------------------------------------------------------------===//
13a5b9332418f25338f118358e27303cd510d54107Chandler Carruth
14be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#define DEBUG_TYPE "delay-slot-filler"
15be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie
16be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "Mips.h"
17be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "MipsTargetMachine.h"
18a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/ADT/BitVector.h"
19a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/ADT/SmallPtrSet.h"
20be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "llvm/ADT/Statistic.h"
21a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/Analysis/AliasAnalysis.h"
22a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/Analysis/ValueTracking.h"
23be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "llvm/CodeGen/MachineFunctionPass.h"
24a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/CodeGen/MachineInstrBuilder.h"
25a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/CodeGen/PseudoSourceValue.h"
26be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "llvm/Support/CommandLine.h"
27a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/Target/TargetInstrInfo.h"
28be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie#include "llvm/Target/TargetMachine.h"
29a5b9332418f25338f118358e27303cd510d54107Chandler Carruth#include "llvm/Target/TargetRegisterInfo.h"
30be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ffDavid Blaikie
31a5b9332418f25338f118358e27303cd510d54107Chandler Carruthusing namespace llvm;
32a5b9332418f25338f118358e27303cd510d54107Chandler Carruth
33a5b9332418f25338f118358e27303cd510d54107Chandler CarruthSTATISTIC(FilledSlots, "Number of delay slots filled");
34a5b9332418f25338f118358e27303cd510d54107Chandler CarruthSTATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
35a5b9332418f25338f118358e27303cd510d54107Chandler Carruth                       " are not NOP.");
36a5b9332418f25338f118358e27303cd510d54107Chandler Carruth
37a5b9332418f25338f118358e27303cd510d54107Chandler Carruthstatic cl::opt<bool> DisableDelaySlotFiller(
38a5b9332418f25338f118358e27303cd510d54107Chandler Carruth  "disable-mips-delay-filler",
39a5b9332418f25338f118358e27303cd510d54107Chandler Carruth  cl::init(false),
40a5b9332418f25338f118358e27303cd510d54107Chandler Carruth  cl::desc("Fill all delay slots with NOPs."),
41  cl::Hidden);
42
43// This option can be used to silence complaints by machine verifier passes.
44static cl::opt<bool> SkipDelaySlotFiller(
45  "skip-mips-delay-filler",
46  cl::init(false),
47  cl::desc("Skip MIPS' delay slot filling pass."),
48  cl::Hidden);
49
50namespace {
51  class RegDefsUses {
52  public:
53    RegDefsUses(TargetMachine &TM);
54    void init(const MachineInstr &MI);
55    bool update(const MachineInstr &MI, unsigned Begin, unsigned End);
56
57  private:
58    bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg,
59                          bool IsDef) const;
60
61    /// Returns true if Reg or its alias is in RegSet.
62    bool isRegInSet(const BitVector &RegSet, unsigned Reg) const;
63
64    const TargetRegisterInfo &TRI;
65    BitVector Defs, Uses;
66  };
67
68  /// This class maintains memory dependence information.
69  class MemDefsUses {
70  public:
71    MemDefsUses(const MachineFrameInfo *MFI);
72
73    /// Return true if MI cannot be moved to delay slot.
74    bool hasHazard(const MachineInstr &MI);
75
76  private:
77    /// Update Defs and Uses. Return true if there exist dependences that
78    /// disqualify the delay slot candidate between V and values in Uses and Defs.
79    bool updateDefsUses(const Value *V, bool MayStore);
80
81    /// Get the list of underlying objects of MI's memory operand.
82    bool getUnderlyingObjects(const MachineInstr &MI,
83                              SmallVectorImpl<const Value *> &Objects) const;
84
85    const MachineFrameInfo *MFI;
86    SmallPtrSet<const Value*, 4> Uses, Defs;
87
88    /// Flags indicating whether loads or stores have been seen.
89    bool SeenLoad, SeenStore;
90
91    /// Flags indicating whether loads or stores with no underlying objects have
92    /// been seen.
93    bool SeenNoObjLoad, SeenNoObjStore;
94
95    /// Memory instructions are not allowed to move to delay slot if this flag
96    /// is true.
97    bool ForbidMemInstr;
98  };
99
100  class Filler : public MachineFunctionPass {
101  public:
102    Filler(TargetMachine &tm)
103      : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { }
104
105    virtual const char *getPassName() const {
106      return "Mips Delay Slot Filler";
107    }
108
109    bool runOnMachineFunction(MachineFunction &F) {
110      if (SkipDelaySlotFiller)
111        return false;
112
113      bool Changed = false;
114      for (MachineFunction::iterator FI = F.begin(), FE = F.end();
115           FI != FE; ++FI)
116        Changed |= runOnMachineBasicBlock(*FI);
117      return Changed;
118    }
119
120  private:
121    typedef MachineBasicBlock::iterator Iter;
122    typedef MachineBasicBlock::reverse_iterator ReverseIter;
123
124    bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
125
126    /// This function checks if it is valid to move Candidate to the delay slot
127    /// and returns true if it isn't. It also updates memory and register
128    /// dependence information.
129    bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU,
130                        MemDefsUses &MemDU) const;
131
132    bool searchBackward(MachineBasicBlock &MBB, Iter Slot, Iter &Filler) const;
133
134    bool terminateSearch(const MachineInstr &Candidate) const;
135
136    TargetMachine &TM;
137    const TargetInstrInfo *TII;
138
139    static char ID;
140  };
141  char Filler::ID = 0;
142} // end of anonymous namespace
143
144RegDefsUses::RegDefsUses(TargetMachine &TM)
145  : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false),
146    Uses(TRI.getNumRegs(), false) {}
147
148void RegDefsUses::init(const MachineInstr &MI) {
149  // Add all register operands which are explicit and non-variadic.
150  update(MI, 0, MI.getDesc().getNumOperands());
151
152  // If MI is a call, add RA to Defs to prevent users of RA from going into
153  // delay slot.
154  if (MI.isCall())
155    Defs.set(Mips::RA);
156
157  // Add all implicit register operands of branch instructions except
158  // register AT.
159  if (MI.isBranch()) {
160    update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands());
161    Defs.reset(Mips::AT);
162  }
163}
164
165bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) {
166  BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs());
167  bool HasHazard = false;
168
169  for (unsigned I = Begin; I != End; ++I) {
170    const MachineOperand &MO = MI.getOperand(I);
171
172    if (MO.isReg() && MO.getReg())
173      HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef());
174  }
175
176  Defs |= NewDefs;
177  Uses |= NewUses;
178
179  return HasHazard;
180}
181
182bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses,
183                                   unsigned Reg, bool IsDef) const {
184  if (IsDef) {
185    NewDefs.set(Reg);
186    // check whether Reg has already been defined or used.
187    return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
188  }
189
190  NewUses.set(Reg);
191  // check whether Reg has already been defined.
192  return isRegInSet(Defs, Reg);
193}
194
195bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const {
196  // Check Reg and all aliased Registers.
197  for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)
198    if (RegSet.test(*AI))
199      return true;
200  return false;
201}
202
203MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_)
204  : MFI(MFI_), SeenLoad(false), SeenStore(false), SeenNoObjLoad(false),
205    SeenNoObjStore(false),  ForbidMemInstr(false) {}
206
207bool MemDefsUses::hasHazard(const MachineInstr &MI) {
208  if (!MI.mayStore() && !MI.mayLoad())
209    return false;
210
211  if (ForbidMemInstr)
212    return true;
213
214  bool OrigSeenLoad = SeenLoad, OrigSeenStore = SeenStore;
215
216  SeenLoad |= MI.mayLoad();
217  SeenStore |= MI.mayStore();
218
219  // If MI is an ordered or volatile memory reference, disallow moving
220  // subsequent loads and stores to delay slot.
221  if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) {
222    ForbidMemInstr = true;
223    return true;
224  }
225
226  bool HasHazard = false;
227  SmallVector<const Value *, 4> Objs;
228
229  // Check underlying object list.
230  if (getUnderlyingObjects(MI, Objs)) {
231    for (SmallVector<const Value *, 4>::const_iterator I = Objs.begin();
232         I != Objs.end(); ++I)
233      HasHazard |= updateDefsUses(*I, MI.mayStore());
234
235    return HasHazard;
236  }
237
238  // No underlying objects found.
239  HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore);
240  HasHazard |= MI.mayLoad() || OrigSeenStore;
241
242  SeenNoObjLoad |= MI.mayLoad();
243  SeenNoObjStore |= MI.mayStore();
244
245  return HasHazard;
246}
247
248bool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) {
249  if (MayStore)
250    return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad;
251
252  Uses.insert(V);
253  return Defs.count(V) || SeenNoObjStore;
254}
255
256bool MemDefsUses::
257getUnderlyingObjects(const MachineInstr &MI,
258                     SmallVectorImpl<const Value *> &Objects) const {
259  if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue())
260    return false;
261
262  const Value *V = (*MI.memoperands_begin())->getValue();
263
264  SmallVector<Value *, 4> Objs;
265  GetUnderlyingObjects(const_cast<Value *>(V), Objs);
266
267  for (SmallVector<Value*, 4>::iterator I = Objs.begin(), E = Objs.end();
268       I != E; ++I) {
269    if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) {
270      if (PSV->isAliased(MFI))
271        return false;
272    } else if (!isIdentifiedObject(V))
273      return false;
274
275    Objects.push_back(*I);
276  }
277
278  return true;
279}
280
281/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
282/// We assume there is only one delay slot per delayed instruction.
283bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
284  bool Changed = false;
285
286  for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
287    if (!I->hasDelaySlot())
288      continue;
289
290    ++FilledSlots;
291    Changed = true;
292    Iter D;
293
294    // Delay slot filling is disabled at -O0.
295    if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None) &&
296        searchBackward(MBB, I, D)) {
297      MBB.splice(llvm::next(I), &MBB, D);
298      ++UsefulSlots;
299    } else
300      BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
301
302    // Bundle the delay slot filler to the instruction with the delay slot.
303    MIBundleBuilder(MBB, I, llvm::next(llvm::next(I)));
304  }
305
306  return Changed;
307}
308
309/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
310/// slots in Mips MachineFunctions
311FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) {
312  return new Filler(tm);
313}
314
315bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot,
316                            Iter &Filler) const {
317  RegDefsUses RegDU(TM);
318  MemDefsUses MemDU(MBB.getParent()->getFrameInfo());
319
320  RegDU.init(*Slot);
321
322  for (ReverseIter I(Slot); I != MBB.rend(); ++I) {
323    // skip debug value
324    if (I->isDebugValue())
325      continue;
326
327    if (terminateSearch(*I))
328      break;
329
330    assert((!I->isCall() && !I->isReturn() && !I->isBranch()) &&
331           "Cannot put calls, returns or branches in delay slot.");
332
333    if (delayHasHazard(*I, RegDU, MemDU))
334      continue;
335
336    Filler = llvm::next(I).base();
337    return true;
338  }
339
340  return false;
341}
342
343bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU,
344                            MemDefsUses &MemDU) const {
345  bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill());
346
347  HasHazard |= MemDU.hasHazard(Candidate);
348  HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands());
349
350  return HasHazard;
351}
352
353bool Filler::terminateSearch(const MachineInstr &Candidate) const {
354  return (Candidate.isTerminator() || Candidate.isCall() ||
355          Candidate.isLabel() || Candidate.isInlineAsm() ||
356          Candidate.hasUnmodeledSideEffects());
357}
358