LLVM 24.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"
22#include "llvm/IR/Analysis.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "delay-slot-filler"
27
28STATISTIC(FilledSlots, "Number of delay slots filled");
29
30namespace {
31struct FillerImpl {
32 const LanaiOptions *CLOpts;
33 // Target machine description which we query for reg. names, data
34 // layout, etc.
35 const TargetInstrInfo *TII;
38
40
41 bool runOnMachineFunction(MachineFunction &MF) {
43 CLOpts = &Subtarget.getCLOpts();
44 TII = Subtarget.getInstrInfo();
45 TRI = Subtarget.getRegisterInfo();
46
47 bool Changed = false;
48 for (MachineBasicBlock &MBB : MF)
50 return Changed;
51 }
52
54 SmallSet<unsigned, 32> &RegDefs,
55 SmallSet<unsigned, 32> &RegUses);
56
57 bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
58
60 bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
61 SmallSet<unsigned, 32> &RegUses);
62
63 bool findDelayInstr(MachineBasicBlock &MBB,
66};
67
68class LanaiDelaySlotFillerLegacy : public MachineFunctionPass {
69 static char ID;
70
71public:
72 explicit LanaiDelaySlotFillerLegacy() : MachineFunctionPass(ID) {}
73
74 StringRef getPassName() const override { return "Lanai Delay Slot Filler"; }
75
76 MachineFunctionProperties getRequiredProperties() const override {
77 return MachineFunctionProperties().setNoVRegs();
78 }
79
80 bool runOnMachineFunction(MachineFunction &MF) override;
81};
82char LanaiDelaySlotFillerLegacy::ID = 0;
83} // end of anonymous namespace
84
85// createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
86// slots in Lanai MachineFunctions
89 return new LanaiDelaySlotFillerLegacy();
90}
91
92// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
93// There is one or two delay slot per delayed instruction.
94bool FillerImpl::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
95 bool Changed = false;
96 LastFiller = MBB.instr_end();
97
98 for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
99 I != MBB.instr_end(); ++I) {
100 if (I->getDesc().hasDelaySlot()) {
101 MachineBasicBlock::instr_iterator InstrWithSlot = I;
103
104 // Treat RET specially as it is only instruction with 2 delay slots
105 // generated while all others generated have 1 delay slot.
106 if (I->getOpcode() == Lanai::RET) {
107 // RET is generated as part of epilogue generation and hence we know
108 // what the two instructions preceding it are and that it is safe to
109 // insert RET above them.
111 assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
112 RI->getOperand(0).getReg() == Lanai::FP &&
113 RI->getOperand(1).isReg() &&
114 RI->getOperand(1).getReg() == Lanai::FP &&
115 RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
116 ++RI;
117 assert(RI->getOpcode() == Lanai::ADD_I_LO &&
118 RI->getOperand(0).isReg() &&
119 RI->getOperand(0).getReg() == Lanai::SP &&
120 RI->getOperand(1).isReg() &&
121 RI->getOperand(1).getReg() == Lanai::FP);
122 MachineBasicBlock::instr_iterator FI = RI.getReverse();
123 MBB.splice(std::next(I), &MBB, FI, I);
124 FilledSlots += 2;
125 } else {
126 if (!CLOpts->nop_delay_filler && findDelayInstr(MBB, I, J)) {
127 MBB.splice(std::next(I), &MBB, J);
128 } else {
129 BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
130 }
131 ++FilledSlots;
132 }
133
134 Changed = true;
135 // Record the filler instruction that filled the delay slot.
136 // The instruction after it will be visited in the next iteration.
137 LastFiller = ++I;
138 // RET has 2 delay slots, so we need to advance past the second filler
139 // too.
140 if (InstrWithSlot->getOpcode() == Lanai::RET)
141 ++LastFiller;
142
143 // Bundle the delay slot filler to InstrWithSlot so that the machine
144 // verifier doesn't expect this instruction to be a terminator.
145 MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
146 }
147 }
148 return Changed;
149}
150
151bool FillerImpl::findDelayInstr(MachineBasicBlock &MBB,
154 SmallSet<unsigned, 32> RegDefs;
155 SmallSet<unsigned, 32> RegUses;
156
157 insertDefsUses(Slot, RegDefs, RegUses);
158
159 bool SawLoad = false;
160 bool SawStore = false;
161
163 I != MBB.instr_rend(); ++I) {
164 // skip debug value
165 if (I->isDebugInstr())
166 continue;
167
168 // Convert to forward iterator.
169 MachineBasicBlock::instr_iterator FI = I.getReverse();
170
171 if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
172 FI == LastFiller || I->isPseudo())
173 break;
174
175 if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
176 insertDefsUses(FI, RegDefs, RegUses);
177 continue;
178 }
179 Filler = FI;
180 return true;
181 }
182 return false;
183}
184
185bool FillerImpl::delayHasHazard(MachineBasicBlock::instr_iterator MI,
186 bool &SawLoad, bool &SawStore,
187 SmallSet<unsigned, 32> &RegDefs,
188 SmallSet<unsigned, 32> &RegUses) {
189 if (MI->isImplicitDef() || MI->isKill())
190 return true;
191
192 // Loads or stores cannot be moved past a store to the delay slot
193 // and stores cannot be moved past a load.
194 if (MI->mayLoad()) {
195 if (SawStore)
196 return true;
197 SawLoad = true;
198 }
199
200 if (MI->mayStore()) {
201 if (SawStore)
202 return true;
203 SawStore = true;
204 if (SawLoad)
205 return true;
206 }
207
208 assert((!MI->isCall() && !MI->isReturn()) &&
209 "Cannot put calls or returns in delay slot.");
210
211 for (const MachineOperand &MO : MI->operands()) {
212 unsigned Reg;
213
214 if (!MO.isReg() || !(Reg = MO.getReg()))
215 continue; // skip
216
217 if (MO.isDef()) {
218 // check whether Reg is defined or used before delay slot.
219 if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
220 return true;
221 }
222 if (MO.isUse()) {
223 // check whether Reg is defined before delay slot.
224 if (isRegInSet(RegDefs, Reg))
225 return true;
226 }
227 }
228 return false;
229}
230
231// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
232void FillerImpl::insertDefsUses(MachineBasicBlock::instr_iterator MI,
233 SmallSet<unsigned, 32> &RegDefs,
234 SmallSet<unsigned, 32> &RegUses) {
235 for (const MachineOperand &MO : MI->operands()) {
236 if (MO.isRegMask()) {
237 // For calls, the regmask clobbers many registers. However, we don't
238 // want to add all of those to RegDefs as it would prevent any useful
239 // delay slot filling. The caller-saved registers will be handled
240 // separately.
241 continue;
242 }
243
244 if (!MO.isReg())
245 continue;
246
247 Register Reg = MO.getReg();
248 if (Reg != MO.getReg())
249 continue;
250
251 // For calls/returns, we must track implicit uses (function arguments)
252 // to prevent moving their definitions into the delay slot. We previously
253 // only looked at explicit operands which missed implicit argument uses.
254 if (MO.isDef()) {
255 // For implicit defs from calls (like return value $rv), we add them.
256 // But we've already filtered out regmasks above.
257 RegDefs.insert(Reg);
258 } else if (MO.isUse()) {
259 RegUses.insert(Reg);
260 }
261 }
262
263 // Call & return instructions define SP implicitly. Instructions modifying SP
264 // cannot be inserted in the delay slot of a call/return as these instructions
265 // are expanded to multiple instructions with SP modified before the branch
266 // that has the delay slot.
267 if (MI->isCall() || MI->isReturn())
268 RegDefs.insert(Lanai::SP);
269}
270
271// Returns true if the Reg or its alias is in the RegSet.
272bool FillerImpl::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
273 // Check Reg and all aliased Registers.
274 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
275 if (RegSet.count(*AI))
276 return true;
277 return false;
278}
279
280bool LanaiDelaySlotFillerLegacy::runOnMachineFunction(MachineFunction &MF) {
281 FillerImpl Impl;
282 return Impl.runOnMachineFunction(MF);
283}
284
285PreservedAnalyses
288 FillerImpl Impl;
289 return Impl.runOnMachineFunction(MF)
293}
const AArch64Subtarget & Subtarget
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static void insertDefsUses(MachineBasicBlock::iterator MI, SmallSet< unsigned, 32 > &RegDefs, SmallSet< unsigned, 32 > &RegUses, const SparcSubtarget *Subtarget)
static MachineBasicBlock::iterator findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot, const SparcSubtarget *Subtarget)
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool runOnMachineBasicBlock(MachineBasicBlock &MBB, MachineInstr *FirstNextMBBInstr, function_ref< MachineBranchProbabilityInfo &()> GetMBPI)
runOnMachineBasicBlock - Fill in delay slots for the given basic block.
static bool delayHasHazard(const MipsSubtarget &STI, const MachineInstr &Candidate, const BranchInformation &BranchInfo, RegDefsUses &RegDU, InspectMemInstr &IM)
This function checks if it is valid to move Candidate to the delay slot and returns true if it isn't.
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:171
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
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...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
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:184
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createLanaiDelaySlotFillerLegacyPass(const LanaiTargetMachine &TM)