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 "MCTargetDesc/AArch64AddressingModes.h" 105#include "llvm/ADT/BitVector.h" 106#include "llvm/ADT/DenseMap.h" 107#include "llvm/ADT/MapVector.h" 108#include "llvm/ADT/SetVector.h" 109#include "llvm/ADT/SmallVector.h" 110#include "llvm/CodeGen/MachineBasicBlock.h" 111#include "llvm/CodeGen/MachineDominators.h" 112#include "llvm/CodeGen/MachineFunctionPass.h" 113#include "llvm/CodeGen/MachineInstr.h" 114#include "llvm/CodeGen/MachineInstrBuilder.h" 115#include "llvm/Target/TargetInstrInfo.h" 116#include "llvm/Target/TargetMachine.h" 117#include "llvm/Target/TargetRegisterInfo.h" 118#include "llvm/Support/CommandLine.h" 119#include "llvm/Support/Debug.h" 120#include "llvm/Support/ErrorHandling.h" 121#include "llvm/Support/raw_ostream.h" 122#include "llvm/ADT/Statistic.h" 123using namespace llvm; 124 125#define DEBUG_TYPE "aarch64-collect-loh" 126 127static cl::opt<bool> 128PreCollectRegister("aarch64-collect-loh-pre-collect-register", cl::Hidden, 129 cl::desc("Restrict analysis to registers invovled" 130 " in LOHs"), 131 cl::init(true)); 132 133static cl::opt<bool> 134BasicBlockScopeOnly("aarch64-collect-loh-bb-only", cl::Hidden, 135 cl::desc("Restrict analysis at basic block scope"), 136 cl::init(true)); 137 138STATISTIC(NumADRPSimpleCandidate, 139 "Number of simplifiable ADRP dominate by another"); 140STATISTIC(NumADRPComplexCandidate2, 141 "Number of simplifiable ADRP reachable by 2 defs"); 142STATISTIC(NumADRPComplexCandidate3, 143 "Number of simplifiable ADRP reachable by 3 defs"); 144STATISTIC(NumADRPComplexCandidateOther, 145 "Number of simplifiable ADRP reachable by 4 or more defs"); 146STATISTIC(NumADDToSTRWithImm, 147 "Number of simplifiable STR with imm reachable by ADD"); 148STATISTIC(NumLDRToSTRWithImm, 149 "Number of simplifiable STR with imm reachable by LDR"); 150STATISTIC(NumADDToSTR, "Number of simplifiable STR reachable by ADD"); 151STATISTIC(NumLDRToSTR, "Number of simplifiable STR reachable by LDR"); 152STATISTIC(NumADDToLDRWithImm, 153 "Number of simplifiable LDR with imm reachable by ADD"); 154STATISTIC(NumLDRToLDRWithImm, 155 "Number of simplifiable LDR with imm reachable by LDR"); 156STATISTIC(NumADDToLDR, "Number of simplifiable LDR reachable by ADD"); 157STATISTIC(NumLDRToLDR, "Number of simplifiable LDR reachable by LDR"); 158STATISTIC(NumADRPToLDR, "Number of simplifiable LDR reachable by ADRP"); 159STATISTIC(NumCplxLvl1, "Number of complex case of level 1"); 160STATISTIC(NumTooCplxLvl1, "Number of too complex case of level 1"); 161STATISTIC(NumCplxLvl2, "Number of complex case of level 2"); 162STATISTIC(NumTooCplxLvl2, "Number of too complex case of level 2"); 163STATISTIC(NumADRSimpleCandidate, "Number of simplifiable ADRP + ADD"); 164STATISTIC(NumADRComplexCandidate, "Number of too complex ADRP + ADD"); 165 166namespace llvm { 167void initializeAArch64CollectLOHPass(PassRegistry &); 168} 169 170namespace { 171struct AArch64CollectLOH : public MachineFunctionPass { 172 static char ID; 173 AArch64CollectLOH() : MachineFunctionPass(ID) { 174 initializeAArch64CollectLOHPass(*PassRegistry::getPassRegistry()); 175 } 176 177 bool runOnMachineFunction(MachineFunction &MF) override; 178 179 const char *getPassName() const override { 180 return "AArch64 Collect Linker Optimization Hint (LOH)"; 181 } 182 183 void getAnalysisUsage(AnalysisUsage &AU) const override { 184 AU.setPreservesAll(); 185 MachineFunctionPass::getAnalysisUsage(AU); 186 AU.addRequired<MachineDominatorTree>(); 187 } 188 189private: 190}; 191 192/// A set of MachineInstruction. 193typedef SetVector<const MachineInstr *> SetOfMachineInstr; 194/// Map a basic block to a set of instructions per register. 195/// This is used to represent the exposed uses of a basic block 196/// per register. 197typedef MapVector<const MachineBasicBlock *, SetOfMachineInstr *> 198BlockToSetOfInstrsPerColor; 199/// Map a basic block to an instruction per register. 200/// This is used to represent the live-out definitions of a basic block 201/// per register. 202typedef MapVector<const MachineBasicBlock *, const MachineInstr **> 203BlockToInstrPerColor; 204/// Map an instruction to a set of instructions. Used to represent the 205/// mapping def to reachable uses or use to definitions. 206typedef MapVector<const MachineInstr *, SetOfMachineInstr> InstrToInstrs; 207/// Map a basic block to a BitVector. 208/// This is used to record the kill registers per basic block. 209typedef MapVector<const MachineBasicBlock *, BitVector> BlockToRegSet; 210 211/// Map a register to a dense id. 212typedef DenseMap<unsigned, unsigned> MapRegToId; 213/// Map a dense id to a register. Used for debug purposes. 214typedef SmallVector<unsigned, 32> MapIdToReg; 215} // end anonymous namespace. 216 217char AArch64CollectLOH::ID = 0; 218 219INITIALIZE_PASS_BEGIN(AArch64CollectLOH, "aarch64-collect-loh", 220 "AArch64 Collect Linker Optimization Hint (LOH)", false, 221 false) 222INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 223INITIALIZE_PASS_END(AArch64CollectLOH, "aarch64-collect-loh", 224 "AArch64 Collect Linker Optimization Hint (LOH)", false, 225 false) 226 227/// Given a couple (MBB, reg) get the corresponding set of instruction from 228/// the given "sets". 229/// If this couple does not reference any set, an empty set is added to "sets" 230/// for this couple and returned. 231/// \param nbRegs is used internally allocate some memory. It must be consistent 232/// with the way sets is used. 233static SetOfMachineInstr &getSet(BlockToSetOfInstrsPerColor &sets, 234 const MachineBasicBlock &MBB, unsigned reg, 235 unsigned nbRegs) { 236 SetOfMachineInstr *result; 237 BlockToSetOfInstrsPerColor::iterator it = sets.find(&MBB); 238 if (it != sets.end()) 239 result = it->second; 240 else 241 result = sets[&MBB] = new SetOfMachineInstr[nbRegs]; 242 243 return result[reg]; 244} 245 246/// Given a couple (reg, MI) get the corresponding set of instructions from the 247/// the given "sets". 248/// This is used to get the uses record in sets of a definition identified by 249/// MI and reg, i.e., MI defines reg. 250/// If the couple does not reference anything, an empty set is added to 251/// "sets[reg]". 252/// \pre set[reg] is valid. 253static SetOfMachineInstr &getUses(InstrToInstrs *sets, unsigned reg, 254 const MachineInstr &MI) { 255 return sets[reg][&MI]; 256} 257 258/// Same as getUses but does not modify the input map: sets. 259/// \return NULL if the couple (reg, MI) is not in sets. 260static const SetOfMachineInstr *getUses(const InstrToInstrs *sets, unsigned reg, 261 const MachineInstr &MI) { 262 InstrToInstrs::const_iterator Res = sets[reg].find(&MI); 263 if (Res != sets[reg].end()) 264 return &(Res->second); 265 return nullptr; 266} 267 268/// Initialize the reaching definition algorithm: 269/// For each basic block BB in MF, record: 270/// - its kill set. 271/// - its reachable uses (uses that are exposed to BB's predecessors). 272/// - its the generated definitions. 273/// \param DummyOp if not NULL, specifies a Dummy Operation to be added to 274/// the list of uses of exposed defintions. 275/// \param ADRPMode specifies to only consider ADRP instructions for generated 276/// definition. It also consider definitions of ADRP instructions as uses and 277/// ignore other uses. The ADRPMode is used to collect the information for LHO 278/// that involve ADRP operation only. 279static void initReachingDef(MachineFunction &MF, 280 InstrToInstrs *ColorOpToReachedUses, 281 BlockToInstrPerColor &Gen, BlockToRegSet &Kill, 282 BlockToSetOfInstrsPerColor &ReachableUses, 283 const MapRegToId &RegToId, 284 const MachineInstr *DummyOp, bool ADRPMode) { 285 const TargetMachine &TM = MF.getTarget(); 286 const TargetRegisterInfo *TRI = TM.getRegisterInfo(); 287 288 unsigned NbReg = RegToId.size(); 289 290 for (MachineBasicBlock &MBB : MF) { 291 const MachineInstr **&BBGen = Gen[&MBB]; 292 BBGen = new const MachineInstr *[NbReg]; 293 memset(BBGen, 0, sizeof(const MachineInstr *) * NbReg); 294 295 BitVector &BBKillSet = Kill[&MBB]; 296 BBKillSet.resize(NbReg); 297 for (const MachineInstr &MI : MBB) { 298 bool IsADRP = MI.getOpcode() == AArch64::ADRP; 299 300 // Process uses first. 301 if (IsADRP || !ADRPMode) 302 for (const MachineOperand &MO : MI.operands()) { 303 // Treat ADRP def as use, as the goal of the analysis is to find 304 // ADRP defs reached by other ADRP defs. 305 if (!MO.isReg() || (!ADRPMode && !MO.isUse()) || 306 (ADRPMode && (!IsADRP || !MO.isDef()))) 307 continue; 308 unsigned CurReg = MO.getReg(); 309 MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg); 310 if (ItCurRegId == RegToId.end()) 311 continue; 312 CurReg = ItCurRegId->second; 313 314 // if CurReg has not been defined, this use is reachable. 315 if (!BBGen[CurReg] && !BBKillSet.test(CurReg)) 316 getSet(ReachableUses, MBB, CurReg, NbReg).insert(&MI); 317 // current basic block definition for this color, if any, is in Gen. 318 if (BBGen[CurReg]) 319 getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(&MI); 320 } 321 322 // Process clobbers. 323 for (const MachineOperand &MO : MI.operands()) { 324 if (!MO.isRegMask()) 325 continue; 326 // Clobbers kill the related colors. 327 const uint32_t *PreservedRegs = MO.getRegMask(); 328 329 // Set generated regs. 330 for (const auto Entry : RegToId) { 331 unsigned Reg = Entry.second; 332 // Use the global register ID when querying APIs external to this 333 // pass. 334 if (MachineOperand::clobbersPhysReg(PreservedRegs, Entry.first)) { 335 // Do not register clobbered definition for no ADRP. 336 // This definition is not used anyway (otherwise register 337 // allocation is wrong). 338 BBGen[Reg] = ADRPMode ? &MI : nullptr; 339 BBKillSet.set(Reg); 340 } 341 } 342 } 343 344 // Process register defs. 345 for (const MachineOperand &MO : MI.operands()) { 346 if (!MO.isReg() || !MO.isDef()) 347 continue; 348 unsigned CurReg = MO.getReg(); 349 MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg); 350 if (ItCurRegId == RegToId.end()) 351 continue; 352 353 for (MCRegAliasIterator AI(CurReg, TRI, true); AI.isValid(); ++AI) { 354 MapRegToId::const_iterator ItRegId = RegToId.find(*AI); 355 assert(ItRegId != RegToId.end() && 356 "Sub-register of an " 357 "involved register, not recorded as involved!"); 358 BBKillSet.set(ItRegId->second); 359 BBGen[ItRegId->second] = &MI; 360 } 361 BBGen[ItCurRegId->second] = &MI; 362 } 363 } 364 365 // If we restrict our analysis to basic block scope, conservatively add a 366 // dummy 367 // use for each generated value. 368 if (!ADRPMode && DummyOp && !MBB.succ_empty()) 369 for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg) 370 if (BBGen[CurReg]) 371 getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(DummyOp); 372 } 373} 374 375/// Reaching def core algorithm: 376/// while an Out has changed 377/// for each bb 378/// for each color 379/// In[bb][color] = U Out[bb.predecessors][color] 380/// insert reachableUses[bb][color] in each in[bb][color] 381/// op.reachedUses 382/// 383/// Out[bb] = Gen[bb] U (In[bb] - Kill[bb]) 384static void reachingDefAlgorithm(MachineFunction &MF, 385 InstrToInstrs *ColorOpToReachedUses, 386 BlockToSetOfInstrsPerColor &In, 387 BlockToSetOfInstrsPerColor &Out, 388 BlockToInstrPerColor &Gen, BlockToRegSet &Kill, 389 BlockToSetOfInstrsPerColor &ReachableUses, 390 unsigned NbReg) { 391 bool HasChanged; 392 do { 393 HasChanged = false; 394 for (MachineBasicBlock &MBB : MF) { 395 unsigned CurReg; 396 for (CurReg = 0; CurReg < NbReg; ++CurReg) { 397 SetOfMachineInstr &BBInSet = getSet(In, MBB, CurReg, NbReg); 398 SetOfMachineInstr &BBReachableUses = 399 getSet(ReachableUses, MBB, CurReg, NbReg); 400 SetOfMachineInstr &BBOutSet = getSet(Out, MBB, CurReg, NbReg); 401 unsigned Size = BBOutSet.size(); 402 // In[bb][color] = U Out[bb.predecessors][color] 403 for (MachineBasicBlock *PredMBB : MBB.predecessors()) { 404 SetOfMachineInstr &PredOutSet = getSet(Out, *PredMBB, CurReg, NbReg); 405 BBInSet.insert(PredOutSet.begin(), PredOutSet.end()); 406 } 407 // insert reachableUses[bb][color] in each in[bb][color] op.reachedses 408 for (const MachineInstr *MI : BBInSet) { 409 SetOfMachineInstr &OpReachedUses = 410 getUses(ColorOpToReachedUses, CurReg, *MI); 411 OpReachedUses.insert(BBReachableUses.begin(), BBReachableUses.end()); 412 } 413 // Out[bb] = Gen[bb] U (In[bb] - Kill[bb]) 414 if (!Kill[&MBB].test(CurReg)) 415 BBOutSet.insert(BBInSet.begin(), BBInSet.end()); 416 if (Gen[&MBB][CurReg]) 417 BBOutSet.insert(Gen[&MBB][CurReg]); 418 HasChanged |= BBOutSet.size() != Size; 419 } 420 } 421 } while (HasChanged); 422} 423 424/// Release all memory dynamically allocated during the reaching 425/// definition algorithm. 426static void finitReachingDef(BlockToSetOfInstrsPerColor &In, 427 BlockToSetOfInstrsPerColor &Out, 428 BlockToInstrPerColor &Gen, 429 BlockToSetOfInstrsPerColor &ReachableUses) { 430 for (auto &IT : Out) 431 delete[] IT.second; 432 for (auto &IT : In) 433 delete[] IT.second; 434 for (auto &IT : ReachableUses) 435 delete[] IT.second; 436 for (auto &IT : Gen) 437 delete[] IT.second; 438} 439 440/// Reaching definition algorithm. 441/// \param MF function on which the algorithm will operate. 442/// \param[out] ColorOpToReachedUses will contain the result of the reaching 443/// def algorithm. 444/// \param ADRPMode specify whether the reaching def algorithm should be tuned 445/// for ADRP optimization. \see initReachingDef for more details. 446/// \param DummyOp if not NULL, the algorithm will work at 447/// basic block scope and will set for every exposed definition a use to 448/// @p DummyOp. 449/// \pre ColorOpToReachedUses is an array of at least number of registers of 450/// InstrToInstrs. 451static void reachingDef(MachineFunction &MF, 452 InstrToInstrs *ColorOpToReachedUses, 453 const MapRegToId &RegToId, bool ADRPMode = false, 454 const MachineInstr *DummyOp = nullptr) { 455 // structures: 456 // For each basic block. 457 // Out: a set per color of definitions that reach the 458 // out boundary of this block. 459 // In: Same as Out but for in boundary. 460 // Gen: generated color in this block (one operation per color). 461 // Kill: register set of killed color in this block. 462 // ReachableUses: a set per color of uses (operation) reachable 463 // for "In" definitions. 464 BlockToSetOfInstrsPerColor Out, In, ReachableUses; 465 BlockToInstrPerColor Gen; 466 BlockToRegSet Kill; 467 468 // Initialize Gen, kill and reachableUses. 469 initReachingDef(MF, ColorOpToReachedUses, Gen, Kill, ReachableUses, RegToId, 470 DummyOp, ADRPMode); 471 472 // Algo. 473 if (!DummyOp) 474 reachingDefAlgorithm(MF, ColorOpToReachedUses, In, Out, Gen, Kill, 475 ReachableUses, RegToId.size()); 476 477 // finit. 478 finitReachingDef(In, Out, Gen, ReachableUses); 479} 480 481#ifndef NDEBUG 482/// print the result of the reaching definition algorithm. 483static void printReachingDef(const InstrToInstrs *ColorOpToReachedUses, 484 unsigned NbReg, const TargetRegisterInfo *TRI, 485 const MapIdToReg &IdToReg) { 486 unsigned CurReg; 487 for (CurReg = 0; CurReg < NbReg; ++CurReg) { 488 if (ColorOpToReachedUses[CurReg].empty()) 489 continue; 490 DEBUG(dbgs() << "*** Reg " << PrintReg(IdToReg[CurReg], TRI) << " ***\n"); 491 492 for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) { 493 DEBUG(dbgs() << "Def:\n"); 494 DEBUG(DefsIt.first->print(dbgs())); 495 DEBUG(dbgs() << "Reachable uses:\n"); 496 for (const MachineInstr *MI : DefsIt.second) { 497 DEBUG(MI->print(dbgs())); 498 } 499 } 500 } 501} 502#endif // NDEBUG 503 504/// Answer the following question: Can Def be one of the definition 505/// involved in a part of a LOH? 506static bool canDefBePartOfLOH(const MachineInstr *Def) { 507 unsigned Opc = Def->getOpcode(); 508 // Accept ADRP, ADDLow and LOADGot. 509 switch (Opc) { 510 default: 511 return false; 512 case AArch64::ADRP: 513 return true; 514 case AArch64::ADDXri: 515 // Check immediate to see if the immediate is an address. 516 switch (Def->getOperand(2).getType()) { 517 default: 518 return false; 519 case MachineOperand::MO_GlobalAddress: 520 case MachineOperand::MO_JumpTableIndex: 521 case MachineOperand::MO_ConstantPoolIndex: 522 case MachineOperand::MO_BlockAddress: 523 return true; 524 } 525 case AArch64::LDRXui: 526 // Check immediate to see if the immediate is an address. 527 switch (Def->getOperand(2).getType()) { 528 default: 529 return false; 530 case MachineOperand::MO_GlobalAddress: 531 return true; 532 } 533 } 534 // Unreachable. 535 return false; 536} 537 538/// Check whether the given instruction can the end of a LOH chain involving a 539/// store. 540static bool isCandidateStore(const MachineInstr *Instr) { 541 switch (Instr->getOpcode()) { 542 default: 543 return false; 544 case AArch64::STRBui: 545 case AArch64::STRHui: 546 case AArch64::STRWui: 547 case AArch64::STRXui: 548 case AArch64::STRSui: 549 case AArch64::STRDui: 550 case AArch64::STRQui: 551 // In case we have str xA, [xA, #imm], this is two different uses 552 // of xA and we cannot fold, otherwise the xA stored may be wrong, 553 // even if #imm == 0. 554 if (Instr->getOperand(0).getReg() != Instr->getOperand(1).getReg()) 555 return true; 556 } 557 return false; 558} 559 560/// Given the result of a reaching definition algorithm in ColorOpToReachedUses, 561/// Build the Use to Defs information and filter out obvious non-LOH candidates. 562/// In ADRPMode, non-LOH candidates are "uses" with non-ADRP definitions. 563/// In non-ADRPMode, non-LOH candidates are "uses" with several definition, 564/// i.e., no simple chain. 565/// \param ADRPMode -- \see initReachingDef. 566static void reachedUsesToDefs(InstrToInstrs &UseToReachingDefs, 567 const InstrToInstrs *ColorOpToReachedUses, 568 const MapRegToId &RegToId, 569 bool ADRPMode = false) { 570 571 SetOfMachineInstr NotCandidate; 572 unsigned NbReg = RegToId.size(); 573 MapRegToId::const_iterator EndIt = RegToId.end(); 574 for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg) { 575 // If this color is never defined, continue. 576 if (ColorOpToReachedUses[CurReg].empty()) 577 continue; 578 579 for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) { 580 for (const MachineInstr *MI : DefsIt.second) { 581 const MachineInstr *Def = DefsIt.first; 582 MapRegToId::const_iterator It; 583 // if all the reaching defs are not adrp, this use will not be 584 // simplifiable. 585 if ((ADRPMode && Def->getOpcode() != AArch64::ADRP) || 586 (!ADRPMode && !canDefBePartOfLOH(Def)) || 587 (!ADRPMode && isCandidateStore(MI) && 588 // store are LOH candidate iff the end of the chain is used as 589 // base. 590 ((It = RegToId.find((MI)->getOperand(1).getReg())) == EndIt || 591 It->second != CurReg))) { 592 NotCandidate.insert(MI); 593 continue; 594 } 595 // Do not consider self reaching as a simplifiable case for ADRP. 596 if (!ADRPMode || MI != DefsIt.first) { 597 UseToReachingDefs[MI].insert(DefsIt.first); 598 // If UsesIt has several reaching definitions, it is not 599 // candidate for simplificaton in non-ADRPMode. 600 if (!ADRPMode && UseToReachingDefs[MI].size() > 1) 601 NotCandidate.insert(MI); 602 } 603 } 604 } 605 } 606 for (const MachineInstr *Elem : NotCandidate) { 607 DEBUG(dbgs() << "Too many reaching defs: " << *Elem << "\n"); 608 // It would have been better if we could just remove the entry 609 // from the map. Because of that, we have to filter the garbage 610 // (second.empty) in the subsequence analysis. 611 UseToReachingDefs[Elem].clear(); 612 } 613} 614 615/// Based on the use to defs information (in ADRPMode), compute the 616/// opportunities of LOH ADRP-related. 617static void computeADRP(const InstrToInstrs &UseToDefs, 618 AArch64FunctionInfo &AArch64FI, 619 const MachineDominatorTree *MDT) { 620 DEBUG(dbgs() << "*** Compute LOH for ADRP\n"); 621 for (const auto &Entry : UseToDefs) { 622 unsigned Size = Entry.second.size(); 623 if (Size == 0) 624 continue; 625 if (Size == 1) { 626 const MachineInstr *L2 = *Entry.second.begin(); 627 const MachineInstr *L1 = Entry.first; 628 if (!MDT->dominates(L2, L1)) { 629 DEBUG(dbgs() << "Dominance check failed:\n" << *L2 << '\n' << *L1 630 << '\n'); 631 continue; 632 } 633 DEBUG(dbgs() << "Record AdrpAdrp:\n" << *L2 << '\n' << *L1 << '\n'); 634 SmallVector<const MachineInstr *, 2> Args; 635 Args.push_back(L2); 636 Args.push_back(L1); 637 AArch64FI.addLOHDirective(MCLOH_AdrpAdrp, Args); 638 ++NumADRPSimpleCandidate; 639 } 640#ifdef DEBUG 641 else if (Size == 2) 642 ++NumADRPComplexCandidate2; 643 else if (Size == 3) 644 ++NumADRPComplexCandidate3; 645 else 646 ++NumADRPComplexCandidateOther; 647#endif 648 // if Size < 1, the use should have been removed from the candidates 649 assert(Size >= 1 && "No reaching defs for that use!"); 650 } 651} 652 653/// Check whether the given instruction can be the end of a LOH chain 654/// involving a load. 655static bool isCandidateLoad(const MachineInstr *Instr) { 656 switch (Instr->getOpcode()) { 657 default: 658 return false; 659 case AArch64::LDRSBWui: 660 case AArch64::LDRSBXui: 661 case AArch64::LDRSHWui: 662 case AArch64::LDRSHXui: 663 case AArch64::LDRSWui: 664 case AArch64::LDRBui: 665 case AArch64::LDRHui: 666 case AArch64::LDRWui: 667 case AArch64::LDRXui: 668 case AArch64::LDRSui: 669 case AArch64::LDRDui: 670 case AArch64::LDRQui: 671 if (Instr->getOperand(2).getTargetFlags() & AArch64II::MO_GOT) 672 return false; 673 return true; 674 } 675 // Unreachable. 676 return false; 677} 678 679/// Check whether the given instruction can load a litteral. 680static bool supportLoadFromLiteral(const MachineInstr *Instr) { 681 switch (Instr->getOpcode()) { 682 default: 683 return false; 684 case AArch64::LDRSWui: 685 case AArch64::LDRWui: 686 case AArch64::LDRXui: 687 case AArch64::LDRSui: 688 case AArch64::LDRDui: 689 case AArch64::LDRQui: 690 return true; 691 } 692 // Unreachable. 693 return false; 694} 695 696/// Check whether the given instruction is a LOH candidate. 697/// \param UseToDefs is used to check that Instr is at the end of LOH supported 698/// chain. 699/// \pre UseToDefs contains only on def per use, i.e., obvious non candidate are 700/// already been filtered out. 701static bool isCandidate(const MachineInstr *Instr, 702 const InstrToInstrs &UseToDefs, 703 const MachineDominatorTree *MDT) { 704 if (!isCandidateLoad(Instr) && !isCandidateStore(Instr)) 705 return false; 706 707 const MachineInstr *Def = *UseToDefs.find(Instr)->second.begin(); 708 if (Def->getOpcode() != AArch64::ADRP) { 709 // At this point, Def is ADDXri or LDRXui of the right type of 710 // symbol, because we filtered out the uses that were not defined 711 // by these kind of instructions (+ ADRP). 712 713 // Check if this forms a simple chain: each intermediate node must 714 // dominates the next one. 715 if (!MDT->dominates(Def, Instr)) 716 return false; 717 // Move one node up in the simple chain. 718 if (UseToDefs.find(Def) == 719 UseToDefs.end() 720 // The map may contain garbage we have to ignore. 721 || 722 UseToDefs.find(Def)->second.empty()) 723 return false; 724 Instr = Def; 725 Def = *UseToDefs.find(Def)->second.begin(); 726 } 727 // Check if we reached the top of the simple chain: 728 // - top is ADRP. 729 // - check the simple chain property: each intermediate node must 730 // dominates the next one. 731 if (Def->getOpcode() == AArch64::ADRP) 732 return MDT->dominates(Def, Instr); 733 return false; 734} 735 736static bool registerADRCandidate(const MachineInstr &Use, 737 const InstrToInstrs &UseToDefs, 738 const InstrToInstrs *DefsPerColorToUses, 739 AArch64FunctionInfo &AArch64FI, 740 SetOfMachineInstr *InvolvedInLOHs, 741 const MapRegToId &RegToId) { 742 // Look for opportunities to turn ADRP -> ADD or 743 // ADRP -> LDR GOTPAGEOFF into ADR. 744 // If ADRP has more than one use. Give up. 745 if (Use.getOpcode() != AArch64::ADDXri && 746 (Use.getOpcode() != AArch64::LDRXui || 747 !(Use.getOperand(2).getTargetFlags() & AArch64II::MO_GOT))) 748 return false; 749 InstrToInstrs::const_iterator It = UseToDefs.find(&Use); 750 // The map may contain garbage that we need to ignore. 751 if (It == UseToDefs.end() || It->second.empty()) 752 return false; 753 const MachineInstr &Def = **It->second.begin(); 754 if (Def.getOpcode() != AArch64::ADRP) 755 return false; 756 // Check the number of users of ADRP. 757 const SetOfMachineInstr *Users = 758 getUses(DefsPerColorToUses, 759 RegToId.find(Def.getOperand(0).getReg())->second, Def); 760 if (Users->size() > 1) { 761 ++NumADRComplexCandidate; 762 return false; 763 } 764 ++NumADRSimpleCandidate; 765 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Def)) && 766 "ADRP already involved in LOH."); 767 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Use)) && 768 "ADD already involved in LOH."); 769 DEBUG(dbgs() << "Record AdrpAdd\n" << Def << '\n' << Use << '\n'); 770 771 SmallVector<const MachineInstr *, 2> Args; 772 Args.push_back(&Def); 773 Args.push_back(&Use); 774 775 AArch64FI.addLOHDirective(Use.getOpcode() == AArch64::ADDXri ? MCLOH_AdrpAdd 776 : MCLOH_AdrpLdrGot, 777 Args); 778 return true; 779} 780 781/// Based on the use to defs information (in non-ADRPMode), compute the 782/// opportunities of LOH non-ADRP-related 783static void computeOthers(const InstrToInstrs &UseToDefs, 784 const InstrToInstrs *DefsPerColorToUses, 785 AArch64FunctionInfo &AArch64FI, const MapRegToId &RegToId, 786 const MachineDominatorTree *MDT) { 787 SetOfMachineInstr *InvolvedInLOHs = nullptr; 788#ifdef DEBUG 789 SetOfMachineInstr InvolvedInLOHsStorage; 790 InvolvedInLOHs = &InvolvedInLOHsStorage; 791#endif // DEBUG 792 DEBUG(dbgs() << "*** Compute LOH for Others\n"); 793 // ADRP -> ADD/LDR -> LDR/STR pattern. 794 // Fall back to ADRP -> ADD pattern if we fail to catch the bigger pattern. 795 796 // FIXME: When the statistics are not important, 797 // This initial filtering loop can be merged into the next loop. 798 // Currently, we didn't do it to have the same code for both DEBUG and 799 // NDEBUG builds. Indeed, the iterator of the second loop would need 800 // to be changed. 801 SetOfMachineInstr PotentialCandidates; 802 SetOfMachineInstr PotentialADROpportunities; 803 for (auto &Use : UseToDefs) { 804 // If no definition is available, this is a non candidate. 805 if (Use.second.empty()) 806 continue; 807 // Keep only instructions that are load or store and at the end of 808 // a ADRP -> ADD/LDR/Nothing chain. 809 // We already filtered out the no-chain cases. 810 if (!isCandidate(Use.first, UseToDefs, MDT)) { 811 PotentialADROpportunities.insert(Use.first); 812 continue; 813 } 814 PotentialCandidates.insert(Use.first); 815 } 816 817 // Make the following distinctions for statistics as the linker does 818 // know how to decode instructions: 819 // - ADD/LDR/Nothing make there different patterns. 820 // - LDR/STR make two different patterns. 821 // Hence, 6 - 1 base patterns. 822 // (because ADRP-> Nothing -> STR is not simplifiable) 823 824 // The linker is only able to have a simple semantic, i.e., if pattern A 825 // do B. 826 // However, we want to see the opportunity we may miss if we were able to 827 // catch more complex cases. 828 829 // PotentialCandidates are result of a chain ADRP -> ADD/LDR -> 830 // A potential candidate becomes a candidate, if its current immediate 831 // operand is zero and all nodes of the chain have respectively only one user 832#ifdef DEBUG 833 SetOfMachineInstr DefsOfPotentialCandidates; 834#endif 835 for (const MachineInstr *Candidate : PotentialCandidates) { 836 // Get the definition of the candidate i.e., ADD or LDR. 837 const MachineInstr *Def = *UseToDefs.find(Candidate)->second.begin(); 838 // Record the elements of the chain. 839 const MachineInstr *L1 = Def; 840 const MachineInstr *L2 = nullptr; 841 unsigned ImmediateDefOpc = Def->getOpcode(); 842 if (Def->getOpcode() != AArch64::ADRP) { 843 // Check the number of users of this node. 844 const SetOfMachineInstr *Users = 845 getUses(DefsPerColorToUses, 846 RegToId.find(Def->getOperand(0).getReg())->second, *Def); 847 if (Users->size() > 1) { 848#ifdef DEBUG 849 // if all the uses of this def are in potential candidate, this is 850 // a complex candidate of level 2. 851 bool IsLevel2 = true; 852 for (const MachineInstr *MI : *Users) { 853 if (!PotentialCandidates.count(MI)) { 854 ++NumTooCplxLvl2; 855 IsLevel2 = false; 856 break; 857 } 858 } 859 if (IsLevel2) 860 ++NumCplxLvl2; 861#endif // DEBUG 862 PotentialADROpportunities.insert(Def); 863 continue; 864 } 865 L2 = Def; 866 Def = *UseToDefs.find(Def)->second.begin(); 867 L1 = Def; 868 } // else the element in the middle of the chain is nothing, thus 869 // Def already contains the first element of the chain. 870 871 // Check the number of users of the first node in the chain, i.e., ADRP 872 const SetOfMachineInstr *Users = 873 getUses(DefsPerColorToUses, 874 RegToId.find(Def->getOperand(0).getReg())->second, *Def); 875 if (Users->size() > 1) { 876#ifdef DEBUG 877 // if all the uses of this def are in the defs of the potential candidate, 878 // this is a complex candidate of level 1 879 if (DefsOfPotentialCandidates.empty()) { 880 // lazy init 881 DefsOfPotentialCandidates = PotentialCandidates; 882 for (const MachineInstr *Candidate : PotentialCandidates) { 883 if (!UseToDefs.find(Candidate)->second.empty()) 884 DefsOfPotentialCandidates.insert( 885 *UseToDefs.find(Candidate)->second.begin()); 886 } 887 } 888 bool Found = false; 889 for (auto &Use : *Users) { 890 if (!DefsOfPotentialCandidates.count(Use)) { 891 ++NumTooCplxLvl1; 892 Found = true; 893 break; 894 } 895 } 896 if (!Found) 897 ++NumCplxLvl1; 898#endif // DEBUG 899 continue; 900 } 901 902 bool IsL2Add = (ImmediateDefOpc == AArch64::ADDXri); 903 // If the chain is three instructions long and ldr is the second element, 904 // then this ldr must load form GOT, otherwise this is not a correct chain. 905 if (L2 && !IsL2Add && L2->getOperand(2).getTargetFlags() != AArch64II::MO_GOT) 906 continue; 907 SmallVector<const MachineInstr *, 3> Args; 908 MCLOHType Kind; 909 if (isCandidateLoad(Candidate)) { 910 if (!L2) { 911 // At this point, the candidate LOH indicates that the ldr instruction 912 // may use a direct access to the symbol. There is not such encoding 913 // for loads of byte and half. 914 if (!supportLoadFromLiteral(Candidate)) 915 continue; 916 917 DEBUG(dbgs() << "Record AdrpLdr:\n" << *L1 << '\n' << *Candidate 918 << '\n'); 919 Kind = MCLOH_AdrpLdr; 920 Args.push_back(L1); 921 Args.push_back(Candidate); 922 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) && 923 "L1 already involved in LOH."); 924 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) && 925 "Candidate already involved in LOH."); 926 ++NumADRPToLDR; 927 } else { 928 DEBUG(dbgs() << "Record Adrp" << (IsL2Add ? "Add" : "LdrGot") 929 << "Ldr:\n" << *L1 << '\n' << *L2 << '\n' << *Candidate 930 << '\n'); 931 932 Kind = IsL2Add ? MCLOH_AdrpAddLdr : MCLOH_AdrpLdrGotLdr; 933 Args.push_back(L1); 934 Args.push_back(L2); 935 Args.push_back(Candidate); 936 937 PotentialADROpportunities.remove(L2); 938 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) && 939 "L1 already involved in LOH."); 940 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L2)) && 941 "L2 already involved in LOH."); 942 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) && 943 "Candidate already involved in LOH."); 944#ifdef DEBUG 945 // get the immediate of the load 946 if (Candidate->getOperand(2).getImm() == 0) 947 if (ImmediateDefOpc == AArch64::ADDXri) 948 ++NumADDToLDR; 949 else 950 ++NumLDRToLDR; 951 else if (ImmediateDefOpc == AArch64::ADDXri) 952 ++NumADDToLDRWithImm; 953 else 954 ++NumLDRToLDRWithImm; 955#endif // DEBUG 956 } 957 } else { 958 if (ImmediateDefOpc == AArch64::ADRP) 959 continue; 960 else { 961 962 DEBUG(dbgs() << "Record Adrp" << (IsL2Add ? "Add" : "LdrGot") 963 << "Str:\n" << *L1 << '\n' << *L2 << '\n' << *Candidate 964 << '\n'); 965 966 Kind = IsL2Add ? MCLOH_AdrpAddStr : MCLOH_AdrpLdrGotStr; 967 Args.push_back(L1); 968 Args.push_back(L2); 969 Args.push_back(Candidate); 970 971 PotentialADROpportunities.remove(L2); 972 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L1)) && 973 "L1 already involved in LOH."); 974 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(L2)) && 975 "L2 already involved in LOH."); 976 assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Candidate)) && 977 "Candidate already involved in LOH."); 978#ifdef DEBUG 979 // get the immediate of the store 980 if (Candidate->getOperand(2).getImm() == 0) 981 if (ImmediateDefOpc == AArch64::ADDXri) 982 ++NumADDToSTR; 983 else 984 ++NumLDRToSTR; 985 else if (ImmediateDefOpc == AArch64::ADDXri) 986 ++NumADDToSTRWithImm; 987 else 988 ++NumLDRToSTRWithImm; 989#endif // DEBUG 990 } 991 } 992 AArch64FI.addLOHDirective(Kind, Args); 993 } 994 995 // Now, we grabbed all the big patterns, check ADR opportunities. 996 for (const MachineInstr *Candidate : PotentialADROpportunities) 997 registerADRCandidate(*Candidate, UseToDefs, DefsPerColorToUses, AArch64FI, 998 InvolvedInLOHs, RegToId); 999} 1000 1001/// Look for every register defined by potential LOHs candidates. 1002/// Map these registers with dense id in @p RegToId and vice-versa in 1003/// @p IdToReg. @p IdToReg is populated only in DEBUG mode. 1004static void collectInvolvedReg(MachineFunction &MF, MapRegToId &RegToId, 1005 MapIdToReg &IdToReg, 1006 const TargetRegisterInfo *TRI) { 1007 unsigned CurRegId = 0; 1008 if (!PreCollectRegister) { 1009 unsigned NbReg = TRI->getNumRegs(); 1010 for (; CurRegId < NbReg; ++CurRegId) { 1011 RegToId[CurRegId] = CurRegId; 1012 DEBUG(IdToReg.push_back(CurRegId)); 1013 DEBUG(assert(IdToReg[CurRegId] == CurRegId && "Reg index mismatches")); 1014 } 1015 return; 1016 } 1017 1018 DEBUG(dbgs() << "** Collect Involved Register\n"); 1019 for (const auto &MBB : MF) { 1020 for (const MachineInstr &MI : MBB) { 1021 if (!canDefBePartOfLOH(&MI)) 1022 continue; 1023 1024 // Process defs 1025 for (MachineInstr::const_mop_iterator IO = MI.operands_begin(), 1026 IOEnd = MI.operands_end(); 1027 IO != IOEnd; ++IO) { 1028 if (!IO->isReg() || !IO->isDef()) 1029 continue; 1030 unsigned CurReg = IO->getReg(); 1031 for (MCRegAliasIterator AI(CurReg, TRI, true); AI.isValid(); ++AI) 1032 if (RegToId.find(*AI) == RegToId.end()) { 1033 DEBUG(IdToReg.push_back(*AI); 1034 assert(IdToReg[CurRegId] == *AI && 1035 "Reg index mismatches insertion index.")); 1036 RegToId[*AI] = CurRegId++; 1037 DEBUG(dbgs() << "Register: " << PrintReg(*AI, TRI) << '\n'); 1038 } 1039 } 1040 } 1041 } 1042} 1043 1044bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) { 1045 const TargetMachine &TM = MF.getTarget(); 1046 const TargetRegisterInfo *TRI = TM.getRegisterInfo(); 1047 const MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>(); 1048 1049 MapRegToId RegToId; 1050 MapIdToReg IdToReg; 1051 AArch64FunctionInfo *AArch64FI = MF.getInfo<AArch64FunctionInfo>(); 1052 assert(AArch64FI && "No MachineFunctionInfo for this function!"); 1053 1054 DEBUG(dbgs() << "Looking for LOH in " << MF.getName() << '\n'); 1055 1056 collectInvolvedReg(MF, RegToId, IdToReg, TRI); 1057 if (RegToId.empty()) 1058 return false; 1059 1060 MachineInstr *DummyOp = nullptr; 1061 if (BasicBlockScopeOnly) { 1062 const AArch64InstrInfo *TII = 1063 static_cast<const AArch64InstrInfo *>(TM.getInstrInfo()); 1064 // For local analysis, create a dummy operation to record uses that are not 1065 // local. 1066 DummyOp = MF.CreateMachineInstr(TII->get(AArch64::COPY), DebugLoc()); 1067 } 1068 1069 unsigned NbReg = RegToId.size(); 1070 bool Modified = false; 1071 1072 // Start with ADRP. 1073 InstrToInstrs *ColorOpToReachedUses = new InstrToInstrs[NbReg]; 1074 1075 // Compute the reaching def in ADRP mode, meaning ADRP definitions 1076 // are first considered as uses. 1077 reachingDef(MF, ColorOpToReachedUses, RegToId, true, DummyOp); 1078 DEBUG(dbgs() << "ADRP reaching defs\n"); 1079 DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg)); 1080 1081 // Translate the definition to uses map into a use to definitions map to ease 1082 // statistic computation. 1083 InstrToInstrs ADRPToReachingDefs; 1084 reachedUsesToDefs(ADRPToReachingDefs, ColorOpToReachedUses, RegToId, true); 1085 1086 // Compute LOH for ADRP. 1087 computeADRP(ADRPToReachingDefs, *AArch64FI, MDT); 1088 delete[] ColorOpToReachedUses; 1089 1090 // Continue with general ADRP -> ADD/LDR -> LDR/STR pattern. 1091 ColorOpToReachedUses = new InstrToInstrs[NbReg]; 1092 1093 // first perform a regular reaching def analysis. 1094 reachingDef(MF, ColorOpToReachedUses, RegToId, false, DummyOp); 1095 DEBUG(dbgs() << "All reaching defs\n"); 1096 DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg)); 1097 1098 // Turn that into a use to defs to ease statistic computation. 1099 InstrToInstrs UsesToReachingDefs; 1100 reachedUsesToDefs(UsesToReachingDefs, ColorOpToReachedUses, RegToId, false); 1101 1102 // Compute other than AdrpAdrp LOH. 1103 computeOthers(UsesToReachingDefs, ColorOpToReachedUses, *AArch64FI, RegToId, 1104 MDT); 1105 delete[] ColorOpToReachedUses; 1106 1107 if (BasicBlockScopeOnly) 1108 MF.DeleteMachineInstr(DummyOp); 1109 1110 return Modified; 1111} 1112 1113/// createAArch64CollectLOHPass - returns an instance of the Statistic for 1114/// linker optimization pass. 1115FunctionPass *llvm::createAArch64CollectLOHPass() { 1116 return new AArch64CollectLOH(); 1117} 1118