From de17fb6e4dd8f169f707d58d4e124c8d4d2c7dba Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 31 Oct 2009 23:46:45 +0000 Subject: [PATCH] Use cbz and cbnz instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85698 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMConstantIslandPass.cpp | 64 ++++++++++++++++++++++++++------ lib/Target/ARM/ARMInstrThumb.td | 9 +++++ test/CodeGen/Thumb2/machine-licm.ll | 2 + test/CodeGen/Thumb2/thumb2-cbnz.ll | 32 ++++++++++++++++ 4 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 test/CodeGen/Thumb2/thumb2-cbnz.ll diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 0a27d179e90..981962522db 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -41,6 +41,7 @@ STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); STATISTIC(NumTBs, "Number of table branches generated"); STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk"); STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk"); +STATISTIC(NumCBZ, "Number of CBZ / CBNZ formed"); namespace { /// ARMConstantIslands - Due to limited PC-relative displacements, ARM @@ -1486,24 +1487,65 @@ bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) { Bits = 11; Scale = 2; break; - case ARM::t2Bcc: + case ARM::t2Bcc: { NewOpc = ARM::tBcc; Bits = 8; - Scale = 2; + Scale = 2; break; } - if (!NewOpc) + } + if (NewOpc) { + unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); + if (BBIsInRange(Br.MI, DestBB, MaxOffs)) { + Br.MI->setDesc(TII->get(NewOpc)); + MachineBasicBlock *MBB = Br.MI->getParent(); + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumT2BrShrunk; + MadeChange = true; + } + } + + Opcode = Br.MI->getOpcode(); + if (Opcode != ARM::tBcc) continue; - unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + NewOpc = 0; + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(Br.MI, PredReg); + if (Pred == ARMCC::EQ) + NewOpc = ARM::tCBZ; + else if (Pred == ARMCC::NE) + NewOpc = ARM::tCBNZ; + if (!NewOpc) + continue; MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); - if (BBIsInRange(Br.MI, DestBB, MaxOffs)) { - Br.MI->setDesc(TII->get(NewOpc)); - MachineBasicBlock *MBB = Br.MI->getParent(); - BBSizes[MBB->getNumber()] -= 2; - AdjustBBOffsetsAfter(MBB, -2); - ++NumT2BrShrunk; - MadeChange = true; + // Check if the distance is within 126. Subtract starting offset by 2 + // because the cmp will be eliminated. + unsigned BrOffset = GetOffsetOf(Br.MI) + 4 - 2; + unsigned DestOffset = BBOffsets[DestBB->getNumber()]; + if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) { + MachineBasicBlock::iterator CmpMI = Br.MI; --CmpMI; + if (CmpMI->getOpcode() == ARM::tCMPzi8) { + unsigned Reg = CmpMI->getOperand(0).getReg(); + Pred = llvm::getInstrPredicate(CmpMI, PredReg); + if (Pred == ARMCC::AL && + CmpMI->getOperand(1).getImm() == 0 && + isARMLowRegister(Reg)) { + MachineBasicBlock *MBB = Br.MI->getParent(); + MachineInstr *NewBR = + BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc)) + .addReg(Reg).addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags()); + CmpMI->eraseFromParent(); + Br.MI->eraseFromParent(); + Br.MI = NewBR; + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumCBZ; + MadeChange = true; + } + } } } diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 4ceb4eff9b1..724366cce39 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -278,6 +278,15 @@ let isBranch = 1, isTerminator = 1 in "b$cc\t$target", [/*(ARMbrcond bb:$target, imm:$cc)*/]>; +// Compare and branch on zero / non-zero +let isBranch = 1, isTerminator = 1 in { + def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, + "cbz\t$cmp, $target", []>; + + def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, + "cbnz\t$cmp, $target", []>; +} + //===----------------------------------------------------------------------===// // Load Store Instructions. // diff --git a/test/CodeGen/Thumb2/machine-licm.ll b/test/CodeGen/Thumb2/machine-licm.ll index 07587e9b830..f9c56f07147 100644 --- a/test/CodeGen/Thumb2/machine-licm.ll +++ b/test/CodeGen/Thumb2/machine-licm.ll @@ -8,6 +8,8 @@ define arm_apcscc void @t(i32* nocapture %vals, i32 %c) nounwind { entry: +; CHECK: t: +; CHECK: cbz %0 = icmp eq i32 %c, 0 ; [#uses=1] br i1 %0, label %return, label %bb.nph diff --git a/test/CodeGen/Thumb2/thumb2-cbnz.ll b/test/CodeGen/Thumb2/thumb2-cbnz.ll new file mode 100644 index 00000000000..55c1276e41b --- /dev/null +++ b/test/CodeGen/Thumb2/thumb2-cbnz.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 | FileCheck %s +; rdar://7354379 + +declare arm_apcscc double @floor(double) nounwind readnone + +define void @t(i1 %a, double %b) { +entry: + br i1 %a, label %bb3, label %bb1 + +bb1: ; preds = %entry + unreachable + +bb3: ; preds = %entry + br i1 %a, label %bb7, label %bb5 + +bb5: ; preds = %bb3 + unreachable + +bb7: ; preds = %bb3 + br i1 %a, label %bb11, label %bb9 + +bb9: ; preds = %bb7 +; CHECK: @ BB#3: +; CHECK: cbnz + %0 = tail call arm_apcscc double @floor(double %b) nounwind readnone ; [#uses=0] + br label %bb11 + +bb11: ; preds = %bb9, %bb7 + %1 = getelementptr i32* undef, i32 0 + store i32 0, i32* %1 + ret void +} -- 2.11.0