LLVM  14.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"
101 #include "AArch64InstrInfo.h"
103 #include "llvm/ADT/BitVector.h"
104 #include "llvm/ADT/DenseMap.h"
105 #include "llvm/ADT/MapVector.h"
106 #include "llvm/ADT/SmallSet.h"
107 #include "llvm/ADT/SmallVector.h"
108 #include "llvm/ADT/Statistic.h"
113 #include "llvm/Support/Debug.h"
117 using namespace llvm;
118 
119 #define DEBUG_TYPE "aarch64-collect-loh"
120 
121 STATISTIC(NumADRPSimpleCandidate,
122  "Number of simplifiable ADRP dominate by another");
123 STATISTIC(NumADDToSTR, "Number of simplifiable STR reachable by ADD");
124 STATISTIC(NumLDRToSTR, "Number of simplifiable STR reachable by LDR");
125 STATISTIC(NumADDToLDR, "Number of simplifiable LDR reachable by ADD");
126 STATISTIC(NumLDRToLDR, "Number of simplifiable LDR reachable by LDR");
127 STATISTIC(NumADRPToLDR, "Number of simplifiable LDR reachable by ADRP");
128 STATISTIC(NumADRSimpleCandidate, "Number of simplifiable ADRP + ADD");
129 
130 #define AARCH64_COLLECT_LOH_NAME "AArch64 Collect Linker Optimization Hint (LOH)"
131 
132 namespace {
133 
134 struct AArch64CollectLOH : public MachineFunctionPass {
135  static char ID;
136  AArch64CollectLOH() : MachineFunctionPass(ID) {}
137 
138  bool runOnMachineFunction(MachineFunction &MF) override;
139 
140  MachineFunctionProperties getRequiredProperties() const override {
143  }
144 
145  StringRef getPassName() const override { return AARCH64_COLLECT_LOH_NAME; }
146 
147  void getAnalysisUsage(AnalysisUsage &AU) const override {
149  AU.setPreservesAll();
150  }
151 };
152 
153 char AArch64CollectLOH::ID = 0;
154 
155 } // end anonymous namespace.
156 
157 INITIALIZE_PASS(AArch64CollectLOH, "aarch64-collect-loh",
158  AARCH64_COLLECT_LOH_NAME, false, false)
159 
160 static bool canAddBePartOfLOH(const MachineInstr &MI) {
161  // Check immediate to see if the immediate is an address.
162  switch (MI.getOperand(2).getType()) {
163  default:
164  return false;
169  return true;
170  }
171 }
172 
173 /// Answer the following question: Can Def be one of the definition
174 /// involved in a part of a LOH?
175 static bool canDefBePartOfLOH(const MachineInstr &MI) {
176  // Accept ADRP, ADDLow and LOADGot.
177  switch (MI.getOpcode()) {
178  default:
179  return false;
180  case AArch64::ADRP:
181  return true;
182  case AArch64::ADDXri:
183  return canAddBePartOfLOH(MI);
184  case AArch64::LDRXui:
185  case AArch64::LDRWui:
186  // Check immediate to see if the immediate is an address.
187  switch (MI.getOperand(2).getType()) {
188  default:
189  return false;
191  return MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT;
192  }
193  }
194 }
195 
196 /// Check whether the given instruction can the end of a LOH chain involving a
197 /// store.
198 static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO) {
199  switch (MI.getOpcode()) {
200  default:
201  return false;
202  case AArch64::STRBBui:
203  case AArch64::STRHHui:
204  case AArch64::STRBui:
205  case AArch64::STRHui:
206  case AArch64::STRWui:
207  case AArch64::STRXui:
208  case AArch64::STRSui:
209  case AArch64::STRDui:
210  case AArch64::STRQui:
211  // We can only optimize the index operand.
212  // In case we have str xA, [xA, #imm], this is two different uses
213  // of xA and we cannot fold, otherwise the xA stored may be wrong,
214  // even if #imm == 0.
215  return MI.getOperandNo(&MO) == 1 &&
216  MI.getOperand(0).getReg() != MI.getOperand(1).getReg();
217  }
218 }
219 
220 /// Check whether the given instruction can be the end of a LOH chain
221 /// involving a load.
222 static bool isCandidateLoad(const MachineInstr &MI) {
223  switch (MI.getOpcode()) {
224  default:
225  return false;
226  case AArch64::LDRSBWui:
227  case AArch64::LDRSBXui:
228  case AArch64::LDRSHWui:
229  case AArch64::LDRSHXui:
230  case AArch64::LDRSWui:
231  case AArch64::LDRBui:
232  case AArch64::LDRHui:
233  case AArch64::LDRWui:
234  case AArch64::LDRXui:
235  case AArch64::LDRSui:
236  case AArch64::LDRDui:
237  case AArch64::LDRQui:
238  return !(MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT);
239  }
240 }
241 
242 /// Check whether the given instruction can load a litteral.
244  switch (MI.getOpcode()) {
245  default:
246  return false;
247  case AArch64::LDRSWui:
248  case AArch64::LDRWui:
249  case AArch64::LDRXui:
250  case AArch64::LDRSui:
251  case AArch64::LDRDui:
252  case AArch64::LDRQui:
253  return true;
254  }
255 }
256 
257 /// Number of GPR registers traked by mapRegToGPRIndex()
258 static const unsigned N_GPR_REGS = 31;
259 /// Map register number to index from 0-30.
261  static_assert(AArch64::X28 - AArch64::X0 + 3 == N_GPR_REGS, "Number of GPRs");
262  static_assert(AArch64::W30 - AArch64::W0 + 1 == N_GPR_REGS, "Number of GPRs");
263  if (AArch64::X0 <= Reg && Reg <= AArch64::X28)
264  return Reg - AArch64::X0;
265  if (AArch64::W0 <= Reg && Reg <= AArch64::W30)
266  return Reg - AArch64::W0;
267  // TableGen gives "FP" and "LR" an index not adjacent to X28 so we have to
268  // handle them as special cases.
269  if (Reg == AArch64::FP)
270  return 29;
271  if (Reg == AArch64::LR)
272  return 30;
273  return -1;
274 }
275 
276 /// State tracked per register.
277 /// The main algorithm walks backwards over a basic block maintaining this
278 /// datastructure for each tracked general purpose register.
279 struct LOHInfo {
280  MCLOHType Type : 8; ///< "Best" type of LOH possible.
281  bool IsCandidate : 1; ///< Possible LOH candidate.
282  bool OneUser : 1; ///< Found exactly one user (yet).
283  bool MultiUsers : 1; ///< Found multiple users.
284  const MachineInstr *MI0; ///< First instruction involved in the LOH.
285  const MachineInstr *MI1; ///< Second instruction involved in the LOH
286  /// (if any).
287  const MachineInstr *LastADRP; ///< Last ADRP in same register.
288 };
289 
290 /// Update state \p Info given \p MI uses the tracked register.
291 static void handleUse(const MachineInstr &MI, const MachineOperand &MO,
292  LOHInfo &Info) {
293  // We have multiple uses if we already found one before.
294  if (Info.MultiUsers || Info.OneUser) {
295  Info.IsCandidate = false;
296  Info.MultiUsers = true;
297  return;
298  }
299  Info.OneUser = true;
300 
301  // Start new LOHInfo if applicable.
302  if (isCandidateLoad(MI)) {
303  Info.Type = MCLOH_AdrpLdr;
304  Info.IsCandidate = true;
305  Info.MI0 = &MI;
306  // Note that even this is AdrpLdr now, we can switch to a Ldr variant
307  // later.
308  } else if (isCandidateStore(MI, MO)) {
309  Info.Type = MCLOH_AdrpAddStr;
310  Info.IsCandidate = true;
311  Info.MI0 = &MI;
312  Info.MI1 = nullptr;
313  } else if (MI.getOpcode() == AArch64::ADDXri) {
314  Info.Type = MCLOH_AdrpAdd;
315  Info.IsCandidate = true;
316  Info.MI0 = &MI;
317  } else if ((MI.getOpcode() == AArch64::LDRXui ||
318  MI.getOpcode() == AArch64::LDRWui) &&
319  MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) {
320  Info.Type = MCLOH_AdrpLdrGot;
321  Info.IsCandidate = true;
322  Info.MI0 = &MI;
323  }
324 }
325 
326 /// Update state \p Info given the tracked register is clobbered.
327 static void handleClobber(LOHInfo &Info) {
328  Info.IsCandidate = false;
329  Info.OneUser = false;
330  Info.MultiUsers = false;
331  Info.LastADRP = nullptr;
332 }
333 
334 /// Update state \p Info given that \p MI is possibly the middle instruction
335 /// of an LOH involving 3 instructions.
336 static bool handleMiddleInst(const MachineInstr &MI, LOHInfo &DefInfo,
337  LOHInfo &OpInfo) {
338  if (!DefInfo.IsCandidate || (&DefInfo != &OpInfo && OpInfo.OneUser))
339  return false;
340  // Copy LOHInfo for dest register to LOHInfo for source register.
341  if (&DefInfo != &OpInfo) {
342  OpInfo = DefInfo;
343  // Invalidate \p DefInfo because we track it in \p OpInfo now.
344  handleClobber(DefInfo);
345  } else
346  DefInfo.LastADRP = nullptr;
347 
348  // Advance state machine.
349  assert(OpInfo.IsCandidate && "Expect valid state");
350  if (MI.getOpcode() == AArch64::ADDXri && canAddBePartOfLOH(MI)) {
351  if (OpInfo.Type == MCLOH_AdrpLdr) {
352  OpInfo.Type = MCLOH_AdrpAddLdr;
353  OpInfo.IsCandidate = true;
354  OpInfo.MI1 = &MI;
355  return true;
356  } else if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
357  OpInfo.Type = MCLOH_AdrpAddStr;
358  OpInfo.IsCandidate = true;
359  OpInfo.MI1 = &MI;
360  return true;
361  }
362  } else {
363  assert((MI.getOpcode() == AArch64::LDRXui ||
364  MI.getOpcode() == AArch64::LDRWui) &&
365  "Expect LDRXui or LDRWui");
366  assert((MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) &&
367  "Expected GOT relocation");
368  if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
369  OpInfo.Type = MCLOH_AdrpLdrGotStr;
370  OpInfo.IsCandidate = true;
371  OpInfo.MI1 = &MI;
372  return true;
373  } else if (OpInfo.Type == MCLOH_AdrpLdr) {
374  OpInfo.Type = MCLOH_AdrpLdrGotLdr;
375  OpInfo.IsCandidate = true;
376  OpInfo.MI1 = &MI;
377  return true;
378  }
379  }
380  return false;
381 }
382 
383 /// Update state when seeing and ADRP instruction.
385  LOHInfo &Info, LOHInfo *LOHInfos) {
386  if (Info.LastADRP != nullptr) {
387  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdrp:\n"
388  << '\t' << MI << '\t' << *Info.LastADRP);
389  AFI.addLOHDirective(MCLOH_AdrpAdrp, {&MI, Info.LastADRP});
390  ++NumADRPSimpleCandidate;
391  }
392 
393  // Produce LOH directive if possible.
394  if (Info.IsCandidate) {
395  switch (Info.Type) {
396  case MCLOH_AdrpAdd: {
397  // ADRPs and ADDs for this candidate may be split apart if using
398  // GlobalISel instead of pseudo-expanded. If that happens, the
399  // def register of the ADD may have a use in between. Adding an LOH in
400  // this case can cause the linker to rewrite the ADRP to write to that
401  // register, clobbering the use.
402  const MachineInstr *AddMI = Info.MI0;
403  int DefIdx = mapRegToGPRIndex(MI.getOperand(0).getReg());
404  int OpIdx = mapRegToGPRIndex(AddMI->getOperand(0).getReg());
405  LOHInfo DefInfo = LOHInfos[OpIdx];
406  if (DefIdx != OpIdx && (DefInfo.OneUser || DefInfo.MultiUsers))
407  break;
408  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdd:\n"
409  << '\t' << MI << '\t' << *Info.MI0);
410  AFI.addLOHDirective(MCLOH_AdrpAdd, {&MI, Info.MI0});
411  ++NumADRSimpleCandidate;
412  break;
413  }
414  case MCLOH_AdrpLdr:
415  if (supportLoadFromLiteral(*Info.MI0)) {
416  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdr:\n"
417  << '\t' << MI << '\t' << *Info.MI0);
418  AFI.addLOHDirective(MCLOH_AdrpLdr, {&MI, Info.MI0});
419  ++NumADRPToLDR;
420  }
421  break;
422  case MCLOH_AdrpAddLdr: {
423  // There is a possibility that the linker may try to rewrite:
424  // adrp x0, @sym@PAGE
425  // add x1, x0, @sym@PAGEOFF
426  // [x0 = some other def]
427  // ldr x2, [x1]
428  // ...into...
429  // adrp x0, @sym
430  // nop
431  // [x0 = some other def]
432  // ldr x2, [x0]
433  // ...if the offset to the symbol won't fit within a literal load.
434  // This causes the load to use the result of the adrp, which in this
435  // case has already been clobbered.
436  // FIXME: Implement proper liveness tracking for all registers. For now,
437  // don't emit the LOH if there are any instructions between the add and
438  // the ldr.
439  MachineInstr *AddMI = const_cast<MachineInstr *>(Info.MI1);
440  const MachineInstr *LdrMI = Info.MI0;
441  auto AddIt = MachineBasicBlock::iterator(AddMI);
442  auto EndIt = AddMI->getParent()->end();
443  if (AddMI->getIterator() == EndIt || LdrMI != &*next_nodbg(AddIt, EndIt))
444  break;
445 
446  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddLdr:\n"
447  << '\t' << MI << '\t' << *Info.MI1 << '\t'
448  << *Info.MI0);
449  AFI.addLOHDirective(MCLOH_AdrpAddLdr, {&MI, Info.MI1, Info.MI0});
450  ++NumADDToLDR;
451  break;
452  }
453  case MCLOH_AdrpAddStr:
454  if (Info.MI1 != nullptr) {
455  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddStr:\n"
456  << '\t' << MI << '\t' << *Info.MI1 << '\t'
457  << *Info.MI0);
458  AFI.addLOHDirective(MCLOH_AdrpAddStr, {&MI, Info.MI1, Info.MI0});
459  ++NumADDToSTR;
460  }
461  break;
462  case MCLOH_AdrpLdrGotLdr:
463  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotLdr:\n"
464  << '\t' << MI << '\t' << *Info.MI1 << '\t'
465  << *Info.MI0);
466  AFI.addLOHDirective(MCLOH_AdrpLdrGotLdr, {&MI, Info.MI1, Info.MI0});
467  ++NumLDRToLDR;
468  break;
469  case MCLOH_AdrpLdrGotStr:
470  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotStr:\n"
471  << '\t' << MI << '\t' << *Info.MI1 << '\t'
472  << *Info.MI0);
473  AFI.addLOHDirective(MCLOH_AdrpLdrGotStr, {&MI, Info.MI1, Info.MI0});
474  ++NumLDRToSTR;
475  break;
476  case MCLOH_AdrpLdrGot:
477  LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGot:\n"
478  << '\t' << MI << '\t' << *Info.MI0);
479  AFI.addLOHDirective(MCLOH_AdrpLdrGot, {&MI, Info.MI0});
480  break;
481  case MCLOH_AdrpAdrp:
482  llvm_unreachable("MCLOH_AdrpAdrp not used in state machine");
483  }
484  }
485 
487  Info.LastADRP = &MI;
488 }
489 
490 static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg,
491  LOHInfo *LOHInfos) {
492  if (!MachineOperand::clobbersPhysReg(RegMask, Reg))
493  return;
494  int Idx = mapRegToGPRIndex(Reg);
495  if (Idx >= 0)
496  handleClobber(LOHInfos[Idx]);
497 }
498 
499 static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos) {
500  // Handle defs and regmasks.
501  for (const MachineOperand &MO : MI.operands()) {
502  if (MO.isRegMask()) {
503  const uint32_t *RegMask = MO.getRegMask();
504  for (MCPhysReg Reg : AArch64::GPR32RegClass)
505  handleRegMaskClobber(RegMask, Reg, LOHInfos);
506  for (MCPhysReg Reg : AArch64::GPR64RegClass)
507  handleRegMaskClobber(RegMask, Reg, LOHInfos);
508  continue;
509  }
510  if (!MO.isReg() || !MO.isDef())
511  continue;
512  int Idx = mapRegToGPRIndex(MO.getReg());
513  if (Idx < 0)
514  continue;
515  handleClobber(LOHInfos[Idx]);
516  }
517  // Handle uses.
518 
519  SmallSet<int, 4> UsesSeen;
520  for (const MachineOperand &MO : MI.uses()) {
521  if (!MO.isReg() || !MO.readsReg())
522  continue;
523  int Idx = mapRegToGPRIndex(MO.getReg());
524  if (Idx < 0)
525  continue;
526 
527  // Multiple uses of the same register within a single instruction don't
528  // count as MultiUser or block optimization. This is especially important on
529  // arm64_32, where any memory operation is likely to be an explicit use of
530  // xN and an implicit use of wN (the base address register).
531  if (!UsesSeen.count(Idx)) {
532  handleUse(MI, MO, LOHInfos[Idx]);
533  UsesSeen.insert(Idx);
534  }
535  }
536 }
537 
538 bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
539  if (skipFunction(MF.getFunction()))
540  return false;
541 
542  LLVM_DEBUG(dbgs() << "********** AArch64 Collect LOH **********\n"
543  << "Looking in function " << MF.getName() << '\n');
544 
545  LOHInfo LOHInfos[N_GPR_REGS];
547  for (const MachineBasicBlock &MBB : MF) {
548  // Reset register tracking state.
549  memset(LOHInfos, 0, sizeof(LOHInfos));
550  // Live-out registers are used.
551  for (const MachineBasicBlock *Succ : MBB.successors()) {
552  for (const auto &LI : Succ->liveins()) {
553  int RegIdx = mapRegToGPRIndex(LI.PhysReg);
554  if (RegIdx >= 0)
555  LOHInfos[RegIdx].OneUser = true;
556  }
557  }
558 
559  // Walk the basic block backwards and update the per register state machine
560  // in the process.
561  for (const MachineInstr &MI :
563  unsigned Opcode = MI.getOpcode();
564  switch (Opcode) {
565  case AArch64::ADDXri:
566  case AArch64::LDRXui:
567  case AArch64::LDRWui:
568  if (canDefBePartOfLOH(MI)) {
569  const MachineOperand &Def = MI.getOperand(0);
570  const MachineOperand &Op = MI.getOperand(1);
571  assert(Def.isReg() && Def.isDef() && "Expected reg def");
572  assert(Op.isReg() && Op.isUse() && "Expected reg use");
573  int DefIdx = mapRegToGPRIndex(Def.getReg());
574  int OpIdx = mapRegToGPRIndex(Op.getReg());
575  if (DefIdx >= 0 && OpIdx >= 0 &&
576  handleMiddleInst(MI, LOHInfos[DefIdx], LOHInfos[OpIdx]))
577  continue;
578  }
579  break;
580  case AArch64::ADRP:
581  const MachineOperand &Op0 = MI.getOperand(0);
582  int Idx = mapRegToGPRIndex(Op0.getReg());
583  if (Idx >= 0) {
584  handleADRP(MI, AFI, LOHInfos[Idx], LOHInfos);
585  continue;
586  }
587  break;
588  }
589  handleNormalInst(MI, LOHInfos);
590  }
591  }
592 
593  // Return "no change": The pass only collects information.
594  return false;
595 }
596 
598  return new AArch64CollectLOH();
599 }
llvm::next_nodbg
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
Definition: MachineBasicBlock.h:1230
canDefBePartOfLOH
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:175
llvm::MachineOperand::MO_BlockAddress
@ MO_BlockAddress
Address of a basic block.
Definition: MachineOperand.h:63
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
MachineInstr.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
AArch64MachineFunctionInfo.h
Reg
unsigned Reg
Definition: MachineSink.cpp:1558
supportLoadFromLiteral
static bool supportLoadFromLiteral(const MachineInstr &MI)
Check whether the given instruction can load a litteral.
Definition: AArch64CollectLOH.cpp:243
AArch64.h
llvm::MCLOHType
MCLOHType
Linker Optimization Hint Type.
Definition: MCLinkerOptimizationHint.h:33
Statistic.h
isCandidateLoad
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:222
llvm::MCLOH_AdrpAddLdr
@ MCLOH_AdrpAddLdr
Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
Definition: MCLinkerOptimizationHint.h:36
ErrorHandling.h
MapVector.h
mapRegToGPRIndex
static int mapRegToGPRIndex(MCPhysReg Reg)
Map register number to index from 0-30.
Definition: AArch64CollectLOH.cpp:260
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
MachineBasicBlock.h
DenseMap.h
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
llvm::MachineFunctionProperties
Properties which a MachineFunction may have at a given point in time.
Definition: MachineFunction.h:111
llvm::MCLOH_AdrpLdrGotLdr
@ MCLOH_AdrpLdrGotLdr
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
Definition: MCLinkerOptimizationHint.h:37
N_GPR_REGS
static const unsigned N_GPR_REGS
Number of GPR registers traked by mapRegToGPRIndex()
Definition: AArch64CollectLOH.cpp:258
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
handleMiddleInst
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:336
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
AArch64InstrInfo.h
TargetMachine.h
llvm::MachineOperand::MO_GlobalAddress
@ MO_GlobalAddress
Address of a global value.
Definition: MachineOperand.h:62
llvm::MachineFunction::getInfo
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Definition: MachineFunction.h:739
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:499
isCandidateStore
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:198
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::MachineFunctionProperties::set
MachineFunctionProperties & set(Property P)
Definition: MachineFunction.h:180
LOHInfo::MI0
const MachineInstr * MI0
First instruction involved in the LOH.
Definition: AArch64CollectLOH.cpp:284
llvm::MachineBasicBlock::rend
reverse_iterator rend()
Definition: MachineBasicBlock.h:278
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
BitVector.h
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::MachineFunctionProperties::Property::NoVRegs
@ NoVRegs
llvm::MachineOperand::clobbersPhysReg
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
Definition: MachineOperand.h:617
llvm::SmallSet::count
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition: SmallSet.h:164
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
INITIALIZE_PASS
INITIALIZE_PASS(AArch64CollectLOH, "aarch64-collect-loh", AARCH64_COLLECT_LOH_NAME, false, false) static bool canAddBePartOfLOH(const MachineInstr &MI)
Definition: AArch64CollectLOH.cpp:157
const
aarch64 promote const
Definition: AArch64PromoteConstant.cpp:232
llvm::AArch64FunctionInfo
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
Definition: AArch64MachineFunctionInfo.h:37
llvm::MCPhysReg
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition: MCRegister.h:21
handleRegMaskClobber
static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg, LOHInfo *LOHInfos)
Definition: AArch64CollectLOH.cpp:490
MachineFunctionPass.h
handleClobber
static void handleClobber(LOHInfo &Info)
Update state Info given the tracked register is clobbered.
Definition: AArch64CollectLOH.cpp:327
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:545
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::MCLOH_AdrpAddStr
@ MCLOH_AdrpAddStr
Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
Definition: MCLinkerOptimizationHint.h:38
llvm::MachineFunction
Definition: MachineFunction.h:241
handleADRP
static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI, LOHInfo &Info, LOHInfo *LOHInfos)
Update state when seeing and ADRP instruction.
Definition: AArch64CollectLOH.cpp:384
llvm::MachineOperand::MO_JumpTableIndex
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
Definition: MachineOperand.h:60
llvm::MachineBasicBlock::iterator
MachineInstrBundleIterator< MachineInstr > iterator
Definition: MachineBasicBlock.h:233
llvm::MachineBasicBlock::successors
iterator_range< succ_iterator > successors()
Definition: MachineBasicBlock.h:355
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::MachineBasicBlock::rbegin
reverse_iterator rbegin()
Definition: MachineBasicBlock.h:272
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition: ilist_node.h:81
llvm::SmallSet::insert
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:180
llvm::MachineInstr::getParent
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:286
LOHInfo::Type
MCLOHType Type
"Best" type of LOH possible.
Definition: AArch64CollectLOH.cpp:280
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
LOHInfo::MI1
const MachineInstr * MI1
Second instruction involved in the LOH (if any).
Definition: AArch64CollectLOH.cpp:285
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:607
llvm::AnalysisUsage::setPreservesAll
void setPreservesAll()
Set by analyses that do not transform their input at all.
Definition: PassAnalysisSupport.h:130
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:325
llvm::MCLOH_AdrpAdrp
@ MCLOH_AdrpAdrp
Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
Definition: MCLinkerOptimizationHint.h:34
LOHInfo::OneUser
bool OneUser
Found exactly one user (yet).
Definition: AArch64CollectLOH.cpp:282
llvm::createAArch64CollectLOHPass
FunctionPass * createAArch64CollectLOHPass()
Definition: AArch64CollectLOH.cpp:597
llvm::MCLOH_AdrpAdd
@ MCLOH_AdrpAdd
Adrp _v@PAGE -> Add _v@PAGEOFF.
Definition: MCLinkerOptimizationHint.h:40
handleUse
static void handleUse(const MachineInstr &MI, const MachineOperand &MO, LOHInfo &Info)
Update state Info given MI uses the tracked register.
Definition: AArch64CollectLOH.cpp:291
llvm::AArch64ISD::ADRP
@ ADRP
Definition: AArch64ISelLowering.h:61
AARCH64_COLLECT_LOH_NAME
#define AARCH64_COLLECT_LOH_NAME
Definition: AArch64CollectLOH.cpp:130
llvm::MCLOH_AdrpLdr
@ MCLOH_AdrpLdr
Adrp _v@PAGE -> Ldr _v@PAGEOFF.
Definition: MCLinkerOptimizationHint.h:35
llvm::MCLOH_AdrpLdrGotStr
@ MCLOH_AdrpLdrGotStr
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
Definition: MCLinkerOptimizationHint.h:39
SmallVector.h
LOHInfo
State tracked per register.
Definition: AArch64CollectLOH.cpp:279
LOHInfo::MultiUsers
bool MultiUsers
Found multiple users.
Definition: AArch64CollectLOH.cpp:283
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::MCLOH_AdrpLdrGot
@ MCLOH_AdrpLdrGot
Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
Definition: MCLinkerOptimizationHint.h:41
LOHInfo::LastADRP
const MachineInstr * LastADRP
Last ADRP in same register.
Definition: AArch64CollectLOH.cpp:287
raw_ostream.h
LOHInfo::IsCandidate
bool IsCandidate
Possible LOH candidate.
Definition: AArch64CollectLOH.cpp:281
llvm::AArch64II::MO_GOT
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
Definition: AArch64BaseInfo.h:714
llvm::AArch64FunctionInfo::addLOHDirective
void addLOHDirective(MCLOHType Kind, MILOHArgs Args)
Add a LOH directive of this Kind and this Args.
Definition: AArch64MachineFunctionInfo.h:366
TargetRegisterInfo.h
Debug.h
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:270
llvm::instructionsWithoutDebug
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
Definition: MachineBasicBlock.h:1244
SmallSet.h
handleNormalInst
static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos)
Definition: AArch64CollectLOH.cpp:499
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::MachineOperand::MO_ConstantPoolIndex
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
Definition: MachineOperand.h:58