AArch64: Move remaining target specific BranchRelaxation bits to TII

llvm-svn: 283458
This commit is contained in:
Matt Arsenault 2016-10-06 15:38:09 +00:00
parent ee554e6155
commit 0a3ea89e85
4 changed files with 49 additions and 53 deletions

View File

@ -443,6 +443,18 @@ public:
const MachineInstr &MI1, const MachineInstr &MI1,
const MachineRegisterInfo *MRI = nullptr) const; 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 /// 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 /// 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 /// implemented for a target). Upon success, this returns false and returns

View File

@ -14,8 +14,6 @@
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
@ -229,43 +227,23 @@ AArch64BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI) {
/// specific BB can fit in MI's displacement field. /// specific BB can fit in MI's displacement field.
bool AArch64BranchRelaxation::isBlockInRange( bool AArch64BranchRelaxation::isBlockInRange(
const MachineInstr &MI, const MachineBasicBlock &DestBB) const { const MachineInstr &MI, const MachineBasicBlock &DestBB) const {
unsigned BrOffset = getInstrOffset(MI); int64_t BrOffset = getInstrOffset(MI);
unsigned DestOffset = BlockInfo[DestBB.getNumber()].Offset; int64_t DestOffset = BlockInfo[DestBB.getNumber()].Offset;
if (TII->isBranchInRange(MI.getOpcode(), BrOffset, DestOffset)) if (TII->isBranchOffsetInRange(MI.getOpcode(), DestOffset - BrOffset))
return true; return true;
DEBUG( DEBUG(
dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber() dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber()
<< " from BB#" << MI.getParent()->getNumber() << " from BB#" << MI.getParent()->getNumber()
<< " to " << DestOffset << " to " << DestOffset
<< " offset " << static_cast<int>(DestOffset - BrOffset) << " offset " << DestOffset - BrOffset
<< '\t' << MI << '\t' << MI
); );
return false; 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 /// fixupConditionalBranch - Fix up a conditional branch whose destination is
/// too far away to fit in its displacement field. It is converted to an inverse /// too far away to fit in its displacement field. It is converted to an inverse
/// conditional branch + an unconditional branch to the destination. /// conditional branch + an unconditional branch to the destination.
@ -368,7 +346,7 @@ bool AArch64BranchRelaxation::relaxBranchInstructions() {
MachineInstr &MI = *J; MachineInstr &MI = *J;
if (MI.isConditionalBranch()) { if (MI.isConditionalBranch()) {
MachineBasicBlock *DestBB = getDestBlock(MI); MachineBasicBlock *DestBB = TII->getBranchDestBlock(MI);
if (!isBlockInRange(MI, *DestBB)) { if (!isBlockInRange(MI, *DestBB)) {
if (Next != MBB.end() && Next->isConditionalBranch()) { if (Next != MBB.end() && Next->isConditionalBranch()) {
// If there are multiple conditional branches, this isn't an // If there are multiple conditional branches, this isn't an

View File

@ -128,6 +128,8 @@ static unsigned getBranchDisplacementBits(unsigned Opc) {
switch (Opc) { switch (Opc) {
default: default:
llvm_unreachable("unexpected opcode!"); llvm_unreachable("unexpected opcode!");
case AArch64::B:
return 64;
case AArch64::TBNZW: case AArch64::TBNZW:
case AArch64::TBZW: case AArch64::TBZW:
case AArch64::TBNZX: case AArch64::TBNZX:
@ -143,30 +145,33 @@ static unsigned getBranchDisplacementBits(unsigned Opc) {
} }
} }
static unsigned getBranchMaxDisplacementBytes(unsigned Opc) { bool AArch64InstrInfo::isBranchOffsetInRange(unsigned BranchOp,
if (Opc == AArch64::B) int64_t BrOffset) const {
return -1; unsigned Bits = getBranchDisplacementBits(BranchOp);
assert(Bits >= 3 && "max branch displacement must be enough to jump"
unsigned Bits = getBranchDisplacementBits(Opc); "over conditional branch expansion");
unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2; return isIntN(Bits, BrOffset / 4);
// 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::isBranchInRange(unsigned BranchOp, uint64_t BrOffset, MachineBasicBlock *AArch64InstrInfo::getBranchDestBlock(
uint64_t DestOffset) const { const MachineInstr &MI) const {
unsigned MaxOffs = getBranchMaxDisplacementBytes(BranchOp); switch (MI.getOpcode()) {
default:
// Branch before the Dest. llvm_unreachable("unexpected opcode!");
if (BrOffset <= DestOffset) case AArch64::B:
return (DestOffset - BrOffset <= MaxOffs); return MI.getOperand(0).getMBB();
return (BrOffset - DestOffset <= MaxOffs); 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. // Branch analysis.

View File

@ -174,10 +174,11 @@ public:
LiveIntervals *LIS = nullptr) const override; LiveIntervals *LIS = nullptr) const override;
/// \returns true if a branch from an instruction with opcode \p BranchOpc /// \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 /// bytes is capable of jumping to a position \p BrOffset bytes away.
/// DestOffset. bool isBranchOffsetInRange(unsigned BranchOpc,
bool isBranchInRange(unsigned BranchOpc, uint64_t BrOffset, int64_t BrOffset) const override;
uint64_t DestOffset) const;
MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB, MachineBasicBlock *&FBB,