LLVM 24.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()
192 .resetTracksLiveness()
193 .resetIsSSA()
194 .setNoVRegs()
195 .setNoPHIs();
197
198 // Create entry block.
199 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
200 IRBuilder<> Builder(EntryBB);
201 Builder.CreateRetVoid();
202
203 // Insert the new block into the function.
205 MF.insert(MF.begin(), MBB);
206
207 return MF;
208}
209
210/// Emit a store-pair instruction for frame-setup.
211/// If Reg2 is AArch64::NoRegister, emit STR instead.
214 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
215 int Offset, bool IsPreDec) {
216 assert(Reg1 != AArch64::NoRegister);
217 const bool IsPaired = Reg2 != AArch64::NoRegister;
218 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
219 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
220 unsigned Opc;
221 if (IsPreDec) {
222 if (IsFloat)
223 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
224 else
225 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
226 } else {
227 if (IsFloat)
228 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
229 else
230 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
231 }
232 // The implicit scale for Offset is 8.
233 TypeSize Scale(0U, false), Width(0U, false);
234 int64_t MinOffset, MaxOffset;
235 [[maybe_unused]] bool Success =
236 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
237 assert(Success && "Invalid Opcode");
238 Offset *= (8 / (int)Scale);
239
240 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
241 if (IsPreDec)
242 MIB.addDef(AArch64::SP);
243 if (IsPaired)
244 MIB.addReg(Reg2);
245 MIB.addReg(Reg1)
246 .addReg(AArch64::SP)
247 .addImm(Offset)
249}
250
251/// Emit a load-pair instruction for frame-destroy.
252/// If Reg2 is AArch64::NoRegister, emit LDR instead.
255 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
256 int Offset, bool IsPostDec) {
257 assert(Reg1 != AArch64::NoRegister);
258 const bool IsPaired = Reg2 != AArch64::NoRegister;
259 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
260 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
261 unsigned Opc;
262 if (IsPostDec) {
263 if (IsFloat)
264 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
265 else
266 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
267 } else {
268 if (IsFloat)
269 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
270 else
271 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
272 }
273 // The implicit scale for Offset is 8.
274 TypeSize Scale(0U, false), Width(0U, false);
275 int64_t MinOffset, MaxOffset;
276 [[maybe_unused]] bool Success =
277 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
278 assert(Success && "Invalid Opcode");
279 Offset *= (8 / (int)Scale);
280
281 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
282 if (IsPostDec)
283 MIB.addDef(AArch64::SP);
284 if (IsPaired)
285 MIB.addReg(Reg2, getDefRegState(true));
286 MIB.addReg(Reg1, getDefRegState(true))
287 .addReg(AArch64::SP)
288 .addImm(Offset)
290}
291
292/// Return a unique function if a helper can be formed with the given Regs
293/// and frame type.
294/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
295/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
296/// stp x20, x19, [sp, #16]
297/// ret
298///
299/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
300/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
301/// stp x20, x19, [sp, #16]
302/// add fp, sp, #32
303/// ret
304///
305/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
306/// mov x16, x30
307/// ldp x29, x30, [sp, #32]
308/// ldp x20, x19, [sp, #16]
309/// ldp x22, x21, [sp], #48
310/// ret x16
311///
312/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
313/// ldp x29, x30, [sp, #32]
314/// ldp x20, x19, [sp, #16]
315/// ldp x22, x21, [sp], #48
316/// ret
317/// @param M module
318/// @param MMI machine module info
319/// @param Regs callee save regs that the helper will handle
320/// @param Type frame helper type
321/// @return a helper function
325 unsigned FpOffset = 0) {
326 assert(Regs.size() >= 2);
327 auto Name = getFrameHelperName(Regs, Type, FpOffset);
328 auto *F = M->getFunction(Name);
329 if (F)
330 return F;
331
332 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
333 MachineBasicBlock &MBB = *MF.begin();
334 const TargetSubtargetInfo &STI = MF.getSubtarget();
335 const TargetInstrInfo &TII = *STI.getInstrInfo();
336
337 int Size = (int)Regs.size();
338 switch (Type) {
341 // Compute the remaining SP adjust beyond FP/LR.
342 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
343
344 // If the register stored to the lowest address is not LR, we must subtract
345 // more from SP here.
346 if (LRIdx != Size - 2) {
347 assert(Regs[Size - 2] != AArch64::LR);
348 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
349 LRIdx - Size + 2, true);
350 }
351
352 // Store CSRs in the reverse order.
353 for (int I = Size - 3; I >= 0; I -= 2) {
354 // FP/LR has been stored at call-site.
355 if (Regs[I - 1] == AArch64::LR)
356 continue;
357 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
358 false);
359 }
361 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
362 .addDef(AArch64::FP)
363 .addUse(AArch64::SP)
364 .addImm(FpOffset)
365 .addImm(0)
367
368 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
369 .addReg(AArch64::LR);
370 break;
371 }
375 // Stash LR to X16
376 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
377 .addDef(AArch64::X16)
378 .addReg(AArch64::XZR)
379 .addUse(AArch64::LR)
380 .addImm(0);
381
382 for (int I = 0; I < Size - 2; I += 2)
383 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
384 false);
385 // Restore the last CSR with post-increment of SP.
386 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
387 true);
388
389 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
390 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
391 break;
392 }
393
394 return M->getFunction(Name);
395}
396
397/// This function checks if a frame helper should be used for
398/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
399/// @param MBB machine basic block
400/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
401/// @param Regs callee save registers that are saved or restored.
402/// @param Type frame helper type
403/// @return True if a use of helper is qualified.
408 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
409 auto RegCount = Regs.size();
410 assert(RegCount > 0 && (RegCount % 2 == 0));
411 // # of instructions that will be outlined.
412 int InstCount = RegCount / 2;
413
414 // Do not use a helper call when not saving LR.
415 if (!llvm::is_contained(Regs, AArch64::LR))
416 return false;
417
418 switch (Type) {
420 // Prolog helper cannot save FP/LR.
421 InstCount--;
422 break;
424 // Effectively no change in InstCount since FpAdjustment is included.
425 break;
426 }
428 // Bail-out if X16 is live across the epilog helper because it is used in
429 // the helper to handle X30.
430 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
431 if (NextMI->readsRegister(AArch64::W16, TRI))
432 return false;
433 }
434 // Epilog may not be in the last block. Check the liveness in successors.
435 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
436 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
437 return false;
438 }
439 // No change in InstCount for the regular epilog case.
440 break;
442 // EpilogTail helper includes the caller's return.
443 if (NextMBBI == MBB.end())
444 return false;
445 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
446 return false;
447 InstCount++;
448 break;
449 }
450 }
451
452 return InstCount >= FrameHelperSizeThreshold;
453}
454
455/// Lower a HOM_Epilog pseudo instruction into a helper call while
456/// creating the helper on demand. Or emit a sequence of loads in place when not
457/// using a helper call.
458///
459/// 1. With a helper including ret
460/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
461/// ret ; NextMBBI
462/// =>
463/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
464/// ... ; NextMBBI
465///
466/// 2. With a helper
467/// HOM_Epilog x30, x29, x19, x20, x21, x22
468/// =>
469/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
470///
471/// 3. Without a helper
472/// HOM_Epilog x30, x29, x19, x20, x21, x22
473/// =>
474/// ldp x29, x30, [sp, #32]
475/// ldp x20, x19, [sp, #16]
476/// ldp x22, x21, [sp], #48
477bool AArch64LowerHomogeneousPrologEpilogImpl::lowerEpilog(
479 MachineBasicBlock::iterator &NextMBBI) {
480 auto &MF = *MBB.getParent();
481 MachineInstr &MI = *MBBI;
482
483 DebugLoc DL = MI.getDebugLoc();
485 bool HasUnpairedReg = false;
486 for (auto &MO : MI.operands())
487 if (MO.isReg()) {
488 if (!MO.getReg().isValid()) {
489 // For now we are only expecting unpaired GP registers which should
490 // occur exactly once.
491 assert(!HasUnpairedReg);
492 HasUnpairedReg = true;
493 }
494 Regs.push_back(MO.getReg());
495 }
496 (void)HasUnpairedReg;
497 int Size = (int)Regs.size();
498 if (Size == 0)
499 return false;
500 // Registers are in pair.
501 assert(Size % 2 == 0);
502 assert(MI.getOpcode() == AArch64::HOM_Epilog);
503
504 auto Return = NextMBBI;
505 MachineInstr *HelperCall = nullptr;
507 // When MBB ends with a return, emit a tail-call to the epilog helper
508 auto *EpilogTailHelper =
510 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
511 .addGlobalAddress(EpilogTailHelper)
512 .addImm(0)
515 .copyImplicitOps(*Return);
516 NextMBBI = std::next(Return);
517 Return->removeFromParent();
518 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
520 // The default epilog helper case.
521 auto *EpilogHelper =
523 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
524 .addGlobalAddress(EpilogHelper)
527 } else {
528 // Fall back to no-helper.
529 for (int I = 0; I < Size - 2; I += 2)
530 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
531 // Restore the last CSR with post-increment of SP.
532 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
533 }
534
535 // Make sure all explicit definitions are preserved in the helper call;
536 // implicit ones are already handled by copyImplicitOps.
537 if (HelperCall)
538 for (auto &Def : MBBI->defs())
539 HelperCall->addRegisterDefined(Def.getReg(),
542 return true;
543}
544
545/// Lower a HOM_Prolog pseudo instruction into a helper call while
546/// creating the helper on demand. Or emit a sequence of stores in place when
547/// not using a helper call.
548///
549/// 1. With a helper including frame-setup
550/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
551/// =>
552/// stp x29, x30, [sp, #-16]!
553/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
554///
555/// 2. With a helper
556/// HOM_Prolog x30, x29, x19, x20, x21, x22
557/// =>
558/// stp x29, x30, [sp, #-16]!
559/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
560///
561/// 3. Without a helper
562/// HOM_Prolog x30, x29, x19, x20, x21, x22
563/// =>
564/// stp x22, x21, [sp, #-48]!
565/// stp x20, x19, [sp, #16]
566/// stp x29, x30, [sp, #32]
567bool AArch64LowerHomogeneousPrologEpilogImpl::lowerProlog(
569 MachineBasicBlock::iterator &NextMBBI) {
570 auto &MF = *MBB.getParent();
571 MachineInstr &MI = *MBBI;
572
573 DebugLoc DL = MI.getDebugLoc();
575 bool HasUnpairedReg = false;
576 int LRIdx = 0;
577 std::optional<int> FpOffset;
578 for (auto &MO : MI.operands()) {
579 if (MO.isReg()) {
580 if (MO.getReg().isValid()) {
581 if (MO.getReg() == AArch64::LR)
582 LRIdx = Regs.size();
583 } else {
584 // For now we are only expecting unpaired GP registers which should
585 // occur exactly once.
586 assert(!HasUnpairedReg);
587 HasUnpairedReg = true;
588 }
589 Regs.push_back(MO.getReg());
590 } else if (MO.isImm()) {
591 FpOffset = MO.getImm();
592 }
593 }
594 (void)HasUnpairedReg;
595 int Size = (int)Regs.size();
596 if (Size == 0)
597 return false;
598 // Allow compact unwind case only for oww.
599 assert(Size % 2 == 0);
600 assert(MI.getOpcode() == AArch64::HOM_Prolog);
601
602 if (FpOffset &&
604 // FP/LR is stored at the top of stack before the prolog helper call.
605 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
606 auto *PrologFrameHelper = getOrCreateFrameHelper(
607 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
608 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
609 .addGlobalAddress(PrologFrameHelper)
613 .addReg(AArch64::SP, RegState::Implicit);
614 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
616 // FP/LR is stored at the top of stack before the prolog helper call.
617 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
618 auto *PrologHelper =
620 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
621 .addGlobalAddress(PrologHelper)
624 } else {
625 // Fall back to no-helper.
626 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
627 for (int I = Size - 3; I >= 0; I -= 2)
628 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
629 if (FpOffset) {
630 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
631 .addDef(AArch64::FP)
632 .addUse(AArch64::SP)
633 .addImm(*FpOffset)
634 .addImm(0)
636 }
637 }
638
640 return true;
641}
642
643/// Process each machine instruction
644/// @param MBB machine basic block
645/// @param MBBI current instruction iterator
646/// @param NextMBBI next instruction iterator which can be updated
647/// @return True when IR is changed.
648bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMI(
650 MachineBasicBlock::iterator &NextMBBI) {
651 MachineInstr &MI = *MBBI;
652 unsigned Opcode = MI.getOpcode();
653 switch (Opcode) {
654 default:
655 break;
656 case AArch64::HOM_Prolog:
657 return lowerProlog(MBB, MBBI, NextMBBI);
658 case AArch64::HOM_Epilog:
659 return lowerEpilog(MBB, MBBI, NextMBBI);
660 }
661 return false;
662}
663
664bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMBB(MachineBasicBlock &MBB) {
665 bool Modified = false;
666
668 while (MBBI != E) {
669 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
670 Modified |= runOnMI(MBB, MBBI, NMBBI);
671 MBBI = NMBBI;
672 }
673
674 return Modified;
675}
676
677bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMachineFunction(
678 MachineFunction &MF) {
679 TII = MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
680
681 bool Modified = false;
682 for (auto &MBB : MF)
683 Modified |= runOnMBB(MBB);
684 return Modified;
685}
686
688 return new AArch64LowerHomogeneousPrologEpilogLegacy();
689}
#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:484
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:126
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:2893
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:282
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:578
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:1765
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:1947
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39