Skip to content

Commit

Permalink
[ARM] Search backwards for CMP when combining into CBZ
Browse files Browse the repository at this point in the history
The constant island pass currently only looks at the instruction immediately
before a branch for a CMP to fold into a CBZ/CBNZ. This extends it to search
backwards for the instruction that defines CPSR. We need to ensure that the
register is not overridden between the CMP and the branch.

Differential Revision: https://reviews.llvm.org/D59317

llvm-svn: 356336
  • Loading branch information
davemgreen committed Mar 17, 2019
1 parent 3067329 commit e0b48a8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 46 deletions.
94 changes: 59 additions & 35 deletions llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,16 @@ bool ARMConstantIslands::optimizeThumb2Instructions() {
return MadeChange;
}

static bool registerDefinedBetween(unsigned Reg,
MachineBasicBlock::iterator From,
MachineBasicBlock::iterator To,
const TargetRegisterInfo *TRI) {
for (auto I = From; I != To; ++I)
if (I->modifiesRegister(Reg, TRI))
return true;
return false;
}

bool ARMConstantIslands::optimizeThumb2Branches() {
bool MadeChange = false;

Expand Down Expand Up @@ -1899,32 +1909,56 @@ bool ARMConstantIslands::optimizeThumb2Branches() {
// because the cmp will be eliminated.
unsigned BrOffset = getOffsetOf(Br.MI) + 4 - 2;
unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) {
MachineBasicBlock::iterator CmpMI = Br.MI;
if (CmpMI != Br.MI->getParent()->begin()) {
--CmpMI;
if (CmpMI->getOpcode() == ARM::tCMPi8) {
unsigned Reg = CmpMI->getOperand(0).getReg();
Pred = getInstrPredicate(*CmpMI, PredReg);
if (Pred == ARMCC::AL &&
CmpMI->getOperand(1).getImm() == 0 &&
isARMLowRegister(Reg)) {
MachineBasicBlock *MBB = Br.MI->getParent();
LLVM_DEBUG(dbgs() << "Fold: " << *CmpMI << " and: " << *Br.MI);
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;
BBInfo[MBB->getNumber()].Size -= 2;
adjustBBOffsetsAfter(MBB);
++NumCBZ;
MadeChange = true;
}
}
}
if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
continue;

// Search backwards to the instruction that defines CSPR
auto *TRI = STI->getRegisterInfo();
MachineBasicBlock::iterator CmpMI = Br.MI;
while (CmpMI != Br.MI->getParent()->begin()) {
--CmpMI;
if (CmpMI->modifiesRegister(ARM::CPSR, TRI))
break;
}

// Check that this inst is a CMP r[0-7], #0 and that the register
// is not redefined between the cmp and the br.
if (CmpMI->getOpcode() != ARM::tCMPi8)
continue;
unsigned Reg = CmpMI->getOperand(0).getReg();
Pred = getInstrPredicate(*CmpMI, PredReg);
if (Pred != ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)
continue;
if (registerDefinedBetween(Reg, CmpMI->getNextNode(), Br.MI, TRI))
continue;

// Check for Kill flags on Reg. If they are present remove them and set kill
// on the new CBZ.
MachineBasicBlock::iterator KillMI = Br.MI;
bool RegKilled = false;
do {
--KillMI;
if (KillMI->killsRegister(Reg, TRI)) {
KillMI->clearRegisterKills(Reg, TRI);
RegKilled = true;
break;
}
} while (KillMI != CmpMI);

// Create the new CBZ/CBNZ
MachineBasicBlock *MBB = Br.MI->getParent();
LLVM_DEBUG(dbgs() << "Fold: " << *CmpMI << " and: " << *Br.MI);
MachineInstr *NewBR =
BuildMI(*MBB, Br.MI, Br.MI->getDebugLoc(), TII->get(NewOpc))
.addReg(Reg, getKillRegState(RegKilled))
.addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags());
CmpMI->eraseFromParent();
Br.MI->eraseFromParent();
Br.MI = NewBR;
BBInfo[MBB->getNumber()].Size -= 2;
adjustBBOffsetsAfter(MBB);
++NumCBZ;
MadeChange = true;
}

return MadeChange;
Expand Down Expand Up @@ -2084,16 +2118,6 @@ static void RemoveDeadAddBetweenLEAAndJT(MachineInstr *LEAMI,
DeadSize += 4;
}

static bool registerDefinedBetween(unsigned Reg,
MachineBasicBlock::iterator From,
MachineBasicBlock::iterator To,
const TargetRegisterInfo *TRI) {
for (auto I = From; I != To; ++I)
if (I->modifiesRegister(Reg, TRI))
return true;
return false;
}

/// optimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller
/// jumptables when it's possible.
bool ARMConstantIslands::optimizeThumb2JumpTables() {
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/Thumb2/constant-islands-cbz.ll
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ define i32* @test(i32* returned %this, i32 %event_size, i8* %event_pointer) {
; CHECK-T2-NEXT: mov r4, r0
; CHECK-T2-NEXT: movs r0, #0
; CHECK-T2-NEXT: strd r0, r0, [r4, #4]
; CHECK-T2-NEXT: cmp r2, #0
; CHECK-T2-NEXT: strd r0, r0, [r4, #12]
; CHECK-T2-NEXT: mov r0, r4
; CHECK-T2-NEXT: beq .LBB0_2
; CHECK-T2-NEXT: cbz r2, .LBB0_2
; CHECK-T2-NEXT: @ %bb.1: @ %if.else
; CHECK-T2-NEXT: bl equeue_create_inplace
; CHECK-T2-NEXT: mov r0, r4
Expand Down
14 changes: 5 additions & 9 deletions llvm/test/CodeGen/Thumb2/constant-islands-cbz.mir
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ body: |
; CHECK: bb.0:
; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000)
; CHECK: renamable $r0, $cpsr = tADDrr killed renamable $r0, renamable $r1, 14, $noreg
; CHECK: tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
; CHECK: renamable $r1 = t2ADDrs renamable $r0, killed renamable $r1, 18, 14, $noreg, $noreg
; CHECK: tBcc %bb.2, 0, killed $cpsr
; CHECK: tCBZ $r0, %bb.2
; CHECK: bb.1:
; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.x)
; CHECK: tTAILJMPdND @c, 14, $noreg, implicit $sp, implicit $sp, implicit killed $r0
Expand Down Expand Up @@ -135,9 +134,8 @@ body: |
; CHECK-LABEL: name: test_notredefined
; CHECK: bb.0:
; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000)
; CHECK: tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
; CHECK: renamable $r1 = t2ADDrs renamable $r0, killed renamable $r1, 18, 14, $noreg, $noreg
; CHECK: tBcc %bb.2, 0, killed $cpsr
; CHECK: tCBZ $r0, %bb.2
; CHECK: bb.1:
; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.x)
; CHECK: tTAILJMPdND @c, 14, $noreg, implicit $sp, implicit $sp, implicit killed $r0
Expand Down Expand Up @@ -211,9 +209,8 @@ body: |
; CHECK-LABEL: name: test_killflag_1
; CHECK: bb.0:
; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000)
; CHECK: tCMPi8 killed renamable $r1, 0, 14, $noreg, implicit-def $cpsr
; CHECK: renamable $r0 = t2ADDrs killed renamable $r0, killed renamable $r0, 18, 14, $noreg, $noreg
; CHECK: tBcc %bb.2, 0, killed $cpsr
; CHECK: tCBZ killed $r1, %bb.2
; CHECK: bb.1:
; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.x)
; CHECK: tTAILJMPdND @c, 14, $noreg, implicit $sp, implicit $sp, implicit killed $r0
Expand Down Expand Up @@ -249,9 +246,8 @@ body: |
; CHECK-LABEL: name: test_killflag_2
; CHECK: bb.0:
; CHECK: successors: %bb.2(0x30000000), %bb.1(0x50000000)
; CHECK: tCMPi8 renamable $r1, 0, 14, $noreg, implicit-def $cpsr
; CHECK: renamable $r0 = t2ADDrs killed renamable $r1, killed renamable $r0, 18, 14, $noreg, $noreg
; CHECK: tBcc %bb.2, 0, killed $cpsr
; CHECK: renamable $r0 = t2ADDrs renamable $r1, killed renamable $r0, 18, 14, $noreg, $noreg
; CHECK: tCBZ killed $r1, %bb.2
; CHECK: bb.1:
; CHECK: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.x)
; CHECK: tTAILJMPdND @c, 14, $noreg, implicit $sp, implicit $sp, implicit killed $r0
Expand Down

0 comments on commit e0b48a8

Please sign in to comment.