From 187afcd54800a37a513ab93f4c6966cd963d1741 Mon Sep 17 00:00:00 2001 From: Vasileios Kalintiris Date: Fri, 17 Apr 2015 12:01:02 +0000 Subject: [PATCH] [mips] Teach the delay slot filler to remove needless KILL instructions. Summary: Previously, the presence of KILL instructions would block valid candidates from filling a specific delay slot. With the elimination of the KILL instructions, in the appropriate range, we are able to fill more slots and keep the information from future def/use analysis consistent. Reviewers: dsanders Reviewed By: dsanders Subscribers: hfinkel, llvm-commits Differential Revision: http://reviews.llvm.org/D7724 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235183 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsDelaySlotFiller.cpp | 41 ++++++++++++++++++------- test/CodeGen/Mips/delay-slot-kill.ll | 14 +++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 test/CodeGen/Mips/delay-slot-kill.ll diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index 606964dc129..de9f4a59e01 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -643,18 +643,34 @@ template 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 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, // 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::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()); diff --git a/test/CodeGen/Mips/delay-slot-kill.ll b/test/CodeGen/Mips/delay-slot-kill.ll new file mode 100644 index 00000000000..57b630303c2 --- /dev/null +++ b/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 +} -- 2.34.1