27 #define DEBUG_TYPE "aarch64-branch-relax"
31 cl::desc(
"Relax out of range conditional branches"));
35 cl::desc(
"Restrict range of TB[N]Z instructions (DEBUG)"));
39 cl::desc(
"Restrict range of CB[N]Z instructions (DEBUG)"));
43 cl::desc(
"Restrict range of Bcc instructions (DEBUG)"));
45 STATISTIC(NumSplit,
"Number of basic blocks split");
46 STATISTIC(NumRelaxed,
"Number of conditional branches relaxed");
52 struct BasicBlockInfo {
66 BasicBlockInfo() : Offset(0), Size(0) {}
71 unsigned postOffset(
unsigned LogAlign = 0)
const {
72 unsigned PO = Offset + Size;
73 unsigned Align = 1 << LogAlign;
74 return (PO + Align - 1) / Align *
Align;
83 bool relaxBranchInstructions();
100 const char *getPassName()
const override {
101 return "AArch64 branch relaxation pass";
110 unsigned PrevNum = MF->begin()->getNumber();
112 unsigned Align = MBB.getAlignment();
113 unsigned Num = MBB.getNumber();
114 assert(BlockInfo[Num].Offset % (1u << Align) == 0);
115 assert(!Num || BlockInfo[PrevNum].postOffset() <= BlockInfo[Num].Offset);
122 void AArch64BranchRelaxation::dumpBBs() {
123 for (
auto &MBB : *MF) {
124 const BasicBlockInfo &BBI = BlockInfo[MBB.getNumber()];
125 dbgs() <<
format(
"BB#%u\toffset=%08x\t", MBB.getNumber(), BBI.Offset)
126 <<
format(
"size=%#x\n", BBI.Size);
149 void AArch64BranchRelaxation::scanFunction() {
151 BlockInfo.resize(MF->getNumBlockIDs());
158 computeBlockSize(MBB);
161 adjustBlockOffsets(*MF->begin());
169 Size +=
TII->GetInstSizeInBytes(&
MI);
170 BlockInfo[MBB.getNumber()].Size = Size;
176 unsigned AArch64BranchRelaxation::getInstrOffset(
MachineInstr *
MI)
const {
182 unsigned Offset = BlockInfo[MBB->
getNumber()].Offset;
186 assert(
I != MBB->
end() &&
"Didn't find MI in its own basic block?");
187 Offset +=
TII->GetInstSizeInBytes(
I);
201 BlockInfo[Num].Offset = BlockInfo[PrevNum].postOffset(LogAlign);
213 AArch64BranchRelaxation::splitBlockBeforeInstr(
MachineInstr *MI) {
233 BlockInfo.insert(BlockInfo.begin() + NewBB->
getNumber(), BasicBlockInfo());
240 computeBlockSize(*OrigBB);
244 computeBlockSize(*NewBB);
247 adjustBlockOffsets(*OrigBB);
256 bool AArch64BranchRelaxation::isBlockInRange(
MachineInstr *MI,
259 unsigned MaxOffs = ((1 << (Bits - 1)) - 1) << 2;
260 unsigned BrOffset = getInstrOffset(MI);
261 unsigned DestOffset = BlockInfo[DestBB->
getNumber()].Offset;
265 <<
" max delta=" << MaxOffs <<
" from " << getInstrOffset(MI)
266 <<
" to " << DestOffset <<
" offset "
267 <<
int(DestOffset - BrOffset) <<
"\t" << *
MI);
270 if (BrOffset <= DestOffset)
271 return (DestOffset - BrOffset <= MaxOffs);
272 return (BrOffset - DestOffset <= MaxOffs);
314 case AArch64::TBNZW:
return AArch64::TBZW;
315 case AArch64::TBNZX:
return AArch64::TBZX;
316 case AArch64::TBZW:
return AArch64::TBNZW;
317 case AArch64::TBZX:
return AArch64::TBNZX;
318 case AArch64::CBNZW:
return AArch64::CBZW;
319 case AArch64::CBNZX:
return AArch64::CBZX;
320 case AArch64::CBZW:
return AArch64::CBNZW;
321 case AArch64::CBZX:
return AArch64::CBNZX;
322 case AArch64::Bcc:
return AArch64::Bcc;
346 assert(MI->
getOpcode() == AArch64::Bcc &&
"Unexpected opcode!");
355 bool AArch64BranchRelaxation::fixupConditionalBranch(
MachineInstr *MI) {
385 if (isBlockInRange(MI, NewDest,
387 DEBUG(
dbgs() <<
" Invert condition and swap its destination with "
390 unsigned OpNum = (MI->
getOpcode() == AArch64::TBZW ||
414 int delta =
TII->GetInstSizeInBytes(&MBB->
back());
415 BlockInfo[MBB->
getNumber()].Size -= delta;
427 <<
", invert condition and change dest. to BB#"
449 adjustBlockOffsets(*MBB);
453 bool AArch64BranchRelaxation::relaxBranchInstructions() {
454 bool Changed =
false;
457 for (
auto &MBB : *MF) {
462 fixupConditionalBranch(MI);
470 bool AArch64BranchRelaxation::runOnMachineFunction(
MachineFunction &mf) {
477 DEBUG(
dbgs() <<
"***** AArch64BranchRelaxation *****\n");
483 MF->RenumberBlocks();
489 DEBUG(
dbgs() <<
" Basic blocks before relaxation\n");
492 bool MadeChange =
false;
493 while (relaxBranchInstructions())
499 DEBUG(
dbgs() <<
" Basic blocks after relaxation\n");
510 return new AArch64BranchRelaxation();
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
STATISTIC(NumFunctions,"Total number of functions")
FunctionPass * createAArch64BranchRelaxation()
createAArch64BranchRelaxation - returns an instance of the constpool island pass. ...
MachineBasicBlock * getMBB() const
int getNumber() const
getNumber - MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a M...
static CondCode getInvertedCondCode(CondCode Code)
iterator getFirstTerminator()
getFirstTerminator - returns an iterator to the first terminator instruction of this basic block...
iterator_range< succ_iterator > successors()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static MachineBasicBlock * getDestBlock(MachineInstr *MI)
iterator getLastNonDebugInstr()
getLastNonDebugInstr - returns an iterator to the last non-debug instruction in the basic block...
static void invertBccCondition(MachineInstr *MI)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
getBasicBlock - Return the LLVM basic block that this instance corresponded to originally.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
static cl::opt< bool > BranchRelaxation("aarch64-branch-relax", cl::Hidden, cl::init(true), cl::desc("Relax out of range conditional branches"))
const MachineOperand & getOperand(unsigned i) const
void setMBB(MachineBasicBlock *MBB)
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
replaceSuccessor - Replace successor OLD with NEW and update weight info.
Representation of each machine instruction.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
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 bool isConditionalBranch(unsigned Opc)
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
BasicBlockListType::iterator iterator
static bool BBHasFallthrough(MachineBasicBlock *MBB)
BBHasFallthrough - Return true if the specified basic block can fallthrough into the block immediatel...
void addSuccessor(MachineBasicBlock *succ, uint32_t weight=0)
addSuccessor - Add succ as a successor of this MachineBasicBlock.
static unsigned getOppositeConditionOpcode(unsigned Opc)
static unsigned getBranchDisplacementBits(unsigned Opc)
unsigned getAlignment() const
getAlignment - Return alignment of the basic block.