Index: lib/Target/AArch64/AArch64InstrInfo.h =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.h +++ lib/Target/AArch64/AArch64InstrInfo.h @@ -216,6 +216,7 @@ ArrayRef Cond) const; bool substituteCmpToZero(MachineInstr &CmpInstr, unsigned SrcReg, const MachineRegisterInfo *MRI) const; + bool optimizeCmpAndBccSeq(MachineInstr &BrcInstr) const; }; /// emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg Index: lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.cpp +++ lib/Target/AArch64/AArch64InstrInfo.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include +#include using namespace llvm; @@ -3799,6 +3800,90 @@ return; } +static bool isCmpToZero(MachineInstr &CmpInstr) { + return isSUBSRegImm(CmpInstr.getOpcode()) + && (CmpInstr.getOperand(2).getImm() == 0); +} + +static MachineRegisterInfo *getMRI(MachineInstr &MI) { + assert(MI.getParent() && "Incomplete machine instruciton\n"); + assert(MI.getParent()->getParent()); + return &MI.getParent()->getParent()->getRegInfo(); +} + +/// Returns basic blocks which correspond to True- and False paths of the +/// specified conditional branch. +static std::tuple +findTrueAndFalseTargets(MachineInstr &BrcInstr) { + assert(BrcInstr.getOpcode() == AArch64::Bcc); + MachineBasicBlock *TBB = BrcInstr.getOperand(1).getMBB(); + // Find fallthrough basic block + auto BBI = std::find_if(BrcInstr.getParent()->succ_begin(), + BrcInstr.getParent()->succ_end(), + [TBB](MachineBasicBlock *BB) { + assert(BB); + return !BB->isEHPad() && BB != TBB; + }); + assert(BBI != BrcInstr.getParent()->succ_end()); + return std::make_tuple(TBB, *BBI); +} + +/// Optimize Cmp and Bcc sequences. +/// When we compare with zero a result is known. We can figure out +/// which path is taken by Brc. We substitute Brc by an unconditional +/// branch to that path. +/// +/// Rules: +/// SUBS reg, 0; B.LO => B +/// SUBS reg, 0; B.HS