forked from OSchip/llvm-project
parent
5cba8de2c8
commit
6f29ad9170
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue