Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -567,6 +567,16 @@ unsigned FrameReg, int &Offset, const ARMBaseInstrInfo &TII); +/// Return true if Reg is defd between From and To +bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, + MachineBasicBlock::iterator To, + const TargetRegisterInfo *TRI); + +/// Search backwards from a tBcc to find a tCMPi8 against 0, meaning +/// we can convert them to a tCBZ or tCBNZ. Return nullptr if not found. +MachineInstr *findCMPToFoldIntoCBZ(MachineInstr *Br, + const TargetRegisterInfo *TRI); + } // end namespace llvm #endif // LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1904,19 +1904,10 @@ if (!Pred->empty()) { MachineInstr *LastMI = &*Pred->rbegin(); if (LastMI->getOpcode() == ARM::t2Bcc) { - MachineBasicBlock::iterator CmpMI = LastMI; - if (CmpMI != Pred->begin()) { - --CmpMI; - if (CmpMI->getOpcode() == ARM::tCMPi8 || - CmpMI->getOpcode() == ARM::t2CMPri) { - unsigned Reg = CmpMI->getOperand(0).getReg(); - unsigned PredReg = 0; - ARMCC::CondCodes P = getInstrPredicate(*CmpMI, PredReg); - if (P == ARMCC::AL && CmpMI->getOperand(1).getImm() == 0 && - isARMLowRegister(Reg)) - return false; - } - } + const TargetRegisterInfo *TRI = &getRegisterInfo(); + MachineInstr *CmpMI = findCMPToFoldIntoCBZ(LastMI, TRI); + if (CmpMI) + return false; } } } @@ -5202,3 +5193,44 @@ {MO_NONLAZY, "arm-nonlazy"}}; return makeArrayRef(TargetFlags); } + +bool llvm::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; +} + +MachineInstr *llvm::findCMPToFoldIntoCBZ(MachineInstr *Br, + const TargetRegisterInfo *TRI) { + // Search backwards to the instruction that defines CSPR. This may or not + // be a CMP, we check that after this loop. If we find another instruction + // that reads cpsr, we return nullptr. + MachineBasicBlock::iterator CmpMI = Br; + while (CmpMI != Br->getParent()->begin()) { + --CmpMI; + if (CmpMI->modifiesRegister(ARM::CPSR, TRI)) + break; + if (CmpMI->readsRegister(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 && CmpMI->getOpcode() != ARM::t2CMPri) + return nullptr; + unsigned Reg = CmpMI->getOperand(0).getReg(); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = getInstrPredicate(*CmpMI, PredReg); + if (Pred != ARMCC::AL || CmpMI->getOperand(1).getImm() != 0) + return nullptr; + if (!isARMLowRegister(Reg)) + return nullptr; + if (registerDefinedBetween(Reg, CmpMI->getNextNode(), Br, TRI)) + return nullptr; + + return &*CmpMI; +} Index: llvm/lib/Target/ARM/ARMConstantIslandPass.cpp =================================================================== --- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1838,16 +1838,6 @@ 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; @@ -1915,29 +1905,13 @@ if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126) continue; - // Search backwards to the instruction that defines CSPR. This may or not - // be a CMP, we check that after this loop. If we find an instruction that - // reads cpsr, we need to keep the original cmp. + // Search backwards to find a tCMPi8 auto *TRI = STI->getRegisterInfo(); - MachineBasicBlock::iterator CmpMI = Br.MI; - while (CmpMI != Br.MI->getParent()->begin()) { - --CmpMI; - if (CmpMI->modifiesRegister(ARM::CPSR, TRI)) - break; - if (CmpMI->readsRegister(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) + MachineInstr *CmpMI = findCMPToFoldIntoCBZ(Br.MI, TRI); + if (!CmpMI || 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. Index: llvm/test/CodeGen/Thumb2/ifcvt-cbz.mir =================================================================== --- llvm/test/CodeGen/Thumb2/ifcvt-cbz.mir +++ llvm/test/CodeGen/Thumb2/ifcvt-cbz.mir @@ -133,10 +133,13 @@ body: | ; CHECK-LABEL: name: f3 ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) ; CHECK: liveins: $r0, $lr, $r7 ; CHECK: t2CMPri killed renamable $r0, 0, 14, $noreg, implicit-def $cpsr - ; CHECK: dead $r1 = t2MOVi 0, 14, $noreg, $noreg - ; CHECK: tBX_RET 1, killed $cpsr + ; CHECK: $r1 = t2MOVi 0, 14, $noreg, $noreg + ; CHECK: t2Bcc %bb.2, 1, killed $cpsr + ; CHECK: bb.1: + ; CHECK: liveins: $r7, $lr ; CHECK: $sp = frame-setup t2STMDB_UPD $sp, 14, $noreg, killed $r7, killed $lr ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8 ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -4 @@ -145,6 +148,9 @@ ; CHECK: tBL 14, $noreg, @fn, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit-def $sp, implicit-def dead $r0 ; CHECK: $sp = t2LDMIA_UPD $sp, 14, $noreg, def $r7, def $lr ; CHECK: tBX_RET 14, $noreg + ; CHECK: bb.2: + ; CHECK: liveins: $lr, $r7 + ; CHECK: tBX_RET 14, $noreg bb.0: successors: %bb.1(0x40000000), %bb.2(0x40000000) liveins: $r0, $lr, $r7