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" 103 #include "AArch64MachineFunctionInfo.h" 104 #include "AArch64Subtarget.h" 105 #include "MCTargetDesc/AArch64AddressingModes.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" 112 #include "llvm/CodeGen/MachineBasicBlock.h" 113 #include "llvm/CodeGen/MachineDominators.h" 114 #include "llvm/CodeGen/MachineFunctionPass.h" 115 #include "llvm/CodeGen/MachineInstr.h" 116 #include "llvm/CodeGen/MachineInstrBuilder.h" 117 #include "llvm/Support/CommandLine.h" 118 #include "llvm/Support/Debug.h" 119 #include "llvm/Support/ErrorHandling.h" 120 #include "llvm/Support/raw_ostream.h" 121 #include "llvm/Target/TargetInstrInfo.h" 122 #include "llvm/Target/TargetMachine.h" 123 #include "llvm/Target/TargetRegisterInfo.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 { 168 void initializeAArch64CollectLOHPass(PassRegistry &); 169 } 170 171 namespace { 172 struct AArch64CollectLOH : public MachineFunctionPass { 173 static char ID; 174 AArch64CollectLOH() : MachineFunctionPass(ID) { 175 initializeAArch64CollectLOHPass(*PassRegistry::getPassRegistry()); 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(); 186 MachineFunctionPass::getAnalysisUsage(AU); 187 AU.addRequired<MachineDominatorTree>(); 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. 209 typedef MapVector<const MachineInstr *, SetOfMachineInstr> InstrToInstrs; 210 /// Map a basic block to a BitVector. 211 /// This is used to record the kill registers per basic block. 212 typedef MapVector<const MachineBasicBlock *, BitVector> BlockToRegSet; 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) 225 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 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; 501 case MachineOperand::MO_GlobalAddress: 502 case MachineOperand::MO_JumpTableIndex: 503 case MachineOperand::MO_ConstantPoolIndex: 504 case MachineOperand::MO_BlockAddress: 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; 512 case MachineOperand::MO_GlobalAddress: 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'); 616 SmallVector<const MachineInstr *, 2> Args; 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 718 static bool registerADRCandidate(const MachineInstr &Use, 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 || 729 !(Use.getOperand(2).getTargetFlags() & AArch64II::MO_GOT))) 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 753 SmallVector<const MachineInstr *, 2> Args; 754 Args.push_back(&Def); 755 Args.push_back(&Use); 756 757 AArch64FI.addLOHDirective(Use.getOpcode() == AArch64::ADDXri ? MCLOH_AdrpAdd 758 : MCLOH_AdrpLdrGot, 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; 889 SmallVector<const MachineInstr *, 3> Args; 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. 1095 FunctionPass *llvm::createAArch64CollectLOHPass() { 1096 return new AArch64CollectLOH(); 1097 } 1098