void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize) { // load $vr0, FI // copy lo, $vr0 // load $vr1, FI + 4 // copy hi, $vr1 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo); unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi); DebugLoc DL = I->getDebugLoc(); const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY); TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0); BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill); TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize); BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill); }
void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize) { // copy $vr0, lo // store $vr0, FI // copy $vr1, hi // store $vr1, FI + 4 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); unsigned SrcKill = getKillRegState(I->getOperand(0).isKill()); unsigned Lo = RegInfo.getSubReg(Src, Mips::sub_lo); unsigned Hi = RegInfo.getSubReg(Src, Mips::sub_hi); DebugLoc DL = I->getDebugLoc(); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(Lo, SrcKill); TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(Hi, SrcKill); TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize); }
bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, unsigned MFLoOpc) { // mflo $vr0, src // copy dst_lo, $vr0 // mfhi $vr1, src // copy dst_hi, $vr1 unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2; const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); unsigned SrcKill = getKillRegState(I->getOperand(1).isKill()); unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo); unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi); DebugLoc DL = I->getDebugLoc(); BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo) .addReg(VR0, RegState::Kill); BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi) .addReg(VR1, RegState::Kill); return true; }
void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, unsigned MFLoOpc, unsigned RegSize) { // mflo $vr0, src // store $vr0, FI // mfhi $vr1, src // store $vr1, FI + 4 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); unsigned SrcKill = getKillRegState(I->getOperand(0).isKill()); DebugLoc DL = I->getDebugLoc(); BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src); TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0); BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill); TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize); }
bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); if (Mips::ACRegsDSPRegClass.contains(Dst, Src)) return expandCopyACC(MBB, I, Dst, Src, 4); if (Mips::ACRegs128RegClass.contains(Dst, Src)) return expandCopyACC(MBB, I, Dst, Src, 8); return false; }
void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { // copy $vr, ccond // store $vr, FI assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR) .addReg(Src, getKillRegState(I->getOperand(0).isKill())); TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0); }
void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { // load $vr, FI // copy ccond, $vr assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0); BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst) .addReg(VR, RegState::Kill); }
// Replace Br with a branch which has the opposite condition code and a // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, MachineBasicBlock *MBBOpnd) { const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc); for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) { MachineOperand &MO = Br->getOperand(I); if (!MO.isReg()) { assert(MO.isMBB() && "MBB operand expected."); break; } MIB.addReg(MO.getReg()); } MIB.addMBB(MBBOpnd); if (Br->hasDelaySlot()) { // Bundle the instruction in the delay slot to the newly created branch // and erase the original branch. assert(Br->isBundledWithSucc()); MachineBasicBlock::instr_iterator II(Br); MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); } Br->eraseFromParent(); }
bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst, unsigned Src, unsigned RegSize) { // copy $vr0, src_lo // copy dst_lo, $vr0 // copy $vr1, src_hi // copy dst_hi, $vr1 const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); unsigned SrcKill = getKillRegState(I->getOperand(1).isKill()); unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo); unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi); unsigned SrcLo = RegInfo.getSubReg(Src, Mips::sub_lo); unsigned SrcHi = RegInfo.getSubReg(Src, Mips::sub_hi); DebugLoc DL = I->getDebugLoc(); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(SrcLo, SrcKill); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo) .addReg(VR0, RegState::Kill); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(SrcHi, SrcKill); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi) .addReg(VR1, RegState::Kill); return true; }
bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { unsigned Src = I->getOperand(1).getReg(); std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src); if (!Opcodes.first) return false; return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second); }
// Replace Jumps with the compact jump instruction. Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB, Iter Jump, DebugLoc DL) { const MipsInstrInfo *TII = MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM); MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc); MIB.addReg(Jump->getOperand(0).getReg()); Iter tmpIter = Jump; Jump = std::prev(Jump); MBB.erase(tmpIter); return Jump; }
/// This function adds registers Filler defines to MBB's live-in register list. static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { for (unsigned I = 0, E = Filler->getNumOperands(); I != E; ++I) { const MachineOperand &MO = Filler->getOperand(I); unsigned R; if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg())) continue; #ifndef NDEBUG const MachineFunction &MF = *MBB.getParent(); assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && "Shouldn't move an instruction with unallocatable registers across " "basic block boundaries."); #endif if (!MBB.isLiveIn(R)) MBB.addLiveIn(R); } }
// Replace Branch with the compact branch instruction. Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL) { const MipsInstrInfo *TII = MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); unsigned NewOpcode = (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM : Mips::BNEZC_MM; const MCInstrDesc &NewDesc = TII->get(NewOpcode); MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); MIB.addReg(Branch->getOperand(0).getReg()); MIB.addMBB(Branch->getOperand(2).getMBB()); Iter tmpIter = Branch; Branch = std::prev(Branch); MBB.erase(tmpIter); return Branch; }
// Replace Br with a branch which has the opposite condition code and a // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, MachineBasicBlock *MBBOpnd) { const MipsInstrInfo *TII = static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc); for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) { MachineOperand &MO = Br->getOperand(I); if (!MO.isReg()) { assert(MO.isMBB() && "MBB operand expected."); break; } MIB.addReg(MO.getReg()); } MIB.addMBB(MBBOpnd); Br->eraseFromParent(); }
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// We assume there is only one delay slot per delayed instruction. bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); bool InMicroMipsMode = STI.inMicroMipsMode(); const MipsInstrInfo *TII = STI.getInstrInfo(); for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) continue; ++FilledSlots; Changed = true; // Delay slot filling is disabled at -O0. if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { bool Filled = false; if (searchBackward(MBB, I)) { Filled = true; } else if (I->isTerminator()) { if (searchSuccBBs(MBB, I)) { Filled = true; } } else if (searchForward(MBB, I)) { Filled = true; } if (Filled) { // Get instruction with delay slot. MachineBasicBlock::instr_iterator DSI(I); if (InMicroMipsMode && TII->GetInstSizeInBytes(std::next(DSI)) == 2 && DSI->isCall()) { // If instruction in delay slot is 16b change opcode to // corresponding instruction with short delay slot. DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); } continue; } } // If instruction is BEQ or BNE with one ZERO register, then instead of // adding NOP replace this instruction with the corresponding compact // branch instruction, i.e. BEQZC or BNEZC. unsigned Opcode = I->getOpcode(); if (InMicroMipsMode) { switch (Opcode) { case Mips::BEQ: case Mips::BNE: if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); continue; } break; case Mips::JR: case Mips::PseudoReturn: case Mips::PseudoIndirectBranch: // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways // expanded to JR_MM, so they can be replaced with JRC16_MM. I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); continue; default: break; } } // Bundle the NOP to the instruction with the delay slot. BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); MIBundleBuilder(MBB, I, std::next(I, 2)); } return Changed; }