LLVM 20.0.0git
GCNPreRALongBranchReg.cpp
Go to the documentation of this file.
1//===-- GCNPreRALongBranchReg.cpp ----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// \file
9// \brief Pass to estimate pre RA branch size and reserve a pair of SGPRs if
10// there is a long branch. Branch size at this point is difficult to track since
11// we have no idea what spills will be inserted later on. We just assume 8 bytes
12// per instruction to compute approximations without computing the actual
13// instruction size to see if we're in the neighborhood of the maximum branch
14// distrance threshold tuning of what is considered "long" is handled through
15// amdgpu-long-branch-factor cl argument which sets LongBranchFactor.
16//===----------------------------------------------------------------------===//
17#include "AMDGPU.h"
18#include "GCNSubtarget.h"
22
23using namespace llvm;
24
25#define DEBUG_TYPE "amdgpu-pre-ra-long-branch-reg"
26
27namespace {
28
29static cl::opt<double> LongBranchFactor(
30 "amdgpu-long-branch-factor", cl::init(1.0), cl::Hidden,
31 cl::desc("Factor to apply to what qualifies as a long branch "
32 "to reserve a pair of scalar registers. If this value "
33 "is 0 the long branch registers are never reserved. As this "
34 "value grows the greater chance the branch distance will fall "
35 "within the threshold and the registers will be marked to be "
36 "reserved. We lean towards always reserving a register for "
37 "long jumps"));
38
39class GCNPreRALongBranchReg : public MachineFunctionPass {
40
41 struct BasicBlockInfo {
42 // Offset - Distance from the beginning of the function to the beginning
43 // of this basic block.
44 uint64_t Offset = 0;
45 // Size - Size of the basic block in bytes
46 uint64_t Size = 0;
47 };
48 void generateBlockInfo(MachineFunction &MF,
50
51public:
52 static char ID;
53 GCNPreRALongBranchReg() : MachineFunctionPass(ID) {
55 }
56 bool runOnMachineFunction(MachineFunction &MF) override;
57 StringRef getPassName() const override {
58 return "AMDGPU Pre-RA Long Branch Reg";
59 }
60 void getAnalysisUsage(AnalysisUsage &AU) const override {
61 AU.setPreservesAll();
63 }
64};
65} // End anonymous namespace.
66char GCNPreRALongBranchReg::ID = 0;
67
68INITIALIZE_PASS(GCNPreRALongBranchReg, DEBUG_TYPE,
69 "AMDGPU Pre-RA Long Branch Reg", false, false)
70
71char &llvm::GCNPreRALongBranchRegID = GCNPreRALongBranchReg::ID;
72void GCNPreRALongBranchReg::generateBlockInfo(
74
75 BlockInfo.resize(MF.getNumBlockIDs());
76
77 // Approximate the size of all basic blocks by just
78 // assuming 8 bytes per instruction
79 for (const MachineBasicBlock &MBB : MF) {
80 uint64_t NumInstr = 0;
81 // Loop through the basic block and add up all non-debug
82 // non-meta instructions
83 for (const MachineInstr &MI : MBB) {
84 // isMetaInstruction is a superset of isDebugIstr
85 if (MI.isMetaInstruction())
86 continue;
87 NumInstr += 1;
88 }
89 // Approximate size as just 8 bytes per instruction
90 BlockInfo[MBB.getNumber()].Size = 8 * NumInstr;
91 }
92 uint64_t PrevNum = (&MF)->begin()->getNumber();
93 for (auto &MBB :
94 make_range(std::next(MachineFunction::iterator((&MF)->begin())),
95 (&MF)->end())) {
96 uint64_t Num = MBB.getNumber();
97 // Compute the offset immediately following this block.
98 BlockInfo[Num].Offset = BlockInfo[PrevNum].Offset + BlockInfo[PrevNum].Size;
99 PrevNum = Num;
100 }
101}
102bool GCNPreRALongBranchReg::runOnMachineFunction(MachineFunction &MF) {
103 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
104 const SIInstrInfo *TII = STM.getInstrInfo();
105 const SIRegisterInfo *TRI = STM.getRegisterInfo();
108
109 // For now, reserve highest available SGPR pair. After RA,
110 // shift down to a lower unused pair of SGPRs
111 // If all registers are used, then findUnusedRegister will return
112 // AMDGPU::NoRegister.
113 constexpr bool ReserveHighestRegister = true;
114 Register LongBranchReservedReg = TRI->findUnusedRegister(
115 MRI, &AMDGPU::SGPR_64RegClass, MF, ReserveHighestRegister);
116 if (!LongBranchReservedReg)
117 return false;
118
119 // Approximate code size and offsets of each basic block
121 generateBlockInfo(MF, BlockInfo);
122
123 for (const MachineBasicBlock &MBB : MF) {
125 if (Last == MBB.end() || !Last->isUnconditionalBranch())
126 continue;
127 MachineBasicBlock *DestBB = TII->getBranchDestBlock(*Last);
128 uint64_t BlockDistance = static_cast<uint64_t>(
129 LongBranchFactor * BlockInfo[DestBB->getNumber()].Offset);
130 // If the distance falls outside the threshold assume it is a long branch
131 // and we need to reserve the registers
132 if (!TII->isBranchOffsetInRange(Last->getOpcode(), BlockDistance)) {
133 MFI->setLongBranchReservedReg(LongBranchReservedReg);
134 return true;
135 }
136 }
137 return false;
138}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
#define DEBUG_TYPE
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
const SIInstrInfo * getInstrInfo() const override
Definition: GCNSubtarget.h:279
const SIRegisterInfo * getRegisterInfo() const override
Definition: GCNSubtarget.h:291
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setLongBranchReservedReg(Register Reg)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:235
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeGCNPreRALongBranchRegPass(PassRegistry &)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
char & GCNPreRALongBranchRegID
BasicBlockInfo - Information about the offset and size of a single basic block.