LLVM 20.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
22using namespace llvm;
23
24#define DEBUG_TYPE "delay-slot-filler"
25
26STATISTIC(FilledSlots, "Number of delay slots filled");
27
28static cl::opt<bool>
29 NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
30 cl::desc("Fill Lanai delay slots with NOPs."),
32
33namespace {
34struct Filler : public MachineFunctionPass {
35 // Target machine description which we query for reg. names, data
36 // layout, etc.
37 const TargetInstrInfo *TII;
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
61 MachineFunctionProperties::Property::NoVRegs);
62 }
63
64 void insertDefsUses(MachineBasicBlock::instr_iterator MI,
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};
78char 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.
90bool 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()) {
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.
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);
118 MachineBasicBlock::instr_iterator FI = RI.getReverse();
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
143bool Filler::findDelayInstr(MachineBasicBlock &MBB,
148
149 insertDefsUses(Slot, RegDefs, RegUses);
150
151 bool SawLoad = false;
152 bool SawStore = false;
153
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
177bool 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.
223void 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 const 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.
253bool 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}
MachineBasicBlock & MBB
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static cl::opt< bool > NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false), cl::desc("Fill Lanai delay slots with NOPs."), cl::Hidden)
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
const LanaiRegisterInfo * getRegisterInfo() const override
const LanaiInstrInfo * getInstrInfo() const override
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:237
MCRegAliasIterator enumerates all registers aliasing Reg.
Helper class for constructing bundles of MachineInstrs.
instr_iterator instr_begin()
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
instr_iterator instr_end()
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 '...
Instructions::reverse_iterator reverse_instr_iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:132
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition: SmallSet.h:175
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:181
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createLanaiDelaySlotFillerPass(const LanaiTargetMachine &TM)