Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h +++ include/llvm/Target/TargetInstrInfo.h @@ -480,6 +480,30 @@ return true; } + /// Return true if the offset is in range of the branch instruction and + /// false otherwise. + virtual bool isBranchOffsetInRange(unsigned Opcode, int64_t Offset) const { + return true; + } + + /// Return the opcode if there exist a branch instruction with a smaller + /// encoding, or -1 otherwise. + virtual int optimizeShortBranch(MachineInstr &MI, int64_t Offset) const { + return -1; + } + + /// Return the upperbound value of the supported branch range, or -1 if + /// it is not implemented. + virtual int64_t getBranchRangeUpperbound(unsigned Opcode) const { + return -1; + } + + /// Return the lowerbound value of the supported branch range, or 1 if + /// it is not implemented. + virtual int64_t getBranchRangeLowerbound(unsigned Opcode) const { + return 1; + } + /// Represents a predicate at the MachineFunction level. The control flow a /// MachineBranchPredicate represents is: /// Index: lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- lib/Target/ARM/ARMBaseInstrInfo.h +++ lib/Target/ARM/ARMBaseInstrInfo.h @@ -120,6 +120,10 @@ const ScheduleDAG *DAG) const override; // Branch analysis. + int64_t getBranchRangeUpperbound(unsigned Opcode) const override; + int64_t getBranchRangeLowerbound(unsigned Opcode) const override; + bool isBranchOffsetInRange(unsigned Opcode, int64_t Offset) const override; + int optimizeShortBranch(MachineInstr &MI, int64_t Offset) const override; bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl &Cond, Index: lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- lib/Target/ARM/ARMBaseInstrInfo.cpp +++ lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -290,6 +290,57 @@ } // Branch analysis. + +int64_t ARMBaseInstrInfo::getBranchRangeUpperbound(unsigned Opcode) const { + switch (Opcode) { + case ARM::tBcc: + return 254; + case ARM::tB: + return 2046; + } + return -1; +} + +int64_t ARMBaseInstrInfo::getBranchRangeLowerbound(unsigned Opcode) const { + switch (Opcode) { + case ARM::tBcc: + return -256; + case ARM::tB: + return -2048; + } + return 1; +} + +bool ARMBaseInstrInfo::isBranchOffsetInRange(unsigned Opcode, + int64_t Offset) const { + const int64_t OffsetLwb = getBranchRangeLowerbound(Opcode); + const int64_t OffsetUpb = getBranchRangeUpperbound(Opcode); + assert(OffsetLwb != 1); + assert(OffsetUpb != -1); + + switch (Opcode) { + case ARM::tBcc: + if (Offset < OffsetLwb || Offset > OffsetUpb) + return false; + case ARM::tB: + if (Offset < OffsetLwb || Offset > OffsetUpb) + return false; + } + return true; +} + +// Map branch instructions to Thumb1 equivalent branches. +int ARMBaseInstrInfo::optimizeShortBranch(MachineInstr &MI, + int64_t Offset) const { + switch (MI.getOpcode()) { + case ARM::t2B: + return ARM::tB; + case ARM::t2Bcc: + return ARM::tBcc; + } + return -1; +} + bool ARMBaseInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,