diff options
| author | David Green <david.green@arm.com> | 2019-03-17 16:11:22 +0000 |
|---|---|---|
| committer | David Green <david.green@arm.com> | 2019-03-17 16:11:22 +0000 |
| commit | e0b48a80150de2aab365f84f2c7613fdf4229947 (patch) | |
| tree | 20d2871bba4cf2cbf31eb3120114279fe97d46f9 /llvm/lib/Target/ARM | |
| parent | 30673299d45e667c5a0ffcbc632a78ca53dc1eea (diff) | |
| download | bcm5719-llvm-e0b48a80150de2aab365f84f2c7613fdf4229947.tar.gz bcm5719-llvm-e0b48a80150de2aab365f84f2c7613fdf4229947.zip | |
[ARM] Search backwards for CMP when combining into CBZ
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
Diffstat (limited to 'llvm/lib/Target/ARM')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index 5107df85a60..7aefa01f63d 100644 --- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -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; @@ -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; @@ -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() { |

