69 #define DEBUG_TYPE "systemz-long-branch"
71 STATISTIC(LongBranches,
"Number of long branches.");
88 unsigned NumTerminators;
91 :
Address(0), Size(0), Alignment(0), NumTerminators(0) {}
95 struct TerminatorInfo {
108 unsigned TargetBlock;
112 unsigned ExtraRelaxSize;
114 TerminatorInfo() :
Branch(nullptr), Size(0), TargetBlock(0),
119 struct BlockPosition {
127 BlockPosition(
unsigned InitialAlignment)
128 :
Address(0), KnownBits(InitialAlignment) {}
137 const char *getPassName()
const override {
138 return "SystemZ Long Branch";
144 void skipNonTerminators(BlockPosition &Position, MBBInfo &
Block);
145 void skipTerminator(BlockPosition &Position, TerminatorInfo &
Terminator,
148 uint64_t initMBBInfo();
150 bool mustRelaxABranch();
151 void setWorstCaseAddresses();
153 void splitCompareBranch(
MachineInstr *
MI,
unsigned CompareOpcode);
155 void relaxBranches();
165 const uint64_t MaxBackwardRange = 0x10000;
166 const uint64_t MaxForwardRange = 0xfffe;
170 return new SystemZLongBranch(TM);
176 void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
178 if (Block.Alignment > Position.KnownBits) {
181 Position.Address += ((uint64_t(1) << Block.Alignment) -
182 (uint64_t(1) << Position.KnownBits));
183 Position.KnownBits = Block.Alignment;
187 uint64_t AlignMask = (uint64_t(1) << Block.Alignment) - 1;
188 Position.Address = (Position.Address + AlignMask) & ~AlignMask;
191 Block.Address = Position.Address;
194 Position.Address += Block.Size;
200 void SystemZLongBranch::skipTerminator(BlockPosition &Position,
202 bool AssumeRelaxed) {
203 Terminator.Address = Position.Address;
204 Position.Address += Terminator.Size;
206 Position.Address += Terminator.ExtraRelaxSize;
210 TerminatorInfo SystemZLongBranch::describeTerminator(
MachineInstr *
MI) {
212 Terminator.Size =
TII->getInstSizeInBytes(MI);
217 Terminator.ExtraRelaxSize = 2;
221 Terminator.ExtraRelaxSize = 2;
226 Terminator.ExtraRelaxSize = 6;
231 Terminator.ExtraRelaxSize = 2;
236 Terminator.ExtraRelaxSize = 4;
241 Terminator.ExtraRelaxSize = 4;
246 Terminator.ExtraRelaxSize = 6;
251 Terminator.Branch =
MI;
252 Terminator.TargetBlock =
253 TII->getBranchInfo(MI).Target->getMBB()->getNumber();
261 uint64_t SystemZLongBranch::initMBBInfo() {
262 MF->RenumberBlocks();
263 unsigned NumBlocks = MF->size();
266 MBBs.resize(NumBlocks);
269 Terminators.reserve(NumBlocks);
271 BlockPosition Position(MF->getAlignment());
272 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
274 MBBInfo &Block = MBBs[
I];
282 while (MI != End && !MI->isTerminator()) {
283 Block.Size +=
TII->getInstSizeInBytes(MI);
286 skipNonTerminators(Position, Block);
290 if (!MI->isDebugValue()) {
291 assert(MI->isTerminator() &&
"Terminator followed by non-terminator");
292 Terminators.push_back(describeTerminator(MI));
293 skipTerminator(Position, Terminators.back(),
false);
294 ++Block.NumTerminators;
300 return Position.Address;
305 bool SystemZLongBranch::mustRelaxBranch(
const TerminatorInfo &Terminator,
307 if (!Terminator.Branch)
310 const MBBInfo &
Target = MBBs[Terminator.TargetBlock];
311 if (Address >= Target.Address) {
312 if (Address - Target.Address <= MaxBackwardRange)
315 if (Target.Address - Address <= MaxForwardRange)
324 bool SystemZLongBranch::mustRelaxABranch() {
325 for (
auto &Terminator : Terminators)
326 if (mustRelaxBranch(Terminator, Terminator.Address))
333 void SystemZLongBranch::setWorstCaseAddresses() {
335 BlockPosition Position(MF->getAlignment());
336 for (
auto &Block : MBBs) {
337 skipNonTerminators(Position, Block);
338 for (
unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
339 skipTerminator(Position, *TI,
true);
347 void SystemZLongBranch::splitBranchOnCount(
MachineInstr *MI,
348 unsigned AddOpcode) {
366 void SystemZLongBranch::splitCompareBranch(
MachineInstr *MI,
367 unsigned CompareOpcode) {
370 BuildMI(*MBB, MI, DL,
TII->get(CompareOpcode))
383 void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
393 splitBranchOnCount(Branch, SystemZ::AHI);
396 splitBranchOnCount(Branch, SystemZ::AGHI);
399 splitCompareBranch(Branch, SystemZ::CR);
402 splitCompareBranch(Branch, SystemZ::CGR);
405 splitCompareBranch(Branch, SystemZ::CHI);
408 splitCompareBranch(Branch, SystemZ::CGHI);
411 splitCompareBranch(Branch, SystemZ::CLR);
414 splitCompareBranch(Branch, SystemZ::CLGR);
417 splitCompareBranch(Branch, SystemZ::CLFI);
420 splitCompareBranch(Branch, SystemZ::CLGFI);
426 Terminator.Size += Terminator.ExtraRelaxSize;
427 Terminator.ExtraRelaxSize = 0;
428 Terminator.Branch =
nullptr;
434 void SystemZLongBranch::relaxBranches() {
436 BlockPosition Position(MF->getAlignment());
437 for (
auto &Block : MBBs) {
438 skipNonTerminators(Position, Block);
439 for (
unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) {
440 assert(Position.Address <= TI->Address &&
441 "Addresses shouldn't go forwards");
442 if (mustRelaxBranch(*TI, Position.Address))
444 skipTerminator(Position, *TI,
false);
453 uint64_t Size = initMBBInfo();
454 if (Size <= MaxForwardRange || !mustRelaxABranch())
457 setWorstCaseAddresses();
STATISTIC(NumFunctions,"Total number of functions")
bool isConditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
const unsigned CCMASK_ICMP
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
const HexagonRegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
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...
const unsigned CCMASK_CMP_NE
FunctionPass * createSystemZLongBranchPass(SystemZTargetMachine &TM)
Target - Wrapper for Target specific information.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Representation of each machine instruction.
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
bool addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block...
unsigned getAlignment() const
getAlignment - Return alignment of the basic block.