LLVM 22.0.0git
AArch64LowerHomogeneousPrologEpilog.cpp
Go to the documentation of this file.
1//===- AArch64LowerHomogeneousPrologEpilog.cpp ----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a pass that lowers homogeneous prolog/epilog instructions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64InstrInfo.h"
14#include "AArch64Subtarget.h"
23#include "llvm/IR/DebugLoc.h"
24#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/Module.h"
26#include "llvm/Pass.h"
27#include <optional>
28#include <sstream>
29
30using namespace llvm;
31
32#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME \
33 "AArch64 homogeneous prolog/epilog lowering pass"
34
36 "frame-helper-size-threshold", cl::init(2), cl::Hidden,
37 cl::desc("The minimum number of instructions that are outlined in a frame "
38 "helper (default = 2)"));
39
40namespace {
41
42class AArch64LowerHomogeneousPE {
43public:
44 const AArch64InstrInfo *TII;
45
46 AArch64LowerHomogeneousPE(Module *M, MachineModuleInfo *MMI)
47 : M(M), MMI(MMI) {}
48
49 bool run();
50 bool runOnMachineFunction(MachineFunction &Fn);
51
52private:
53 Module *M;
54 MachineModuleInfo *MMI;
55
56 bool runOnMBB(MachineBasicBlock &MBB);
57 bool runOnMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
59
60 /// Lower a HOM_Prolog pseudo instruction into a helper call
61 /// or a sequence of homogeneous stores.
62 /// When a fp setup follows, it can be optimized.
63 bool lowerProlog(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
65 /// Lower a HOM_Epilog pseudo instruction into a helper call
66 /// or a sequence of homogeneous loads.
67 /// When a return follow, it can be optimized.
68 bool lowerEpilog(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
70};
71
72class AArch64LowerHomogeneousPrologEpilog : public ModulePass {
73public:
74 static char ID;
75
76 AArch64LowerHomogeneousPrologEpilog() : ModulePass(ID) {}
77 void getAnalysisUsage(AnalysisUsage &AU) const override {
78 AU.addRequired<MachineModuleInfoWrapperPass>();
79 AU.addPreserved<MachineModuleInfoWrapperPass>();
80 AU.setPreservesAll();
81 ModulePass::getAnalysisUsage(AU);
82 }
83 bool runOnModule(Module &M) override;
84
85 StringRef getPassName() const override {
87 }
88};
89
90} // end anonymous namespace
91
92char AArch64LowerHomogeneousPrologEpilog::ID = 0;
93
94INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilog,
95 "aarch64-lower-homogeneous-prolog-epilog",
97
98bool AArch64LowerHomogeneousPrologEpilog::runOnModule(Module &M) {
99 if (skipModule(M))
100 return false;
101
102 MachineModuleInfo *MMI =
103 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
104 return AArch64LowerHomogeneousPE(&M, MMI).run();
105}
106
107bool AArch64LowerHomogeneousPE::run() {
108 bool Changed = false;
109 for (auto &F : *M) {
110 if (F.empty())
111 continue;
112
113 MachineFunction *MF = MMI->getMachineFunction(F);
114 if (!MF)
115 continue;
116 Changed |= runOnMachineFunction(*MF);
117 }
118
119 return Changed;
120}
122
123/// Return a frame helper name with the given CSRs and the helper type.
124/// For instance, a prolog helper that saves x19 and x20 is named as
125/// OUTLINED_FUNCTION_PROLOG_x19x20.
127 FrameHelperType Type, unsigned FpOffset) {
128 std::ostringstream RegStream;
129 switch (Type) {
131 RegStream << "OUTLINED_FUNCTION_PROLOG_";
132 break;
134 RegStream << "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset << "_";
135 break;
137 RegStream << "OUTLINED_FUNCTION_EPILOG_";
138 break;
140 RegStream << "OUTLINED_FUNCTION_EPILOG_TAIL_";
141 break;
142 }
143
144 for (auto Reg : Regs) {
145 if (Reg == AArch64::NoRegister)
146 continue;
148 }
149
150 return RegStream.str();
151}
152
153/// Create a Function for the unique frame helper with the given name.
154/// Return a newly created MachineFunction with an empty MachineBasicBlock.
157 StringRef Name) {
158 LLVMContext &C = M->getContext();
159 Function *F = M->getFunction(Name);
160 assert(F == nullptr && "Function has been created before");
163 assert(F && "Function was null!");
164
165 // Use ODR linkage to avoid duplication.
167 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
168
169 // Set minsize, so we don't insert padding between outlined functions.
170 F->addFnAttr(Attribute::NoInline);
171 F->addFnAttr(Attribute::MinSize);
172 F->addFnAttr(Attribute::Naked);
173
175 // Remove unnecessary register liveness and set NoVRegs.
176 MF.getProperties().resetTracksLiveness().resetIsSSA().setNoVRegs();
178
179 // Create entry block.
180 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
181 IRBuilder<> Builder(EntryBB);
182 Builder.CreateRetVoid();
183
184 // Insert the new block into the function.
186 MF.insert(MF.begin(), MBB);
187
188 return MF;
189}
190
191/// Emit a store-pair instruction for frame-setup.
192/// If Reg2 is AArch64::NoRegister, emit STR instead.
195 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
196 int Offset, bool IsPreDec) {
197 assert(Reg1 != AArch64::NoRegister);
198 const bool IsPaired = Reg2 != AArch64::NoRegister;
199 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
200 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
201 unsigned Opc;
202 if (IsPreDec) {
203 if (IsFloat)
204 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
205 else
206 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
207 } else {
208 if (IsFloat)
209 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
210 else
211 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
212 }
213 // The implicit scale for Offset is 8.
214 TypeSize Scale(0U, false), Width(0U, false);
215 int64_t MinOffset, MaxOffset;
216 [[maybe_unused]] bool Success =
217 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
218 assert(Success && "Invalid Opcode");
219 Offset *= (8 / (int)Scale);
220
221 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
222 if (IsPreDec)
223 MIB.addDef(AArch64::SP);
224 if (IsPaired)
225 MIB.addReg(Reg2);
226 MIB.addReg(Reg1)
227 .addReg(AArch64::SP)
228 .addImm(Offset)
230}
231
232/// Emit a load-pair instruction for frame-destroy.
233/// If Reg2 is AArch64::NoRegister, emit LDR instead.
236 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
237 int Offset, bool IsPostDec) {
238 assert(Reg1 != AArch64::NoRegister);
239 const bool IsPaired = Reg2 != AArch64::NoRegister;
240 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
241 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
242 unsigned Opc;
243 if (IsPostDec) {
244 if (IsFloat)
245 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
246 else
247 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
248 } else {
249 if (IsFloat)
250 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
251 else
252 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
253 }
254 // The implicit scale for Offset is 8.
255 TypeSize Scale(0U, false), Width(0U, false);
256 int64_t MinOffset, MaxOffset;
257 [[maybe_unused]] bool Success =
258 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
259 assert(Success && "Invalid Opcode");
260 Offset *= (8 / (int)Scale);
261
262 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
263 if (IsPostDec)
264 MIB.addDef(AArch64::SP);
265 if (IsPaired)
266 MIB.addReg(Reg2, getDefRegState(true));
267 MIB.addReg(Reg1, getDefRegState(true))
268 .addReg(AArch64::SP)
269 .addImm(Offset)
271}
272
273/// Return a unique function if a helper can be formed with the given Regs
274/// and frame type.
275/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
276/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
277/// stp x20, x19, [sp, #16]
278/// ret
279///
280/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
281/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
282/// stp x20, x19, [sp, #16]
283/// add fp, sp, #32
284/// ret
285///
286/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
287/// mov x16, x30
288/// ldp x29, x30, [sp, #32]
289/// ldp x20, x19, [sp, #16]
290/// ldp x22, x21, [sp], #48
291/// ret x16
292///
293/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
294/// ldp x29, x30, [sp, #32]
295/// ldp x20, x19, [sp, #16]
296/// ldp x22, x21, [sp], #48
297/// ret
298/// @param M module
299/// @param MMI machine module info
300/// @param Regs callee save regs that the helper will handle
301/// @param Type frame helper type
302/// @return a helper function
306 unsigned FpOffset = 0) {
307 assert(Regs.size() >= 2);
308 auto Name = getFrameHelperName(Regs, Type, FpOffset);
309 auto *F = M->getFunction(Name);
310 if (F)
311 return F;
312
313 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
314 MachineBasicBlock &MBB = *MF.begin();
315 const TargetSubtargetInfo &STI = MF.getSubtarget();
316 const TargetInstrInfo &TII = *STI.getInstrInfo();
317
318 int Size = (int)Regs.size();
319 switch (Type) {
322 // Compute the remaining SP adjust beyond FP/LR.
323 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
324
325 // If the register stored to the lowest address is not LR, we must subtract
326 // more from SP here.
327 if (LRIdx != Size - 2) {
328 assert(Regs[Size - 2] != AArch64::LR);
329 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
330 LRIdx - Size + 2, true);
331 }
332
333 // Store CSRs in the reverse order.
334 for (int I = Size - 3; I >= 0; I -= 2) {
335 // FP/LR has been stored at call-site.
336 if (Regs[I - 1] == AArch64::LR)
337 continue;
338 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
339 false);
340 }
342 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
343 .addDef(AArch64::FP)
344 .addUse(AArch64::SP)
345 .addImm(FpOffset)
346 .addImm(0)
348
349 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
350 .addReg(AArch64::LR);
351 break;
352 }
356 // Stash LR to X16
357 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
358 .addDef(AArch64::X16)
359 .addReg(AArch64::XZR)
360 .addUse(AArch64::LR)
361 .addImm(0);
362
363 for (int I = 0; I < Size - 2; I += 2)
364 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
365 false);
366 // Restore the last CSR with post-increment of SP.
367 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
368 true);
369
370 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
371 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
372 break;
373 }
374
375 return M->getFunction(Name);
376}
377
378/// This function checks if a frame helper should be used for
379/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
380/// @param MBB machine basic block
381/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
382/// @param Regs callee save registers that are saved or restored.
383/// @param Type frame helper type
384/// @return True if a use of helper is qualified.
389 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
390 auto RegCount = Regs.size();
391 assert(RegCount > 0 && (RegCount % 2 == 0));
392 // # of instructions that will be outlined.
393 int InstCount = RegCount / 2;
394
395 // Do not use a helper call when not saving LR.
396 if (!llvm::is_contained(Regs, AArch64::LR))
397 return false;
398
399 switch (Type) {
401 // Prolog helper cannot save FP/LR.
402 InstCount--;
403 break;
405 // Effectively no change in InstCount since FpAdjustment is included.
406 break;
407 }
409 // Bail-out if X16 is live across the epilog helper because it is used in
410 // the helper to handle X30.
411 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
412 if (NextMI->readsRegister(AArch64::W16, TRI))
413 return false;
414 }
415 // Epilog may not be in the last block. Check the liveness in successors.
416 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
417 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
418 return false;
419 }
420 // No change in InstCount for the regular epilog case.
421 break;
423 // EpilogTail helper includes the caller's return.
424 if (NextMBBI == MBB.end())
425 return false;
426 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
427 return false;
428 InstCount++;
429 break;
430 }
431 }
432
433 return InstCount >= FrameHelperSizeThreshold;
434}
435
436/// Lower a HOM_Epilog pseudo instruction into a helper call while
437/// creating the helper on demand. Or emit a sequence of loads in place when not
438/// using a helper call.
439///
440/// 1. With a helper including ret
441/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
442/// ret ; NextMBBI
443/// =>
444/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
445/// ... ; NextMBBI
446///
447/// 2. With a helper
448/// HOM_Epilog x30, x29, x19, x20, x21, x22
449/// =>
450/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
451///
452/// 3. Without a helper
453/// HOM_Epilog x30, x29, x19, x20, x21, x22
454/// =>
455/// ldp x29, x30, [sp, #32]
456/// ldp x20, x19, [sp, #16]
457/// ldp x22, x21, [sp], #48
458bool AArch64LowerHomogeneousPE::lowerEpilog(
459 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
460 MachineBasicBlock::iterator &NextMBBI) {
461 auto &MF = *MBB.getParent();
462 MachineInstr &MI = *MBBI;
463
464 DebugLoc DL = MI.getDebugLoc();
465 SmallVector<unsigned, 8> Regs;
466 bool HasUnpairedReg = false;
467 for (auto &MO : MI.operands())
468 if (MO.isReg()) {
469 if (!MO.getReg().isValid()) {
470 // For now we are only expecting unpaired GP registers which should
471 // occur exactly once.
472 assert(!HasUnpairedReg);
473 HasUnpairedReg = true;
474 }
475 Regs.push_back(MO.getReg());
476 }
477 (void)HasUnpairedReg;
478 int Size = (int)Regs.size();
479 if (Size == 0)
480 return false;
481 // Registers are in pair.
482 assert(Size % 2 == 0);
483 assert(MI.getOpcode() == AArch64::HOM_Epilog);
484
485 auto Return = NextMBBI;
486 MachineInstr *HelperCall = nullptr;
488 // When MBB ends with a return, emit a tail-call to the epilog helper
489 auto *EpilogTailHelper =
491 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
492 .addGlobalAddress(EpilogTailHelper)
493 .addImm(0)
496 .copyImplicitOps(*Return);
497 NextMBBI = std::next(Return);
498 Return->removeFromParent();
499 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
501 // The default epilog helper case.
502 auto *EpilogHelper =
504 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
505 .addGlobalAddress(EpilogHelper)
508 } else {
509 // Fall back to no-helper.
510 for (int I = 0; I < Size - 2; I += 2)
511 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
512 // Restore the last CSR with post-increment of SP.
513 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
514 }
515
516 // Make sure all explicit definitions are preserved in the helper call;
517 // implicit ones are already handled by copyImplicitOps.
518 if (HelperCall)
519 for (auto &Def : MBBI->defs())
520 HelperCall->addRegisterDefined(Def.getReg(),
523 return true;
524}
525
526/// Lower a HOM_Prolog pseudo instruction into a helper call while
527/// creating the helper on demand. Or emit a sequence of stores in place when
528/// not using a helper call.
529///
530/// 1. With a helper including frame-setup
531/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
532/// =>
533/// stp x29, x30, [sp, #-16]!
534/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
535///
536/// 2. With a helper
537/// HOM_Prolog x30, x29, x19, x20, x21, x22
538/// =>
539/// stp x29, x30, [sp, #-16]!
540/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
541///
542/// 3. Without a helper
543/// HOM_Prolog x30, x29, x19, x20, x21, x22
544/// =>
545/// stp x22, x21, [sp, #-48]!
546/// stp x20, x19, [sp, #16]
547/// stp x29, x30, [sp, #32]
548bool AArch64LowerHomogeneousPE::lowerProlog(
549 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
550 MachineBasicBlock::iterator &NextMBBI) {
551 auto &MF = *MBB.getParent();
552 MachineInstr &MI = *MBBI;
553
554 DebugLoc DL = MI.getDebugLoc();
555 SmallVector<unsigned, 8> Regs;
556 bool HasUnpairedReg = false;
557 int LRIdx = 0;
558 std::optional<int> FpOffset;
559 for (auto &MO : MI.operands()) {
560 if (MO.isReg()) {
561 if (MO.getReg().isValid()) {
562 if (MO.getReg() == AArch64::LR)
563 LRIdx = Regs.size();
564 } else {
565 // For now we are only expecting unpaired GP registers which should
566 // occur exactly once.
567 assert(!HasUnpairedReg);
568 HasUnpairedReg = true;
569 }
570 Regs.push_back(MO.getReg());
571 } else if (MO.isImm()) {
572 FpOffset = MO.getImm();
573 }
574 }
575 (void)HasUnpairedReg;
576 int Size = (int)Regs.size();
577 if (Size == 0)
578 return false;
579 // Allow compact unwind case only for oww.
580 assert(Size % 2 == 0);
581 assert(MI.getOpcode() == AArch64::HOM_Prolog);
582
583 if (FpOffset &&
585 // FP/LR is stored at the top of stack before the prolog helper call.
586 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
587 auto *PrologFrameHelper = getOrCreateFrameHelper(
588 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
589 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
590 .addGlobalAddress(PrologFrameHelper)
594 .addReg(AArch64::SP, RegState::Implicit);
595 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
597 // FP/LR is stored at the top of stack before the prolog helper call.
598 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
599 auto *PrologHelper =
601 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
602 .addGlobalAddress(PrologHelper)
605 } else {
606 // Fall back to no-helper.
607 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
608 for (int I = Size - 3; I >= 0; I -= 2)
609 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
610 if (FpOffset) {
611 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
612 .addDef(AArch64::FP)
613 .addUse(AArch64::SP)
614 .addImm(*FpOffset)
615 .addImm(0)
617 }
618 }
619
621 return true;
622}
623
624/// Process each machine instruction
625/// @param MBB machine basic block
626/// @param MBBI current instruction iterator
627/// @param NextMBBI next instruction iterator which can be updated
628/// @return True when IR is changed.
629bool AArch64LowerHomogeneousPE::runOnMI(MachineBasicBlock &MBB,
631 MachineBasicBlock::iterator &NextMBBI) {
632 MachineInstr &MI = *MBBI;
633 unsigned Opcode = MI.getOpcode();
634 switch (Opcode) {
635 default:
636 break;
637 case AArch64::HOM_Prolog:
638 return lowerProlog(MBB, MBBI, NextMBBI);
639 case AArch64::HOM_Epilog:
640 return lowerEpilog(MBB, MBBI, NextMBBI);
641 }
642 return false;
643}
644
645bool AArch64LowerHomogeneousPE::runOnMBB(MachineBasicBlock &MBB) {
646 bool Modified = false;
647
649 while (MBBI != E) {
650 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
651 Modified |= runOnMI(MBB, MBBI, NMBBI);
652 MBBI = NMBBI;
653 }
654
655 return Modified;
656}
657
658bool AArch64LowerHomogeneousPE::runOnMachineFunction(MachineFunction &MF) {
659 TII = MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
660
661 bool Modified = false;
662 for (auto &MBB : MF)
663 Modified |= runOnMBB(MBB);
664 return Modified;
665}
666
668 return new AArch64LowerHomogeneousPrologEpilog();
669}
#define Success
static Function * getOrCreateFrameHelper(Module *M, MachineModuleInfo *MMI, SmallVectorImpl< unsigned > &Regs, FrameHelperType Type, unsigned FpOffset=0)
Return a unique function if a helper can be formed with the given Regs and frame type.
static bool shouldUseFrameHelper(MachineBasicBlock &MBB, MachineBasicBlock::iterator &NextMBBI, SmallVectorImpl< unsigned > &Regs, FrameHelperType Type)
This function checks if a frame helper should be used for HOM_Prolog/HOM_Epilog pseudo instruction ex...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME
static cl::opt< int > FrameHelperSizeThreshold("frame-helper-size-threshold", cl::init(2), cl::Hidden, cl::desc("The minimum number of instructions that are outlined in a frame " "helper (default = 2)"))
static std::string getFrameHelperName(SmallVectorImpl< unsigned > &Regs, FrameHelperType Type, unsigned FpOffset)
Return a frame helper name with the given CSRs and the helper type.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
static MachineFunction & createFrameHelperMachineFunction(Module *M, MachineModuleInfo *MMI, StringRef Name)
Create a Function for the unique frame helper with the given name.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
Register Reg
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
A debug info location.
Definition DebugLoc.h:123
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:166
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:56
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:90
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI MachineBasicBlock * removeFromParent()
This method unlinks 'this' from the containing function, and returns it, but does not delete it.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineFunctionProperties & getProperties() const
Get the function properties.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction & getOrCreateMachineFunction(Function &F)
Returns the MachineFunction constructed for the IR function F.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
LLVM_ABI void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
const TargetRegisterInfo * getTargetRegisterInfo() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
TargetInstrInfo - Interface to description of machine instruction set.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
Changed
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1763
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getDefRegState(bool B)
ModulePass * createAArch64LowerHomogeneousPrologEpilogPass()
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1909