113#define DEBUG_TYPE "aarch64-collect-loh"
116 "Number of simplifiable ADRP dominate by another");
117STATISTIC(NumADDToSTR,
"Number of simplifiable STR reachable by ADD");
118STATISTIC(NumLDRToSTR,
"Number of simplifiable STR reachable by LDR");
119STATISTIC(NumADDToLDR,
"Number of simplifiable LDR reachable by ADD");
120STATISTIC(NumLDRToLDR,
"Number of simplifiable LDR reachable by LDR");
121STATISTIC(NumADRPToLDR,
"Number of simplifiable LDR reachable by ADRP");
122STATISTIC(NumADRSimpleCandidate,
"Number of simplifiable ADRP + ADD");
124#define AARCH64_COLLECT_LOH_NAME "AArch64 Collect Linker Optimization Hint (LOH)"
128 switch (
MI.getOperand(2).getType()) {
143 switch (
MI.getOpcode()) {
148 case AArch64::ADDXri:
150 case AArch64::LDRXui:
151 case AArch64::LDRWui:
153 switch (
MI.getOperand(2).getType()) {
165 switch (
MI.getOpcode()) {
168 case AArch64::STRBBui:
169 case AArch64::STRHHui:
170 case AArch64::STRBui:
171 case AArch64::STRHui:
172 case AArch64::STRWui:
173 case AArch64::STRXui:
174 case AArch64::STRSui:
175 case AArch64::STRDui:
176 case AArch64::STRQui:
182 MI.getOperand(0).getReg() !=
MI.getOperand(1).getReg();
189 switch (
MI.getOpcode()) {
192 case AArch64::LDRSBWui:
193 case AArch64::LDRSBXui:
194 case AArch64::LDRSHWui:
195 case AArch64::LDRSHXui:
196 case AArch64::LDRSWui:
197 case AArch64::LDRBui:
198 case AArch64::LDRHui:
199 case AArch64::LDRWui:
200 case AArch64::LDRXui:
201 case AArch64::LDRSui:
202 case AArch64::LDRDui:
203 case AArch64::LDRQui:
210 switch (
MI.getOpcode()) {
213 case AArch64::LDRSWui:
214 case AArch64::LDRWui:
215 case AArch64::LDRXui:
216 case AArch64::LDRSui:
217 case AArch64::LDRDui:
218 case AArch64::LDRQui:
227 auto It =
First->getIterator();
228 auto EndIt =
First->getParent()->instr_end();
238 static_assert(AArch64::X28 - AArch64::X0 + 3 ==
N_GPR_REGS,
"Number of GPRs");
239 static_assert(AArch64::W30 - AArch64::W0 + 1 ==
N_GPR_REGS,
"Number of GPRs");
240 if (AArch64::X0 <=
Reg &&
Reg <= AArch64::X28)
241 return Reg - AArch64::X0;
242 if (AArch64::W0 <=
Reg &&
Reg <= AArch64::W30)
243 return Reg - AArch64::W0;
246 if (
Reg == AArch64::FP)
248 if (
Reg == AArch64::LR)
274 if (Info.MultiUsers || Info.OneUser) {
275 Info.IsCandidate = false;
276 Info.MultiUsers = true;
284 Info.IsCandidate =
true;
290 Info.IsCandidate =
true;
293 }
else if (
MI.getOpcode() == AArch64::ADDXri) {
294 Info.Type = MCLOH_AdrpAdd;
295 Info.IsCandidate = true;
297 }
else if ((
MI.getOpcode() == AArch64::LDRXui ||
298 MI.getOpcode() == AArch64::LDRWui) &&
300 Info.Type = MCLOH_AdrpLdrGot;
301 Info.IsCandidate = true;
308 Info.IsCandidate =
false;
309 Info.OneUser =
false;
310 Info.MultiUsers =
false;
311 Info.LastADRP =
nullptr;
321 if (&DefInfo != &OpInfo) {
329 assert(OpInfo.IsCandidate &&
"Expect valid state");
333 OpInfo.IsCandidate =
true;
338 OpInfo.IsCandidate =
true;
343 assert((
MI.getOpcode() == AArch64::LDRXui ||
344 MI.getOpcode() == AArch64::LDRWui) &&
345 "Expect LDRXui or LDRWui");
347 "Expected GOT relocation");
350 OpInfo.IsCandidate =
true;
355 OpInfo.IsCandidate =
true;
366 if (Info.LastADRP !=
nullptr) {
368 <<
'\t' <<
MI <<
'\t' << *Info.LastADRP);
370 ++NumADRPSimpleCandidate;
374 if (Info.IsCandidate) {
389 <<
'\t' <<
MI <<
'\t' << *Info.MI0);
391 ++NumADRSimpleCandidate;
397 <<
'\t' <<
MI <<
'\t' << *Info.MI0);
422 <<
'\t' <<
MI <<
'\t' << *Info.MI1 <<
'\t'
433 <<
'\t' <<
MI <<
'\t' << *Info.MI1 <<
'\t'
440 <<
'\t' <<
MI <<
'\t' << *Info.MI1 <<
'\t'
447 <<
'\t' <<
MI <<
'\t' << *Info.MI1 <<
'\t'
454 <<
'\t' <<
MI <<
'\t' << *Info.MI0);
478 if (MO.isRegMask()) {
479 const uint32_t *RegMask = MO.getRegMask();
486 if (!MO.isReg() || !MO.isDef())
497 if (!MO.isReg() || !MO.readsReg())
507 if (UsesSeen.
insert(Idx).second)
514void runAArch64CollectLOH(MachineFunction &MF) {
515 LLVM_DEBUG(
dbgs() <<
"********** AArch64 Collect LOH **********\n"
516 <<
"Looking in function " << MF.
getName() <<
'\n');
519 AArch64FunctionInfo &AFI = *MF.
getInfo<AArch64FunctionInfo>();
520 for (
const MachineBasicBlock &
MBB : MF) {
522 memset(LOHInfos, 0,
sizeof(LOHInfos));
525 for (
const auto &LI : Succ->liveins()) {
528 LOHInfos[RegIdx].
OneUser =
true;
534 for (
const MachineInstr &
MI :
536 unsigned Opcode =
MI.getOpcode();
538 case AArch64::ADDXri:
539 case AArch64::LDRXui:
540 case AArch64::LDRWui:
542 const MachineOperand &
Def =
MI.getOperand(0);
543 const MachineOperand &
Op =
MI.getOperand(1);
544 assert(
Def.isReg() &&
Def.isDef() &&
"Expected reg def");
545 assert(
Op.isReg() &&
Op.isUse() &&
"Expected reg use");
548 if (DefIdx >= 0 &&
OpIdx >= 0 &&
554 const MachineOperand &Op0 =
MI.getOperand(0);
567struct AArch64CollectLOHLegacy :
public MachineFunctionPass {
569 AArch64CollectLOHLegacy() : MachineFunctionPass(
ID) {}
571 bool runOnMachineFunction(MachineFunction &MF)
override {
574 runAArch64CollectLOH(MF);
580 MachineFunctionProperties getRequiredProperties()
const override {
581 return MachineFunctionProperties().setNoVRegs();
586 void getAnalysisUsage(AnalysisUsage &AU)
const override {
592char AArch64CollectLOHLegacy::ID = 0;
602 runAArch64CollectLOH(MF);
609 return new AArch64CollectLOHLegacy();
static int mapRegToGPRIndex(MCRegister Reg)
Map register number to index from 0-30.
#define AARCH64_COLLECT_LOH_NAME
static bool handleMiddleInst(const MachineInstr &MI, LOHInfo &DefInfo, LOHInfo &OpInfo)
Update state Info given that MI is possibly the middle instruction of an LOH involving 3 instructions...
static bool areInstructionsConsecutive(const MachineInstr *First, const MachineInstr *Second)
Returns true if there are no non-debug instructions between First and Second.
static const unsigned N_GPR_REGS
Number of GPR registers tracked by mapRegToGPRIndex()
static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO)
Check whether the given instruction can the end of a LOH chain involving a store.
static bool supportLoadFromLiteral(const MachineInstr &MI)
Check whether the given instruction can load a literal.
static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI, LOHInfo &Info, LOHInfo *LOHInfos)
Update state when seeing and ADRP instruction.
static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg, LOHInfo *LOHInfos)
static void handleClobber(LOHInfo &Info)
Update state Info given the tracked register is clobbered.
static bool canDefBePartOfLOH(const MachineInstr &MI)
Answer the following question: Can Def be one of the definition involved in a part of a LOH?
static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos)
static void handleUse(const MachineInstr &MI, const MachineOperand &MO, LOHInfo &Info)
Update state Info given MI uses the tracked register.
static bool canAddBePartOfLOH(const MachineInstr &MI)
static bool isCandidateLoad(const MachineInstr &MI)
Check whether the given instruction can be the end of a LOH chain involving a load.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
void addLOHDirective(MCLOHType Kind, MILOHArgs Args)
Add a LOH directive of this Kind and this Args.
void setPreservesAll()
Set by analyses that do not transform their input at all.
FunctionPass class - This class is used to implement most global optimizations.
Wrapper class representing physical registers. Should be passed by value.
reverse_instr_iterator instr_rbegin()
reverse_instr_iterator instr_rend()
iterator_range< succ_iterator > successors()
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
Register getReg() const
getReg - Returns the register number.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAArch64CollectLOHPass()
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
MCLOHType
Linker Optimization Hint Type.
@ MCLOH_AdrpAddLdr
Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
@ MCLOH_AdrpLdrGotStr
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
@ MCLOH_AdrpLdrGotLdr
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
@ MCLOH_AdrpLdrGot
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
@ MCLOH_AdrpLdr
Adrp _v@PAGE -> Ldr _v@PAGEOFF.
@ MCLOH_AdrpAdd
Adrp _v@PAGE -> Add _v@PAGEOFF.
@ MCLOH_AdrpAddStr
Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
@ MCLOH_AdrpAdrp
Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
DWARFExpression::Operation Op
State tracked per register.
MCLOHType Type
"Best" type of LOH possible.
unsigned IsCandidate
Possible LOH candidate.
unsigned OneUser
Found exactly one user (yet).
const MachineInstr * LastADRP
Last ADRP in same register.
const MachineInstr * MI1
Second instruction involved in the LOH (if any).
const MachineInstr * MI0
First instruction involved in the LOH.
unsigned MultiUsers
Found multiple users.