1 //===-- DelaySlotFiller.cpp - SPARC delay slot filler ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This is a simple local pass that attempts to fill delay slots with useful
11 // instructions. If no instructions can be moved into the delay slot, then a
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "delay-slot-filler"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Target/TargetMachine.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Target/TargetRegisterInfo.h"
23 #include "llvm/ADT/SmallSet.h"
24 #include "llvm/ADT/Statistic.h"
28 STATISTIC(FilledSlots
, "Number of delay slots filled");
30 static cl::opt
<bool> DisableDelaySlotFiller(
31 "disable-sparc-delay-filler",
33 cl::desc("Disable the Sparc delay slot filler."),
37 struct Filler
: public MachineFunctionPass
{
38 /// Target machine description which we query for reg. names, data
42 const TargetInstrInfo
*TII
;
45 Filler(TargetMachine
&tm
)
46 : MachineFunctionPass(ID
), TM(tm
), TII(tm
.getInstrInfo()) { }
48 virtual const char *getPassName() const {
49 return "SPARC Delay Slot Filler";
52 bool runOnMachineBasicBlock(MachineBasicBlock
&MBB
);
53 bool runOnMachineFunction(MachineFunction
&F
) {
55 for (MachineFunction::iterator FI
= F
.begin(), FE
= F
.end();
57 Changed
|= runOnMachineBasicBlock(*FI
);
61 bool isDelayFiller(MachineBasicBlock
&MBB
,
62 MachineBasicBlock::iterator candidate
);
64 void insertCallUses(MachineBasicBlock::iterator MI
,
65 SmallSet
<unsigned, 32>& RegUses
);
67 void insertDefsUses(MachineBasicBlock::iterator MI
,
68 SmallSet
<unsigned, 32>& RegDefs
,
69 SmallSet
<unsigned, 32>& RegUses
);
71 bool IsRegInSet(SmallSet
<unsigned, 32>& RegSet
,
74 bool delayHasHazard(MachineBasicBlock::iterator candidate
,
75 bool &sawLoad
, bool &sawStore
,
76 SmallSet
<unsigned, 32> &RegDefs
,
77 SmallSet
<unsigned, 32> &RegUses
);
79 MachineBasicBlock::iterator
80 findDelayInstr(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator slot
);
82 bool needsUnimp(MachineBasicBlock::iterator I
, unsigned &StructSize
);
86 } // end of anonymous namespace
88 /// createSparcDelaySlotFillerPass - Returns a pass that fills in delay
89 /// slots in Sparc MachineFunctions
91 FunctionPass
*llvm::createSparcDelaySlotFillerPass(TargetMachine
&tm
) {
92 return new Filler(tm
);
96 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
97 /// We assume there is only one delay slot per delayed instruction.
99 bool Filler::runOnMachineBasicBlock(MachineBasicBlock
&MBB
) {
100 bool Changed
= false;
102 for (MachineBasicBlock::iterator I
= MBB
.begin(); I
!= MBB
.end(); ++I
)
103 if (I
->getDesc().hasDelaySlot()) {
104 MachineBasicBlock::iterator D
= MBB
.end();
105 MachineBasicBlock::iterator J
= I
;
107 if (!DisableDelaySlotFiller
)
108 D
= findDelayInstr(MBB
, I
);
114 BuildMI(MBB
, ++J
, I
->getDebugLoc(), TII
->get(SP::NOP
));
116 MBB
.splice(++J
, &MBB
, D
);
117 unsigned structSize
= 0;
118 if (needsUnimp(I
, structSize
)) {
119 MachineBasicBlock::iterator J
= I
;
120 ++J
; //skip the delay filler.
121 BuildMI(MBB
, ++J
, I
->getDebugLoc(),
122 TII
->get(SP::UNIMP
)).addImm(structSize
);
128 MachineBasicBlock::iterator
129 Filler::findDelayInstr(MachineBasicBlock
&MBB
,
130 MachineBasicBlock::iterator slot
)
132 SmallSet
<unsigned, 32> RegDefs
;
133 SmallSet
<unsigned, 32> RegUses
;
134 bool sawLoad
= false;
135 bool sawStore
= false;
137 MachineBasicBlock::iterator I
= slot
;
139 if (slot
->getOpcode() == SP::RET
)
142 if (slot
->getOpcode() == SP::RETL
) {
144 if (I
->getOpcode() != SP::RESTORErr
)
147 slot
->setDesc(TII
->get(SP::RET
));
151 //Call's delay filler can def some of call's uses.
152 if (slot
->getDesc().isCall())
153 insertCallUses(slot
, RegUses
);
155 insertDefsUses(slot
, RegDefs
, RegUses
);
160 done
= (I
== MBB
.begin());
166 if (I
->isDebugValue())
170 if (I
->hasUnmodeledSideEffects()
173 || I
->getDesc().hasDelaySlot()
174 || isDelayFiller(MBB
, I
))
177 if (delayHasHazard(I
, sawLoad
, sawStore
, RegDefs
, RegUses
)) {
178 insertDefsUses(I
, RegDefs
, RegUses
);
187 bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate
,
190 SmallSet
<unsigned, 32> &RegDefs
,
191 SmallSet
<unsigned, 32> &RegUses
)
194 if (candidate
->isImplicitDef() || candidate
->isKill())
197 if (candidate
->getDesc().mayLoad()) {
203 if (candidate
->getDesc().mayStore()) {
211 for (unsigned i
= 0, e
= candidate
->getNumOperands(); i
!= e
; ++i
) {
212 const MachineOperand
&MO
= candidate
->getOperand(i
);
216 unsigned Reg
= MO
.getReg();
219 //check whether Reg is defined or used before delay slot.
220 if (IsRegInSet(RegDefs
, Reg
) || IsRegInSet(RegUses
, Reg
))
224 //check whether Reg is defined before delay slot.
225 if (IsRegInSet(RegDefs
, Reg
))
233 void Filler::insertCallUses(MachineBasicBlock::iterator MI
,
234 SmallSet
<unsigned, 32>& RegUses
)
237 switch(MI
->getOpcode()) {
238 default: llvm_unreachable("Unknown opcode.");
239 case SP::CALL
: break;
242 assert(MI
->getNumOperands() >= 2);
243 const MachineOperand
&Reg
= MI
->getOperand(0);
244 assert(Reg
.isReg() && "JMPL first operand is not a register.");
245 assert(Reg
.isUse() && "JMPL first operand is not a use.");
246 RegUses
.insert(Reg
.getReg());
248 const MachineOperand
&RegOrImm
= MI
->getOperand(1);
249 if (RegOrImm
.isImm())
251 assert(RegOrImm
.isReg() && "JMPLrr second operand is not a register.");
252 assert(RegOrImm
.isUse() && "JMPLrr second operand is not a use.");
253 RegUses
.insert(RegOrImm
.getReg());
258 //Insert Defs and Uses of MI into the sets RegDefs and RegUses.
259 void Filler::insertDefsUses(MachineBasicBlock::iterator MI
,
260 SmallSet
<unsigned, 32>& RegDefs
,
261 SmallSet
<unsigned, 32>& RegUses
)
263 for (unsigned i
= 0, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
264 const MachineOperand
&MO
= MI
->getOperand(i
);
268 unsigned Reg
= MO
.getReg();
279 //returns true if the Reg or its alias is in the RegSet.
280 bool Filler::IsRegInSet(SmallSet
<unsigned, 32>& RegSet
, unsigned Reg
)
282 if (RegSet
.count(Reg
))
284 // check Aliased Registers
285 for (const unsigned *Alias
= TM
.getRegisterInfo()->getAliasSet(Reg
);
287 if (RegSet
.count(*Alias
))
293 // return true if the candidate is a delay filler.
294 bool Filler::isDelayFiller(MachineBasicBlock
&MBB
,
295 MachineBasicBlock::iterator candidate
)
297 if (candidate
== MBB
.begin())
299 if (candidate
->getOpcode() == SP::UNIMP
)
301 const TargetInstrDesc
&prevdesc
= (--candidate
)->getDesc();
302 return prevdesc
.hasDelaySlot();
305 bool Filler::needsUnimp(MachineBasicBlock::iterator I
, unsigned &StructSize
)
307 if (!I
->getDesc().isCall())
310 unsigned structSizeOpNum
= 0;
311 switch (I
->getOpcode()) {
312 default: llvm_unreachable("Unknown call opcode.");
313 case SP::CALL
: structSizeOpNum
= 1; break;
315 case SP::JMPLri
: structSizeOpNum
= 2; break;
318 const MachineOperand
&MO
= I
->getOperand(structSizeOpNum
);
321 StructSize
= MO
.getImm();