Index: lib/Target/Mips/MipsDelaySlotFiller.cpp =================================================================== --- lib/Target/Mips/MipsDelaySlotFiller.cpp +++ lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -494,42 +494,69 @@ return true; } +// For given opcode returns opcode of corresponding instruction with short +// delay slot. +static int getEquivalentCallShort(int Opcode) { + switch (Opcode) { + case Mips::BGEZAL: + return Mips::BGEZALS_MM; + case Mips::BLTZAL: + return Mips::BLTZALS_MM; + case Mips::JAL: + return Mips::JALS_MM; + case Mips::JALR: + return Mips::JALRS_MM; + case Mips::JALR16_MM: + return Mips::JALRS16_MM; + default: + llvm_unreachable("Unexpected call instruction for microMIPS."); + } +} + /// 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; bool InMicroMipsMode = TM.getSubtarget().inMicroMipsMode(); + const MipsInstrInfo *TII = + static_cast(TM.getSubtargetImpl()->getInstrInfo()); for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) continue; - // For microMIPS, at the moment, do not fill delay slots of call - // instructions. - // - // TODO: Support for replacing regular call instructions with corresponding - // short delay slot instructions should be implemented. - if (!InMicroMipsMode || !I->isCall()) { - ++FilledSlots; - Changed = true; - - // Delay slot filling is disabled at -O0. - if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { - if (searchBackward(MBB, I)) - continue; - - if (I->isTerminator()) { - if (searchSuccBBs(MBB, I)) - continue; - } else if (searchForward(MBB, 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 chenge opcode to + // corresponding instruction with short delay slot. + DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); + + continue; } } // Bundle the NOP to the instruction with the delay slot. - const MipsInstrInfo *TII = static_cast( - TM.getSubtargetImpl()->getInstrInfo()); BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); MIBundleBuilder(MBB, I, std::next(I, 2)); } Index: test/CodeGen/Mips/micromips-delay-slot.ll =================================================================== --- test/CodeGen/Mips/micromips-delay-slot.ll +++ test/CodeGen/Mips/micromips-delay-slot.ll @@ -1,18 +1,17 @@ ; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ -; RUN: -relocation-model=pic -O3 < %s | FileCheck %s +; RUN: -relocation-model=static -O2 < %s | FileCheck %s -; Function Attrs: nounwind uwtable -define i32 @foo(i32 %a) #0 { +; Function Attrs: nounwind +define i32 @foo(i32 signext %a) #0 { entry: %a.addr = alloca i32, align 4 store i32 %a, i32* %a.addr, align 4 %0 = load i32* %a.addr, align 4 %shl = shl i32 %0, 2 - %call = call i32 @bar(i32 %shl) + %call = call i32 @bar(i32 signext %shl) ret i32 %call } -declare i32 @bar(i32) #1 - -; CHECK: nop +declare i32 @bar(i32 signext) #1 +; CHECK: jals