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 : }
|