STATISTIC(FilledSlots, "Number of delay slots filled");
STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
- "are not NOP.");
+ " are not NOP.");
static cl::opt<bool> EnableDelaySlotFiller(
"enable-mips-delay-filler",
LastFiller = MBB.end();
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
- if (I->getDesc().hasDelaySlot()) {
+ if (I->hasDelaySlot()) {
++FilledSlots;
Changed = true;
if (EnableDelaySlotFiller && findDelayInstr(MBB, I, D)) {
MBB.splice(llvm::next(I), &MBB, D);
++UsefulSlots;
- }
- else
+ } else
BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
// Record the filler instruction that filled the delay slot.
SmallSet<unsigned, 32> RegDefs;
SmallSet<unsigned, 32> RegUses;
- // Call's delay filler can def some of call's uses.
- if (slot->getDesc().isCall())
- insertCallUses(slot, RegDefs, RegUses);
- else
- insertDefsUses(slot, RegDefs, RegUses);
+ insertDefsUses(slot, RegDefs, RegUses);
bool sawLoad = false;
bool sawStore = false;
continue;
// Convert to forward iterator.
- MachineBasicBlock::iterator FI(next(I).base());
+ MachineBasicBlock::iterator FI(llvm::next(I).base());
if (I->hasUnmodeledSideEffects()
|| I->isInlineAsm()
|| I->isLabel()
|| FI == LastFiller
- || I->getDesc().isPseudo()
+ || I->isPseudo()
//
// Should not allow:
// ERET, DERET or WAIT, PAUSE. Need to add these to instruction
}
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
- bool &sawLoad,
- bool &sawStore,
+ bool &sawLoad, bool &sawStore,
SmallSet<unsigned, 32> &RegDefs,
SmallSet<unsigned, 32> &RegUses) {
if (candidate->isImplicitDef() || candidate->isKill())
// Loads or stores cannot be moved past a store to the delay slot
// and stores cannot be moved past a load.
- if (candidate->getDesc().mayLoad()) {
+ if (candidate->mayLoad()) {
if (sawStore)
return true;
sawLoad = true;
}
- if (candidate->getDesc().mayStore()) {
+ if (candidate->mayStore()) {
if (sawStore)
return true;
sawStore = true;
return true;
}
+ assert((!candidate->isCall() && !candidate->isReturn()) &&
+ "Cannot put calls or returns in delay slot.");
+
for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
const MachineOperand &MO = candidate->getOperand(i);
- if (!MO.isReg())
- continue; // skip
+ unsigned Reg;
- unsigned Reg = MO.getReg();
+ if (!MO.isReg() || !(Reg = MO.getReg()))
+ continue; // skip
if (MO.isDef()) {
// check whether Reg is defined or used before delay slot.
return false;
}
-void Filler::insertCallUses(MachineBasicBlock::iterator MI,
- SmallSet<unsigned, 32>& RegDefs,
- SmallSet<unsigned, 32>& RegUses) {
- switch(MI->getOpcode()) {
- default: llvm_unreachable("Unknown opcode.");
- case Mips::JAL:
- RegDefs.insert(31);
- break;
- case Mips::JALR:
- assert(MI->getNumOperands() >= 1);
- const MachineOperand &Reg = MI->getOperand(0);
- assert(Reg.isReg() && "JALR first operand is not a register.");
- RegUses.insert(Reg.getReg());
- RegDefs.insert(31);
- break;
- }
-}
-
// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
void Filler::insertDefsUses(MachineBasicBlock::iterator MI,
SmallSet<unsigned, 32>& RegDefs,
SmallSet<unsigned, 32>& RegUses) {
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ // If MI is a call or return, just examine the explicit non-variadic operands.
+ MCInstrDesc MCID = MI->getDesc();
+ unsigned e = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() :
+ MI->getNumOperands();
+
+ // Add RA to RegDefs to prevent users of RA from going into delay slot.
+ if (MI->isCall())
+ RegDefs.insert(Mips::RA);
+
+ for (unsigned i = 0; i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
- if (!MO.isReg())
- continue;
+ unsigned Reg;
- unsigned Reg = MO.getReg();
- if (Reg == 0)
+ if (!MO.isReg() || !(Reg = MO.getReg()))
continue;
+
if (MO.isDef())
RegDefs.insert(Reg);
- if (MO.isUse())
+ else if (MO.isUse())
RegUses.insert(Reg);
}
}