LLVM  8.0.1
LanaiDelaySlotFiller.cpp
Go to the documentation of this file.
1 //===-- LanaiDelaySlotFiller.cpp - Lanai 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 #include "Lanai.h"
15 #include "LanaiTargetMachine.h"
16 #include "llvm/ADT/SmallSet.h"
17 #include "llvm/ADT/Statistic.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "delay-slot-filler"
26 
27 STATISTIC(FilledSlots, "Number of delay slots filled");
28 
29 static cl::opt<bool>
30  NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
31  cl::desc("Fill Lanai delay slots with NOPs."),
32  cl::Hidden);
33 
34 namespace {
35 struct Filler : public MachineFunctionPass {
36  // Target machine description which we query for reg. names, data
37  // layout, etc.
38  const TargetInstrInfo *TII;
39  const TargetRegisterInfo *TRI;
41 
42  static char ID;
43  explicit Filler() : MachineFunctionPass(ID) {}
44 
45  StringRef getPassName() const override { return "Lanai Delay Slot Filler"; }
46 
47  bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
48 
49  bool runOnMachineFunction(MachineFunction &MF) override {
50  const LanaiSubtarget &Subtarget = MF.getSubtarget<LanaiSubtarget>();
51  TII = Subtarget.getInstrInfo();
52  TRI = Subtarget.getRegisterInfo();
53 
54  bool Changed = false;
55  for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
56  ++FI)
57  Changed |= runOnMachineBasicBlock(*FI);
58  return Changed;
59  }
60 
61  MachineFunctionProperties getRequiredProperties() const override {
64  }
65 
66  void insertDefsUses(MachineBasicBlock::instr_iterator MI,
67  SmallSet<unsigned, 32> &RegDefs,
68  SmallSet<unsigned, 32> &RegUses);
69 
70  bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
71 
72  bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
73  bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
74  SmallSet<unsigned, 32> &RegUses);
75 
76  bool findDelayInstr(MachineBasicBlock &MBB,
79 };
80 char Filler::ID = 0;
81 } // end of anonymous namespace
82 
83 // createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
84 // slots in Lanai MachineFunctions
87  return new Filler();
88 }
89 
90 // runOnMachineBasicBlock - Fill in delay slots for the given basic block.
91 // There is one or two delay slot per delayed instruction.
92 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
93  bool Changed = false;
94  LastFiller = MBB.instr_end();
95 
97  I != MBB.instr_end(); ++I) {
98  if (I->getDesc().hasDelaySlot()) {
99  MachineBasicBlock::instr_iterator InstrWithSlot = I;
101 
102  // Treat RET specially as it is only instruction with 2 delay slots
103  // generated while all others generated have 1 delay slot.
104  if (I->getOpcode() == Lanai::RET) {
105  // RET is generated as part of epilogue generation and hence we know
106  // what the two instructions preceding it are and that it is safe to
107  // insert RET above them.
108  MachineBasicBlock::reverse_instr_iterator RI = ++I.getReverse();
109  assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
110  RI->getOperand(0).getReg() == Lanai::FP &&
111  RI->getOperand(1).isReg() &&
112  RI->getOperand(1).getReg() == Lanai::FP &&
113  RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
114  ++RI;
115  assert(RI->getOpcode() == Lanai::ADD_I_LO &&
116  RI->getOperand(0).isReg() &&
117  RI->getOperand(0).getReg() == Lanai::SP &&
118  RI->getOperand(1).isReg() &&
119  RI->getOperand(1).getReg() == Lanai::FP);
121  MBB.splice(std::next(I), &MBB, FI, I);
122  FilledSlots += 2;
123  } else {
124  if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) {
125  MBB.splice(std::next(I), &MBB, J);
126  } else {
127  BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
128  }
129  ++FilledSlots;
130  }
131 
132  Changed = true;
133  // Record the filler instruction that filled the delay slot.
134  // The instruction after it will be visited in the next iteration.
135  LastFiller = ++I;
136 
137  // Bundle the delay slot filler to InstrWithSlot so that the machine
138  // verifier doesn't expect this instruction to be a terminator.
139  MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
140  }
141  }
142  return Changed;
143 }
144 
145 bool Filler::findDelayInstr(MachineBasicBlock &MBB,
148  SmallSet<unsigned, 32> RegDefs;
149  SmallSet<unsigned, 32> RegUses;
150 
151  insertDefsUses(Slot, RegDefs, RegUses);
152 
153  bool SawLoad = false;
154  bool SawStore = false;
155 
157  I != MBB.instr_rend(); ++I) {
158  // skip debug value
159  if (I->isDebugInstr())
160  continue;
161 
162  // Convert to forward iterator.
163  MachineBasicBlock::instr_iterator FI = I.getReverse();
164 
165  if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
166  FI == LastFiller || I->isPseudo())
167  break;
168 
169  if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
170  insertDefsUses(FI, RegDefs, RegUses);
171  continue;
172  }
173  Filler = FI;
174  return true;
175  }
176  return false;
177 }
178 
179 bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
180  bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
181  SmallSet<unsigned, 32> &RegUses) {
182  if (MI->isImplicitDef() || MI->isKill())
183  return true;
184 
185  // Loads or stores cannot be moved past a store to the delay slot
186  // and stores cannot be moved past a load.
187  if (MI->mayLoad()) {
188  if (SawStore)
189  return true;
190  SawLoad = true;
191  }
192 
193  if (MI->mayStore()) {
194  if (SawStore)
195  return true;
196  SawStore = true;
197  if (SawLoad)
198  return true;
199  }
200 
201  assert((!MI->isCall() && !MI->isReturn()) &&
202  "Cannot put calls or returns in delay slot.");
203 
204  for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
205  const MachineOperand &MO = MI->getOperand(I);
206  unsigned Reg;
207 
208  if (!MO.isReg() || !(Reg = MO.getReg()))
209  continue; // skip
210 
211  if (MO.isDef()) {
212  // check whether Reg is defined or used before delay slot.
213  if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
214  return true;
215  }
216  if (MO.isUse()) {
217  // check whether Reg is defined before delay slot.
218  if (isRegInSet(RegDefs, Reg))
219  return true;
220  }
221  }
222  return false;
223 }
224 
225 // Insert Defs and Uses of MI into the sets RegDefs and RegUses.
226 void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
227  SmallSet<unsigned, 32> &RegDefs,
228  SmallSet<unsigned, 32> &RegUses) {
229  // If MI is a call or return, just examine the explicit non-variadic operands.
230  MCInstrDesc MCID = MI->getDesc();
231  unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands()
232  : MI->getNumOperands();
233  for (unsigned I = 0; I != E; ++I) {
234  const MachineOperand &MO = MI->getOperand(I);
235  unsigned Reg;
236 
237  if (!MO.isReg() || !(Reg = MO.getReg()))
238  continue;
239 
240  if (MO.isDef())
241  RegDefs.insert(Reg);
242  else if (MO.isUse())
243  RegUses.insert(Reg);
244  }
245 
246  // Call & return instructions defines SP implicitly. Implicit defines are not
247  // included in the RegDefs set of calls but instructions modifying SP cannot
248  // be inserted in the delay slot of a call/return as these instructions are
249  // expanded to multiple instructions with SP modified before the branch that
250  // has the delay slot.
251  if (MI->isCall() || MI->isReturn())
252  RegDefs.insert(Lanai::SP);
253 }
254 
255 // Returns true if the Reg or its alias is in the RegSet.
256 bool Filler::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
257  // Check Reg and all aliased Registers.
258  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
259  if (RegSet.count(*AI))
260  return true;
261  return false;
262 }
static cl::opt< bool > NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false), cl::desc("Fill Lanai delay slots with NOPs."), cl::Hidden)
instr_iterator instr_begin()
instr_iterator instr_end()
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const LanaiInstrInfo * getInstrInfo() const override
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
unsigned getReg() const
getReg - Returns the register number.
unsigned Reg
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:34
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:211
const HexagonInstrInfo * TII
FunctionPass * createLanaiDelaySlotFillerPass(const LanaiTargetMachine &TM)
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:423
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
MCRegAliasIterator enumerates all registers aliasing Reg.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn&#39;t already there.
Definition: SmallSet.h:181
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Iterator for intrusive lists based on ilist_node.
MachineOperand class - Representation of each machine instruction operand.
reverse_instr_iterator instr_rend()
MachineFunctionProperties & set(Property P)
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB &#39;Other&#39; at the position From, and insert it into this MBB right before &#39;...
#define I(x, y, z)
Definition: MD5.cpp:58
ilist_iterator< OptionsT, !IsReverse, IsConst > getReverse() const
Get a reverse iterator to the same node.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const LanaiRegisterInfo * getRegisterInfo() const override
Properties which a MachineFunction may have at a given point in time.
Helper class for constructing bundles of MachineInstrs.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition: SmallSet.h:165