Index: llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ llvm/trunk/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -643,18 +643,34 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot, IterTy &Filler) const { - for (IterTy I = Begin; I != End; ++I) { + bool IsReverseIter = std::is_convertible::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; const MipsSubtarget &STI = MBB.getParent()->getSubtarget(); @@ -664,21 +680,21 @@ // 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, STI.getRegisterInfo())) + if ((isBasePlusOffsetMemoryAccess(CurrI->getOpcode(), &AddrIdx) && + baseRegNeedsLoadStoreMask(CurrI->getOperand(AddrIdx).getReg())) || + CurrI->modifiesRegister(Mips::SP, STI.getRegisterInfo())) continue; } 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; } @@ -843,7 +859,10 @@ 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()); Index: llvm/trunk/test/CodeGen/Mips/delay-slot-kill.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/delay-slot-kill.ll +++ llvm/trunk/test/CodeGen/Mips/delay-slot-kill.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s + +; Currently, the following IR assembly generates a KILL instruction between +; the bitwise-and instruction and the return instruction. We verify that the +; delay slot filler ignores such KILL instructions by filling the slot of the +; return instruction properly. +define signext i32 @f1(i32 signext %a, i32 signext %b) { +entry: + ; CHECK: jr $ra + ; CHECK-NEXT: and $2, $4, $5 + + %r = and i32 %a, %b + ret i32 %r +}