LLVM 23.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 "AArch64.h"
14#include "AArch64InstrInfo.h"
15#include "AArch64Subtarget.h"
25#include "llvm/IR/DebugLoc.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/Module.h"
28#include "llvm/IR/PassManager.h"
29#include "llvm/Pass.h"
30#include <optional>
31#include <sstream>
32
33using namespace llvm;
34
35#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME \
36 "AArch64 homogeneous prolog/epilog lowering pass"
37
39 "frame-helper-size-threshold", cl::init(2), cl::Hidden,
40 cl::desc("The minimum number of instructions that are outlined in a frame "
41 "helper (default = 2)"));
42
43namespace {
44
45class AArch64LowerHomogeneousPrologEpilogImpl {
46public:
47 const AArch64InstrInfo *TII;
48
49 AArch64LowerHomogeneousPrologEpilogImpl(Module *M, MachineModuleInfo *MMI)
50 : M(M), MMI(MMI) {}
51
52 bool run();
53 bool runOnMachineFunction(MachineFunction &Fn);
54
55private:
56 Module *M;
57 MachineModuleInfo *MMI;
58
59 bool runOnMBB(MachineBasicBlock &MBB);
60 bool runOnMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
62
63 /// Lower a HOM_Prolog pseudo instruction into a helper call
64 /// or a sequence of homogeneous stores.
65 /// When a fp setup follows, it can be optimized.
66 bool lowerProlog(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
68 /// Lower a HOM_Epilog pseudo instruction into a helper call
69 /// or a sequence of homogeneous loads.
70 /// When a return follow, it can be optimized.
71 bool lowerEpilog(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
73};
74
75class AArch64LowerHomogeneousPrologEpilogLegacy : public ModulePass {
76public:
77 static char ID;
78
79 AArch64LowerHomogeneousPrologEpilogLegacy() : ModulePass(ID) {}
80 void getAnalysisUsage(AnalysisUsage &AU) const override {
81 AU.addRequired<MachineModuleInfoWrapperPass>();
82 AU.addPreserved<MachineModuleInfoWrapperPass>();
83 AU.setPreservesAll();
84 ModulePass::getAnalysisUsage(AU);
85 }
86 bool runOnModule(Module &M) override;
87
88 StringRef getPassName() const override {
90 }
91};
92
93} // end anonymous namespace
94
95char AArch64LowerHomogeneousPrologEpilogLegacy::ID = 0;
96
97INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilogLegacy,
98 "aarch64-lower-homogeneous-prolog-epilog",
100
101bool AArch64LowerHomogeneousPrologEpilogLegacy::runOnModule(Module &M) {
102 if (skipModule(M))
103 return false;
104
105 MachineModuleInfo *MMI =
106 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
107 return AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
108}
109
113 MachineModuleInfo *MMI = &MAM.getResult<MachineModuleAnalysis>(M).getMMI();
114 bool Changed = AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
115 if (!Changed)
116 return PreservedAnalyses::all();
119 return PA;
120}
121
122bool AArch64LowerHomogeneousPrologEpilogImpl::run() {
123 bool Changed = false;
124 for (auto &F : *M) {
125 if (F.empty())
126 continue;
127
128 MachineFunction *MF = MMI->getMachineFunction(F);
129 if (!MF)
130 continue;
131 Changed |= runOnMachineFunction(*MF);
132 }
133
134 return Changed;
135}
137
138/// Return a frame helper name with the given CSRs and the helper type.
139/// For instance, a prolog helper that saves x19 and x20 is named as
140/// OUTLINED_FUNCTION_PROLOG_x19x20.
142 FrameHelperType Type, unsigned FpOffset) {
143 std::ostringstream RegStream;
144 switch (Type) {
146 RegStream << "OUTLINED_FUNCTION_PROLOG_";
147 break;
149 RegStream << "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset << "_";
150 break;
152 RegStream << "OUTLINED_FUNCTION_EPILOG_";
153 break;
155 RegStream << "OUTLINED_FUNCTION_EPILOG_TAIL_";
156 break;
157 }
158
159 for (auto Reg : Regs) {
160 if (Reg == AArch64::NoRegister)
161 continue;
163 }
164
165 return RegStream.str();
166}
167
168/// Create a Function for the unique frame helper with the given name.
169/// Return a newly created MachineFunction with an empty MachineBasicBlock.
172 StringRef Name) {
173 LLVMContext &C = M->getContext();
174 Function *F = M->getFunction(Name);
175 assert(F == nullptr && "Function has been created before");
178 assert(F && "Function was null!");
179
180 // Use ODR linkage to avoid duplication.
182 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
183
184 // Set minsize, so we don't insert padding between outlined functions.
185 F->addFnAttr(Attribute::NoInline);
186 F->addFnAttr(Attribute::MinSize);
187 F->addFnAttr(Attribute::Naked);
188
190 // Remove unnecessary register liveness and set NoVRegs.
191 MF.getProperties().resetTracksLiveness().resetIsSSA().setNoVRegs();
193
194 // Create entry block.
195 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
196 IRBuilder<> Builder(EntryBB);
197 Builder.CreateRetVoid();
198
199 // Insert the new block into the function.
201 MF.insert(MF.begin(), MBB);
202
203 return MF;
204}
205
206/// Emit a store-pair instruction for frame-setup.
207/// If Reg2 is AArch64::NoRegister, emit STR instead.
210 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
211 int Offset, bool IsPreDec) {
212 assert(Reg1 != AArch64::NoRegister);
213 const bool IsPaired = Reg2 != AArch64::NoRegister;
214 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
215 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
216 unsigned Opc;
217 if (IsPreDec) {
218 if (IsFloat)
219 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
220 else
221 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
222 } else {
223 if (IsFloat)
224 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
225 else
226 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
227 }
228 // The implicit scale for Offset is 8.
229 TypeSize Scale(0U, false), Width(0U, false);
230 int64_t MinOffset, MaxOffset;
231 [[maybe_unused]] bool Success =
232 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
233 assert(Success && "Invalid Opcode");
234 Offset *= (8 / (int)Scale);
235
236 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
237 if (IsPreDec)
238 MIB.addDef(AArch64::SP);
239 if (IsPaired)
240 MIB.addReg(Reg2);
241 MIB.addReg(Reg1)
242 .addReg(AArch64::SP)
243 .addImm(Offset)
245}
246
247/// Emit a load-pair instruction for frame-destroy.
248/// If Reg2 is AArch64::NoRegister, emit LDR instead.
251 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
252 int Offset, bool IsPostDec) {
253 assert(Reg1 != AArch64::NoRegister);
254 const bool IsPaired = Reg2 != AArch64::NoRegister;
255 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
256 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
257 unsigned Opc;
258 if (IsPostDec) {
259 if (IsFloat)
260 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
261 else
262 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
263 } else {
264 if (IsFloat)
265 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
266 else
267 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
268 }
269 // The implicit scale for Offset is 8.
270 TypeSize Scale(0U, false), Width(0U, false);
271 int64_t MinOffset, MaxOffset;
272 [[maybe_unused]] bool Success =
273 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
274 assert(Success && "Invalid Opcode");
275 Offset *= (8 / (int)Scale);
276
277 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
278 if (IsPostDec)
279 MIB.addDef(AArch64::SP);
280 if (IsPaired)
281 MIB.addReg(Reg2, getDefRegState(true));
282 MIB.addReg(Reg1, getDefRegState(true))
283 .addReg(AArch64::SP)
284 .addImm(Offset)
286}
287
288/// Return a unique function if a helper can be formed with the given Regs
289/// and frame type.
290/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
291/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
292/// stp x20, x19, [sp, #16]
293/// ret
294///
295/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
296/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
297/// stp x20, x19, [sp, #16]
298/// add fp, sp, #32
299/// ret
300///
301/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
302/// mov x16, x30
303/// ldp x29, x30, [sp, #32]
304/// ldp x20, x19, [sp, #16]
305/// ldp x22, x21, [sp], #48
306/// ret x16
307///
308/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
309/// ldp x29, x30, [sp, #32]
310/// ldp x20, x19, [sp, #16]
311/// ldp x22, x21, [sp], #48
312/// ret
313/// @param M module
314/// @param MMI machine module info
315/// @param Regs callee save regs that the helper will handle
316/// @param Type frame helper type
317/// @return a helper function
321 unsigned FpOffset = 0) {
322 assert(Regs.size() >= 2);
323 auto Name = getFrameHelperName(Regs, Type, FpOffset);
324 auto *F = M->getFunction(Name);
325 if (F)
326 return F;
327
328 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
329 MachineBasicBlock &MBB = *MF.begin();
330 const TargetSubtargetInfo &STI = MF.getSubtarget();
331 const TargetInstrInfo &TII = *STI.getInstrInfo();
332
333 int Size = (int)Regs.size();
334 switch (Type) {
337 // Compute the remaining SP adjust beyond FP/LR.
338 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
339
340 // If the register stored to the lowest address is not LR, we must subtract
341 // more from SP here.
342 if (LRIdx != Size - 2) {
343 assert(Regs[Size - 2] != AArch64::LR);
344 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
345 LRIdx - Size + 2, true);
346 }
347
348 // Store CSRs in the reverse order.
349 for (int I = Size - 3; I >= 0; I -= 2) {
350 // FP/LR has been stored at call-site.
351 if (Regs[I - 1] == AArch64::LR)
352 continue;
353 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
354 false);
355 }
357 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
358 .addDef(AArch64::FP)
359 .addUse(AArch64::SP)
360 .addImm(FpOffset)
361 .addImm(0)
363
364 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
365 .addReg(AArch64::LR);
366 break;
367 }
371 // Stash LR to X16
372 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
373 .addDef(AArch64::X16)
374 .addReg(AArch64::XZR)
375 .addUse(AArch64::LR)
376 .addImm(0);
377
378 for (int I = 0; I < Size - 2; I += 2)
379 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
380 false);
381 // Restore the last CSR with post-increment of SP.
382 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
383 true);
384
385 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
386 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
387 break;
388 }
389
390 return M->getFunction(Name);
391}
392
393/// This function checks if a frame helper should be used for
394/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
395/// @param MBB machine basic block
396/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
397/// @param Regs callee save registers that are saved or restored.
398/// @param Type frame helper type
399/// @return True if a use of helper is qualified.
404 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
405 auto RegCount = Regs.size();
406 assert(RegCount > 0 && (RegCount % 2 == 0));
407 // # of instructions that will be outlined.
408 int InstCount = RegCount / 2;
409
410 // Do not use a helper call when not saving LR.
411 if (!llvm::is_contained(Regs, AArch64::LR))
412 return false;
413
414 switch (Type) {
416 // Prolog helper cannot save FP/LR.
417 InstCount--;
418 break;
420 // Effectively no change in InstCount since FpAdjustment is included.
421 break;
422 }
424 // Bail-out if X16 is live across the epilog helper because it is used in
425 // the helper to handle X30.
426 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
427 if (NextMI->readsRegister(AArch64::W16, TRI))
428 return false;
429 }
430 // Epilog may not be in the last block. Check the liveness in successors.
431 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
432 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
433 return false;
434 }
435 // No change in InstCount for the regular epilog case.
436 break;
438 // EpilogTail helper includes the caller's return.
439 if (NextMBBI == MBB.end())
440 return false;
441 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
442 return false;
443 InstCount++;
444 break;
445 }
446 }
447
448 return InstCount >= FrameHelperSizeThreshold;
449}
450
451/// Lower a HOM_Epilog pseudo instruction into a helper call while
452/// creating the helper on demand. Or emit a sequence of loads in place when not
453/// using a helper call.
454///
455/// 1. With a helper including ret
456/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
457/// ret ; NextMBBI
458/// =>
459/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
460/// ... ; NextMBBI
461///
462/// 2. With a helper
463/// HOM_Epilog x30, x29, x19, x20, x21, x22
464/// =>
465/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
466///
467/// 3. Without a helper
468/// HOM_Epilog x30, x29, x19, x20, x21, x22
469/// =>
470/// ldp x29, x30, [sp, #32]
471/// ldp x20, x19, [sp, #16]
472/// ldp x22, x21, [sp], #48
473bool AArch64LowerHomogeneousPrologEpilogImpl::lowerEpilog(
475 MachineBasicBlock::iterator &NextMBBI) {
476 auto &MF = *MBB.getParent();
477 MachineInstr &MI = *MBBI;
478
479 DebugLoc DL = MI.getDebugLoc();
481 bool HasUnpairedReg = false;
482 for (auto &MO : MI.operands())
483 if (MO.isReg()) {
484 if (!MO.getReg().isValid()) {
485 // For now we are only expecting unpaired GP registers which should
486 // occur exactly once.
487 assert(!HasUnpairedReg);
488 HasUnpairedReg = true;
489 }
490 Regs.push_back(MO.getReg());
491 }
492 (void)HasUnpairedReg;
493 int Size = (int)Regs.size();
494 if (Size == 0)
495 return false;
496 // Registers are in pair.
497 assert(Size % 2 == 0);
498 assert(MI.getOpcode() == AArch64::HOM_Epilog);
499
500 auto Return = NextMBBI;
501 MachineInstr *HelperCall = nullptr;
503 // When MBB ends with a return, emit a tail-call to the epilog helper
504 auto *EpilogTailHelper =
506 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
507 .addGlobalAddress(EpilogTailHelper)
508 .addImm(0)
511 .copyImplicitOps(*Return);
512 NextMBBI = std::next(Return);
513 Return->removeFromParent();
514 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
516 // The default epilog helper case.
517 auto *EpilogHelper =
519 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
520 .addGlobalAddress(EpilogHelper)
523 } else {
524 // Fall back to no-helper.
525 for (int I = 0; I < Size - 2; I += 2)
526 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
527 // Restore the last CSR with post-increment of SP.
528 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
529 }
530
531 // Make sure all explicit definitions are preserved in the helper call;
532 // implicit ones are already handled by copyImplicitOps.
533 if (HelperCall)
534 for (auto &Def : MBBI->defs())
535 HelperCall->addRegisterDefined(Def.getReg(),
538 return true;
539}
540
541/// Lower a HOM_Prolog pseudo instruction into a helper call while
542/// creating the helper on demand. Or emit a sequence of stores in place when
543/// not using a helper call.
544///
545/// 1. With a helper including frame-setup
546/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
547/// =>
548/// stp x29, x30, [sp, #-16]!
549/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
550///
551/// 2. With a helper
552/// HOM_Prolog x30, x29, x19, x20, x21, x22
553/// =>
554/// stp x29, x30, [sp, #-16]!
555/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
556///
557/// 3. Without a helper
558/// HOM_Prolog x30, x29, x19, x20, x21, x22
559/// =>
560/// stp x22, x21, [sp, #-48]!
561/// stp x20, x19, [sp, #16]
562/// stp x29, x30, [sp, #32]
563bool AArch64LowerHomogeneousPrologEpilogImpl::lowerProlog(
565 MachineBasicBlock::iterator &NextMBBI) {
566 auto &MF = *MBB.getParent();
567 MachineInstr &MI = *MBBI;
568
569 DebugLoc DL = MI.getDebugLoc();
571 bool HasUnpairedReg = false;
572 int LRIdx = 0;
573 std::optional<int> FpOffset;
574 for (auto &MO : MI.operands()) {
575 if (MO.isReg()) {
576 if (MO.getReg().isValid()) {
577 if (MO.getReg() == AArch64::LR)
578 LRIdx = Regs.size();
579 } else {
580 // For now we are only expecting unpaired GP registers which should
581 // occur exactly once.
582 assert(!HasUnpairedReg);
583 HasUnpairedReg = true;
584 }
585 Regs.push_back(MO.getReg());
586 } else if (MO.isImm()) {
587 FpOffset = MO.getImm();
588 }
589 }
590 (void)HasUnpairedReg;
591 int Size = (int)Regs.size();
592 if (Size == 0)
593 return false;
594 // Allow compact unwind case only for oww.
595 assert(Size % 2 == 0);
596 assert(MI.getOpcode() == AArch64::HOM_Prolog);
597
598 if (FpOffset &&
600 // FP/LR is stored at the top of stack before the prolog helper call.
601 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
602 auto *PrologFrameHelper = getOrCreateFrameHelper(
603 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
604 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
605 .addGlobalAddress(PrologFrameHelper)
609 .addReg(AArch64::SP, RegState::Implicit);
610 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
612 // FP/LR is stored at the top of stack before the prolog helper call.
613 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
614 auto *PrologHelper =
616 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
617 .addGlobalAddress(PrologHelper)
620 } else {
621 // Fall back to no-helper.
622 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
623 for (int I = Size - 3; I >= 0; I -= 2)
624 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
625 if (FpOffset) {
626 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
627 .addDef(AArch64::FP)
628 .addUse(AArch64::SP)
629 .addImm(*FpOffset)
630 .addImm(0)
632 }
633 }
634
636 return true;
637}
638
639/// Process each machine instruction
640/// @param MBB machine basic block
641/// @param MBBI current instruction iterator
642/// @param NextMBBI next instruction iterator which can be updated
643/// @return True when IR is changed.
644bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMI(
646 MachineBasicBlock::iterator &NextMBBI) {
647 MachineInstr &MI = *MBBI;
648 unsigned Opcode = MI.getOpcode();
649 switch (Opcode) {
650 default:
651 break;
652 case AArch64::HOM_Prolog:
653 return lowerProlog(MBB, MBBI, NextMBBI);
654 case AArch64::HOM_Epilog:
655 return lowerEpilog(MBB, MBBI, NextMBBI);
656 }
657 return false;
658}
659
660bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMBB(MachineBasicBlock &MBB) {
661 bool Modified = false;
662
664 while (MBBI != E) {
665 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
666 Modified |= runOnMI(MBB, MBBI, NMBBI);
667 MBBI = NMBBI;
668 }
669
670 return Modified;
671}
672
673bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMachineFunction(
674 MachineFunction &MF) {
675 TII = MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
676
677 bool Modified = false;
678 for (auto &MBB : MF)
679 Modified |= runOnMBB(MBB);
680 return Modified;
681}
682
684 return new AArch64LowerHomogeneousPrologEpilogLegacy();
685}
#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!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#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
ModuleAnalysisManager MAM
#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:483
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.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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:168
@ 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:2858
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
Representation of each machine instruction.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
An analysis that produces MachineModuleInfo for a module.
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 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
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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:46
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:286
Changed
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
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:1764
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
constexpr RegState getDefRegState(bool B)
ModulePass * createAArch64LowerHomogeneousPrologEpilogPass()
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39