diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 178 |
1 files changed, 117 insertions, 61 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index d5027b9..4faeb33 100644 --- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -69,7 +69,7 @@ namespace { class RegDefsUses { public: - RegDefsUses(TargetMachine &TM); + RegDefsUses(const TargetRegisterInfo &TRI); void init(const MachineInstr &MI); /// This function sets all caller-saved registers in Defs. @@ -140,7 +140,7 @@ namespace { /// memory instruction can be moved to a delay slot. class MemDefsUses : public InspectMemInstr { public: - MemDefsUses(const MachineFrameInfo *MFI); + MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI); private: typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType; @@ -158,6 +158,7 @@ namespace { const MachineFrameInfo *MFI; SmallPtrSet<ValueType, 4> Uses, Defs; + const DataLayout &DL; /// Flags indicating whether loads or stores with no underlying objects have /// been seen. @@ -199,6 +200,9 @@ namespace { Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL); + Iter replaceWithCompactJump(MachineBasicBlock &MBB, + Iter Jump, DebugLoc DL); + /// This function checks if it is valid to move Candidate to the delay slot /// and returns true if it isn't. It also updates memory and register /// dependence information. @@ -209,8 +213,8 @@ namespace { /// moved to the delay slot. Returns true on success. template<typename IterTy> bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr &IM, - IterTy &Filler, Iter Slot) const; + RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot, + IterTy &Filler) const; /// This function searches in the backward direction for an instruction that /// can be moved to the delay slot. Returns true on success. @@ -278,11 +282,7 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { #ifndef NDEBUG const MachineFunction &MF = *MBB.getParent(); - assert(MF.getTarget() - .getSubtargetImpl() - ->getRegisterInfo() - ->getAllocatableSet(MF) - .test(R) && + assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && "Shouldn't move an instruction with unallocatable registers across " "basic block boundaries."); #endif @@ -292,9 +292,8 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { } } -RegDefsUses::RegDefsUses(TargetMachine &TM) - : TRI(*TM.getSubtargetImpl()->getRegisterInfo()), - Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} +RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI) + : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} void RegDefsUses::init(const MachineInstr &MI) { // Add all register operands which are explicit and non-variadic. @@ -316,13 +315,22 @@ void RegDefsUses::init(const MachineInstr &MI) { void RegDefsUses::setCallerSaved(const MachineInstr &MI) { assert(MI.isCall()); + // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into + // the delay slot. The reason is that RA/RA_64 must not be changed + // in the delay slot so that the callee can return to the caller. + if (MI.definesRegister(Mips::RA) || MI.definesRegister(Mips::RA_64)) { + Defs.set(Mips::RA); + Defs.set(Mips::RA_64); + } + // If MI is a call, add all caller-saved registers to Defs. BitVector CallerSavedRegs(TRI.getNumRegs(), true); CallerSavedRegs.reset(Mips::ZERO); CallerSavedRegs.reset(Mips::ZERO_64); - for (const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R) + for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent()); + *R; ++R) for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) CallerSavedRegs.reset(*AI); @@ -429,9 +437,9 @@ bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { return true; } -MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) - : InspectMemInstr(false), MFI(MFI_), SeenNoObjLoad(false), - SeenNoObjStore(false) {} +MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_) + : InspectMemInstr(false), MFI(MFI_), DL(DL), SeenNoObjLoad(false), + SeenNoObjStore(false) {} bool MemDefsUses::hasHazard_(const MachineInstr &MI) { bool HasHazard = false; @@ -484,7 +492,7 @@ getUnderlyingObjects(const MachineInstr &MI, const Value *V = (*MI.memoperands_begin())->getValue(); SmallVector<Value *, 4> Objs; - GetUnderlyingObjects(const_cast<Value *>(V), Objs); + GetUnderlyingObjects(const_cast<Value *>(V), Objs, DL); for (SmallVectorImpl<Value *>::iterator I = Objs.begin(), E = Objs.end(); I != E; ++I) { @@ -500,8 +508,8 @@ getUnderlyingObjects(const MachineInstr &MI, // Replace Branch with the compact branch instruction. Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL) { - const MipsInstrInfo *TII= static_cast<const MipsInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const MipsInstrInfo *TII = + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); unsigned NewOpcode = (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM @@ -520,6 +528,24 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, return Branch; } +// 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; +} + // For given opcode returns opcode of corresponding instruction with short // delay slot. static int getEquivalentCallShort(int Opcode) { @@ -543,9 +569,9 @@ static int getEquivalentCallShort(int Opcode) { /// We assume there is only one delay slot per delayed instruction. bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + 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)) @@ -587,17 +613,29 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { // adding NOP replace this instruction with the corresponding compact // branch instruction, i.e. BEQZC or BNEZC. unsigned Opcode = I->getOpcode(); - if (InMicroMipsMode && - (Opcode == Mips::BEQ || Opcode == Mips::BNE) && - ((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { - - I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); - - } else { - // 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)); + 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; @@ -611,45 +649,60 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { template<typename IterTy> bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr& IM, - IterTy &Filler, Iter Slot) const { - for (IterTy I = Begin; I != End; ++I) { + RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot, + IterTy &Filler) const { + bool IsReverseIter = std::is_convertible<IterTy, ReverseIter>::value; + + for (IterTy I = Begin; I != End;) { + IterTy CurrI = I; + ++I; + // skip debug value - if (I->isDebugValue()) + if (CurrI->isDebugValue()) continue; - if (terminateSearch(*I)) + if (terminateSearch(*CurrI)) break; - assert((!I->isCall() && !I->isReturn() && !I->isBranch()) && + assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) && "Cannot put calls, returns or branches in delay slot."); - if (delayHasHazard(*I, RegDU, IM)) + if (CurrI->isKill()) { + CurrI->eraseFromParent(); + + // This special case is needed for reverse iterators, because when we + // erase an instruction, the iterators are updated to point to the next + // instruction. + if (IsReverseIter && I != End) + I = CurrI; + continue; + } + + if (delayHasHazard(*CurrI, RegDU, IM)) continue; - if (TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + if (STI.isTargetNaCl()) { // In NaCl, instructions that must be masked are forbidden in delay slots. // We only check for loads, stores and SP changes. Calls, returns and // branches are not checked because non-NaCl targets never put them in // delay slots. unsigned AddrIdx; - if ((isBasePlusOffsetMemoryAccess(I->getOpcode(), &AddrIdx) && - baseRegNeedsLoadStoreMask(I->getOperand(AddrIdx).getReg())) || - I->modifiesRegister(Mips::SP, - TM.getSubtargetImpl()->getRegisterInfo())) + if ((isBasePlusOffsetMemoryAccess(CurrI->getOpcode(), &AddrIdx) && + baseRegNeedsLoadStoreMask(CurrI->getOperand(AddrIdx).getReg())) || + CurrI->modifiesRegister(Mips::SP, STI.getRegisterInfo())) continue; } - bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); - const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + bool InMicroMipsMode = STI.inMicroMipsMode(); + const MipsInstrInfo *TII = STI.getInstrInfo(); unsigned Opcode = (*Slot).getOpcode(); - if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*I)) == 2 && + if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*CurrI)) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || Opcode == Mips::PseudoReturn)) continue; - Filler = I; + Filler = CurrI; return true; } @@ -660,14 +713,14 @@ bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableBackwardSearch) return false; - RegDefsUses RegDU(TM); - MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); + MemDefsUses MemDU(*TM.getDataLayout(), MBB.getParent()->getFrameInfo()); ReverseIter Filler; RegDU.init(*Slot); - if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler, - Slot)) + if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Slot, + Filler)) return false; MBB.splice(std::next(Slot), &MBB, std::next(Filler).base()); @@ -681,13 +734,13 @@ bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableForwardSearch || !Slot->isCall()) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); NoMemInstr NM; Iter Filler; RegDU.setCallerSaved(*Slot); - if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Filler, Slot)) + if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) return false; MBB.splice(std::next(Slot), &MBB, Filler); @@ -705,7 +758,7 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { if (!SuccBB) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); bool HasMultipleSuccs = false; BB2BrMap BrMap; std::unique_ptr<InspectMemInstr> IM; @@ -727,11 +780,11 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { IM.reset(new LoadFromStackOrConst()); } else { const MachineFrameInfo *MFI = MBB.getParent()->getFrameInfo(); - IM.reset(new MemDefsUses(MFI)); + IM.reset(new MemDefsUses(*TM.getDataLayout(), MFI)); } - if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler, - Slot)) + if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot, + Filler)) return false; insertDelayFiller(Filler, BrMap); @@ -758,7 +811,7 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { std::pair<MipsInstrInfo::BranchType, MachineInstr *> Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; SmallVector<MachineInstr*, 2> BranchInstrs; SmallVector<MachineOperand, 2> Cond; @@ -814,7 +867,10 @@ bool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, InspectMemInstr &IM) const { - bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); + assert(!Candidate.isKill() && + "KILL instructions should have been eliminated at this point."); + + bool HasHazard = Candidate.isImplicitDef(); HasHazard |= IM.hasHazard(Candidate); HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); |