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) &&
224 "Missing size value for instruction.");
229TerminatorInfo SystemZLongBranch::describeTerminator(
MachineInstr &
MI) {
232 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
233 switch (
MI.getOpcode()) {
276 TII->getBranchInfo(
MI).getMBBTarget()->getNumber();
284uint64_t SystemZLongBranch::initMBBInfo() {
285 MF->RenumberBlocks();
286 unsigned NumBlocks = MF->size();
289 MBBs.resize(NumBlocks);
292 Terminators.reserve(NumBlocks);
294 BlockPosition Position(
Log2(MF->getAlignment()));
295 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
305 while (
MI !=
End && !
MI->isTerminator()) {
309 skipNonTerminators(Position,
Block);
313 if (!
MI->isDebugInstr()) {
314 assert(
MI->isTerminator() &&
"Terminator followed by non-terminator");
315 Terminators.push_back(describeTerminator(*
MI));
316 skipTerminator(Position, Terminators.back(),
false);
317 ++
Block.NumTerminators;
323 return Position.Address;
328bool SystemZLongBranch::mustRelaxBranch(
const TerminatorInfo &Terminator,
334 if (Address >=
Target.Address) {
335 if (Address -
Target.Address <= MaxBackwardRange)
338 if (
Target.Address - Address <= MaxForwardRange)
347bool SystemZLongBranch::mustRelaxABranch() {
348 for (
auto &Terminator : Terminators)
349 if (mustRelaxBranch(Terminator,
Terminator.Address))
356void SystemZLongBranch::setWorstCaseAddresses() {
358 BlockPosition Position(
Log2(MF->getAlignment()));
359 for (
auto &
Block : MBBs) {
360 skipNonTerminators(Position,
Block);
361 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
362 skipTerminator(Position, *TI,
true);
371 unsigned AddOpcode) {
375 .
add(
MI->getOperand(0))
376 .
add(
MI->getOperand(1))
381 .
add(
MI->getOperand(2));
384 MI->eraseFromParent();
390 unsigned CompareOpcode) {
394 .
add(
MI->getOperand(0))
395 .
add(
MI->getOperand(1));
398 .
add(
MI->getOperand(2))
399 .
add(
MI->getOperand(3));
402 MI->eraseFromParent();
406void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
408 switch (
Branch->getOpcode()) {
413 Branch->setDesc(
TII->get(SystemZ::BRCL));
416 splitBranchOnCount(Branch, SystemZ::AHI);
419 splitBranchOnCount(Branch, SystemZ::AGHI);
422 splitCompareBranch(Branch, SystemZ::CR);
425 splitCompareBranch(Branch, SystemZ::CGR);
428 splitCompareBranch(Branch, SystemZ::CHI);
431 splitCompareBranch(Branch, SystemZ::CGHI);
434 splitCompareBranch(Branch, SystemZ::CLR);
437 splitCompareBranch(Branch, SystemZ::CLGR);
440 splitCompareBranch(Branch, SystemZ::CLFI);
443 splitCompareBranch(Branch, SystemZ::CLGFI);
457void SystemZLongBranch::relaxBranches() {
459 BlockPosition Position(
Log2(MF->getAlignment()));
460 for (
auto &
Block : MBBs) {
461 skipNonTerminators(Position,
Block);
462 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
463 assert(Position.Address <= TI->Address &&
464 "Addresses shouldn't go forwards");
465 if (mustRelaxBranch(*TI, Position.Address))
467 skipTerminator(Position, *TI,
false);
477 if (
Size <= MaxForwardRange || !mustRelaxABranch())
480 setWorstCaseAddresses();
486 return new SystemZLongBranch();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
const char LLVMTargetMachineRef TM
#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.