Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h +++ include/llvm/Target/TargetInstrInfo.h @@ -443,6 +443,18 @@ const MachineInstr &MI1, const MachineRegisterInfo *MRI = nullptr) const; + /// \returns true if a branch from an instruction with opcode \p BranchOpc + /// bytes is capable of jumping to a position \p BrOffset bytes away. + virtual bool isBranchOffsetInRange(unsigned BranchOpc, + int64_t BrOffset) const { + llvm_unreachable("target did not implement"); + } + + /// \returns The block that branch instruction \p MI jumps to. + virtual MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const { + llvm_unreachable("target did not implement"); + } + /// Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't /// implemented for a target). Upon success, this returns false and returns Index: lib/Target/AArch64/AArch64BranchRelaxation.cpp =================================================================== --- lib/Target/AArch64/AArch64BranchRelaxation.cpp +++ lib/Target/AArch64/AArch64BranchRelaxation.cpp @@ -14,8 +14,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" @@ -231,43 +229,23 @@ /// specific BB can fit in MI's displacement field. bool AArch64BranchRelaxation::isBlockInRange( const MachineInstr &MI, const MachineBasicBlock &DestBB) const { - unsigned BrOffset = getInstrOffset(MI); - unsigned DestOffset = BlockInfo[DestBB.getNumber()].Offset; + int64_t BrOffset = getInstrOffset(MI); + int64_t DestOffset = BlockInfo[DestBB.getNumber()].Offset; - if (TII->isBranchInRange(MI.getOpcode(), BrOffset, DestOffset)) + if (TII->isBranchOffsetInRange(MI.getOpcode(), DestOffset - BrOffset)) return true; DEBUG( dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber() << " from BB#" << MI.getParent()->getNumber() << " to " << DestOffset - << " offset " << static_cast(DestOffset - BrOffset) + << " offset " << DestOffset - BrOffset << '\t' << MI ); return false; } -static MachineBasicBlock *getDestBlock(const MachineInstr &MI) { - switch (MI.getOpcode()) { - default: - llvm_unreachable("unexpected opcode!"); - case AArch64::B: - return MI.getOperand(0).getMBB(); - case AArch64::TBZW: - case AArch64::TBNZW: - case AArch64::TBZX: - case AArch64::TBNZX: - return MI.getOperand(2).getMBB(); - case AArch64::CBZW: - case AArch64::CBNZW: - case AArch64::CBZX: - case AArch64::CBNZX: - case AArch64::Bcc: - return MI.getOperand(1).getMBB(); - } -} - /// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. @@ -370,7 +348,7 @@ MachineInstr &MI = *J; if (MI.isConditionalBranch()) { - MachineBasicBlock *DestBB = getDestBlock(MI); + MachineBasicBlock *DestBB = TII->getBranchDestBlock(MI); if (!isBlockInRange(MI, *DestBB)) { if (Next != MBB.end() && Next->isConditionalBranch()) { // If there are multiple conditional branches, this isn't an Index: lib/Target/AArch64/AArch64InstrInfo.h =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.h +++ lib/Target/AArch64/AArch64InstrInfo.h @@ -174,10 +174,11 @@ LiveIntervals *LIS = nullptr) const override; /// \returns true if a branch from an instruction with opcode \p BranchOpc - /// located at \p BrOffset bytes is capable of jumping to a position at \p - /// DestOffset. - bool isBranchInRange(unsigned BranchOpc, uint64_t BrOffset, - uint64_t DestOffset) const; + /// bytes is capable of jumping to a position \p BrOffset bytes away. + bool isBranchOffsetInRange(unsigned BranchOpc, + int64_t BrOffset) const override; + + MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, Index: lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.cpp +++ lib/Target/AArch64/AArch64InstrInfo.cpp @@ -128,6 +128,8 @@ switch (Opc) { default: llvm_unreachable("unexpected opcode!"); + case AArch64::B: + return 64; case AArch64::TBNZW: case AArch64::TBZW: case AArch64::TBNZX: @@ -143,30 +145,33 @@ } } -static unsigned getBranchMaxDisplacementBytes(unsigned Opc) { - if (Opc == AArch64::B) - return -1; - - unsigned Bits = getBranchDisplacementBits(Opc); - unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2; - - // Verify the displacement bits options have sane values. - // XXX: Is there a better place for this? - assert(MaxOffs >= 8 && - "max branch displacement must be enough to jump" - "over conditional branch expansion"); - - return MaxOffs; +bool AArch64InstrInfo::isBranchOffsetInRange(unsigned BranchOp, + int64_t BrOffset) const { + unsigned Bits = getBranchDisplacementBits(BranchOp); + assert(Bits >= 3 && "max branch displacement must be enough to jump" + "over conditional branch expansion"); + return isIntN(Bits, BrOffset / 4); } -bool AArch64InstrInfo::isBranchInRange(unsigned BranchOp, uint64_t BrOffset, - uint64_t DestOffset) const { - unsigned MaxOffs = getBranchMaxDisplacementBytes(BranchOp); - - // Branch before the Dest. - if (BrOffset <= DestOffset) - return (DestOffset - BrOffset <= MaxOffs); - return (BrOffset - DestOffset <= MaxOffs); +MachineBasicBlock *AArch64InstrInfo::getBranchDestBlock( + const MachineInstr &MI) const { + switch (MI.getOpcode()) { + default: + llvm_unreachable("unexpected opcode!"); + case AArch64::B: + return MI.getOperand(0).getMBB(); + case AArch64::TBZW: + case AArch64::TBNZW: + case AArch64::TBZX: + case AArch64::TBNZX: + return MI.getOperand(2).getMBB(); + case AArch64::CBZW: + case AArch64::CBNZW: + case AArch64::CBZX: + case AArch64::CBNZX: + case AArch64::Bcc: + return MI.getOperand(1).getMBB(); + } } // Branch analysis.