73#define DEBUG_TYPE "systemz-long-branch"
93 unsigned NumTerminators = 0;
99struct TerminatorInfo {
112 unsigned TargetBlock = 0;
116 unsigned ExtraRelaxSize = 0;
118 TerminatorInfo() =
default;
122struct BlockPosition {
130 BlockPosition(
unsigned InitialLogAlignment)
147 void skipNonTerminators(BlockPosition &Position, MBBInfo &
Block);
148 void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
152 bool mustRelaxBranch(
const TerminatorInfo &Terminator,
uint64_t Address);
153 bool mustRelaxABranch();
154 void setWorstCaseAddresses();
156 void splitCompareBranch(
MachineInstr *
MI,
unsigned CompareOpcode);
157 void relaxBranch(TerminatorInfo &Terminator);
158 void relaxBranches();
166char SystemZLongBranch::ID = 0;
168const uint64_t MaxBackwardRange = 0x10000;
169const uint64_t MaxForwardRange = 0xfffe;
179void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
181 if (
Log2(
Block.Alignment) > Position.KnownBits) {
185 (
Block.Alignment.value() - (
uint64_t(1) << Position.KnownBits));
186 Position.KnownBits =
Log2(
Block.Alignment);
190 Position.Address =
alignTo(Position.Address,
Block.Alignment);
193 Block.Address = Position.Address;
196 Position.Address +=
Block.Size;
202void SystemZLongBranch::skipTerminator(BlockPosition &Position,
203 TerminatorInfo &Terminator,
204 bool AssumeRelaxed) {
208 Position.Address +=
Terminator.ExtraRelaxSize;
213 unsigned Size =
TII->getInstSizeInBytes(
MI);
216 MI.isDebugOrPseudoInstr() ||
MI.isPosition() ||
MI.isKill() ||
217 MI.isImplicitDef() ||
MI.getOpcode() == TargetOpcode::MEMBARRIER ||
218 MI.getOpcode() == TargetOpcode::INIT_UNDEF ||
MI.isFakeUse() ||
220 MI.isInlineAsm() ||
MI.getOpcode() == SystemZ::STACKMAP ||
221 MI.getOpcode() == SystemZ::PATCHPOINT ||
224 MI.getOpcode() == SystemZ::EH_SjLj_Setup) &&
225 "Missing size value for instruction.");
230TerminatorInfo SystemZLongBranch::describeTerminator(
MachineInstr &
MI) {
233 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
234 switch (
MI.getOpcode()) {
277 TII->getBranchInfo(
MI).getMBBTarget()->getNumber();
285uint64_t SystemZLongBranch::initMBBInfo() {
286 MF->RenumberBlocks();
287 unsigned NumBlocks = MF->size();
290 MBBs.resize(NumBlocks);
293 Terminators.reserve(NumBlocks);
295 BlockPosition Position(
Log2(MF->getAlignment()));
296 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
306 while (
MI !=
End && !
MI->isTerminator()) {
310 skipNonTerminators(Position,
Block);
314 if (!
MI->isDebugInstr()) {
315 assert(
MI->isTerminator() &&
"Terminator followed by non-terminator");
316 Terminators.push_back(describeTerminator(*
MI));
317 skipTerminator(Position, Terminators.back(),
false);
318 ++
Block.NumTerminators;
324 return Position.Address;
329bool SystemZLongBranch::mustRelaxBranch(
const TerminatorInfo &Terminator,
335 if (Address >=
Target.Address) {
336 if (Address -
Target.Address <= MaxBackwardRange)
339 if (
Target.Address - Address <= MaxForwardRange)
348bool SystemZLongBranch::mustRelaxABranch() {
349 for (
auto &Terminator : Terminators)
350 if (mustRelaxBranch(Terminator,
Terminator.Address))
357void SystemZLongBranch::setWorstCaseAddresses() {
359 BlockPosition Position(
Log2(MF->getAlignment()));
360 for (
auto &
Block : MBBs) {
361 skipNonTerminators(Position,
Block);
362 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
363 skipTerminator(Position, *TI,
true);
372 unsigned AddOpcode) {
376 .
add(
MI->getOperand(0))
377 .
add(
MI->getOperand(1))
382 .
add(
MI->getOperand(2));
388 MI->eraseFromParent();
394 unsigned CompareOpcode) {
398 .
add(
MI->getOperand(0))
399 .
add(
MI->getOperand(1));
402 .
add(
MI->getOperand(2))
403 .
add(
MI->getOperand(3));
408 MI->eraseFromParent();
412void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
414 switch (
Branch->getOpcode()) {
419 Branch->setDesc(
TII->get(SystemZ::BRCL));
422 splitBranchOnCount(Branch, SystemZ::AHI);
425 splitBranchOnCount(Branch, SystemZ::AGHI);
428 splitCompareBranch(Branch, SystemZ::CR);
431 splitCompareBranch(Branch, SystemZ::CGR);
434 splitCompareBranch(Branch, SystemZ::CHI);
437 splitCompareBranch(Branch, SystemZ::CGHI);
440 splitCompareBranch(Branch, SystemZ::CLR);
443 splitCompareBranch(Branch, SystemZ::CLGR);
446 splitCompareBranch(Branch, SystemZ::CLFI);
449 splitCompareBranch(Branch, SystemZ::CLGFI);
463void SystemZLongBranch::relaxBranches() {
465 BlockPosition Position(
Log2(MF->getAlignment()));
466 for (
auto &
Block : MBBs) {
467 skipNonTerminators(Position,
Block);
468 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
469 assert(Position.Address <= TI->Address &&
470 "Addresses shouldn't go forwards");
471 if (mustRelaxBranch(*TI, Position.Address))
473 skipTerminator(Position, *TI,
false);
483 if (
Size <= MaxForwardRange || !mustRelaxABranch())
486 setWorstCaseAddresses();
492 return new SystemZLongBranch();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static unsigned getInstSizeInBytes(const MachineInstr &MI, const SystemZInstrInfo *TII)
FunctionPass class - This class is used to implement most global optimizations.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Align getAlignment() const
Return alignment of the basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, unsigned MaxOperand=UINT_MAX)
Create substitutions for any tracked values in Old, to point at New.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Target - Wrapper for Target specific information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
const unsigned CCMASK_ICMP
const unsigned CCMASK_CMP_NE
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createSystemZLongBranchPass(SystemZTargetMachine &TM)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
unsigned Log2(Align A)
Returns the log2 of the alignment.
This struct is a compact representation of a valid (non-zero power of two) alignment.