From 0a3ea89e85c8ccbe4425b97377e5ad67843f4cf2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 6 Oct 2016 15:38:09 +0000 Subject: [PATCH] AArch64: Move remaining target specific BranchRelaxation bits to TII llvm-svn: 283458 --- llvm/include/llvm/Target/TargetInstrInfo.h | 12 ++++++ .../lib/Target/AArch64/AArch64BranchRelaxation.cpp | 32 +++----------- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 49 ++++++++++++---------- llvm/lib/Target/AArch64/AArch64InstrInfo.h | 9 ++-- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h index 64f45c6..ed770f6 100644 --- a/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/llvm/include/llvm/Target/TargetInstrInfo.h @@ -443,6 +443,18 @@ public: 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 diff --git a/llvm/lib/Target/AArch64/AArch64BranchRelaxation.cpp b/llvm/lib/Target/AArch64/AArch64BranchRelaxation.cpp index c7c804b..6042b0a 100644 --- a/llvm/lib/Target/AArch64/AArch64BranchRelaxation.cpp +++ b/llvm/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" @@ -229,43 +227,23 @@ AArch64BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI) { /// 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. @@ -368,7 +346,7 @@ bool AArch64BranchRelaxation::relaxBranchInstructions() { 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 diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index b26dbce..7d264c8 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -128,6 +128,8 @@ static unsigned getBranchDisplacementBits(unsigned Opc) { 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 getBranchDisplacementBits(unsigned Opc) { } } -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. diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index e03cfd7..149469e 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -174,10 +174,11 @@ public: 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, -- 2.7.4