77#define DEBUG_TYPE "systemz-long-branch"
97 unsigned NumTerminators = 0;
103struct TerminatorInfo {
106 MachineInstr *Branch =
nullptr;
116 unsigned TargetBlock = 0;
120 unsigned ExtraRelaxSize = 0;
122 TerminatorInfo() =
default;
126struct BlockPosition {
134 BlockPosition(
unsigned InitialLogAlignment)
135 : KnownBits(InitialLogAlignment) {}
142 SystemZLongBranchLegacy() : MachineFunctionPass(ID) {}
146 MachineFunctionProperties getRequiredProperties()
const override {
147 return MachineFunctionProperties().setNoVRegs();
150 void getAnalysisUsage(AnalysisUsage &AU)
const override {
156class SystemZLongBranchImpl {
157 void skipNonTerminators(BlockPosition &Position, MBBInfo &
Block);
158 void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator,
160 TerminatorInfo describeTerminator(MachineInstr &
MI);
162 bool mustRelaxBranch(
const TerminatorInfo &Terminator,
uint64_t Address);
163 bool mustRelaxABranch();
164 void setWorstCaseAddresses();
165 void splitBranchOnCount(MachineInstr *
MI,
unsigned AddOpcode);
166 void splitCompareBranch(MachineInstr *
MI,
unsigned CompareOpcode);
167 void relaxBranch(TerminatorInfo &Terminator);
168 void relaxBranches();
170 const SystemZInstrInfo *TII =
nullptr;
179char SystemZLongBranchLegacy::ID = 0;
181const uint64_t MaxBackwardRange = 0x10000;
182const uint64_t MaxForwardRange = 0xfffe;
192void SystemZLongBranchImpl::skipNonTerminators(BlockPosition &Position,
194 if (
Log2(
Block.Alignment) > Position.KnownBits) {
198 (Block.Alignment.value() - (uint64_t(1) << Position.KnownBits));
199 Position.KnownBits = Log2(Block.Alignment);
203 Position.Address =
alignTo(Position.Address,
Block.Alignment);
206 Block.Address = Position.Address;
209 Position.Address +=
Block.Size;
215void SystemZLongBranchImpl::skipTerminator(BlockPosition &Position,
216 TerminatorInfo &Terminator,
217 bool AssumeRelaxed) {
221 Position.Address +=
Terminator.ExtraRelaxSize;
226 unsigned Size =
TII->getInstSizeInBytes(
MI);
229 MI.isDebugOrPseudoInstr() ||
MI.isPosition() ||
MI.isKill() ||
230 MI.isImplicitDef() ||
MI.getOpcode() == TargetOpcode::MEMBARRIER ||
231 MI.getOpcode() == TargetOpcode::INIT_UNDEF ||
MI.isFakeUse() ||
232 MI.getOpcode() == TargetOpcode::RELOC_NONE ||
233 MI.getOpcode() == SystemZ::FENCE ||
235 MI.isInlineAsm() ||
MI.getOpcode() == SystemZ::STACKMAP ||
236 MI.getOpcode() == SystemZ::PATCHPOINT ||
239 MI.getOpcode() == SystemZ::EH_SjLj_Setup) &&
240 "Missing size value for instruction.");
245TerminatorInfo SystemZLongBranchImpl::describeTerminator(MachineInstr &
MI) {
248 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
249 switch (
MI.getOpcode()) {
292 TII->getBranchInfo(
MI).getMBBTarget()->getNumber();
300uint64_t SystemZLongBranchImpl::initMBBInfo() {
302 unsigned NumBlocks = MF->
size();
305 MBBs.resize(NumBlocks);
308 Terminators.reserve(NumBlocks);
311 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
321 while (
MI !=
End && !
MI->isTerminator()) {
325 skipNonTerminators(Position,
Block);
329 if (!
MI->isDebugInstr()) {
330 assert(
MI->isTerminator() &&
"Terminator followed by non-terminator");
331 Terminators.push_back(describeTerminator(*
MI));
332 skipTerminator(Position, Terminators.back(),
false);
333 ++
Block.NumTerminators;
339 return Position.Address;
344bool SystemZLongBranchImpl::mustRelaxBranch(
const TerminatorInfo &Terminator,
363bool SystemZLongBranchImpl::mustRelaxABranch() {
364 for (
auto &Terminator : Terminators)
365 if (mustRelaxBranch(Terminator,
Terminator.Address))
372void SystemZLongBranchImpl::setWorstCaseAddresses() {
373 SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
375 for (
auto &
Block : MBBs) {
376 skipNonTerminators(Position,
Block);
377 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
378 skipTerminator(Position, *TI,
true);
386void SystemZLongBranchImpl::splitBranchOnCount(MachineInstr *
MI,
387 unsigned AddOpcode) {
391 .
add(
MI->getOperand(0))
392 .
add(
MI->getOperand(1))
397 .
add(
MI->getOperand(2));
403 MI->eraseFromParent();
408void SystemZLongBranchImpl::splitCompareBranch(MachineInstr *
MI,
409 unsigned CompareOpcode) {
413 .
add(
MI->getOperand(0))
414 .
add(
MI->getOperand(1));
417 .
add(
MI->getOperand(2))
418 .
add(
MI->getOperand(3));
423 MI->eraseFromParent();
427void SystemZLongBranchImpl::relaxBranch(TerminatorInfo &Terminator) {
429 switch (
Branch->getOpcode()) {
434 Branch->setDesc(
TII->get(SystemZ::BRCL));
437 splitBranchOnCount(Branch, SystemZ::AHI);
440 splitBranchOnCount(Branch, SystemZ::AGHI);
443 splitCompareBranch(Branch, SystemZ::CR);
446 splitCompareBranch(Branch, SystemZ::CGR);
449 splitCompareBranch(Branch, SystemZ::CHI);
452 splitCompareBranch(Branch, SystemZ::CGHI);
455 splitCompareBranch(Branch, SystemZ::CLR);
458 splitCompareBranch(Branch, SystemZ::CLGR);
461 splitCompareBranch(Branch, SystemZ::CLFI);
464 splitCompareBranch(Branch, SystemZ::CLGFI);
478void SystemZLongBranchImpl::relaxBranches() {
479 SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.
begin();
481 for (
auto &
Block : MBBs) {
482 skipNonTerminators(Position,
Block);
483 for (
unsigned BTI = 0, BTE =
Block.NumTerminators; BTI != BTE; ++BTI) {
484 assert(Position.Address <= TI->Address &&
485 "Addresses shouldn't go forwards");
486 if (mustRelaxBranch(*TI, Position.Address))
488 skipTerminator(Position, *TI,
false);
495 TII =
static_cast<const SystemZInstrInfo *
>(
F.getSubtarget().getInstrInfo());
498 if (
Size <= MaxForwardRange || !mustRelaxABranch())
501 setWorstCaseAddresses();
508 return new SystemZLongBranchLegacy();
511bool SystemZLongBranchLegacy::runOnMachineFunction(
MachineFunction &MF) {
512 SystemZLongBranchImpl Impl;
513 return Impl.runOnMachineFunction(MF);
519 SystemZLongBranchImpl Impl;
520 return Impl.runOnMachineFunction(MF)
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)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
const HexagonRegisterInfo & getRegisterInfo() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, unsigned MaxOperand=UINT_MAX)
Create substitutions for any tracked values in Old, to point at New.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Align getAlignment() const
getAlignment - Return the alignment of the function.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const unsigned CCMASK_ICMP
const unsigned CCMASK_CMP_NE
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
unsigned Log2(Align A)
Returns the log2 of the alignment.
@ End
Run the machine verifier once, at the end of the pipeline.
FunctionPass * createSystemZLongBranchLegacyPass(SystemZTargetMachine &TM)
This struct is a compact representation of a valid (non-zero power of two) alignment.