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)
146 MachineFunctionProperties::Property::NoVRegs);
150 void skipNonTerminators(BlockPosition &Position, MBBInfo &
Block);
151 void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
155 bool mustRelaxBranch(
const TerminatorInfo &Terminator,
uint64_t Address);
156 bool mustRelaxABranch();
157 void setWorstCaseAddresses();
159 void splitCompareBranch(
MachineInstr *
MI,
unsigned CompareOpcode);
160 void relaxBranch(TerminatorInfo &Terminator);
161 void relaxBranches();
169char SystemZLongBranch::ID = 0;
171const uint64_t MaxBackwardRange = 0x10000;
172const uint64_t MaxForwardRange = 0xfffe;
182void SystemZLongBranch::skipNonTerminators(BlockPosition &Position,
184 if (
Log2(
Block.Alignment) > Position.KnownBits) {
188 (
Block.Alignment.value() - (
uint64_t(1) << Position.KnownBits));
189 Position.KnownBits =
Log2(
Block.Alignment);
193 Position.Address =
alignTo(Position.Address,
Block.Alignment);
196 Block.Address = Position.Address;
199 Position.Address +=
Block.Size;
205void SystemZLongBranch::skipTerminator(BlockPosition &Position,
206 TerminatorInfo &Terminator,
207 bool AssumeRelaxed) {
211 Position.Address +=
Terminator.ExtraRelaxSize;
216 unsigned Size =
TII->getInstSizeInBytes(
MI);
219 MI.isDebugOrPseudoInstr() ||
MI.isPosition() ||
MI.isKill() ||
220 MI.isImplicitDef() ||
MI.getOpcode() == TargetOpcode::MEMBARRIER ||
222 MI.isInlineAsm() ||
MI.getOpcode() == SystemZ::STACKMAP ||
223 MI.getOpcode() == SystemZ::PATCHPOINT ||
226 MI.getOpcode() == SystemZ::EH_SjLj_Setup) &&
227 "Missing size value for instruction.");
232TerminatorInfo SystemZLongBranch::describeTerminator(
MachineInstr &
MI) {
235 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
236 switch (
MI.getOpcode()) {
279 TII->getBranchInfo(
MI).getMBBTarget()->getNumber();
287uint64_t SystemZLongBranch::initMBBInfo() {
288 MF->RenumberBlocks();
289 unsigned NumBlocks = MF->size();
292 MBBs.resize(NumBlocks);
295 Terminators.reserve(NumBlocks);
297 BlockPosition Position(
Log2(MF->getAlignment()));
298 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
308 while (
MI !=
End && !
MI->isTerminator()) {
312 skipNonTerminators(Position,
Block);
316 if (!
MI->isDebugInstr()) {
317 assert(
MI->isTerminator() &&
"Terminator followed by non-terminator");
318 Terminators.push_back(describeTerminator(*
MI));
319 skipTerminator(Position, Terminators.back(),
false);
320 ++
Block.NumTerminators;
326 return Position.Address;
331bool SystemZLongBranch::mustRelaxBranch(
const TerminatorInfo &Terminator,
337 if (Address >=
Target.Address) {
338 if (Address -
Target.Address <= MaxBackwardRange)
341 if (
Target.Address - Address <= MaxForwardRange)
350bool SystemZLongBranch::mustRelaxABranch() {
351 for (
auto &Terminator : Terminators)
352 if (mustRelaxBranch(Terminator,
Terminator.Address))
359void SystemZLongBranch::setWorstCaseAddresses() {
361 BlockPosition Position(
Log2(MF->getAlignment()));
362 for (
auto &
Block : MBBs) {
363 skipNonTerminators(Position,
Block);
364 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
365 skipTerminator(Position, *TI,
true);
374 unsigned AddOpcode) {
378 .
add(
MI->getOperand(0))
379 .
add(
MI->getOperand(1))
384 .
add(
MI->getOperand(2));
387 MI->eraseFromParent();
393 unsigned CompareOpcode) {
397 .
add(
MI->getOperand(0))
398 .
add(
MI->getOperand(1));
401 .
add(
MI->getOperand(2))
402 .
add(
MI->getOperand(3));
405 MI->eraseFromParent();
409void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
411 switch (
Branch->getOpcode()) {
416 Branch->setDesc(
TII->get(SystemZ::BRCL));
419 splitBranchOnCount(Branch, SystemZ::AHI);
422 splitBranchOnCount(Branch, SystemZ::AGHI);
425 splitCompareBranch(Branch, SystemZ::CR);
428 splitCompareBranch(Branch, SystemZ::CGR);
431 splitCompareBranch(Branch, SystemZ::CHI);
434 splitCompareBranch(Branch, SystemZ::CGHI);
437 splitCompareBranch(Branch, SystemZ::CLR);
440 splitCompareBranch(Branch, SystemZ::CLGR);
443 splitCompareBranch(Branch, SystemZ::CLFI);
446 splitCompareBranch(Branch, SystemZ::CLGFI);
460void SystemZLongBranch::relaxBranches() {
462 BlockPosition Position(
Log2(MF->getAlignment()));
463 for (
auto &
Block : MBBs) {
464 skipNonTerminators(Position,
Block);
465 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
466 assert(Position.Address <= TI->Address &&
467 "Addresses shouldn't go forwards");
468 if (mustRelaxBranch(*TI, Position.Address))
470 skipTerminator(Position, *TI,
false);
480 if (
Size <= MaxForwardRange || !mustRelaxABranch())
483 setWorstCaseAddresses();
489 return new SystemZLongBranch();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
MachineFunctionProperties & set(Property P)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
void initializeSystemZLongBranchPass(PassRegistry &)
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.