[llvm] r277430 - AArch64: BranchRelaxtion cleanups
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 2 01:06:17 PDT 2016
Author: arsenm
Date: Tue Aug 2 03:06:17 2016
New Revision: 277430
URL: http://llvm.org/viewvc/llvm-project?rev=277430&view=rev
Log:
AArch64: BranchRelaxtion cleanups
Move some logic into TII.
Modified:
llvm/trunk/lib/Target/AArch64/AArch64BranchRelaxation.cpp
llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.h
Modified: llvm/trunk/lib/Target/AArch64/AArch64BranchRelaxation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64BranchRelaxation.cpp?rev=277430&r1=277429&r2=277430&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64BranchRelaxation.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64BranchRelaxation.cpp Tue Aug 2 03:06:17 2016
@@ -6,8 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-//===----------------------------------------------------------------------===//
#include "AArch64.h"
#include "AArch64InstrInfo.h"
@@ -26,18 +24,6 @@ using namespace llvm;
#define DEBUG_TYPE "aarch64-branch-relax"
-static cl::opt<unsigned>
-TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
- cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
-
-static cl::opt<unsigned>
-CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
- cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
-
-static cl::opt<unsigned>
-BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
- cl::desc("Restrict range of Bcc instructions (DEBUG)"));
-
STATISTIC(NumSplit, "Number of basic blocks split");
STATISTIC(NumRelaxed, "Number of conditional branches relaxed");
@@ -86,10 +72,18 @@ class AArch64BranchRelaxation : public M
void scanFunction();
MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI);
void adjustBlockOffsets(MachineBasicBlock &MBB);
- bool isBlockInRange(MachineInstr &MI, MachineBasicBlock &BB, unsigned Disp);
+ bool isBlockInRange(const MachineInstr &MI, const MachineBasicBlock &BB) const;
+ void invertConditionalBranch(MachineInstr &MI) const;
+ unsigned insertInvertedConditionalBranch(MachineBasicBlock &MBB,
+ const MachineInstr &OldBr,
+ MachineBasicBlock &NewDestBB) const;
+ unsigned insertUnconditionalBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock &NewDestBB,
+ const DebugLoc &DL) const;
+
bool fixupConditionalBranch(MachineInstr &MI);
void computeBlockSize(const MachineBasicBlock &MBB);
- unsigned getInstrOffset(MachineInstr &MI) const;
+ unsigned getInstrOffset(const MachineInstr &MI) const;
void dumpBBs();
void verify();
@@ -134,21 +128,20 @@ void AArch64BranchRelaxation::dumpBBs()
}
}
-/// BBHasFallthrough - Return true if the specified basic block can fallthrough
+// FIXME: This is a less precise version of MachineBasicBlock::canFallThrough?
+
+/// \returns true if the specified basic block can fallthrough
/// into the block immediately after it.
-static bool BBHasFallthrough(MachineBasicBlock *MBB) {
+static bool hasFallthrough(const MachineBasicBlock &MBB) {
// Get the next machine basic block in the function.
- MachineFunction::iterator MBBI(MBB);
+ MachineFunction::const_iterator MBBI(MBB);
+
// Can't fall off end of function.
auto NextBB = std::next(MBBI);
- if (NextBB == MBB->getParent()->end())
+ if (NextBB == MBB.getParent()->end())
return false;
- for (MachineBasicBlock *S : MBB->successors())
- if (S == &*NextBB)
- return true;
-
- return false;
+ return MBB.isSuccessor(&*NextBB);
}
/// scanFunction - Do the initial scan of the function, building up
@@ -180,8 +173,8 @@ void AArch64BranchRelaxation::computeBlo
/// getInstrOffset - Return the current offset of the specified machine
/// instruction from the start of the function. This offset changes as stuff is
/// moved around inside the function.
-unsigned AArch64BranchRelaxation::getInstrOffset(MachineInstr &MI) const {
- MachineBasicBlock *MBB = MI.getParent();
+unsigned AArch64BranchRelaxation::getInstrOffset(const MachineInstr &MI) const {
+ const MachineBasicBlock *MBB = MI.getParent();
// The offset is composed of two things: the sum of the sizes of all MBB's
// before this instruction's block, and the offset from the start of the block
@@ -189,7 +182,7 @@ unsigned AArch64BranchRelaxation::getIns
unsigned Offset = BlockInfo[MBB->getNumber()].Offset;
// Sum instructions before MI in MBB.
- for (MachineBasicBlock::iterator I = MBB->begin(); &*I != &MI; ++I) {
+ for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != &MI; ++I) {
assert(I != MBB->end() && "Didn't find MI in its own basic block?");
Offset += TII->getInstSizeInBytes(*I);
}
@@ -259,46 +252,31 @@ AArch64BranchRelaxation::splitBlockBefor
/// isBlockInRange - Returns true if the distance between specific MI and
/// specific BB can fit in MI's displacement field.
-bool AArch64BranchRelaxation::isBlockInRange(MachineInstr &MI,
- MachineBasicBlock &DestBB,
- unsigned Bits) {
- unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2;
+bool AArch64BranchRelaxation::isBlockInRange(
+ const MachineInstr &MI, const MachineBasicBlock &DestBB) const {
unsigned BrOffset = getInstrOffset(MI);
unsigned DestOffset = BlockInfo[DestBB.getNumber()].Offset;
- DEBUG(dbgs() << "Branch of destination BB#" << DestBB.getNumber()
- << " from BB#" << MI.getParent()->getNumber()
- << " max delta=" << MaxOffs << " from " << BrOffset
- << " to " << DestOffset << " offset "
- << static_cast<int>(DestOffset - BrOffset) << '\t' << MI);
-
- // Branch before the Dest.
- if (BrOffset <= DestOffset)
- return (DestOffset - BrOffset <= MaxOffs);
- return (BrOffset - DestOffset <= MaxOffs);
-}
-
-static bool isConditionalBranch(unsigned Opc) {
- switch (Opc) {
- default:
- return false;
- case AArch64::TBZW:
- case AArch64::TBNZW:
- case AArch64::TBZX:
- case AArch64::TBNZX:
- case AArch64::CBZW:
- case AArch64::CBNZW:
- case AArch64::CBZX:
- case AArch64::CBNZX:
- case AArch64::Bcc:
+ if (TII->isBranchInRange(MI.getOpcode(), BrOffset, DestOffset))
return true;
- }
+
+ DEBUG(
+ dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber()
+ << " from BB#" << MI.getParent()->getNumber()
+ << " to " << DestOffset
+ << " offset " << static_cast<int>(DestOffset - BrOffset)
+ << '\t' << MI
+ );
+
+ return false;
}
-static MachineBasicBlock *getDestBlock(MachineInstr &MI) {
+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:
@@ -329,30 +307,74 @@ static unsigned getOppositeConditionOpco
}
}
-static unsigned getBranchDisplacementBits(unsigned Opc) {
- switch (Opc) {
- default:
- llvm_unreachable("unexpected opcode!");
- case AArch64::TBNZW:
- case AArch64::TBZW:
- case AArch64::TBNZX:
- case AArch64::TBZX:
- return TBZDisplacementBits;
- case AArch64::CBNZW:
- case AArch64::CBZW:
- case AArch64::CBNZX:
- case AArch64::CBZX:
- return CBZDisplacementBits;
- case AArch64::Bcc:
- return BCCDisplacementBits;
- }
-}
-
static inline void invertBccCondition(MachineInstr &MI) {
assert(MI.getOpcode() == AArch64::Bcc && "Unexpected opcode!");
- AArch64CC::CondCode CC = (AArch64CC::CondCode)MI.getOperand(0).getImm();
- CC = AArch64CC::getInvertedCondCode(CC);
- MI.getOperand(0).setImm((int64_t)CC);
+ MachineOperand &CCOp = MI.getOperand(0);
+
+ AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(CCOp.getImm());
+ CCOp.setImm(AArch64CC::getInvertedCondCode(CC));
+}
+
+/// Invert the branch condition of \p MI and change the destination to \p NewB
+void AArch64BranchRelaxation::invertConditionalBranch(MachineInstr &MI) const {
+ MI.setDesc(TII->get(getOppositeConditionOpcode(MI.getOpcode())));
+
+ if (MI.getOpcode() == AArch64::Bcc)
+ invertBccCondition(MI);
+}
+
+/// Insert a conditional branch at the end of \p MBB to \p NewDestBB, using the
+/// inverse condition of branch \p OldBr.
+/// \returns The number of bytes added to the block.
+unsigned AArch64BranchRelaxation::insertInvertedConditionalBranch(
+ MachineBasicBlock &MBB,
+ const MachineInstr &OldBr,
+ MachineBasicBlock &NewDestBB) const {
+ unsigned OppositeCondOpc = getOppositeConditionOpcode(OldBr.getOpcode());
+
+ MachineInstrBuilder MIB =
+ BuildMI(&MBB, OldBr.getDebugLoc(), TII->get(OppositeCondOpc))
+ .addOperand(OldBr.getOperand(0));
+
+ unsigned Opc = OldBr.getOpcode();
+
+ if (Opc == AArch64::TBZW || Opc == AArch64::TBNZW ||
+ Opc == AArch64::TBZX || Opc == AArch64::TBNZX)
+ MIB.addOperand(OldBr.getOperand(1));
+
+ if (OldBr.getOpcode() == AArch64::Bcc)
+ invertBccCondition(*MIB);
+
+ MIB.addMBB(&NewDestBB);
+
+ return TII->getInstSizeInBytes(*MIB);
+}
+
+/// Insert an unconditional branch at the end of \p MBB to \p DestBB.
+/// \returns the number of bytes emitted.
+unsigned AArch64BranchRelaxation::insertUnconditionalBranch(
+ MachineBasicBlock &MBB,
+ MachineBasicBlock &DestBB,
+ const DebugLoc &DL) const {
+ MachineInstr *MI = BuildMI(&MBB, DL, TII->get(AArch64::B))
+ .addMBB(&DestBB);
+
+ return TII->getInstSizeInBytes(*MI);
+}
+
+static void changeBranchDestBlock(MachineInstr &MI,
+ MachineBasicBlock &NewDestBB) {
+ unsigned OpNum = 0;
+ unsigned Opc = MI.getOpcode();
+
+ if (Opc != AArch64::B) {
+ OpNum = (Opc == AArch64::TBZW ||
+ Opc == AArch64::TBNZW ||
+ Opc == AArch64::TBZX ||
+ Opc == AArch64::TBNZX) ? 2 : 1;
+ }
+
+ MI.getOperand(OpNum).setMBB(&NewDestBB);
}
/// fixupConditionalBranch - Fix up a conditional branch whose destination is
@@ -374,35 +396,26 @@ bool AArch64BranchRelaxation::fixupCondi
// split the MBB before the next instruction.
MachineBasicBlock *MBB = MI.getParent();
MachineInstr *BMI = &MBB->back();
- bool NeedSplit = (BMI != &MI) || !BBHasFallthrough(MBB);
+ bool NeedSplit = (BMI != &MI) || !hasFallthrough(*MBB);
if (BMI != &MI) {
if (std::next(MachineBasicBlock::iterator(MI)) ==
std::prev(MBB->getLastNonDebugInstr()) &&
- BMI->getOpcode() == AArch64::B) {
- // Last MI in the BB is an unconditional branch. Can we simply invert the
+ BMI->isUnconditionalBranch()) {
+ // Last MI in the BB is an unconditional branch. We can simply invert the
// condition and swap destinations:
// beq L1
// b L2
// =>
// bne L2
// b L1
- MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB();
- if (isBlockInRange(MI, *NewDest,
- getBranchDisplacementBits(MI.getOpcode()))) {
+ MachineBasicBlock *NewDest = getDestBlock(*BMI);
+ if (isBlockInRange(MI, *NewDest)) {
DEBUG(dbgs() << " Invert condition and swap its destination with "
<< *BMI);
- BMI->getOperand(0).setMBB(DestBB);
- unsigned OpNum = (MI.getOpcode() == AArch64::TBZW ||
- MI.getOpcode() == AArch64::TBNZW ||
- MI.getOpcode() == AArch64::TBZX ||
- MI.getOpcode() == AArch64::TBNZX)
- ? 2
- : 1;
- MI.getOperand(OpNum).setMBB(NewDest);
- MI.setDesc(TII->get(getOppositeConditionOpcode(MI.getOpcode())));
- if (MI.getOpcode() == AArch64::Bcc)
- invertBccCondition(MI);
+ changeBranchDestBlock(*BMI, *DestBB);
+ invertConditionalBranch(MI);
+ changeBranchDestBlock(MI, *NewDest);
return true;
}
}
@@ -427,29 +440,22 @@ bool AArch64BranchRelaxation::fixupCondi
MBB->replaceSuccessor(FBB, NewBB);
NewBB->addSuccessor(FBB);
}
- MachineBasicBlock *NextBB = &*std::next(MachineFunction::iterator(MBB));
+
+ MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB));
DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber()
<< ", invert condition and change dest. to BB#"
- << NextBB->getNumber() << "\n");
+ << NextBB.getNumber() << '\n');
- unsigned OppositeCondOpc = getOppositeConditionOpcode(MI.getOpcode());
// Insert a new conditional branch and a new unconditional branch.
- MachineInstrBuilder MIB = BuildMI(MBB, DebugLoc(), TII->get(OppositeCondOpc))
- .addOperand(MI.getOperand(0));
+ BlockInfo[MBB->getNumber()].Size
+ += insertInvertedConditionalBranch(*MBB, MI, NextBB);
- if (MI.getOpcode() == AArch64::TBZW || MI.getOpcode() == AArch64::TBNZW ||
- MI.getOpcode() == AArch64::TBZX || MI.getOpcode() == AArch64::TBNZX)
- MIB.addOperand(MI.getOperand(1));
- if (MI.getOpcode() == AArch64::Bcc)
- invertBccCondition(*MIB);
- MIB.addMBB(NextBB);
- BlockInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back());
- BuildMI(MBB, DebugLoc(), TII->get(AArch64::B)).addMBB(DestBB);
- BlockInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back());
+ BlockInfo[MBB->getNumber()].Size +=
+ insertUnconditionalBranch(*MBB, *DestBB, MI.getDebugLoc());
// Remove the old conditional branch. It may or may not still be in MBB.
- BlockInfo[MI.getParent()->getNumber()].Size -= TII->getInstSizeInBytes(MI);
+ BlockInfo[MBB->getNumber()].Size -= TII->getInstSizeInBytes(MI);
MI.eraseFromParent();
// Finally, keep the block offsets up to date.
@@ -468,9 +474,7 @@ bool AArch64BranchRelaxation::relaxBranc
continue;
MachineInstr &MI = *J;
- if (isConditionalBranch(MI.getOpcode()) &&
- !isBlockInRange(MI, *getDestBlock(MI),
- getBranchDisplacementBits(MI.getOpcode()))) {
+ if (MI.isConditionalBranch() && !isBlockInRange(MI, *getDestBlock(MI))) {
fixupConditionalBranch(MI);
++NumRelaxed;
Changed = true;
@@ -484,7 +488,7 @@ bool AArch64BranchRelaxation::runOnMachi
DEBUG(dbgs() << "***** AArch64BranchRelaxation *****\n");
- TII = (const AArch64InstrInfo *)MF->getSubtarget().getInstrInfo();
+ TII = MF->getSubtarget<AArch64Subtarget>().getInstrInfo();
// Renumber all of the machine basic blocks in the function, guaranteeing that
// the numbers agree with the position of the block in the function.
@@ -494,8 +498,7 @@ bool AArch64BranchRelaxation::runOnMachi
// sizes of each block.
scanFunction();
- DEBUG(dbgs() << " Basic blocks before relaxation\n");
- DEBUG(dumpBBs());
+ DEBUG(dbgs() << " Basic blocks before relaxation\n"; dumpBBs(););
bool MadeChange = false;
while (relaxBranchInstructions())
@@ -504,8 +507,7 @@ bool AArch64BranchRelaxation::runOnMachi
// After a while, this might be made debug-only, but it is not expensive.
verify();
- DEBUG(dbgs() << " Basic blocks after relaxation\n");
- DEBUG(dbgs() << '\n'; dumpBBs());
+ DEBUG(dbgs() << " Basic blocks after relaxation\n\n"; dumpBBs());
BlockInfo.clear();
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp?rev=277430&r1=277429&r2=277430&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp Tue Aug 2 03:06:17 2016
@@ -32,6 +32,18 @@ using namespace llvm;
static LLVM_CONSTEXPR MachineMemOperand::Flags MOSuppressPair =
MachineMemOperand::MOTargetFlag1;
+static cl::opt<unsigned>
+TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
+ cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
+
+static cl::opt<unsigned>
+CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
+ cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
+
+static cl::opt<unsigned>
+BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
+ cl::desc("Restrict range of Bcc instructions (DEBUG)"));
+
AArch64InstrInfo::AArch64InstrInfo(const AArch64Subtarget &STI)
: AArch64GenInstrInfo(AArch64::ADJCALLSTACKDOWN, AArch64::ADJCALLSTACKUP),
RI(STI.getTargetTriple()), Subtarget(STI) {}
@@ -95,6 +107,44 @@ static void parseCondBranch(MachineInstr
}
}
+static unsigned getBranchDisplacementBits(unsigned Opc) {
+ switch (Opc) {
+ default:
+ llvm_unreachable("unexpected opcode!");
+ case AArch64::TBNZW:
+ case AArch64::TBZW:
+ case AArch64::TBNZX:
+ case AArch64::TBZX:
+ return TBZDisplacementBits;
+ case AArch64::CBNZW:
+ case AArch64::CBZW:
+ case AArch64::CBNZX:
+ case AArch64::CBZX:
+ return CBZDisplacementBits;
+ case AArch64::Bcc:
+ return BCCDisplacementBits;
+ }
+}
+
+static unsigned getBranchMaxDisplacementBytes(unsigned Opc) {
+ if (Opc == AArch64::B)
+ return -1;
+
+ unsigned Bits = getBranchDisplacementBits(Opc);
+ unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2;
+ return MaxOffs;
+}
+
+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);
+}
+
// Branch analysis.
bool AArch64InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.h?rev=277430&r1=277429&r2=277430&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.h Tue Aug 2 03:06:17 2016
@@ -141,6 +141,12 @@ public:
MachineBasicBlock::iterator InsertPt, int FrameIndex,
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;
+
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
More information about the llvm-commits
mailing list