LLVM 22.0.0git
AArch64CollectLOH.cpp
Go to the documentation of this file.
1//===---------- AArch64CollectLOH.cpp - AArch64 collect LOH pass --*- C++ -*-=//
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//
9// This file contains a pass that collect the Linker Optimization Hint (LOH).
10// This pass should be run at the very end of the compilation flow, just before
11// assembly printer.
12// To be useful for the linker, the LOH must be printed into the assembly file.
13//
14// A LOH describes a sequence of instructions that may be optimized by the
15// linker.
16// This same sequence cannot be optimized by the compiler because some of
17// the information will be known at link time.
18// For instance, consider the following sequence:
19// L1: adrp xA, sym@PAGE
20// L2: add xB, xA, sym@PAGEOFF
21// L3: ldr xC, [xB, #imm]
22// This sequence can be turned into:
23// A literal load if sym@PAGE + sym@PAGEOFF + #imm - address(L3) is < 1MB:
24// L3: ldr xC, sym+#imm
25// It may also be turned into either the following more efficient
26// code sequences:
27// - If sym@PAGEOFF + #imm fits the encoding space of L3.
28// L1: adrp xA, sym@PAGE
29// L3: ldr xC, [xB, sym@PAGEOFF + #imm]
30// - If sym@PAGE + sym@PAGEOFF - address(L1) < 1MB:
31// L1: adr xA, sym
32// L3: ldr xC, [xB, #imm]
33//
34// To be valid a LOH must meet all the requirements needed by all the related
35// possible linker transformations.
36// For instance, using the running example, the constraints to emit
37// ".loh AdrpAddLdr" are:
38// - L1, L2, and L3 instructions are of the expected type, i.e.,
39// respectively ADRP, ADD (immediate), and LD.
40// - The result of L1 is used only by L2.
41// - The register argument (xA) used in the ADD instruction is defined
42// only by L1.
43// - The result of L2 is used only by L3.
44// - The base address (xB) in L3 is defined only L2.
45// - The ADRP in L1 and the ADD in L2 must reference the same symbol using
46// @PAGE/@PAGEOFF with no additional constants
47//
48// Currently supported LOHs are:
49// * So called non-ADRP-related:
50// - .loh AdrpAddLdr L1, L2, L3:
51// L1: adrp xA, sym@PAGE
52// L2: add xB, xA, sym@PAGEOFF
53// L3: ldr xC, [xB, #imm]
54// - .loh AdrpLdrGotLdr L1, L2, L3:
55// L1: adrp xA, sym@GOTPAGE
56// L2: ldr xB, [xA, sym@GOTPAGEOFF]
57// L3: ldr xC, [xB, #imm]
58// - .loh AdrpLdr L1, L3:
59// L1: adrp xA, sym@PAGE
60// L3: ldr xC, [xA, sym@PAGEOFF]
61// - .loh AdrpAddStr L1, L2, L3:
62// L1: adrp xA, sym@PAGE
63// L2: add xB, xA, sym@PAGEOFF
64// L3: str xC, [xB, #imm]
65// - .loh AdrpLdrGotStr L1, L2, L3:
66// L1: adrp xA, sym@GOTPAGE
67// L2: ldr xB, [xA, sym@GOTPAGEOFF]
68// L3: str xC, [xB, #imm]
69// - .loh AdrpAdd L1, L2:
70// L1: adrp xA, sym@PAGE
71// L2: add xB, xA, sym@PAGEOFF
72// For all these LOHs, L1, L2, L3 form a simple chain:
73// L1 result is used only by L2 and L2 result by L3.
74// L3 LOH-related argument is defined only by L2 and L2 LOH-related argument
75// by L1.
76// All these LOHs aim at using more efficient load/store patterns by folding
77// some instructions used to compute the address directly into the load/store.
78//
79// * So called ADRP-related:
80// - .loh AdrpAdrp L2, L1:
81// L2: ADRP xA, sym1@PAGE
82// L1: ADRP xA, sym2@PAGE
83// L2 dominates L1 and xA is not redifined between L2 and L1
84// This LOH aims at getting rid of redundant ADRP instructions.
85//
86// The overall design for emitting the LOHs is:
87// 1. AArch64CollectLOH (this pass) records the LOHs in the AArch64FunctionInfo.
88// 2. AArch64AsmPrinter reads the LOHs from AArch64FunctionInfo and it:
89// 1. Associates them a label.
90// 2. Emits them in a MCStreamer (EmitLOHDirective).
91// - The MCMachOStreamer records them into the MCAssembler.
92// - The MCAsmStreamer prints them.
93// - Other MCStreamers ignore them.
94// 3. Closes the MCStreamer:
95// - The MachObjectWriter gets them from the MCAssembler and writes
96// them in the object file.
97// - Other ObjectWriters ignore them.
98//===----------------------------------------------------------------------===//
99
100#include "AArch64.h"
102#include "llvm/ADT/SmallSet.h"
103#include "llvm/ADT/Statistic.h"
108#include "llvm/Support/Debug.h"
111using namespace llvm;
112
113#define DEBUG_TYPE "aarch64-collect-loh"
114
115STATISTIC(NumADRPSimpleCandidate,
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
128struct AArch64CollectLOH : public MachineFunctionPass {
129 static char ID;
130 AArch64CollectLOH() : MachineFunctionPass(ID) {}
131
132 bool runOnMachineFunction(MachineFunction &MF) override;
133
135 return MachineFunctionProperties().setNoVRegs();
136 }
137
138 StringRef getPassName() const override { return AARCH64_COLLECT_LOH_NAME; }
139
140 void getAnalysisUsage(AnalysisUsage &AU) const override {
142 AU.setPreservesAll();
143 }
144};
145
146char AArch64CollectLOH::ID = 0;
147
148} // end anonymous namespace.
149
150INITIALIZE_PASS(AArch64CollectLOH, "aarch64-collect-loh",
151 AARCH64_COLLECT_LOH_NAME, false, false)
152
153static bool canAddBePartOfLOH(const MachineInstr &MI) {
154 // Check immediate to see if the immediate is an address.
155 switch (MI.getOperand(2).getType()) {
156 default:
157 return false;
162 return true;
163 }
164}
165
166/// Answer the following question: Can Def be one of the definition
167/// involved in a part of a LOH?
168static bool canDefBePartOfLOH(const MachineInstr &MI) {
169 // Accept ADRP, ADDLow and LOADGot.
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 // Check immediate to see if the immediate is an address.
180 switch (MI.getOperand(2).getType()) {
181 default:
182 return false;
184 return MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT;
185 }
186 }
187}
188
189/// Check whether the given instruction can the end of a LOH chain involving a
190/// store.
191static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO) {
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 // We can only optimize the index operand.
205 // In case we have str xA, [xA, #imm], this is two different uses
206 // of xA and we cannot fold, otherwise the xA stored may be wrong,
207 // even if #imm == 0.
208 return MO.getOperandNo() == 1 &&
209 MI.getOperand(0).getReg() != MI.getOperand(1).getReg();
210 }
211}
212
213/// Check whether the given instruction can be the end of a LOH chain
214/// involving a load.
215static bool isCandidateLoad(const MachineInstr &MI) {
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:
231 return !(MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT);
232 }
233}
234
235/// Check whether the given instruction can load a literal.
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/// Returns \p true if there are no non-debug instructions between \p First and
251/// \p Second
253 const MachineInstr *Second) {
254 auto It = First->getIterator();
255 auto EndIt = First->getParent()->instr_end();
256 if (It == EndIt)
257 return false;
258 return next_nodbg(It, EndIt) == Second->getIterator();
259}
260
261/// Number of GPR registers tracked by mapRegToGPRIndex()
262static const unsigned N_GPR_REGS = 31;
263/// Map register number to index from 0-30.
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 // TableGen gives "FP" and "LR" an index not adjacent to X28 so we have to
272 // handle them as special cases.
273 if (Reg == AArch64::FP)
274 return 29;
275 if (Reg == AArch64::LR)
276 return 30;
277 return -1;
278}
279
280/// State tracked per register.
281/// The main algorithm walks backwards over a basic block maintaining this
282/// datastructure for each tracked general purpose register.
283struct LOHInfo {
284 MCLOHType Type : 8; ///< "Best" type of LOH possible.
286 unsigned IsCandidate : 1; ///< Possible LOH candidate.
288 unsigned OneUser : 1; ///< Found exactly one user (yet).
290 unsigned MultiUsers : 1; ///< Found multiple users.
291 const MachineInstr *MI0; ///< First instruction involved in the LOH.
292 const MachineInstr *MI1; ///< Second instruction involved in the LOH
293 /// (if any).
294 const MachineInstr *LastADRP; ///< Last ADRP in same register.
295};
296
297/// Update state \p Info given \p MI uses the tracked register.
299 LOHInfo &Info) {
300 // We have multiple uses if we already found one before.
301 if (Info.MultiUsers || Info.OneUser) {
302 Info.IsCandidate = false;
303 Info.MultiUsers = true;
304 return;
305 }
306 Info.OneUser = true;
307
308 // Start new LOHInfo if applicable.
309 if (isCandidateLoad(MI)) {
310 Info.Type = MCLOH_AdrpLdr;
311 Info.IsCandidate = true;
312 Info.MI0 = &MI;
313 // Note that even this is AdrpLdr now, we can switch to a Ldr variant
314 // later.
315 } else if (isCandidateStore(MI, MO)) {
316 Info.Type = MCLOH_AdrpAddStr;
317 Info.IsCandidate = true;
318 Info.MI0 = &MI;
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) &&
326 MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) {
327 Info.Type = MCLOH_AdrpLdrGot;
328 Info.IsCandidate = true;
329 Info.MI0 = &MI;
330 }
331}
332
333/// Update state \p Info given the tracked register is clobbered.
334static void handleClobber(LOHInfo &Info) {
335 Info.IsCandidate = false;
336 Info.OneUser = false;
337 Info.MultiUsers = false;
338 Info.LastADRP = nullptr;
339}
340
341/// Update state \p Info given that \p MI is possibly the middle instruction
342/// of an LOH involving 3 instructions.
343static bool handleMiddleInst(const MachineInstr &MI, LOHInfo &DefInfo,
344 LOHInfo &OpInfo) {
345 if (!DefInfo.IsCandidate || (&DefInfo != &OpInfo && OpInfo.OneUser))
346 return false;
347 // Copy LOHInfo for dest register to LOHInfo for source register.
348 if (&DefInfo != &OpInfo) {
349 OpInfo = DefInfo;
350 // Invalidate \p DefInfo because we track it in \p OpInfo now.
351 handleClobber(DefInfo);
352 } else
353 DefInfo.LastADRP = nullptr;
354
355 // Advance state machine.
356 assert(OpInfo.IsCandidate && "Expect valid state");
357 if (MI.getOpcode() == AArch64::ADDXri && canAddBePartOfLOH(MI)) {
358 if (OpInfo.Type == MCLOH_AdrpLdr) {
359 OpInfo.Type = MCLOH_AdrpAddLdr;
360 OpInfo.IsCandidate = true;
361 OpInfo.MI1 = &MI;
362 return true;
363 } else if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
364 OpInfo.Type = MCLOH_AdrpAddStr;
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");
373 assert((MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) &&
374 "Expected GOT relocation");
375 if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
376 OpInfo.Type = MCLOH_AdrpLdrGotStr;
377 OpInfo.IsCandidate = true;
378 OpInfo.MI1 = &MI;
379 return true;
380 } else if (OpInfo.Type == MCLOH_AdrpLdr) {
381 OpInfo.Type = MCLOH_AdrpLdrGotLdr;
382 OpInfo.IsCandidate = true;
383 OpInfo.MI1 = &MI;
384 return true;
385 }
386 }
387 return false;
388}
389
390/// Update state when seeing and ADRP instruction.
392 LOHInfo &Info, LOHInfo *LOHInfos) {
393 if (Info.LastADRP != nullptr) {
394 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdrp:\n"
395 << '\t' << MI << '\t' << *Info.LastADRP);
396 AFI.addLOHDirective(MCLOH_AdrpAdrp, {&MI, Info.LastADRP});
397 ++NumADRPSimpleCandidate;
398 }
399
400 // Produce LOH directive if possible.
401 if (Info.IsCandidate) {
402 switch (Info.Type) {
403 case MCLOH_AdrpAdd: {
404 // ADRPs and ADDs for this candidate may be split apart if using
405 // GlobalISel instead of pseudo-expanded. If that happens, the
406 // def register of the ADD may have a use in between. Adding an LOH in
407 // this case can cause the linker to rewrite the ADRP to write to that
408 // register, clobbering the use.
409 const MachineInstr *AddMI = Info.MI0;
410 int DefIdx = mapRegToGPRIndex(MI.getOperand(0).getReg());
411 int OpIdx = mapRegToGPRIndex(AddMI->getOperand(0).getReg());
412 LOHInfo DefInfo = LOHInfos[OpIdx];
413 if (DefIdx != OpIdx && (DefInfo.OneUser || DefInfo.MultiUsers))
414 break;
415 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdd:\n"
416 << '\t' << MI << '\t' << *Info.MI0);
417 AFI.addLOHDirective(MCLOH_AdrpAdd, {&MI, Info.MI0});
418 ++NumADRSimpleCandidate;
419 break;
420 }
421 case MCLOH_AdrpLdr:
422 if (supportLoadFromLiteral(*Info.MI0)) {
423 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdr:\n"
424 << '\t' << MI << '\t' << *Info.MI0);
425 AFI.addLOHDirective(MCLOH_AdrpLdr, {&MI, Info.MI0});
426 ++NumADRPToLDR;
427 }
428 break;
429 case MCLOH_AdrpAddLdr:
430 // There is a possibility that the linker may try to rewrite:
431 // adrp x0, @sym@PAGE
432 // add x1, x0, @sym@PAGEOFF
433 // [x0 = some other def]
434 // ldr x2, [x1]
435 // ...into...
436 // adrp x0, @sym
437 // nop
438 // [x0 = some other def]
439 // ldr x2, [x0]
440 // ...if the offset to the symbol won't fit within a literal load.
441 // This causes the load to use the result of the adrp, which in this
442 // case has already been clobbered.
443 // FIXME: Implement proper liveness tracking for all registers. For now,
444 // don't emit the LOH if there are any instructions between the add and
445 // the ldr.
446 if (!areInstructionsConsecutive(Info.MI1, Info.MI0))
447 break;
448 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddLdr:\n"
449 << '\t' << MI << '\t' << *Info.MI1 << '\t'
450 << *Info.MI0);
451 AFI.addLOHDirective(MCLOH_AdrpAddLdr, {&MI, Info.MI1, Info.MI0});
452 ++NumADDToLDR;
453 break;
454 case MCLOH_AdrpAddStr:
455 if (!Info.MI1)
456 break;
457 if (!areInstructionsConsecutive(Info.MI1, Info.MI0))
458 break;
459 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddStr:\n"
460 << '\t' << MI << '\t' << *Info.MI1 << '\t'
461 << *Info.MI0);
462 AFI.addLOHDirective(MCLOH_AdrpAddStr, {&MI, Info.MI1, Info.MI0});
463 ++NumADDToSTR;
464 break;
466 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotLdr:\n"
467 << '\t' << MI << '\t' << *Info.MI1 << '\t'
468 << *Info.MI0);
470 ++NumLDRToLDR;
471 break;
473 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotStr:\n"
474 << '\t' << MI << '\t' << *Info.MI1 << '\t'
475 << *Info.MI0);
477 ++NumLDRToSTR;
478 break;
479 case MCLOH_AdrpLdrGot:
480 LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGot:\n"
481 << '\t' << MI << '\t' << *Info.MI0);
483 break;
484 case MCLOH_AdrpAdrp:
485 llvm_unreachable("MCLOH_AdrpAdrp not used in state machine");
486 }
487 }
488
490 Info.LastADRP = &MI;
491}
492
493static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg,
494 LOHInfo *LOHInfos) {
495 if (!MachineOperand::clobbersPhysReg(RegMask, Reg))
496 return;
497 int Idx = mapRegToGPRIndex(Reg);
498 if (Idx >= 0)
499 handleClobber(LOHInfos[Idx]);
500}
501
502static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos) {
503 // Handle defs and regmasks.
504 for (const MachineOperand &MO : MI.operands()) {
505 if (MO.isRegMask()) {
506 const uint32_t *RegMask = MO.getRegMask();
507 for (MCPhysReg Reg : AArch64::GPR32RegClass)
508 handleRegMaskClobber(RegMask, Reg, LOHInfos);
509 for (MCPhysReg Reg : AArch64::GPR64RegClass)
510 handleRegMaskClobber(RegMask, Reg, LOHInfos);
511 continue;
512 }
513 if (!MO.isReg() || !MO.isDef())
514 continue;
515 int Idx = mapRegToGPRIndex(MO.getReg());
516 if (Idx < 0)
517 continue;
518 handleClobber(LOHInfos[Idx]);
519 }
520 // Handle uses.
521
522 SmallSet<int, 4> UsesSeen;
523 for (const MachineOperand &MO : MI.uses()) {
524 if (!MO.isReg() || !MO.readsReg())
525 continue;
526 int Idx = mapRegToGPRIndex(MO.getReg());
527 if (Idx < 0)
528 continue;
529
530 // Multiple uses of the same register within a single instruction don't
531 // count as MultiUser or block optimization. This is especially important on
532 // arm64_32, where any memory operation is likely to be an explicit use of
533 // xN and an implicit use of wN (the base address register).
534 if (UsesSeen.insert(Idx).second)
535 handleUse(MI, MO, LOHInfos[Idx]);
536 }
537}
538
539bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
540 if (skipFunction(MF.getFunction()))
541 return false;
542
543 LLVM_DEBUG(dbgs() << "********** AArch64 Collect LOH **********\n"
544 << "Looking in function " << MF.getName() << '\n');
545
546 LOHInfo LOHInfos[N_GPR_REGS];
548 for (const MachineBasicBlock &MBB : MF) {
549 // Reset register tracking state.
550 memset(LOHInfos, 0, sizeof(LOHInfos));
551 // Live-out registers are used.
552 for (const MachineBasicBlock *Succ : MBB.successors()) {
553 for (const auto &LI : Succ->liveins()) {
554 int RegIdx = mapRegToGPRIndex(LI.PhysReg);
555 if (RegIdx >= 0)
556 LOHInfos[RegIdx].OneUser = true;
557 }
558 }
559
560 // Walk the basic block backwards and update the per register state machine
561 // in the process.
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:
569 if (canDefBePartOfLOH(MI)) {
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");
574 int DefIdx = mapRegToGPRIndex(Def.getReg());
575 int OpIdx = mapRegToGPRIndex(Op.getReg());
576 if (DefIdx >= 0 && OpIdx >= 0 &&
577 handleMiddleInst(MI, LOHInfos[DefIdx], LOHInfos[OpIdx]))
578 continue;
579 }
580 break;
581 case AArch64::ADRP:
582 const MachineOperand &Op0 = MI.getOperand(0);
583 int Idx = mapRegToGPRIndex(Op0.getReg());
584 if (Idx >= 0) {
585 handleADRP(MI, AFI, LOHInfos[Idx], LOHInfos);
586 continue;
587 }
588 break;
589 }
590 handleNormalInst(MI, LOHInfos);
591 }
592 }
593
594 // Return "no change": The pass only collects information.
595 return false;
596}
597
599 return new AArch64CollectLOH();
600}
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 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!")
aarch64 promote const
MachineBasicBlock & MBB
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_PREFERRED_TYPE(T)
\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.
Definition: Compiler.h:706
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
IRTranslator LLVM IR MI
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
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)
Definition: Statistic.h:167
#define LLVM_DEBUG(...)
Definition: Debug.h:119
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.
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
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.
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.
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.
Definition: MachineInstr.h:72
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:595
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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:182
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
self_iterator getIterator()
Definition: ilist_node.h:134
#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.
Definition: CallingConv.h:24
NodeAddr< DefNode * > Def
Definition: RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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.
Definition: Debug.cpp:207
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.
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.
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.