[mips][micromips] Use call instructions with short delay slots

Differential Revision: http://reviews.llvm.org/D6338


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222752 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zoran Jovanovic 2014-11-25 10:50:00 +00:00
parent 333d5c9f51
commit 137c475805
2 changed files with 54 additions and 26 deletions

View File

@ -520,36 +520,66 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,
return Branch; return Branch;
} }
// 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. /// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
/// We assume there is only one delay slot per delayed instruction. /// We assume there is only one delay slot per delayed instruction.
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false; bool Changed = false;
bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode();
const MipsInstrInfo *TII =
static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo());
for (Iter I = MBB.begin(); I != MBB.end(); ++I) { for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
if (!hasUnoccupiedSlot(&*I)) if (!hasUnoccupiedSlot(&*I))
continue; continue;
// For microMIPS, at the moment, do not fill delay slots of call ++FilledSlots;
// instructions. Changed = true;
//
// 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. // Delay slot filling is disabled at -O0.
if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) {
if (searchBackward(MBB, I)) bool Filled = false;
continue;
if (I->isTerminator()) { if (searchBackward(MBB, I)) {
if (searchSuccBBs(MBB, I)) Filled = true;
continue; } else if (I->isTerminator()) {
} else if (searchForward(MBB, I)) { if (searchSuccBBs(MBB, I)) {
continue; 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;
} }
} }
@ -565,8 +595,6 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
} else { } else {
// Bundle the NOP to the instruction with the delay slot. // Bundle the NOP to the instruction with the delay slot.
const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(
TM.getSubtargetImpl()->getInstrInfo());
BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
MIBundleBuilder(MBB, I, std::next(I, 2)); MIBundleBuilder(MBB, I, std::next(I, 2));
} }

View File

@ -1,18 +1,18 @@
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ ; 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 ; Function Attrs: nounwind
define i32 @foo(i32 %a) #0 { define i32 @foo(i32 signext %a) #0 {
entry: entry:
%a.addr = alloca i32, align 4 %a.addr = alloca i32, align 4
store i32 %a, i32* %a.addr, align 4 store i32 %a, i32* %a.addr, align 4
%0 = load i32* %a.addr, align 4 %0 = load i32* %a.addr, align 4
%shl = shl i32 %0, 2 %shl = shl i32 %0, 2
%call = call i32 @bar(i32 %shl) %call = call i32 @bar(i32 signext %shl)
ret i32 %call ret i32 %call
} }
declare i32 @bar(i32) #1 declare i32 @bar(i32 signext) #1
; CHECK: nop
; CHECK: jals
; CHECK-NEXT: sll16