1 //===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Simple pass to fills delay slots with useful instructions.
11 //===----------------------------------------------------------------------===//
14 #include "LanaiTargetMachine.h"
15 #include "llvm/ADT/SmallSet.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/TargetInstrInfo.h"
20 #include "llvm/Support/CommandLine.h"
24 #define DEBUG_TYPE "delay-slot-filler"
26 STATISTIC(FilledSlots
, "Number of delay slots filled");
29 NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
30 cl::desc("Fill Lanai delay slots with NOPs."),
34 struct Filler
: public MachineFunctionPass
{
35 // Target machine description which we query for reg. names, data
37 const TargetInstrInfo
*TII
;
38 const TargetRegisterInfo
*TRI
;
39 MachineBasicBlock::instr_iterator LastFiller
;
42 explicit Filler() : MachineFunctionPass(ID
) {}
44 StringRef
getPassName() const override
{ return "Lanai Delay Slot Filler"; }
46 bool runOnMachineBasicBlock(MachineBasicBlock
&MBB
);
48 bool runOnMachineFunction(MachineFunction
&MF
) override
{
49 const LanaiSubtarget
&Subtarget
= MF
.getSubtarget
<LanaiSubtarget
>();
50 TII
= Subtarget
.getInstrInfo();
51 TRI
= Subtarget
.getRegisterInfo();
54 for (MachineFunction::iterator FI
= MF
.begin(), FE
= MF
.end(); FI
!= FE
;
56 Changed
|= runOnMachineBasicBlock(*FI
);
60 MachineFunctionProperties
getRequiredProperties() const override
{
61 return MachineFunctionProperties().set(
62 MachineFunctionProperties::Property::NoVRegs
);
65 void insertDefsUses(MachineBasicBlock::instr_iterator MI
,
66 SmallSet
<unsigned, 32> &RegDefs
,
67 SmallSet
<unsigned, 32> &RegUses
);
69 bool isRegInSet(SmallSet
<unsigned, 32> &RegSet
, unsigned Reg
);
71 bool delayHasHazard(MachineBasicBlock::instr_iterator MI
, bool &SawLoad
,
72 bool &SawStore
, SmallSet
<unsigned, 32> &RegDefs
,
73 SmallSet
<unsigned, 32> &RegUses
);
75 bool findDelayInstr(MachineBasicBlock
&MBB
,
76 MachineBasicBlock::instr_iterator Slot
,
77 MachineBasicBlock::instr_iterator
&Filler
);
80 } // end of anonymous namespace
82 // createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
83 // slots in Lanai MachineFunctions
85 llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine
& /*tm*/) {
89 // runOnMachineBasicBlock - Fill in delay slots for the given basic block.
90 // There is one or two delay slot per delayed instruction.
91 bool Filler::runOnMachineBasicBlock(MachineBasicBlock
&MBB
) {
93 LastFiller
= MBB
.instr_end();
95 for (MachineBasicBlock::instr_iterator I
= MBB
.instr_begin();
96 I
!= MBB
.instr_end(); ++I
) {
97 if (I
->getDesc().hasDelaySlot()) {
98 MachineBasicBlock::instr_iterator InstrWithSlot
= I
;
99 MachineBasicBlock::instr_iterator J
= I
;
101 // Treat RET specially as it is only instruction with 2 delay slots
102 // generated while all others generated have 1 delay slot.
103 if (I
->getOpcode() == Lanai::RET
) {
104 // RET is generated as part of epilogue generation and hence we know
105 // what the two instructions preceding it are and that it is safe to
106 // insert RET above them.
107 MachineBasicBlock::reverse_instr_iterator RI
= ++I
.getReverse();
108 assert(RI
->getOpcode() == Lanai::LDW_RI
&& RI
->getOperand(0).isReg() &&
109 RI
->getOperand(0).getReg() == Lanai::FP
&&
110 RI
->getOperand(1).isReg() &&
111 RI
->getOperand(1).getReg() == Lanai::FP
&&
112 RI
->getOperand(2).isImm() && RI
->getOperand(2).getImm() == -8);
114 assert(RI
->getOpcode() == Lanai::ADD_I_LO
&&
115 RI
->getOperand(0).isReg() &&
116 RI
->getOperand(0).getReg() == Lanai::SP
&&
117 RI
->getOperand(1).isReg() &&
118 RI
->getOperand(1).getReg() == Lanai::FP
);
119 MachineBasicBlock::instr_iterator FI
= RI
.getReverse();
120 MBB
.splice(std::next(I
), &MBB
, FI
, I
);
123 if (!NopDelaySlotFiller
&& findDelayInstr(MBB
, I
, J
)) {
124 MBB
.splice(std::next(I
), &MBB
, J
);
126 BuildMI(MBB
, std::next(I
), DebugLoc(), TII
->get(Lanai::NOP
));
132 // Record the filler instruction that filled the delay slot.
133 // The instruction after it will be visited in the next iteration.
136 // Bundle the delay slot filler to InstrWithSlot so that the machine
137 // verifier doesn't expect this instruction to be a terminator.
138 MIBundleBuilder(MBB
, InstrWithSlot
, std::next(LastFiller
));
144 bool Filler::findDelayInstr(MachineBasicBlock
&MBB
,
145 MachineBasicBlock::instr_iterator Slot
,
146 MachineBasicBlock::instr_iterator
&Filler
) {
147 SmallSet
<unsigned, 32> RegDefs
;
148 SmallSet
<unsigned, 32> RegUses
;
150 insertDefsUses(Slot
, RegDefs
, RegUses
);
152 bool SawLoad
= false;
153 bool SawStore
= false;
155 for (MachineBasicBlock::reverse_instr_iterator I
= ++Slot
.getReverse();
156 I
!= MBB
.instr_rend(); ++I
) {
158 if (I
->isDebugInstr())
161 // Convert to forward iterator.
162 MachineBasicBlock::instr_iterator FI
= I
.getReverse();
164 if (I
->hasUnmodeledSideEffects() || I
->isInlineAsm() || I
->isLabel() ||
165 FI
== LastFiller
|| I
->isPseudo())
168 if (delayHasHazard(FI
, SawLoad
, SawStore
, RegDefs
, RegUses
)) {
169 insertDefsUses(FI
, RegDefs
, RegUses
);
178 bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI
, bool &SawLoad
,
179 bool &SawStore
, SmallSet
<unsigned, 32> &RegDefs
,
180 SmallSet
<unsigned, 32> &RegUses
) {
181 if (MI
->isImplicitDef() || MI
->isKill())
184 // Loads or stores cannot be moved past a store to the delay slot
185 // and stores cannot be moved past a load.
192 if (MI
->mayStore()) {
200 assert((!MI
->isCall() && !MI
->isReturn()) &&
201 "Cannot put calls or returns in delay slot.");
203 for (unsigned I
= 0, E
= MI
->getNumOperands(); I
!= E
; ++I
) {
204 const MachineOperand
&MO
= MI
->getOperand(I
);
207 if (!MO
.isReg() || !(Reg
= MO
.getReg()))
211 // check whether Reg is defined or used before delay slot.
212 if (isRegInSet(RegDefs
, Reg
) || isRegInSet(RegUses
, Reg
))
216 // check whether Reg is defined before delay slot.
217 if (isRegInSet(RegDefs
, Reg
))
224 // Insert Defs and Uses of MI into the sets RegDefs and RegUses.
225 void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI
,
226 SmallSet
<unsigned, 32> &RegDefs
,
227 SmallSet
<unsigned, 32> &RegUses
) {
228 // If MI is a call or return, just examine the explicit non-variadic operands.
229 MCInstrDesc MCID
= MI
->getDesc();
230 unsigned E
= MI
->isCall() || MI
->isReturn() ? MCID
.getNumOperands()
231 : MI
->getNumOperands();
232 for (unsigned I
= 0; I
!= E
; ++I
) {
233 const MachineOperand
&MO
= MI
->getOperand(I
);
236 if (!MO
.isReg() || !(Reg
= MO
.getReg()))
245 // Call & return instructions defines SP implicitly. Implicit defines are not
246 // included in the RegDefs set of calls but instructions modifying SP cannot
247 // be inserted in the delay slot of a call/return as these instructions are
248 // expanded to multiple instructions with SP modified before the branch that
249 // has the delay slot.
250 if (MI
->isCall() || MI
->isReturn())
251 RegDefs
.insert(Lanai::SP
);
254 // Returns true if the Reg or its alias is in the RegSet.
255 bool Filler::isRegInSet(SmallSet
<unsigned, 32> &RegSet
, unsigned Reg
) {
256 // Check Reg and all aliased Registers.
257 for (MCRegAliasIterator
AI(Reg
, TRI
, true); AI
.isValid(); ++AI
)
258 if (RegSet
.count(*AI
))