From 3b8ddb665bb332f0dd484db44ec93da927caa7df Mon Sep 17 00:00:00 2001 From: Jozef Kolek Date: Fri, 21 Nov 2014 22:04:35 +0000 Subject: [PATCH] [mips][microMIPS] This patch implements functionality in MIPS delay slot filler such as if delay slot filler have to put NOP instruction into the delay slot of microMIPS BEQ or BNE instruction which uses the register $0, then instead of emitting NOP this instruction is replaced by the corresponding microMIPS compact branch instruction, i.e. BEQZC or BNEZC. Differential Revision: http://reviews.llvm.org/D3566 llvm-svn: 222580 --- llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 48 +++++++++++++++++++--- llvm/lib/Target/Mips/MipsLongBranch.cpp | 12 +++--- llvm/lib/Target/Mips/MipsSEInstrInfo.cpp | 4 +- llvm/test/CodeGen/Mips/micromips-atomic.ll | 2 +- .../CodeGen/Mips/micromips-compact-branches.ll | 19 +++++++++ 5 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/micromips-compact-branches.ll diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index d7ba6d4..0fdfe69 100644 --- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -196,6 +196,9 @@ namespace { private: bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + Iter replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, 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. @@ -494,6 +497,29 @@ getUnderlyingObjects(const MachineInstr &MI, return true; } +// Replace Branch with the compact branch instruction. +Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, DebugLoc DL) { + const MipsInstrInfo *TII= static_cast( + TM.getSubtargetImpl()->getInstrInfo()); + + unsigned NewOpcode = + (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM + : Mips::BNEZC_MM; + + const MCInstrDesc &NewDesc = TII->get(NewOpcode); + MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); + + MIB.addReg(Branch->getOperand(0).getReg()); + MIB.addMBB(Branch->getOperand(2).getMBB()); + + Iter tmpIter = Branch; + Branch = std::prev(Branch); + MBB.erase(tmpIter); + + return Branch; +} + /// 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) { @@ -527,11 +553,23 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { } } - // 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)); + // If instruction is BEQ or BNE with one ZERO register, then instead of + // 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. + 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)); + } } return Changed; diff --git a/llvm/lib/Target/Mips/MipsLongBranch.cpp b/llvm/lib/Target/Mips/MipsLongBranch.cpp index e44d6ee..cf267c9 100644 --- a/llvm/lib/Target/Mips/MipsLongBranch.cpp +++ b/llvm/lib/Target/Mips/MipsLongBranch.cpp @@ -237,11 +237,13 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, MIB.addMBB(MBBOpnd); - // Bundle the instruction in the delay slot to the newly created branch - // and erase the original branch. - assert(Br->isBundledWithSucc()); - MachineBasicBlock::instr_iterator II(Br); - MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); + if (Br->hasDelaySlot()) { + // Bundle the instruction in the delay slot to the newly created branch + // and erase the original branch. + assert(Br->isBundledWithSucc()); + MachineBasicBlock::instr_iterator II(Br); + MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); + } Br->eraseFromParent(); } diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index 16bea8b..ddfef05 100644 --- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -352,6 +352,8 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BLEZ64: return Mips::BGTZ64; case Mips::BC1T: return Mips::BC1F; case Mips::BC1F: return Mips::BC1T; + case Mips::BEQZC_MM: return Mips::BNEZC_MM; + case Mips::BNEZC_MM: return Mips::BEQZC_MM; } } @@ -422,7 +424,7 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || - Opc == Mips::J) ? + Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? Opc : 0; } diff --git a/llvm/test/CodeGen/Mips/micromips-atomic.ll b/llvm/test/CodeGen/Mips/micromips-atomic.ll index a50e0b7..82eee4b 100644 --- a/llvm/test/CodeGen/Mips/micromips-atomic.ll +++ b/llvm/test/CodeGen/Mips/micromips-atomic.ll @@ -14,5 +14,5 @@ entry: ; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]]) ; CHECK: addu $[[R2:[0-9]+]], $[[R1]], $4 ; CHECK: sc $[[R2]], 0($[[R0]]) -; CHECK: beqz $[[R2]], $[[BB0]] +; CHECK: beqzc $[[R2]], $[[BB0]] } diff --git a/llvm/test/CodeGen/Mips/micromips-compact-branches.ll b/llvm/test/CodeGen/Mips/micromips-compact-branches.ll new file mode 100644 index 0000000..670f9a0 --- /dev/null +++ b/llvm/test/CodeGen/Mips/micromips-compact-branches.ll @@ -0,0 +1,19 @@ +; RUN: llc %s -march=mipsel -mattr=micromips -filetype=asm -O3 \ +; RUN: -disable-mips-delay-filler -relocation-model=pic -o - | FileCheck %s + +define void @main() nounwind uwtable { +entry: + %x = alloca i32, align 4 + %0 = load i32* %x, align 4 + %cmp = icmp eq i32 %0, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: + store i32 10, i32* %x, align 4 + br label %if.end + +if.end: + ret void +} + +; CHECK: bnezc -- 2.7.4