mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-06 03:38:34 +00:00
[mips][microMIPS] Delay slot filler: Replace the microMIPS JR with the JRC
This patch adds functionality in MIPS delay slot filler such as if delay slot filler have to put NOP instruction into the delay slot of microMIPS JR instruction, then instead of emitting NOP this instruction is replaced by compact jump instruction JRC. Differential Revision: http://reviews.llvm.org/D7522 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229128 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d25126faae
commit
85e08ed8a4
@ -199,6 +199,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.
|
||||
@ -515,6 +518,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) {
|
||||
@ -582,17 +603,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;
|
||||
|
@ -126,8 +126,7 @@ end:
|
||||
; MICROMIPS: li16 $[[R2:[0-9]+]], 1
|
||||
; MICROMIPS: sw16 $[[R2]], 0($[[R1]])
|
||||
; MICROMIPS: $[[BB2]]:
|
||||
; MICROMIPS: jr $ra
|
||||
; MICROMIPS: nop
|
||||
; MICROMIPS: jrc $ra
|
||||
|
||||
|
||||
; Check the NaCl version. Check that sp change is not in the branch delay slot
|
||||
|
11
test/CodeGen/Mips/micromips-compact-jump.ll
Normal file
11
test/CodeGen/Mips/micromips-compact-jump.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \
|
||||
; RUN: -disable-mips-delay-filler -O3 < %s | FileCheck %s
|
||||
|
||||
define i32 @foo(i32 signext %a) #0 {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare i32 @bar(i32 signext) #1
|
||||
|
||||
; CHECK: jrc
|
@ -29,8 +29,7 @@ declare i32 @puts(i8* nocapture readonly) #1
|
||||
!3 = !{!"omnipotent char", !4, i64 0}
|
||||
!4 = !{!"Simple C/C++ TBAA"}
|
||||
|
||||
; CHECK: jr
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK: jrc
|
||||
|
||||
%struct.foostruct = type { [3 x float] }
|
||||
%struct.barstruct = type { %struct.foostruct, float }
|
||||
@ -43,6 +42,5 @@ define float* @spooky(i32 signext %i) #0 {
|
||||
}
|
||||
|
||||
; CHECK: spooky:
|
||||
; CHECK: jr $ra
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK: jrc $ra
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user