bool Filler::findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator Slot, MachineBasicBlock::instr_iterator &Filler) { SmallSet<unsigned, 32> RegDefs; SmallSet<unsigned, 32> RegUses; insertDefsUses(Slot, RegDefs, RegUses); bool SawLoad = false; bool SawStore = false; for (MachineBasicBlock::reverse_instr_iterator I = ++Slot.getReverse(); I != MBB.instr_rend(); ++I) { // skip debug value if (I->isDebugValue()) continue; // Convert to forward iterator. MachineBasicBlock::instr_iterator FI = I.getReverse(); if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() || FI == LastFiller || I->isPseudo()) break; if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) { insertDefsUses(FI, RegDefs, RegUses); continue; } Filler = FI; return true; } return false; }
// runOnMachineBasicBlock - Fill in delay slots for the given basic block. // There is one or two delay slot per delayed instruction. bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; LastFiller = MBB.instr_end(); for (MachineBasicBlock::instr_iterator I = MBB.instr_begin(); I != MBB.instr_end(); ++I) { if (I->getDesc().hasDelaySlot()) { MachineBasicBlock::instr_iterator InstrWithSlot = I; MachineBasicBlock::instr_iterator J = I; // Treat RET specially as it is only instruction with 2 delay slots // generated while all others generated have 1 delay slot. if (I->getOpcode() == Lanai::RET) { // RET is generated as part of epilogue generation and hence we know // what the two instructions preceding it are and that it is safe to // insert RET above them. MachineBasicBlock::reverse_instr_iterator RI = ++I.getReverse(); assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() && RI->getOperand(0).getReg() == Lanai::FP && RI->getOperand(1).isReg() && RI->getOperand(1).getReg() == Lanai::FP && RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8); ++RI; assert(RI->getOpcode() == Lanai::ADD_I_LO && RI->getOperand(0).isReg() && RI->getOperand(0).getReg() == Lanai::SP && RI->getOperand(1).isReg() && RI->getOperand(1).getReg() == Lanai::FP); MachineBasicBlock::instr_iterator FI = RI.getReverse(); MBB.splice(std::next(I), &MBB, FI, I); FilledSlots += 2; } else { if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) { MBB.splice(std::next(I), &MBB, J); } else { BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP)); } ++FilledSlots; } Changed = true; // Record the filler instruction that filled the delay slot. // The instruction after it will be visited in the next iteration. LastFiller = ++I; // Bundle the delay slot filler to InstrWithSlot so that the machine // verifier doesn't expect this instruction to be a terminator. MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller)); } } return Changed; }