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