LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64CollectLOH.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 159 162 98.1 %
Date: 2018-10-20 13:21:21 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "llvm/ADT/BitVector.h"
     105             : #include "llvm/ADT/DenseMap.h"
     106             : #include "llvm/ADT/MapVector.h"
     107             : #include "llvm/ADT/SmallVector.h"
     108             : #include "llvm/ADT/Statistic.h"
     109             : #include "llvm/CodeGen/MachineBasicBlock.h"
     110             : #include "llvm/CodeGen/MachineFunctionPass.h"
     111             : #include "llvm/CodeGen/MachineInstr.h"
     112             : #include "llvm/CodeGen/TargetRegisterInfo.h"
     113             : #include "llvm/Support/Debug.h"
     114             : #include "llvm/Support/ErrorHandling.h"
     115             : #include "llvm/Support/raw_ostream.h"
     116             : #include "llvm/Target/TargetMachine.h"
     117             : using namespace llvm;
     118             : 
     119             : #define DEBUG_TYPE "aarch64-collect-loh"
     120             : 
     121             : STATISTIC(NumADRPSimpleCandidate,
     122             :           "Number of simplifiable ADRP dominate by another");
     123             : STATISTIC(NumADDToSTR, "Number of simplifiable STR reachable by ADD");
     124             : STATISTIC(NumLDRToSTR, "Number of simplifiable STR reachable by LDR");
     125             : STATISTIC(NumADDToLDR, "Number of simplifiable LDR reachable by ADD");
     126             : STATISTIC(NumLDRToLDR, "Number of simplifiable LDR reachable by LDR");
     127             : STATISTIC(NumADRPToLDR, "Number of simplifiable LDR reachable by ADRP");
     128             : STATISTIC(NumADRSimpleCandidate, "Number of simplifiable ADRP + ADD");
     129             : 
     130             : #define AARCH64_COLLECT_LOH_NAME "AArch64 Collect Linker Optimization Hint (LOH)"
     131             : 
     132             : namespace {
     133             : 
     134             : struct AArch64CollectLOH : public MachineFunctionPass {
     135             :   static char ID;
     136         261 :   AArch64CollectLOH() : MachineFunctionPass(ID) {}
     137             : 
     138             :   bool runOnMachineFunction(MachineFunction &MF) override;
     139             : 
     140         255 :   MachineFunctionProperties getRequiredProperties() const override {
     141         255 :     return MachineFunctionProperties().set(
     142         255 :         MachineFunctionProperties::Property::NoVRegs);
     143             :   }
     144             : 
     145         255 :   StringRef getPassName() const override { return AARCH64_COLLECT_LOH_NAME; }
     146             : 
     147         255 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
     148         255 :     MachineFunctionPass::getAnalysisUsage(AU);
     149             :     AU.setPreservesAll();
     150         255 :   }
     151             : };
     152             : 
     153             : char AArch64CollectLOH::ID = 0;
     154             : 
     155             : } // end anonymous namespace.
     156             : 
     157      199032 : INITIALIZE_PASS(AArch64CollectLOH, "aarch64-collect-loh",
     158             :                 AARCH64_COLLECT_LOH_NAME, false, false)
     159             : 
     160             : static bool canAddBePartOfLOH(const MachineInstr &MI) {
     161             :   // Check immediate to see if the immediate is an address.
     162         431 :   switch (MI.getOperand(2).getType()) {
     163             :   default:
     164             :     return false;
     165             :   case MachineOperand::MO_GlobalAddress:
     166             :   case MachineOperand::MO_JumpTableIndex:
     167             :   case MachineOperand::MO_ConstantPoolIndex:
     168             :   case MachineOperand::MO_BlockAddress:
     169             :     return true;
     170             :   }
     171             : }
     172             : 
     173             : /// Answer the following question: Can Def be one of the definition
     174             : /// involved in a part of a LOH?
     175         833 : static bool canDefBePartOfLOH(const MachineInstr &MI) {
     176             :   // Accept ADRP, ADDLow and LOADGot.
     177        1666 :   switch (MI.getOpcode()) {
     178             :   default:
     179             :     return false;
     180           0 :   case AArch64::ADRP:
     181           0 :     return true;
     182             :   case AArch64::ADDXri:
     183             :     return canAddBePartOfLOH(MI);
     184         405 :   case AArch64::LDRXui:
     185             :     // Check immediate to see if the immediate is an address.
     186         810 :     switch (MI.getOperand(2).getType()) {
     187             :     default:
     188             :       return false;
     189             :     case MachineOperand::MO_GlobalAddress:
     190         146 :       return MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT;
     191             :     }
     192             :   }
     193             : }
     194             : 
     195             : /// Check whether the given instruction can the end of a LOH chain involving a
     196             : /// store.
     197        8625 : static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO) {
     198        8625 :   switch (MI.getOpcode()) {
     199             :   default:
     200             :     return false;
     201             :   case AArch64::STRBBui:
     202             :   case AArch64::STRHHui:
     203             :   case AArch64::STRBui:
     204             :   case AArch64::STRHui:
     205             :   case AArch64::STRWui:
     206             :   case AArch64::STRXui:
     207             :   case AArch64::STRSui:
     208             :   case AArch64::STRDui:
     209             :   case AArch64::STRQui:
     210             :     // We can only optimize the index operand.
     211             :     // In case we have str xA, [xA, #imm], this is two different uses
     212             :     // of xA and we cannot fold, otherwise the xA stored may be wrong,
     213             :     // even if #imm == 0.
     214        1381 :     return MI.getOperandNo(&MO) == 1 &&
     215         537 :            MI.getOperand(0).getReg() != MI.getOperand(1).getReg();
     216             :   }
     217             : }
     218             : 
     219             : /// Check whether the given instruction can be the end of a LOH chain
     220             : /// involving a load.
     221        8860 : static bool isCandidateLoad(const MachineInstr &MI) {
     222       17720 :   switch (MI.getOpcode()) {
     223             :   default:
     224             :     return false;
     225         306 :   case AArch64::LDRSBWui:
     226             :   case AArch64::LDRSBXui:
     227             :   case AArch64::LDRSHWui:
     228             :   case AArch64::LDRSHXui:
     229             :   case AArch64::LDRSWui:
     230             :   case AArch64::LDRBui:
     231             :   case AArch64::LDRHui:
     232             :   case AArch64::LDRWui:
     233             :   case AArch64::LDRXui:
     234             :   case AArch64::LDRSui:
     235             :   case AArch64::LDRDui:
     236             :   case AArch64::LDRQui:
     237         612 :     return !(MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT);
     238             :   }
     239             : }
     240             : 
     241             : /// Check whether the given instruction can load a litteral.
     242             : static bool supportLoadFromLiteral(const MachineInstr &MI) {
     243          63 :   switch (MI.getOpcode()) {
     244             :   default:
     245             :     return false;
     246             :   case AArch64::LDRSWui:
     247             :   case AArch64::LDRWui:
     248             :   case AArch64::LDRXui:
     249             :   case AArch64::LDRSui:
     250             :   case AArch64::LDRDui:
     251             :   case AArch64::LDRQui:
     252             :     return true;
     253             :   }
     254             : }
     255             : 
     256             : /// Number of GPR registers traked by mapRegToGPRIndex()
     257             : static const unsigned N_GPR_REGS = 31;
     258             : /// Map register number to index from 0-30.
     259             : static int mapRegToGPRIndex(MCPhysReg Reg) {
     260             :   static_assert(AArch64::X28 - AArch64::X0 + 3 == N_GPR_REGS, "Number of GPRs");
     261             :   static_assert(AArch64::W30 - AArch64::W0 + 1 == N_GPR_REGS, "Number of GPRs");
     262       49647 :   if (AArch64::X0 <= Reg && Reg <= AArch64::X28)
     263       18047 :     return Reg - AArch64::X0;
     264       31600 :   if (AArch64::W0 <= Reg && Reg <= AArch64::W30)
     265       11403 :     return Reg - AArch64::W0;
     266             :   // TableGen gives "FP" and "LR" an index not adjacent to X28 so we have to
     267             :   // handle them as special cases.
     268       20197 :   if (Reg == AArch64::FP)
     269             :     return 29;
     270       19346 :   if (Reg == AArch64::LR)
     271             :     return 30;
     272             :   return -1;
     273             : }
     274             : 
     275             : /// State tracked per register.
     276             : /// The main algorithm walks backwards over a basic block maintaining this
     277             : /// datastructure for each tracked general purpose register.
     278             : struct LOHInfo {
     279             :   MCLOHType Type : 8;           ///< "Best" type of LOH possible.
     280             :   bool IsCandidate : 1;         ///< Possible LOH candidate.
     281             :   bool OneUser : 1;             ///< Found exactly one user (yet).
     282             :   bool MultiUsers : 1;          ///< Found multiple users.
     283             :   const MachineInstr *MI0;      ///< First instruction involved in the LOH.
     284             :   const MachineInstr *MI1;      ///< Second instruction involved in the LOH
     285             :                                 ///  (if any).
     286             :   const MachineInstr *LastADRP; ///< Last ADRP in same register.
     287             : };
     288             : 
     289             : /// Update state \p Info given \p MI uses the tracked register.
     290       10213 : static void handleUse(const MachineInstr &MI, const MachineOperand &MO,
     291             :                       LOHInfo &Info) {
     292             :   // We have multiple uses if we already found one before.
     293       10213 :   if (Info.MultiUsers || Info.OneUser) {
     294        1353 :     Info.IsCandidate = false;
     295        1353 :     Info.MultiUsers = true;
     296        1353 :     return;
     297             :   }
     298        8860 :   Info.OneUser = true;
     299             : 
     300             :   // Start new LOHInfo if applicable.
     301        8860 :   if (isCandidateLoad(MI)) {
     302         235 :     Info.Type = MCLOH_AdrpLdr;
     303         235 :     Info.IsCandidate = true;
     304         235 :     Info.MI0 = &MI;
     305             :     // Note that even this is AdrpLdr now, we can switch to a Ldr variant
     306             :     // later.
     307        8625 :   } else if (isCandidateStore(MI, MO)) {
     308         537 :     Info.Type = MCLOH_AdrpAddStr;
     309         537 :     Info.IsCandidate = true;
     310         537 :     Info.MI0 = &MI;
     311         537 :     Info.MI1 = nullptr;
     312       16176 :   } else if (MI.getOpcode() == AArch64::ADDXri) {
     313          87 :     Info.Type = MCLOH_AdrpAdd;
     314          87 :     Info.IsCandidate = true;
     315          87 :     Info.MI0 = &MI;
     316        8001 :   } else if (MI.getOpcode() == AArch64::LDRXui &&
     317         142 :              MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) {
     318          71 :     Info.Type = MCLOH_AdrpLdrGot;
     319          71 :     Info.IsCandidate = true;
     320          71 :     Info.MI0 = &MI;
     321             :   }
     322             : }
     323             : 
     324             : /// Update state \p Info given the tracked register is clobbered.
     325             : static void handleClobber(LOHInfo &Info) {
     326       19110 :   Info.IsCandidate = false;
     327       19110 :   Info.OneUser = false;
     328       19110 :   Info.MultiUsers = false;
     329       18813 :   Info.LastADRP = nullptr;
     330             : }
     331             : 
     332             : /// Update state \p Info given that \p MI is possibly the middle instruction
     333             : /// of an LOH involving 3 instructions.
     334         140 : static bool handleMiddleInst(const MachineInstr &MI, LOHInfo &DefInfo,
     335             :                              LOHInfo &OpInfo) {
     336         140 :   if (!DefInfo.IsCandidate || (&DefInfo != &OpInfo && OpInfo.OneUser))
     337             :     return false;
     338             :   // Copy LOHInfo for dest register to LOHInfo for source register.
     339          55 :   if (&DefInfo != &OpInfo) {
     340           0 :     OpInfo = DefInfo;
     341             :     // Invalidate \p DefInfo because we track it in \p OpInfo now.
     342             :     handleClobber(DefInfo);
     343             :   } else
     344          55 :     DefInfo.LastADRP = nullptr;
     345             : 
     346             :   // Advance state machine.
     347             :   assert(OpInfo.IsCandidate && "Expect valid state");
     348         110 :   if (MI.getOpcode() == AArch64::ADDXri && canAddBePartOfLOH(MI)) {
     349           3 :     if (OpInfo.Type == MCLOH_AdrpLdr) {
     350           2 :       OpInfo.Type = MCLOH_AdrpAddLdr;
     351           2 :       OpInfo.IsCandidate = true;
     352           2 :       OpInfo.MI1 = &MI;
     353           2 :       return true;
     354           1 :     } else if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
     355           1 :       OpInfo.Type = MCLOH_AdrpAddStr;
     356           1 :       OpInfo.IsCandidate = true;
     357           1 :       OpInfo.MI1 = &MI;
     358           1 :       return true;
     359             :     }
     360             :   } else {
     361             :     assert(MI.getOpcode() == AArch64::LDRXui && "Expect LDRXui");
     362             :     assert((MI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) &&
     363             :            "Expected GOT relocation");
     364          52 :     if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {
     365          14 :       OpInfo.Type = MCLOH_AdrpLdrGotStr;
     366          14 :       OpInfo.IsCandidate = true;
     367          14 :       OpInfo.MI1 = &MI;
     368          14 :       return true;
     369          38 :     } else if (OpInfo.Type == MCLOH_AdrpLdr) {
     370          38 :       OpInfo.Type = MCLOH_AdrpLdrGotLdr;
     371          38 :       OpInfo.IsCandidate = true;
     372          38 :       OpInfo.MI1 = &MI;
     373          38 :       return true;
     374             :     }
     375             :   }
     376             :   return false;
     377             : }
     378             : 
     379             : /// Update state when seeing and ADRP instruction.
     380         297 : static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI,
     381             :                        LOHInfo &Info) {
     382         297 :   if (Info.LastADRP != nullptr) {
     383             :     LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdrp:\n"
     384             :                       << '\t' << MI << '\t' << *Info.LastADRP);
     385          22 :     AFI.addLOHDirective(MCLOH_AdrpAdrp, {&MI, Info.LastADRP});
     386             :     ++NumADRPSimpleCandidate;
     387             :   }
     388             : 
     389             :   // Produce LOH directive if possible.
     390         297 :   if (Info.IsCandidate) {
     391         271 :     switch (Info.Type) {
     392          22 :     case MCLOH_AdrpAdd:
     393             :       LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAdd:\n"
     394             :                         << '\t' << MI << '\t' << *Info.MI0);
     395          44 :       AFI.addLOHDirective(MCLOH_AdrpAdd, {&MI, Info.MI0});
     396             :       ++NumADRSimpleCandidate;
     397             :       break;
     398          63 :     case MCLOH_AdrpLdr:
     399          63 :       if (supportLoadFromLiteral(*Info.MI0)) {
     400             :         LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdr:\n"
     401             :                           << '\t' << MI << '\t' << *Info.MI0);
     402         124 :         AFI.addLOHDirective(MCLOH_AdrpLdr, {&MI, Info.MI0});
     403             :         ++NumADRPToLDR;
     404             :       }
     405             :       break;
     406           2 :     case MCLOH_AdrpAddLdr:
     407             :       LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddLdr:\n"
     408             :                         << '\t' << MI << '\t' << *Info.MI1 << '\t'
     409             :                         << *Info.MI0);
     410           4 :       AFI.addLOHDirective(MCLOH_AdrpAddLdr, {&MI, Info.MI1, Info.MI0});
     411             :       ++NumADDToLDR;
     412             :       break;
     413          61 :     case MCLOH_AdrpAddStr:
     414          61 :       if (Info.MI1 != nullptr) {
     415             :         LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddStr:\n"
     416             :                           << '\t' << MI << '\t' << *Info.MI1 << '\t'
     417             :                           << *Info.MI0);
     418           2 :         AFI.addLOHDirective(MCLOH_AdrpAddStr, {&MI, Info.MI1, Info.MI0});
     419             :         ++NumADDToSTR;
     420             :       }
     421             :       break;
     422          38 :     case MCLOH_AdrpLdrGotLdr:
     423             :       LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotLdr:\n"
     424             :                         << '\t' << MI << '\t' << *Info.MI1 << '\t'
     425             :                         << *Info.MI0);
     426          76 :       AFI.addLOHDirective(MCLOH_AdrpLdrGotLdr, {&MI, Info.MI1, Info.MI0});
     427             :       ++NumLDRToLDR;
     428             :       break;
     429          14 :     case MCLOH_AdrpLdrGotStr:
     430             :       LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGotStr:\n"
     431             :                         << '\t' << MI << '\t' << *Info.MI1 << '\t'
     432             :                         << *Info.MI0);
     433          28 :       AFI.addLOHDirective(MCLOH_AdrpLdrGotStr, {&MI, Info.MI1, Info.MI0});
     434             :       ++NumLDRToSTR;
     435             :       break;
     436          71 :     case MCLOH_AdrpLdrGot:
     437             :       LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpLdrGot:\n"
     438             :                         << '\t' << MI << '\t' << *Info.MI0);
     439         142 :       AFI.addLOHDirective(MCLOH_AdrpLdrGot, {&MI, Info.MI0});
     440          71 :       break;
     441             :     case MCLOH_AdrpAdrp:
     442             :       llvm_unreachable("MCLOH_AdrpAdrp not used in state machine");
     443             :     }
     444             :   }
     445             : 
     446             :   handleClobber(Info);
     447         297 :   Info.LastADRP = &MI;
     448         297 : }
     449             : 
     450       20800 : static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg,
     451             :                                  LOHInfo *LOHInfos) {
     452       41600 :   if (!MachineOperand::clobbersPhysReg(RegMask, Reg))
     453             :     return;
     454       11994 :   int Idx = mapRegToGPRIndex(Reg);
     455       11326 :   if (Idx >= 0)
     456       11344 :     handleClobber(LOHInfos[Idx]);
     457             : }
     458             : 
     459       13962 : static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos) {
     460             :   // Handle defs and regmasks.
     461       66559 :   for (const MachineOperand &MO : MI.operands()) {
     462       52597 :     if (MO.isRegMask()) {
     463         325 :       const uint32_t *RegMask = MO.getRegMask();
     464       10725 :       for (MCPhysReg Reg : AArch64::GPR32RegClass)
     465       10400 :         handleRegMaskClobber(RegMask, Reg, LOHInfos);
     466       10725 :       for (MCPhysReg Reg : AArch64::GPR64RegClass)
     467       10400 :         handleRegMaskClobber(RegMask, Reg, LOHInfos);
     468             :       continue;
     469             :     }
     470       52272 :     if (!MO.isReg() || !MO.isDef())
     471             :       continue;
     472       14325 :     int Idx = mapRegToGPRIndex(MO.getReg());
     473        6475 :     if (Idx < 0)
     474             :       continue;
     475        7469 :     handleClobber(LOHInfos[Idx]);
     476             :   }
     477             :   // Handle uses.
     478       57329 :   for (const MachineOperand &MO : MI.uses()) {
     479       43367 :     if (!MO.isReg() || !MO.readsReg())
     480             :       continue;
     481       20828 :     int Idx = mapRegToGPRIndex(MO.getReg());
     482        9501 :     if (Idx < 0)
     483             :       continue;
     484       10213 :     handleUse(MI, MO, LOHInfos[Idx]);
     485             :   }
     486       13962 : }
     487             : 
     488        2195 : bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
     489        2195 :   if (skipFunction(MF.getFunction()))
     490             :     return false;
     491             : 
     492             :   LLVM_DEBUG(dbgs() << "********** AArch64 Collect LOH **********\n"
     493             :                     << "Looking in function " << MF.getName() << '\n');
     494             : 
     495             :   LOHInfo LOHInfos[N_GPR_REGS];
     496        2195 :   AArch64FunctionInfo &AFI = *MF.getInfo<AArch64FunctionInfo>();
     497        5110 :   for (const MachineBasicBlock &MBB : MF) {
     498             :     // Reset register tracking state.
     499        2915 :     memset(LOHInfos, 0, sizeof(LOHInfos));
     500             :     // Live-out registers are used.
     501        3869 :     for (const MachineBasicBlock *Succ : MBB.successors()) {
     502        2877 :       for (const auto &LI : Succ->liveins()) {
     503        1923 :         int RegIdx = mapRegToGPRIndex(LI.PhysReg);
     504        1571 :         if (RegIdx >= 0)
     505        1669 :           LOHInfos[RegIdx].OneUser = true;
     506             :       }
     507             :     }
     508             : 
     509             :     // Walk the basic block backwards and update the per register state machine
     510             :     // in the process.
     511       17229 :     for (const MachineInstr &MI : make_range(MBB.rbegin(), MBB.rend())) {
     512       14314 :       unsigned Opcode = MI.getOpcode();
     513       14314 :       switch (Opcode) {
     514         833 :       case AArch64::ADDXri:
     515             :       case AArch64::LDRXui:
     516         833 :         if (canDefBePartOfLOH(MI)) {
     517         140 :           const MachineOperand &Def = MI.getOperand(0);
     518             :           const MachineOperand &Op = MI.getOperand(1);
     519             :           assert(Def.isReg() && Def.isDef() && "Expected reg def");
     520             :           assert(Op.isReg() && Op.isUse() && "Expected reg use");
     521         140 :           int DefIdx = mapRegToGPRIndex(Def.getReg());
     522         140 :           int OpIdx = mapRegToGPRIndex(Op.getReg());
     523         280 :           if (DefIdx >= 0 && OpIdx >= 0 &&
     524         140 :               handleMiddleInst(MI, LOHInfos[DefIdx], LOHInfos[OpIdx]))
     525             :             continue;
     526             :         }
     527             :         break;
     528         297 :       case AArch64::ADRP:
     529         297 :         const MachineOperand &Op0 = MI.getOperand(0);
     530         297 :         int Idx = mapRegToGPRIndex(Op0.getReg());
     531         297 :         if (Idx >= 0) {
     532         297 :           handleADRP(MI, AFI, LOHInfos[Idx]);
     533         297 :           continue;
     534             :         }
     535             :         break;
     536             :       }
     537       13962 :       handleNormalInst(MI, LOHInfos);
     538             :     }
     539             :   }
     540             : 
     541             :   // Return "no change": The pass only collects information.
     542             :   return false;
     543             : }
     544             : 
     545         261 : FunctionPass *llvm::createAArch64CollectLOHPass() {
     546         261 :   return new AArch64CollectLOH();
     547             : }

Generated by: LCOV version 1.13