forked from OSchip/llvm-project
AArch64: Move remaining target specific BranchRelaxation bits to TII
llvm-svn: 283458
This commit is contained in:
parent
ee554e6155
commit
0a3ea89e85
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue