LLVM  3.7.0
AArch64CollectLOH.cpp
Go to the documentation of this file.
1 //===---------- AArch64CollectLOH.cpp - AArch64 collect LOH pass --*- C++ -*-=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a pass that collect the Linker Optimization Hint (LOH).
11 // This pass should be run at the very end of the compilation flow, just before
12 // assembly printer.
13 // To be useful for the linker, the LOH must be printed into the assembly file.
14 //
15 // A LOH describes a sequence of instructions that may be optimized by the
16 // linker.
17 // This same sequence cannot be optimized by the compiler because some of
18 // the information will be known at link time.
19 // For instance, consider the following sequence:
20 // L1: adrp xA, sym@PAGE
21 // L2: add xB, xA, sym@PAGEOFF
22 // L3: ldr xC, [xB, #imm]
23 // This sequence can be turned into:
24 // A literal load if sym@PAGE + sym@PAGEOFF + #imm - address(L3) is < 1MB:
25 // L3: ldr xC, sym+#imm
26 // It may also be turned into either the following more efficient
27 // code sequences:
28 // - If sym@PAGEOFF + #imm fits the encoding space of L3.
29 // L1: adrp xA, sym@PAGE
30 // L3: ldr xC, [xB, sym@PAGEOFF + #imm]
31 // - If sym@PAGE + sym@PAGEOFF - address(L1) < 1MB:
32 // L1: adr xA, sym
33 // L3: ldr xC, [xB, #imm]
34 //
35 // To be valid a LOH must meet all the requirements needed by all the related
36 // possible linker transformations.
37 // For instance, using the running example, the constraints to emit
38 // ".loh AdrpAddLdr" are:
39 // - L1, L2, and L3 instructions are of the expected type, i.e.,
40 // respectively ADRP, ADD (immediate), and LD.
41 // - The result of L1 is used only by L2.
42 // - The register argument (xA) used in the ADD instruction is defined
43 // only by L1.
44 // - The result of L2 is used only by L3.
45 // - The base address (xB) in L3 is defined only L2.
46 // - The ADRP in L1 and the ADD in L2 must reference the same symbol using
47 // @PAGE/@PAGEOFF with no additional constants
48 //
49 // Currently supported LOHs are:
50 // * So called non-ADRP-related:
51 // - .loh AdrpAddLdr L1, L2, L3:
52 // L1: adrp xA, sym@PAGE
53 // L2: add xB, xA, sym@PAGEOFF
54 // L3: ldr xC, [xB, #imm]
55 // - .loh AdrpLdrGotLdr L1, L2, L3:
56 // L1: adrp xA, sym@GOTPAGE
57 // L2: ldr xB, [xA, sym@GOTPAGEOFF]
58 // L3: ldr xC, [xB, #imm]
59 // - .loh AdrpLdr L1, L3:
60 // L1: adrp xA, sym@PAGE
61 // L3: ldr xC, [xA, sym@PAGEOFF]
62 // - .loh AdrpAddStr L1, L2, L3:
63 // L1: adrp xA, sym@PAGE
64 // L2: add xB, xA, sym@PAGEOFF
65 // L3: str xC, [xB, #imm]
66 // - .loh AdrpLdrGotStr L1, L2, L3:
67 // L1: adrp xA, sym@GOTPAGE
68 // L2: ldr xB, [xA, sym@GOTPAGEOFF]
69 // L3: str xC, [xB, #imm]
70 // - .loh AdrpAdd L1, L2:
71 // L1: adrp xA, sym@PAGE
72 // L2: add xB, xA, sym@PAGEOFF
73 // For all these LOHs, L1, L2, L3 form a simple chain:
74 // L1 result is used only by L2 and L2 result by L3.
75 // L3 LOH-related argument is defined only by L2 and L2 LOH-related argument
76 // by L1.
77 // All these LOHs aim at using more efficient load/store patterns by folding
78 // some instructions used to compute the address directly into the load/store.
79 //
80 // * So called ADRP-related:
81 // - .loh AdrpAdrp L2, L1:
82 // L2: ADRP xA, sym1@PAGE
83 // L1: ADRP xA, sym2@PAGE
84 // L2 dominates L1 and xA is not redifined between L2 and L1
85 // This LOH aims at getting rid of redundant ADRP instructions.
86 //
87 // The overall design for emitting the LOHs is:
88 // 1. AArch64CollectLOH (this pass) records the LOHs in the AArch64FunctionInfo.
89 // 2. AArch64AsmPrinter reads the LOHs from AArch64FunctionInfo and it:
90 // 1. Associates them a label.
91 // 2. Emits them in a MCStreamer (EmitLOHDirective).
92 // - The MCMachOStreamer records them into the MCAssembler.
93 // - The MCAsmStreamer prints them.
94 // - Other MCStreamers ignore them.
95 // 3. Closes the MCStreamer:
96 // - The MachObjectWriter gets them from the MCAssembler and writes
97 // them in the object file.
98 // - Other ObjectWriters ignore them.
99 //===----------------------------------------------------------------------===//
100 
101 #include "AArch64.h"
102 #include "AArch64InstrInfo.h"
104 #include "AArch64Subtarget.h"
106 #include "llvm/ADT/BitVector.h"
107 #include "llvm/ADT/DenseMap.h"
108 #include "llvm/ADT/MapVector.h"
109 #include "llvm/ADT/SetVector.h"
110 #include "llvm/ADT/SmallVector.h"
111 #include "llvm/ADT/Statistic.h"
118 #include "llvm/Support/Debug.h"
124 using namespace llvm;
125 
126 #define DEBUG_TYPE "aarch64-collect-loh"
127 
128 static cl::opt<bool>
129 PreCollectRegister("aarch64-collect-loh-pre-collect-register", cl::Hidden,
130  cl::desc("Restrict analysis to registers invovled"
131  " in LOHs"),
132  cl::init(true));
133 
134 static cl::opt<bool>
135 BasicBlockScopeOnly("aarch64-collect-loh-bb-only", cl::Hidden,
136  cl::desc("Restrict analysis at basic block scope"),
137  cl::init(true));
138 
139 STATISTIC(NumADRPSimpleCandidate,
140  "Number of simplifiable ADRP dominate by another");
141 STATISTIC(NumADRPComplexCandidate2,
142  "Number of simplifiable ADRP reachable by 2 defs");
143 STATISTIC(NumADRPComplexCandidate3,
144  "Number of simplifiable ADRP reachable by 3 defs");
145 STATISTIC(NumADRPComplexCandidateOther,
146  "Number of simplifiable ADRP reachable by 4 or more defs");
147 STATISTIC(NumADDToSTRWithImm,
148  "Number of simplifiable STR with imm reachable by ADD");
149 STATISTIC(NumLDRToSTRWithImm,
150  "Number of simplifiable STR with imm reachable by LDR");
151 STATISTIC(NumADDToSTR, "Number of simplifiable STR reachable by ADD");
152 STATISTIC(NumLDRToSTR, "Number of simplifiable STR reachable by LDR");
153 STATISTIC(NumADDToLDRWithImm,
154  "Number of simplifiable LDR with imm reachable by ADD");
155 STATISTIC(NumLDRToLDRWithImm,
156  "Number of simplifiable LDR with imm reachable by LDR");
157 STATISTIC(NumADDToLDR, "Number of simplifiable LDR reachable by ADD");
158 STATISTIC(NumLDRToLDR, "Number of simplifiable LDR reachable by LDR");
159 STATISTIC(NumADRPToLDR, "Number of simplifiable LDR reachable by ADRP");
160 STATISTIC(NumCplxLvl1, "Number of complex case of level 1");
161 STATISTIC(NumTooCplxLvl1, "Number of too complex case of level 1");
162 STATISTIC(NumCplxLvl2, "Number of complex case of level 2");
163 STATISTIC(NumTooCplxLvl2, "Number of too complex case of level 2");
164 STATISTIC(NumADRSimpleCandidate, "Number of simplifiable ADRP + ADD");
165 STATISTIC(NumADRComplexCandidate, "Number of too complex ADRP + ADD");
166 
167 namespace llvm {
169 }
170 
171 namespace {
172 struct AArch64CollectLOH : public MachineFunctionPass {
173  static char ID;
174  AArch64CollectLOH() : MachineFunctionPass(ID) {
176  }
177 
178  bool runOnMachineFunction(MachineFunction &MF) override;
179 
180  const char *getPassName() const override {
181  return "AArch64 Collect Linker Optimization Hint (LOH)";
182  }
183 
184  void getAnalysisUsage(AnalysisUsage &AU) const override {
185  AU.setPreservesAll();
188  }
189 
190 private:
191 };
192 
193 /// A set of MachineInstruction.
194 typedef SetVector<const MachineInstr *> SetOfMachineInstr;
195 /// Map a basic block to a set of instructions per register.
196 /// This is used to represent the exposed uses of a basic block
197 /// per register.
198 typedef MapVector<const MachineBasicBlock *,
199  std::unique_ptr<SetOfMachineInstr[]>>
200 BlockToSetOfInstrsPerColor;
201 /// Map a basic block to an instruction per register.
202 /// This is used to represent the live-out definitions of a basic block
203 /// per register.
204 typedef MapVector<const MachineBasicBlock *,
205  std::unique_ptr<const MachineInstr *[]>>
206 BlockToInstrPerColor;
207 /// Map an instruction to a set of instructions. Used to represent the
208 /// mapping def to reachable uses or use to definitions.
210 /// Map a basic block to a BitVector.
211 /// This is used to record the kill registers per basic block.
213 
214 /// Map a register to a dense id.
215 typedef DenseMap<unsigned, unsigned> MapRegToId;
216 /// Map a dense id to a register. Used for debug purposes.
217 typedef SmallVector<unsigned, 32> MapIdToReg;
218 } // end anonymous namespace.
219 
220 char AArch64CollectLOH::ID = 0;
221 
222 INITIALIZE_PASS_BEGIN(AArch64CollectLOH, "aarch64-collect-loh",
223  "AArch64 Collect Linker Optimization Hint (LOH)", false,
224  false)
226 INITIALIZE_PASS_END(AArch64CollectLOH, "aarch64-collect-loh",
227  "AArch64 Collect Linker Optimization Hint (LOH)", false,
228  false)
229 
230 /// Given a couple (MBB, reg) get the corresponding set of instruction from
231 /// the given "sets".
232 /// If this couple does not reference any set, an empty set is added to "sets"
233 /// for this couple and returned.
234 /// \param nbRegs is used internally allocate some memory. It must be consistent
235 /// with the way sets is used.
236 static SetOfMachineInstr &getSet(BlockToSetOfInstrsPerColor &sets,
237  const MachineBasicBlock &MBB, unsigned reg,
238  unsigned nbRegs) {
239  SetOfMachineInstr *result;
240  BlockToSetOfInstrsPerColor::iterator it = sets.find(&MBB);
241  if (it != sets.end())
242  result = it->second.get();
243  else
244  result = (sets[&MBB] = make_unique<SetOfMachineInstr[]>(nbRegs)).get();
245 
246  return result[reg];
247 }
248 
249 /// Given a couple (reg, MI) get the corresponding set of instructions from the
250 /// the given "sets".
251 /// This is used to get the uses record in sets of a definition identified by
252 /// MI and reg, i.e., MI defines reg.
253 /// If the couple does not reference anything, an empty set is added to
254 /// "sets[reg]".
255 /// \pre set[reg] is valid.
256 static SetOfMachineInstr &getUses(InstrToInstrs *sets, unsigned reg,
257  const MachineInstr &MI) {
258  return sets[reg][&MI];
259 }
260 
261 /// Same as getUses but does not modify the input map: sets.
262 /// \return NULL if the couple (reg, MI) is not in sets.
263 static const SetOfMachineInstr *getUses(const InstrToInstrs *sets, unsigned reg,
264  const MachineInstr &MI) {
265  InstrToInstrs::const_iterator Res = sets[reg].find(&MI);
266  if (Res != sets[reg].end())
267  return &(Res->second);
268  return nullptr;
269 }
270 
271 /// Initialize the reaching definition algorithm:
272 /// For each basic block BB in MF, record:
273 /// - its kill set.
274 /// - its reachable uses (uses that are exposed to BB's predecessors).
275 /// - its the generated definitions.
276 /// \param DummyOp if not NULL, specifies a Dummy Operation to be added to
277 /// the list of uses of exposed defintions.
278 /// \param ADRPMode specifies to only consider ADRP instructions for generated
279 /// definition. It also consider definitions of ADRP instructions as uses and
280 /// ignore other uses. The ADRPMode is used to collect the information for LHO
281 /// that involve ADRP operation only.
282 static void initReachingDef(const MachineFunction &MF,
283  InstrToInstrs *ColorOpToReachedUses,
284  BlockToInstrPerColor &Gen, BlockToRegSet &Kill,
285  BlockToSetOfInstrsPerColor &ReachableUses,
286  const MapRegToId &RegToId,
287  const MachineInstr *DummyOp, bool ADRPMode) {
288  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
289  unsigned NbReg = RegToId.size();
290 
291  for (const MachineBasicBlock &MBB : MF) {
292  auto &BBGen = Gen[&MBB];
293  BBGen = make_unique<const MachineInstr *[]>(NbReg);
294  std::fill(BBGen.get(), BBGen.get() + NbReg, nullptr);
295 
296  BitVector &BBKillSet = Kill[&MBB];
297  BBKillSet.resize(NbReg);
298  for (const MachineInstr &MI : MBB) {
299  bool IsADRP = MI.getOpcode() == AArch64::ADRP;
300 
301  // Process uses first.
302  if (IsADRP || !ADRPMode)
303  for (const MachineOperand &MO : MI.operands()) {
304  // Treat ADRP def as use, as the goal of the analysis is to find
305  // ADRP defs reached by other ADRP defs.
306  if (!MO.isReg() || (!ADRPMode && !MO.isUse()) ||
307  (ADRPMode && (!IsADRP || !MO.isDef())))
308  continue;
309  unsigned CurReg = MO.getReg();
310  MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg);
311  if (ItCurRegId == RegToId.end())
312  continue;
313  CurReg = ItCurRegId->second;
314 
315  // if CurReg has not been defined, this use is reachable.
316  if (!BBGen[CurReg] && !BBKillSet.test(CurReg))
317  getSet(ReachableUses, MBB, CurReg, NbReg).insert(&MI);
318  // current basic block definition for this color, if any, is in Gen.
319  if (BBGen[CurReg])
320  getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(&MI);
321  }
322 
323  // Process clobbers.
324  for (const MachineOperand &MO : MI.operands()) {
325  if (!MO.isRegMask())
326  continue;
327  // Clobbers kill the related colors.
328  const uint32_t *PreservedRegs = MO.getRegMask();
329 
330  // Set generated regs.
331  for (const auto &Entry : RegToId) {
332  unsigned Reg = Entry.second;
333  // Use the global register ID when querying APIs external to this
334  // pass.
335  if (MachineOperand::clobbersPhysReg(PreservedRegs, Entry.first)) {
336  // Do not register clobbered definition for no ADRP.
337  // This definition is not used anyway (otherwise register
338  // allocation is wrong).
339  BBGen[Reg] = ADRPMode ? &MI : nullptr;
340  BBKillSet.set(Reg);
341  }
342  }
343  }
344 
345  // Process register defs.
346  for (const MachineOperand &MO : MI.operands()) {
347  if (!MO.isReg() || !MO.isDef())
348  continue;
349  unsigned CurReg = MO.getReg();
350  MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg);
351  if (ItCurRegId == RegToId.end())
352  continue;
353 
354  for (MCRegAliasIterator AI(CurReg, TRI, true); AI.isValid(); ++AI) {
355  MapRegToId::const_iterator ItRegId = RegToId.find(*AI);
356  assert(ItRegId != RegToId.end() &&
357  "Sub-register of an "
358  "involved register, not recorded as involved!");
359  BBKillSet.set(ItRegId->second);
360  BBGen[ItRegId->second] = &MI;
361  }
362  BBGen[ItCurRegId->second] = &MI;
363  }
364  }
365 
366  // If we restrict our analysis to basic block scope, conservatively add a
367  // dummy
368  // use for each generated value.
369  if (!ADRPMode && DummyOp && !MBB.succ_empty())
370  for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg)
371  if (BBGen[CurReg])
372  getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(DummyOp);
373  }
374 }
375 
376 /// Reaching def core algorithm:
377 /// while an Out has changed
378 /// for each bb
379 /// for each color
380 /// In[bb][color] = U Out[bb.predecessors][color]
381 /// insert reachableUses[bb][color] in each in[bb][color]
382 /// op.reachedUses
383 ///
384 /// Out[bb] = Gen[bb] U (In[bb] - Kill[bb])
385 static void reachingDefAlgorithm(const MachineFunction &MF,
386  InstrToInstrs *ColorOpToReachedUses,
387  BlockToSetOfInstrsPerColor &In,
388  BlockToSetOfInstrsPerColor &Out,
389  BlockToInstrPerColor &Gen, BlockToRegSet &Kill,
390  BlockToSetOfInstrsPerColor &ReachableUses,
391  unsigned NbReg) {
392  bool HasChanged;
393  do {
394  HasChanged = false;
395  for (const MachineBasicBlock &MBB : MF) {
396  unsigned CurReg;
397  for (CurReg = 0; CurReg < NbReg; ++CurReg) {
398  SetOfMachineInstr &BBInSet = getSet(In, MBB, CurReg, NbReg);
399  SetOfMachineInstr &BBReachableUses =
400  getSet(ReachableUses, MBB, CurReg, NbReg);
401  SetOfMachineInstr &BBOutSet = getSet(Out, MBB, CurReg, NbReg);
402  unsigned Size = BBOutSet.size();
403  // In[bb][color] = U Out[bb.predecessors][color]
404  for (const MachineBasicBlock *PredMBB : MBB.predecessors()) {
405  SetOfMachineInstr &PredOutSet = getSet(Out, *PredMBB, CurReg, NbReg);
406  BBInSet.insert(PredOutSet.begin(), PredOutSet.end());
407  }
408  // insert reachableUses[bb][color] in each in[bb][color] op.reachedses
409  for (const MachineInstr *MI : BBInSet) {
410  SetOfMachineInstr &OpReachedUses =
411  getUses(ColorOpToReachedUses, CurReg, *MI);
412  OpReachedUses.insert(BBReachableUses.begin(), BBReachableUses.end());
413  }
414  // Out[bb] = Gen[bb] U (In[bb] - Kill[bb])
415  if (!Kill[&MBB].test(CurReg))
416  BBOutSet.insert(BBInSet.begin(), BBInSet.end());
417  if (Gen[&MBB][CurReg])
418  BBOutSet.insert(Gen[&MBB][CurReg]);
419  HasChanged |= BBOutSet.size() != Size;
420  }
421  }
422  } while (HasChanged);
423 }
424 
425 /// Reaching definition algorithm.
426 /// \param MF function on which the algorithm will operate.
427 /// \param[out] ColorOpToReachedUses will contain the result of the reaching
428 /// def algorithm.
429 /// \param ADRPMode specify whether the reaching def algorithm should be tuned
430 /// for ADRP optimization. \see initReachingDef for more details.
431 /// \param DummyOp if not NULL, the algorithm will work at
432 /// basic block scope and will set for every exposed definition a use to
433 /// @p DummyOp.
434 /// \pre ColorOpToReachedUses is an array of at least number of registers of
435 /// InstrToInstrs.
436 static void reachingDef(const MachineFunction &MF,
437  InstrToInstrs *ColorOpToReachedUses,
438  const MapRegToId &RegToId, bool ADRPMode = false,
439  const MachineInstr *DummyOp = nullptr) {
440  // structures:
441  // For each basic block.
442  // Out: a set per color of definitions that reach the
443  // out boundary of this block.
444  // In: Same as Out but for in boundary.
445  // Gen: generated color in this block (one operation per color).
446  // Kill: register set of killed color in this block.
447  // ReachableUses: a set per color of uses (operation) reachable
448  // for "In" definitions.
449  BlockToSetOfInstrsPerColor Out, In, ReachableUses;
450  BlockToInstrPerColor Gen;
451  BlockToRegSet Kill;
452 
453  // Initialize Gen, kill and reachableUses.
454  initReachingDef(MF, ColorOpToReachedUses, Gen, Kill, ReachableUses, RegToId,
455  DummyOp, ADRPMode);
456 
457  // Algo.
458  if (!DummyOp)
459  reachingDefAlgorithm(MF, ColorOpToReachedUses, In, Out, Gen, Kill,
460  ReachableUses, RegToId.size());
461 }
462 
463 #ifndef NDEBUG
464 /// print the result of the reaching definition algorithm.
465 static void printReachingDef(const InstrToInstrs *ColorOpToReachedUses,
466  unsigned NbReg, const TargetRegisterInfo *TRI,
467  const MapIdToReg &IdToReg) {
468  unsigned CurReg;
469  for (CurReg = 0; CurReg < NbReg; ++CurReg) {
470  if (ColorOpToReachedUses[CurReg].empty())
471  continue;
472  DEBUG(dbgs() << "*** Reg " << PrintReg(IdToReg[CurReg], TRI) << " ***\n");
473 
474  for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) {
475  DEBUG(dbgs() << "Def:\n");
476  DEBUG(DefsIt.first->print(dbgs()));
477  DEBUG(dbgs() << "Reachable uses:\n");
478  for (const MachineInstr *MI : DefsIt.second) {
479  DEBUG(MI->print(dbgs()));
480  }
481  }
482  }
483 }
484 #endif // NDEBUG
485 
486 /// Answer the following question: Can Def be one of the definition
487 /// involved in a part of a LOH?
488 static bool canDefBePartOfLOH(const MachineInstr *Def) {
489  unsigned Opc = Def->getOpcode();
490  // Accept ADRP, ADDLow and LOADGot.
491  switch (Opc) {
492  default:
493  return false;
494  case AArch64::ADRP:
495  return true;
496  case AArch64::ADDXri:
497  // Check immediate to see if the immediate is an address.
498  switch (Def->getOperand(2).getType()) {
499  default:
500  return false;
505  return true;
506  }
507  case AArch64::LDRXui:
508  // Check immediate to see if the immediate is an address.
509  switch (Def->getOperand(2).getType()) {
510  default:
511  return false;
513  return true;
514  }
515  }
516  // Unreachable.
517  return false;
518 }
519 
520 /// Check whether the given instruction can the end of a LOH chain involving a
521 /// store.
522 static bool isCandidateStore(const MachineInstr *Instr) {
523  switch (Instr->getOpcode()) {
524  default:
525  return false;
526  case AArch64::STRBui:
527  case AArch64::STRHui:
528  case AArch64::STRWui:
529  case AArch64::STRXui:
530  case AArch64::STRSui:
531  case AArch64::STRDui:
532  case AArch64::STRQui:
533  // In case we have str xA, [xA, #imm], this is two different uses
534  // of xA and we cannot fold, otherwise the xA stored may be wrong,
535  // even if #imm == 0.
536  if (Instr->getOperand(0).getReg() != Instr->getOperand(1).getReg())
537  return true;
538  }
539  return false;
540 }
541 
542 /// Given the result of a reaching definition algorithm in ColorOpToReachedUses,
543 /// Build the Use to Defs information and filter out obvious non-LOH candidates.
544 /// In ADRPMode, non-LOH candidates are "uses" with non-ADRP definitions.
545 /// In non-ADRPMode, non-LOH candidates are "uses" with several definition,
546 /// i.e., no simple chain.
547 /// \param ADRPMode -- \see initReachingDef.
548 static void reachedUsesToDefs(InstrToInstrs &UseToReachingDefs,
549  const InstrToInstrs *ColorOpToReachedUses,
550  const MapRegToId &RegToId,
551  bool ADRPMode = false) {
552 
553  SetOfMachineInstr NotCandidate;
554  unsigned NbReg = RegToId.size();
555  MapRegToId::const_iterator EndIt = RegToId.end();
556  for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg) {
557  // If this color is never defined, continue.
558  if (ColorOpToReachedUses[CurReg].empty())
559  continue;
560 
561  for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) {
562  for (const MachineInstr *MI : DefsIt.second) {
563  const MachineInstr *Def = DefsIt.first;
564  MapRegToId::const_iterator It;
565  // if all the reaching defs are not adrp, this use will not be
566  // simplifiable.
567  if ((ADRPMode && Def->getOpcode() != AArch64::ADRP) ||
568  (!ADRPMode && !canDefBePartOfLOH(Def)) ||
569  (!ADRPMode && isCandidateStore(MI) &&
570  // store are LOH candidate iff the end of the chain is used as
571  // base.
572  ((It = RegToId.find((MI)->getOperand(1).getReg())) == EndIt ||
573  It->second != CurReg))) {
574  NotCandidate.insert(MI);
575  continue;
576  }
577  // Do not consider self reaching as a simplifiable case for ADRP.
578  if (!ADRPMode || MI != DefsIt.first) {
579  UseToReachingDefs[MI].insert(DefsIt.first);
580  // If UsesIt has several reaching definitions, it is not
581  // candidate for simplificaton in non-ADRPMode.
582  if (!ADRPMode && UseToReachingDefs[MI].size() > 1)
583  NotCandidate.insert(MI);
584  }
585  }
586  }
587  }
588  for (const MachineInstr *Elem : NotCandidate) {
589  DEBUG(dbgs() << "Too many reaching defs: " << *Elem << "\n");
590  // It would have been better if we could just remove the entry
591  // from the map. Because of that, we have to filter the garbage
592  // (second.empty) in the subsequence analysis.
593  UseToReachingDefs[Elem].clear();
594  }
595 }
596 
597 /// Based on the use to defs information (in ADRPMode), compute the
598 /// opportunities of LOH ADRP-related.
599 static void computeADRP(const InstrToInstrs &UseToDefs,
600  AArch64FunctionInfo &AArch64FI,
601  const MachineDominatorTree *MDT) {
602  DEBUG(dbgs() << "*** Compute LOH for ADRP\n");
603  for (const auto &Entry : UseToDefs) {
604  unsigned Size = Entry.second.size();
605  if (Size == 0)
606  continue;
607  if (Size == 1) {
608  const MachineInstr *L2 = *Entry.second.begin();
609  const MachineInstr *L1 = Entry.first;
610  if (!MDT->dominates(L2, L1)) {
611  DEBUG(dbgs() << "Dominance check failed:\n" << *L2 << '\n' << *L1
612  << '\n');
613  continue;
614  }
615  DEBUG(dbgs() << "Record AdrpAdrp:\n" << *L2 << '\n' << *L1 << '\n');
617  Args.push_back(L2);
618  Args.push_back(L1);
619  AArch64FI.addLOHDirective(MCLOH_AdrpAdrp, Args);
620  ++NumADRPSimpleCandidate;
621  }
622 #ifdef DEBUG
623  else if (Size == 2)
624  ++NumADRPComplexCandidate2;
625  else if (Size == 3)
626  ++NumADRPComplexCandidate3;
627  else
628  ++NumADRPComplexCandidateOther;
629 #endif
630  // if Size < 1, the use should have been removed from the candidates
631  assert(Size >= 1 && "No reaching defs for that use!");
632  }
633 }
634 
635 /// Check whether the given instruction can be the end of a LOH chain
636 /// involving a load.
637 static bool isCandidateLoad(const MachineInstr *Instr) {
638  switch (Instr->getOpcode()) {
639  default:
640  return false;
641  case AArch64::LDRSBWui:
642  case AArch64::LDRSBXui:
643  case AArch64::LDRSHWui:
644  case AArch64::LDRSHXui:
645  case AArch64::LDRSWui:
646  case AArch64::LDRBui:
647  case AArch64::LDRHui:
648  case AArch64::LDRWui:
649  case AArch64::LDRXui:
650  case AArch64::LDRSui:
651  case AArch64::LDRDui:
652  case AArch64::LDRQui:
653  if (Instr->getOperand(2).getTargetFlags() & AArch64II::MO_GOT)
654  return false;
655  return true;
656  }
657  // Unreachable.
658  return false;
659 }
660 
661 /// Check whether the given instruction can load a litteral.
662 static bool supportLoadFromLiteral(const MachineInstr *Instr) {
663  switch (Instr->getOpcode()) {
664  default:
665  return false;
666  case AArch64::LDRSWui:
667  case AArch64::LDRWui:
668  case AArch64::LDRXui:
669  case AArch64::LDRSui:
670  case AArch64::LDRDui:
671  case AArch64::LDRQui:
672  return true;
673  }
674  // Unreachable.
675  return false;
676 }
677 
678 /// Check whether the given instruction is a LOH candidate.
679 /// \param UseToDefs is used to check that Instr is at the end of LOH supported
680 /// chain.
681 /// \pre UseToDefs contains only on def per use, i.e., obvious non candidate are
682 /// already been filtered out.
683 static bool isCandidate(const MachineInstr *Instr,
684  const InstrToInstrs &UseToDefs,
685  const MachineDominatorTree *MDT) {
686  if (!isCandidateLoad(Instr) && !isCandidateStore(Instr))
687  return false;
688 
689  const MachineInstr *Def = *UseToDefs.find(Instr)->second.begin();
690  if (Def->getOpcode() != AArch64::ADRP) {
691  // At this point, Def is ADDXri or LDRXui of the right type of
692  // symbol, because we filtered out the uses that were not defined
693  // by these kind of instructions (+ ADRP).
694 
695  // Check if this forms a simple chain: each intermediate node must
696  // dominates the next one.
697  if (!MDT->dominates(Def, Instr))
698  return false;
699  // Move one node up in the simple chain.
700  if (UseToDefs.find(Def) ==
701  UseToDefs.end()
702  // The map may contain garbage we have to ignore.
703  ||
704  UseToDefs.find(Def)->second.empty())
705  return false;
706  Instr = Def;
707  Def = *UseToDefs.find(Def)->second.begin();
708  }
709  // Check if we reached the top of the simple chain:
710  // - top is ADRP.
711  // - check the simple chain property: each intermediate node must
712  // dominates the next one.
713  if (Def->getOpcode() == AArch64::ADRP)
714  return MDT->dominates(Def, Instr);
715  return false;
716 }
717 
719  const InstrToInstrs &UseToDefs,
720  const InstrToInstrs *DefsPerColorToUses,
721  AArch64FunctionInfo &AArch64FI,
722  SetOfMachineInstr *InvolvedInLOHs,
723  const MapRegToId &RegToId) {
724  // Look for opportunities to turn ADRP -> ADD or
725  // ADRP -> LDR GOTPAGEOFF into ADR.
726  // If ADRP has more than one use. Give up.
727  if (Use.getOpcode() != AArch64::ADDXri &&
728  (Use.getOpcode() != AArch64::LDRXui ||
730  return false;
731  InstrToInstrs::const_iterator It = UseToDefs.find(&Use);
732  // The map may contain garbage that we need to ignore.
733  if (It == UseToDefs.end() || It->second.empty())
734  return false;
735  const MachineInstr &Def = **It->second.begin();
736  if (Def.getOpcode() != AArch64::ADRP)
737  return false;
738  // Check the number of users of ADRP.
739  const SetOfMachineInstr *Users =
740  getUses(DefsPerColorToUses,
741  RegToId.find(Def.getOperand(0).getReg())->second, Def);
742  if (Users->size() > 1) {
743  ++NumADRComplexCandidate;
744  return false;
745  }
746  ++NumADRSimpleCandidate;
747  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Def)) &&
748  "ADRP already involved in LOH.");
749  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Use)) &&
750  "ADD already involved in LOH.");
751  DEBUG(dbgs() << "Record AdrpAdd\n" << Def << '\n' << Use << '\n');
752 
754  Args.push_back(&Def);
755  Args.push_back(&Use);
756 
757  AArch64FI.addLOHDirective(Use.getOpcode() == AArch64::ADDXri ? MCLOH_AdrpAdd
759  Args);
760  return true;
761 }
762 
763 /// Based on the use to defs information (in non-ADRPMode), compute the
764 /// opportunities of LOH non-ADRP-related
765 static void computeOthers(const InstrToInstrs &UseToDefs,
766  const InstrToInstrs *DefsPerColorToUses,
767  AArch64FunctionInfo &AArch64FI, const MapRegToId &RegToId,
768  const MachineDominatorTree *MDT) {
769  SetOfMachineInstr *InvolvedInLOHs = nullptr;
770 #ifdef DEBUG
771  SetOfMachineInstr InvolvedInLOHsStorage;
772  InvolvedInLOHs = &InvolvedInLOHsStorage;
773 #endif // DEBUG
774  DEBUG(dbgs() << "*** Compute LOH for Others\n");
775  // ADRP -> ADD/LDR -> LDR/STR pattern.
776  // Fall back to ADRP -> ADD pattern if we fail to catch the bigger pattern.
777 
778  // FIXME: When the statistics are not important,
779  // This initial filtering loop can be merged into the next loop.
780  // Currently, we didn't do it to have the same code for both DEBUG and
781  // NDEBUG builds. Indeed, the iterator of the second loop would need
782  // to be changed.
783  SetOfMachineInstr PotentialCandidates;
784  SetOfMachineInstr PotentialADROpportunities;
785  for (auto &Use : UseToDefs) {
786  // If no definition is available, this is a non candidate.
787  if (Use.second.empty())
788  continue;
789  // Keep only instructions that are load or store and at the end of
790  // a ADRP -> ADD/LDR/Nothing chain.
791  // We already filtered out the no-chain cases.
792  if (!isCandidate(Use.first, UseToDefs, MDT)) {
793  PotentialADROpportunities.insert(Use.first);
794  continue;
795  }
796  PotentialCandidates.insert(Use.first);
797  }
798 
799  // Make the following distinctions for statistics as the linker does
800  // know how to decode instructions:
801  // - ADD/LDR/Nothing make there different patterns.
802  // - LDR/STR make two different patterns.
803  // Hence, 6 - 1 base patterns.
804  // (because ADRP-> Nothing -> STR is not simplifiable)
805 
806  // The linker is only able to have a simple semantic, i.e., if pattern A
807  // do B.
808  // However, we want to see the opportunity we may miss if we were able to
809  // catch more complex cases.
810 
811  // PotentialCandidates are result of a chain ADRP -> ADD/LDR ->
812  // A potential candidate becomes a candidate, if its current immediate
813  // operand is zero and all nodes of the chain have respectively only one user
814 #ifdef DEBUG
815  SetOfMachineInstr DefsOfPotentialCandidates;
816 #endif
817  for (const MachineInstr *Candidate : PotentialCandidates) {
818  // Get the definition of the candidate i.e., ADD or LDR.
819  const MachineInstr *Def = *UseToDefs.find(Candidate)->second.begin();
820  // Record the elements of the chain.
821  const MachineInstr *L1 = Def;
822  const MachineInstr *L2 = nullptr;
823  unsigned ImmediateDefOpc = Def->getOpcode();
824  if (Def->getOpcode() != AArch64::ADRP) {
825  // Check the number of users of this node.
826  const SetOfMachineInstr *Users =
827  getUses(DefsPerColorToUses,
828  RegToId.find(Def->getOperand(0).getReg())->second, *Def);
829  if (Users->size() > 1) {
830 #ifdef DEBUG
831  // if all the uses of this def are in potential candidate, this is
832  // a complex candidate of level 2.
833  bool IsLevel2 = true;
834  for (const MachineInstr *MI : *Users) {
835  if (!PotentialCandidates.count(MI)) {
836  ++NumTooCplxLvl2;
837  IsLevel2 = false;
838  break;
839  }
840  }
841  if (IsLevel2)
842  ++NumCplxLvl2;
843 #endif // DEBUG
844  PotentialADROpportunities.insert(Def);
845  continue;
846  }
847  L2 = Def;
848  Def = *UseToDefs.find(Def)->second.begin();
849  L1 = Def;
850  } // else the element in the middle of the chain is nothing, thus
851  // Def already contains the first element of the chain.
852 
853  // Check the number of users of the first node in the chain, i.e., ADRP
854  const SetOfMachineInstr *Users =
855  getUses(DefsPerColorToUses,
856  RegToId.find(Def->getOperand(0).getReg())->second, *Def);
857  if (Users->size() > 1) {
858 #ifdef DEBUG
859  // if all the uses of this def are in the defs of the potential candidate,
860  // this is a complex candidate of level 1
861  if (DefsOfPotentialCandidates.empty()) {
862  // lazy init
863  DefsOfPotentialCandidates = PotentialCandidates;
864  for (const MachineInstr *Candidate : PotentialCandidates) {
865  if (!UseToDefs.find(Candidate)->second.empty())
866  DefsOfPotentialCandidates.insert(
867  *UseToDefs.find(Candidate)->second.begin());
868  }
869  }
870  bool Found = false;
871  for (auto &Use : *Users) {
872  if (!DefsOfPotentialCandidates.count(Use)) {
873  ++NumTooCplxLvl1;
874  Found = true;
875  break;
876  }
877  }
878  if (!Found)
879  ++NumCplxLvl1;
880 #endif // DEBUG
881  continue;
882  }
883 
884  bool IsL2Add = (ImmediateDefOpc == AArch64::ADDXri);
885  // If the chain is three instructions long and ldr is the second element,
886  // then this ldr must load form GOT, otherwise this is not a correct chain.
887  if (L2 && !IsL2Add && L2->getOperand(2).getTargetFlags() != AArch64II::MO_GOT)
888  continue;
890  MCLOHType Kind;
891  if (isCandidateLoad(Candidate)) {
892  if (!L2) {
893  // At this point, the candidate LOH indicates that the ldr instruction
894  // may use a direct access to the symbol. There is not such encoding
895  // for loads of byte and half.
896  if (!supportLoadFromLiteral(Candidate))
897  continue;
898 
899  DEBUG(dbgs() << "Record AdrpLdr:\n" << *L1 << '\n' << *Candidate
900  << '\n');
901  Kind = MCLOH_AdrpLdr;
902  Args.push_back(L1);
903  Args.push_back(Candidate);
904  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) &&
905  "L1 already involved in LOH.");
906  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) &&
907  "Candidate already involved in LOH.");
908  ++NumADRPToLDR;
909  } else {
910  DEBUG(dbgs() << "Record Adrp" << (IsL2Add ? "Add" : "LdrGot")
911  << "Ldr:\n" << *L1 << '\n' << *L2 << '\n' << *Candidate
912  << '\n');
913 
914  Kind = IsL2Add ? MCLOH_AdrpAddLdr : MCLOH_AdrpLdrGotLdr;
915  Args.push_back(L1);
916  Args.push_back(L2);
917  Args.push_back(Candidate);
918 
919  PotentialADROpportunities.remove(L2);
920  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) &&
921  "L1 already involved in LOH.");
922  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L2)) &&
923  "L2 already involved in LOH.");
924  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) &&
925  "Candidate already involved in LOH.");
926 #ifdef DEBUG
927  // get the immediate of the load
928  if (Candidate->getOperand(2).getImm() == 0)
929  if (ImmediateDefOpc == AArch64::ADDXri)
930  ++NumADDToLDR;
931  else
932  ++NumLDRToLDR;
933  else if (ImmediateDefOpc == AArch64::ADDXri)
934  ++NumADDToLDRWithImm;
935  else
936  ++NumLDRToLDRWithImm;
937 #endif // DEBUG
938  }
939  } else {
940  if (ImmediateDefOpc == AArch64::ADRP)
941  continue;
942  else {
943 
944  DEBUG(dbgs() << "Record Adrp" << (IsL2Add ? "Add" : "LdrGot")
945  << "Str:\n" << *L1 << '\n' << *L2 << '\n' << *Candidate
946  << '\n');
947 
948  Kind = IsL2Add ? MCLOH_AdrpAddStr : MCLOH_AdrpLdrGotStr;
949  Args.push_back(L1);
950  Args.push_back(L2);
951  Args.push_back(Candidate);
952 
953  PotentialADROpportunities.remove(L2);
954  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) &&
955  "L1 already involved in LOH.");
956  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L2)) &&
957  "L2 already involved in LOH.");
958  assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) &&
959  "Candidate already involved in LOH.");
960 #ifdef DEBUG
961  // get the immediate of the store
962  if (Candidate->getOperand(2).getImm() == 0)
963  if (ImmediateDefOpc == AArch64::ADDXri)
964  ++NumADDToSTR;
965  else
966  ++NumLDRToSTR;
967  else if (ImmediateDefOpc == AArch64::ADDXri)
968  ++NumADDToSTRWithImm;
969  else
970  ++NumLDRToSTRWithImm;
971 #endif // DEBUG
972  }
973  }
974  AArch64FI.addLOHDirective(Kind, Args);
975  }
976 
977  // Now, we grabbed all the big patterns, check ADR opportunities.
978  for (const MachineInstr *Candidate : PotentialADROpportunities)
979  registerADRCandidate(*Candidate, UseToDefs, DefsPerColorToUses, AArch64FI,
980  InvolvedInLOHs, RegToId);
981 }
982 
983 /// Look for every register defined by potential LOHs candidates.
984 /// Map these registers with dense id in @p RegToId and vice-versa in
985 /// @p IdToReg. @p IdToReg is populated only in DEBUG mode.
986 static void collectInvolvedReg(const MachineFunction &MF, MapRegToId &RegToId,
987  MapIdToReg &IdToReg,
988  const TargetRegisterInfo *TRI) {
989  unsigned CurRegId = 0;
990  if (!PreCollectRegister) {
991  unsigned NbReg = TRI->getNumRegs();
992  for (; CurRegId < NbReg; ++CurRegId) {
993  RegToId[CurRegId] = CurRegId;
994  DEBUG(IdToReg.push_back(CurRegId));
995  DEBUG(assert(IdToReg[CurRegId] == CurRegId && "Reg index mismatches"));
996  }
997  return;
998  }
999 
1000  DEBUG(dbgs() << "** Collect Involved Register\n");
1001  for (const auto &MBB : MF) {
1002  for (const MachineInstr &MI : MBB) {
1003  if (!canDefBePartOfLOH(&MI))
1004  continue;
1005 
1006  // Process defs
1007  for (MachineInstr::const_mop_iterator IO = MI.operands_begin(),
1008  IOEnd = MI.operands_end();
1009  IO != IOEnd; ++IO) {
1010  if (!IO->isReg() || !IO->isDef())
1011  continue;
1012  unsigned CurReg = IO->getReg();
1013  for (MCRegAliasIterator AI(CurReg, TRI, true); AI.isValid(); ++AI)
1014  if (RegToId.find(*AI) == RegToId.end()) {
1015  DEBUG(IdToReg.push_back(*AI);
1016  assert(IdToReg[CurRegId] == *AI &&
1017  "Reg index mismatches insertion index."));
1018  RegToId[*AI] = CurRegId++;
1019  DEBUG(dbgs() << "Register: " << PrintReg(*AI, TRI) << '\n');
1020  }
1021  }
1022  }
1023  }
1024 }
1025 
1026 bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
1027  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1028  const MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>();
1029 
1030  MapRegToId RegToId;
1031  MapIdToReg IdToReg;
1032  AArch64FunctionInfo *AArch64FI = MF.getInfo<AArch64FunctionInfo>();
1033  assert(AArch64FI && "No MachineFunctionInfo for this function!");
1034 
1035  DEBUG(dbgs() << "Looking for LOH in " << MF.getName() << '\n');
1036 
1037  collectInvolvedReg(MF, RegToId, IdToReg, TRI);
1038  if (RegToId.empty())
1039  return false;
1040 
1041  MachineInstr *DummyOp = nullptr;
1042  if (BasicBlockScopeOnly) {
1043  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
1044  // For local analysis, create a dummy operation to record uses that are not
1045  // local.
1046  DummyOp = MF.CreateMachineInstr(TII->get(AArch64::COPY), DebugLoc());
1047  }
1048 
1049  unsigned NbReg = RegToId.size();
1050  bool Modified = false;
1051 
1052  // Start with ADRP.
1053  InstrToInstrs *ColorOpToReachedUses = new InstrToInstrs[NbReg];
1054 
1055  // Compute the reaching def in ADRP mode, meaning ADRP definitions
1056  // are first considered as uses.
1057  reachingDef(MF, ColorOpToReachedUses, RegToId, true, DummyOp);
1058  DEBUG(dbgs() << "ADRP reaching defs\n");
1059  DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg));
1060 
1061  // Translate the definition to uses map into a use to definitions map to ease
1062  // statistic computation.
1063  InstrToInstrs ADRPToReachingDefs;
1064  reachedUsesToDefs(ADRPToReachingDefs, ColorOpToReachedUses, RegToId, true);
1065 
1066  // Compute LOH for ADRP.
1067  computeADRP(ADRPToReachingDefs, *AArch64FI, MDT);
1068  delete[] ColorOpToReachedUses;
1069 
1070  // Continue with general ADRP -> ADD/LDR -> LDR/STR pattern.
1071  ColorOpToReachedUses = new InstrToInstrs[NbReg];
1072 
1073  // first perform a regular reaching def analysis.
1074  reachingDef(MF, ColorOpToReachedUses, RegToId, false, DummyOp);
1075  DEBUG(dbgs() << "All reaching defs\n");
1076  DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg));
1077 
1078  // Turn that into a use to defs to ease statistic computation.
1079  InstrToInstrs UsesToReachingDefs;
1080  reachedUsesToDefs(UsesToReachingDefs, ColorOpToReachedUses, RegToId, false);
1081 
1082  // Compute other than AdrpAdrp LOH.
1083  computeOthers(UsesToReachingDefs, ColorOpToReachedUses, *AArch64FI, RegToId,
1084  MDT);
1085  delete[] ColorOpToReachedUses;
1086 
1087  if (BasicBlockScopeOnly)
1088  MF.DeleteMachineInstr(DummyOp);
1089 
1090  return Modified;
1091 }
1092 
1093 /// createAArch64CollectLOHPass - returns an instance of the Statistic for
1094 /// linker optimization pass.
1096  return new AArch64CollectLOH();
1097 }
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Definition: BitVector.h:192
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:240
static bool isCandidateLoad(const MachineInstr *Instr)
Check whether the given instruction can be the end of a LOH chain involving a load.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImp=false)
CreateMachineInstr - Allocate a new MachineInstr.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
STATISTIC(NumFunctions,"Total number of functions")
static void Found()
static SetOfMachineInstr & getUses(InstrToInstrs *sets, unsigned reg, const MachineInstr &MI)
Given a couple (reg, MI) get the corresponding set of instructions from the the given "sets"...
aarch64 collect loh
Address of indexed Jump Table for switch.
print alias sets
Adrp _v -> Add _v -> Ldr.
This class implements a map that also provides access to all stored values in a deterministic order...
Definition: MapVector.h:32
A debug info location.
Definition: DebugLoc.h:34
iv Induction Variable Users
Definition: IVUsers.cpp:43
static void collectInvolvedReg(const MachineFunction &MF, MapRegToId &RegToId, MapIdToReg &IdToReg, const TargetRegisterInfo *TRI)
Look for every register defined by potential LOHs candidates.
aarch64 collect AArch64 Collect Linker Optimization Hint(LOH)"
FunctionPass * createAArch64CollectLOHPass()
createAArch64CollectLOHPass - returns an instance of the Statistic for linker optimization pass...
COPY - Target-independent register copy.
Definition: TargetOpcodes.h:86
Adrp _v -> Ldr _v -> Ldr.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:70
static cl::opt< bool > PreCollectRegister("aarch64-collect-loh-pre-collect-register", cl::Hidden, cl::desc("Restrict analysis to registers invovled"" in LOHs"), cl::init(true))
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static bool canDefBePartOfLOH(const MachineInstr *Def)
Answer the following question: Can Def be one of the definition involved in a part of a LOH...
A Use represents the edge between a Value definition and its users.
Definition: Use.h:69
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:75
Reg
All possible values of the reg field in the ModR/M byte.
void initializeAArch64CollectLOHPass(PassRegistry &)
PrintReg - Helper class for printing registers on a raw_ostream.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
This class provides the core functionality of linking in LLVM.
Definition: Linker/Linker.h:27
static cl::opt< bool > BasicBlockScopeOnly("aarch64-collect-loh-bb-only", cl::Hidden, cl::desc("Restrict analysis at basic block scope"), cl::init(true))
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
TargetInstrInfo - Interface to description of machine instruction set.
Address of a global value.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:325
unsigned getTargetFlags() const
static void reachedUsesToDefs(InstrToInstrs &UseToReachingDefs, const InstrToInstrs *ColorOpToReachedUses, const MapRegToId &RegToId, bool ADRPMode=false)
Given the result of a reaching definition algorithm in ColorOpToReachedUses, Build the Use to Defs in...
static bool isCandidate(const MachineInstr *Instr, const InstrToInstrs &UseToDefs, const MachineDominatorTree *MDT)
Check whether the given instruction is a LOH candidate.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void print(raw_ostream &OS, bool SkipOpers=false) const
static void printReachingDef(const InstrToInstrs *ColorOpToReachedUses, unsigned NbReg, const TargetRegisterInfo *TRI, const MapIdToReg &IdToReg)
print the result of the reaching definition algorithm.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:273
MCRegAliasIterator enumerates all registers aliasing Reg.
Represent the analysis usage information of a pass.
MCLOHType
Linker Optimization Hint Type.
Address of a basic block.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
static bool supportLoadFromLiteral(const MachineInstr *Instr)
Check whether the given instruction can load a litteral.
iterator_range< pred_iterator > predecessors()
unsigned size() const
void DeleteMachineInstr(MachineInstr *MI)
DeleteMachineInstr - Delete the given MachineInstr.
static void initReachingDef(const MachineFunction &MF, InstrToInstrs *ColorOpToReachedUses, BlockToInstrPerColor &Gen, BlockToRegSet &Kill, BlockToSetOfInstrsPerColor &ReachableUses, const MapRegToId &RegToId, const MachineInstr *DummyOp, bool ADRPMode)
Initialize the reaching definition algorithm: For each basic block BB in MF, record: ...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static void reachingDef(const MachineFunction &MF, InstrToInstrs *ColorOpToReachedUses, const MapRegToId &RegToId, bool ADRPMode=false, const MachineInstr *DummyOp=nullptr)
Reaching definition algorithm.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
INITIALIZE_PASS_BEGIN(AArch64CollectLOH,"aarch64-collect-loh","AArch64 Collect Linker Optimization Hint (LOH)", false, false) INITIALIZE_PASS_END(AArch64CollectLOH
static void reachingDefAlgorithm(const MachineFunction &MF, InstrToInstrs *ColorOpToReachedUses, BlockToSetOfInstrsPerColor &In, BlockToSetOfInstrsPerColor &Out, BlockToInstrPerColor &Gen, BlockToRegSet &Kill, BlockToSetOfInstrsPerColor &ReachableUses, unsigned NbReg)
Reaching def core algorithm: while an Out has changed for each bb for each color In[bb][color] = U Ou...
Adrp _v -> Add _v -> Str.
void addLOHDirective(MCLOHType Kind, const MILOHArgs &Args)
Add a LOH directive of this Kind and this Args.
MachineOperand class - Representation of each machine instruction operand.
static void computeADRP(const InstrToInstrs &UseToDefs, AArch64FunctionInfo &AArch64FI, const MachineDominatorTree *MDT)
Based on the use to defs information (in ADRPMode), compute the opportunities of LOH ADRP-related...
aarch64 collect AArch64 Collect Linker Optimization static false SetOfMachineInstr & getSet(BlockToSetOfInstrsPerColor &sets, const MachineBasicBlock &MBB, unsigned reg, unsigned nbRegs)
Given a couple (MBB, reg) get the corresponding set of instruction from the given "sets"...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:123
static bool clobbersPhysReg(const uint32_t *RegMask, unsigned PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
void setPreservesAll()
Set by analyses that do not transform their input at all.
MemCpy Optimization
Representation of each machine instruction.
Definition: MachineInstr.h:51
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Adrp xY, _v1 -> Adrp xY, _v2.
Adrp _v -> Ldr _v -> Str.
void size_t size
unsigned getReg() const
getReg - Returns the register number.
const ARM::ArchExtKind Kind
aarch64 promote const
virtual const TargetInstrInfo * getInstrInfo() const
A vector that has set insertion semantics.
Definition: SetVector.h:37
#define DEBUG(X)
Definition: Debug.h:92
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:41
static void computeOthers(const InstrToInstrs &UseToDefs, const InstrToInstrs *DefsPerColorToUses, AArch64FunctionInfo &AArch64FI, const MapRegToId &RegToId, const MachineDominatorTree *MDT)
Based on the use to defs information (in non-ADRPMode), compute the opportunities of LOH non-ADRP-rel...
Address of indexed Constant in Constant Pool.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
aarch64 collect AArch64 Collect Linker Optimization false
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static bool registerADRCandidate(const MachineInstr &Use, const InstrToInstrs &UseToDefs, const InstrToInstrs *DefsPerColorToUses, AArch64FunctionInfo &AArch64FI, SetOfMachineInstr *InvolvedInLOHs, const MapRegToId &RegToId)
static bool isCandidateStore(const MachineInstr *Instr)
Check whether the given instruction can the end of a LOH chain involving a store. ...