Use cbz and cbnz instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85698 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-10-31 23:46:45 +00:00
parent 8cd0a8cb82
commit de17fb6e4d
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(NumTBs, "Number of table branches generated");
STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk"); STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk");
STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk"); STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk");
STATISTIC(NumCBZ, "Number of CBZ / CBNZ formed");
namespace { namespace {
/// ARMConstantIslands - Due to limited PC-relative displacements, ARM /// ARMConstantIslands - Due to limited PC-relative displacements, ARM
@ -1486,24 +1487,65 @@ bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) {
Bits = 11; Bits = 11;
Scale = 2; Scale = 2;
break; break;
case ARM::t2Bcc: case ARM::t2Bcc: {
NewOpc = ARM::tBcc; NewOpc = ARM::tBcc;
Bits = 8; Bits = 8;
Scale = 2; Scale = 2;
break; 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; 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(); MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
if (BBIsInRange(Br.MI, DestBB, MaxOffs)) { // Check if the distance is within 126. Subtract starting offset by 2
Br.MI->setDesc(TII->get(NewOpc)); // because the cmp will be eliminated.
MachineBasicBlock *MBB = Br.MI->getParent(); unsigned BrOffset = GetOffsetOf(Br.MI) + 4 - 2;
BBSizes[MBB->getNumber()] -= 2; unsigned DestOffset = BBOffsets[DestBB->getNumber()];
AdjustBBOffsetsAfter(MBB, -2); if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) {
++NumT2BrShrunk; MachineBasicBlock::iterator CmpMI = Br.MI; --CmpMI;
MadeChange = true; 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", "b$cc\t$target",
[/*(ARMbrcond bb:$target, imm:$cc)*/]>; [/*(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. // Load Store Instructions.
// //

View File

@ -8,6 +8,8 @@
define arm_apcscc void @t(i32* nocapture %vals, i32 %c) nounwind { define arm_apcscc void @t(i32* nocapture %vals, i32 %c) nounwind {
entry: entry:
; CHECK: t:
; CHECK: cbz
%0 = icmp eq i32 %c, 0 ; <i1> [#uses=1] %0 = icmp eq i32 %c, 0 ; <i1> [#uses=1]
br i1 %0, label %return, label %bb.nph 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
}