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