Use cbz and cbnz instructions.

llvm-svn: 85698
This commit is contained in:
Evan Cheng 2009-10-31 23:46:45 +00:00
parent 5cba8de2c8
commit 6f29ad9170
4 changed files with 96 additions and 11 deletions

View File

@ -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;
}
}
}
}

View File

@ -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.
//

View File

@ -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 ; <i1> [#uses=1]
br i1 %0, label %return, label %bb.nph

View File

@ -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 ; <double> [#uses=0]
br label %bb11
bb11: ; preds = %bb9, %bb7
%1 = getelementptr i32* undef, i32 0
store i32 0, i32* %1
ret void
}