// Insert Defs and Uses of MI into the sets RegDefs and RegUses. void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { // 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(); for (unsigned I = 0; I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); } // Call & return instructions defines SP implicitly. Implicit defines are not // included in the RegDefs set of calls but instructions modifying SP cannot // be inserted in the delay slot of a call/return as these instructions are // expanded to multiple instructions with SP modified before the branch that // has the delay slot. if (MI->isCall() || MI->isReturn()) RegDefs.insert(Lanai::SP); }
// 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); 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); ++RI; MachineBasicBlock::instr_iterator FI(RI.base()); 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; }
void MipsCodeEmitter::emitInstruction(MachineBasicBlock::instr_iterator MI, MachineBasicBlock &MBB) { DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << *MI); // Expand pseudo instruction. Skip if MI was not expanded. if (((MI->getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) && !expandPseudos(MI, MBB)) return; MCE.processDebugLoc(MI->getDebugLoc(), true); emitWord(getBinaryCodeForInstr(*MI)); ++NumEmitted; // Keep track of the # of mi's emitted MCE.processDebugLoc(MI->getDebugLoc(), false); }
// Insert Defs and Uses of MI into the sets RegDefs and RegUses. void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { // 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(); for (unsigned I = 0; I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); } }