LLVM: lib/Target/AArch64/AArch64CollectLOH.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
111using namespace llvm;
112
113#define DEBUG_TYPE "aarch64-collect-loh"
114
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");
123
124#define AARCH64_COLLECT_LOH_NAME "AArch64 Collect Linker Optimization Hint (LOH)"
125
126namespace {
127
129 static char ID;
131
133
136 }
137
139
140 void getAnalysisUsage(AnalysisUsage &AU) const override {
143 }
144};
145
146char AArch64CollectLOH::ID = 0;
147
148}
149
152
154
155 switch (MI.getOperand(2).getType()) {
156 default:
157 return false;
158 case MachineOperand::MO_GlobalAddress:
159 case MachineOperand::MO_JumpTableIndex:
160 case MachineOperand::MO_ConstantPoolIndex:
161 case MachineOperand::MO_BlockAddress:
162 return true;
163 }
164}
165
166
167
169
170 switch (MI.getOpcode()) {
171 default:
172 return false;
173 case AArch64::ADRP:
174 return true;
175 case AArch64::ADDXri:
176 return canAddBePartOfLOH(MI);
177 case AArch64::LDRXui:
178 case AArch64::LDRWui:
179
180 switch (MI.getOperand(2).getType()) {
181 default:
182 return false;
185 }
186 }
187}
188
189
190
192 switch (MI.getOpcode()) {
193 default:
194 return false;
195 case AArch64::STRBBui:
196 case AArch64::STRHHui:
197 case AArch64::STRBui:
198 case AArch64::STRHui:
199 case AArch64::STRWui:
200 case AArch64::STRXui:
201 case AArch64::STRSui:
202 case AArch64::STRDui:
203 case AArch64::STRQui:
204
205
206
207
209 MI.getOperand(0).getReg() != MI.getOperand(1).getReg();
210 }
211}
212
213
214
216 switch (MI.getOpcode()) {
217 default:
218 return false;
219 case AArch64::LDRSBWui:
220 case AArch64::LDRSBXui:
221 case AArch64::LDRSHWui:
222 case AArch64::LDRSHXui:
223 case AArch64::LDRSWui:
224 case AArch64::LDRBui:
225 case AArch64::LDRHui:
226 case AArch64::LDRWui:
227 case AArch64::LDRXui:
228 case AArch64::LDRSui:
229 case AArch64::LDRDui:
230 case AArch64::LDRQui:
232 }
233}
234
235
237 switch (MI.getOpcode()) {
238 default:
239 return false;
240 case AArch64::LDRSWui:
241 case AArch64::LDRWui:
242 case AArch64::LDRXui:
243 case AArch64::LDRSui:
244 case AArch64::LDRDui:
245 case AArch64::LDRQui:
246 return true;
247 }
248}
249
250
251
254 auto It = First->getIterator();
255 auto EndIt = First->getParent()->instr_end();
256 if (It == EndIt)
257 return false;
259}
260
261
263
265 static_assert(AArch64::X28 - AArch64::X0 + 3 == N_GPR_REGS, "Number of GPRs");
266 static_assert(AArch64::W30 - AArch64::W0 + 1 == N_GPR_REGS, "Number of GPRs");
267 if (AArch64::X0 <= Reg && Reg <= AArch64::X28)
268 return Reg - AArch64::X0;
269 if (AArch64::W0 <= Reg && Reg <= AArch64::W30)
270 return Reg - AArch64::W0;
271
272
273 if (Reg == AArch64::FP)
274 return 29;
275 if (Reg == AArch64::LR)
276 return 30;
277 return -1;
278}
279
280
281
282
296
297
300
301 if (Info.MultiUsers || Info.OneUser) {
302 Info.IsCandidate = false;
303 Info.MultiUsers = true;
304 return;
305 }
306 Info.OneUser = true;
307
308
311 Info.IsCandidate = true;
313
314
317 Info.IsCandidate = true;
319 Info.MI1 = nullptr;
320 } else if (MI.getOpcode() == AArch64::ADDXri) {
321 Info.Type = MCLOH_AdrpAdd;
322 Info.IsCandidate = true;
323 Info.MI0 = &MI;
324 } else if ((MI.getOpcode() == AArch64::LDRXui ||
325 MI.getOpcode() == AArch64::LDRWui) &&
327 Info.Type = MCLOH_AdrpLdrGot;
328 Info.IsCandidate = true;
329 Info.MI0 = &MI;
330 }
331}
332
333
335 Info.IsCandidate = false;
336 Info.OneUser = false;
337 Info.MultiUsers = false;
338 Info.LastADRP = nullptr;
339}
340
341
342
346 return false;
347
348 if (&DefInfo != &OpInfo) {
349 OpInfo = DefInfo;
350
352 } else
354
355
356 assert(OpInfo.IsCandidate && "Expect valid state");
357 if (MI.getOpcode() == AArch64::ADDXri && canAddBePartOfLOH(MI)) {
360 OpInfo.IsCandidate = true;
361 OpInfo.MI1 = &MI;
362 return true;
363 } else if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
365 OpInfo.IsCandidate = true;
366 OpInfo.MI1 = &MI;
367 return true;
368 }
369 } else {
370 assert((MI.getOpcode() == AArch64::LDRXui ||
371 MI.getOpcode() == AArch64::LDRWui) &&
372 "Expect LDRXui or LDRWui");
374 "Expected GOT relocation");
375 if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
377 OpInfo.IsCandidate = true;
378 OpInfo.MI1 = &MI;
379 return true;
382 OpInfo.IsCandidate = true;
383 OpInfo.MI1 = &MI;
384 return true;
385 }
386 }
387 return false;
388}
389
390
393 if (Info.LastADRP != nullptr) {
395 << '\t' << MI << '\t' << *Info.LastADRP);
397 ++NumADRPSimpleCandidate;
398 }
399
400
401 if (Info.IsCandidate) {
402 switch (Info.Type) {
404
405
406
407
408
414 break;
416 << '\t' << MI << '\t' << *Info.MI0);
418 ++NumADRSimpleCandidate;
419 break;
420 }
424 << '\t' << MI << '\t' << *Info.MI0);
426 ++NumADRPToLDR;
427 }
428 break;
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
447 break;
449 << '\t' << MI << '\t' << *Info.MI1 << '\t'
450 << *Info.MI0);
452 ++NumADDToLDR;
453 break;
455 if (.MI1)
456 break;
458 break;
460 << '\t' << MI << '\t' << *Info.MI1 << '\t'
461 << *Info.MI0);
463 ++NumADDToSTR;
464 break;
467 << '\t' << MI << '\t' << *Info.MI1 << '\t'
468 << *Info.MI0);
470 ++NumLDRToLDR;
471 break;
474 << '\t' << MI << '\t' << *Info.MI1 << '\t'
475 << *Info.MI0);
477 ++NumLDRToSTR;
478 break;
481 << '\t' << MI << '\t' << *Info.MI0);
483 break;
485 llvm_unreachable("MCLOH_AdrpAdrp not used in state machine");
486 }
487 }
488
491}
492
496 return;
498 if (Idx >= 0)
500}
501
503
505 if (MO.isRegMask()) {
506 const uint32_t *RegMask = MO.getRegMask();
511 continue;
512 }
513 if (!MO.isReg() || !MO.isDef())
514 continue;
516 if (Idx < 0)
517 continue;
519 }
520
521
524 if (!MO.isReg() || !MO.readsReg())
525 continue;
527 if (Idx < 0)
528 continue;
529
530
531
532
533
534 if (UsesSeen.insert(Idx).second)
536 }
537}
538
539bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
541 return false;
542
543 LLVM_DEBUG(dbgs() << "********** AArch64 Collect LOH **********\n"
544 << "Looking in function " << MF.getName() << '\n');
545
547 AArch64FunctionInfo &AFI = *MF.getInfo();
548 for (const MachineBasicBlock &MBB : MF) {
549
550 memset(LOHInfos, 0, sizeof(LOHInfos));
551
552 for (const MachineBasicBlock *Succ : MBB.successors()) {
553 for (const auto &LI : Succ->liveins()) {
555 if (RegIdx >= 0)
556 LOHInfos[RegIdx].OneUser = true;
557 }
558 }
559
560
561
562 for (const MachineInstr &MI :
564 unsigned Opcode = MI.getOpcode();
565 switch (Opcode) {
566 case AArch64::ADDXri:
567 case AArch64::LDRXui:
568 case AArch64::LDRWui:
570 const MachineOperand &Def = MI.getOperand(0);
571 const MachineOperand &Op = MI.getOperand(1);
572 assert(Def.isReg() && Def.isDef() && "Expected reg def");
573 assert(Op.isReg() && Op.isUse() && "Expected reg use");
576 if (DefIdx >= 0 && OpIdx >= 0 &&
578 continue;
579 }
580 break;
581 case AArch64::ADRP:
582 const MachineOperand &Op0 = MI.getOperand(0);
584 if (Idx >= 0) {
585 handleADRP(MI, AFI, LOHInfos[Idx], LOHInfos);
586 continue;
587 }
588 break;
589 }
591 }
592 }
593
594
595 return false;
596}
597
599 return new AArch64CollectLOH();
600}
static int mapRegToGPRIndex(MCRegister Reg)
Map register number to index from 0-30.
Definition AArch64CollectLOH.cpp:264
#define AARCH64_COLLECT_LOH_NAME
Definition AArch64CollectLOH.cpp:124
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...
Definition AArch64CollectLOH.cpp:343
static bool areInstructionsConsecutive(const MachineInstr *First, const MachineInstr *Second)
Returns true if there are no non-debug instructions between First and Second.
Definition AArch64CollectLOH.cpp:252
static const unsigned N_GPR_REGS
Number of GPR registers tracked by mapRegToGPRIndex()
Definition AArch64CollectLOH.cpp:262
static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO)
Check whether the given instruction can the end of a LOH chain involving a store.
Definition AArch64CollectLOH.cpp:191
static bool supportLoadFromLiteral(const MachineInstr &MI)
Check whether the given instruction can load a literal.
Definition AArch64CollectLOH.cpp:236
static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI, LOHInfo &Info, LOHInfo *LOHInfos)
Update state when seeing and ADRP instruction.
Definition AArch64CollectLOH.cpp:391
static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg, LOHInfo *LOHInfos)
Definition AArch64CollectLOH.cpp:493
static void handleClobber(LOHInfo &Info)
Update state Info given the tracked register is clobbered.
Definition AArch64CollectLOH.cpp:334
static bool canDefBePartOfLOH(const MachineInstr &MI)
Answer the following question: Can Def be one of the definition involved in a part of a LOH?
Definition AArch64CollectLOH.cpp:168
static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos)
Definition AArch64CollectLOH.cpp:502
static void handleUse(const MachineInstr &MI, const MachineOperand &MO, LOHInfo &Info)
Update state Info given MI uses the tracked register.
Definition AArch64CollectLOH.cpp:298
static bool isCandidateLoad(const MachineInstr &MI)
Check whether the given instruction can be the end of a LOH chain involving a load.
Definition AArch64CollectLOH.cpp:215
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
#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.
Represent the analysis usage information of a pass.
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()
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.
Properties which a MachineFunction may have at a given point in time.
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_GlobalAddress
Address of a global value.
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.
StringRef - Represent a constant reference to a string, i.e.
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAArch64CollectLOHPass()
Definition AArch64CollectLOH.cpp:598
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.
Definition AArch64CollectLOH.cpp:283
MCLOHType Type
"Best" type of LOH possible.
Definition AArch64CollectLOH.cpp:284
unsigned IsCandidate
Possible LOH candidate.
Definition AArch64CollectLOH.cpp:286
unsigned OneUser
Found exactly one user (yet).
Definition AArch64CollectLOH.cpp:288
const MachineInstr * LastADRP
Last ADRP in same register.
Definition AArch64CollectLOH.cpp:294
const MachineInstr * MI1
Second instruction involved in the LOH (if any).
Definition AArch64CollectLOH.cpp:292
const MachineInstr * MI0
First instruction involved in the LOH.
Definition AArch64CollectLOH.cpp:291
unsigned MultiUsers
Found multiple users.
Definition AArch64CollectLOH.cpp:290