LLVM 19.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"
25#include "llvm/IR/DebugLoc.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/Module.h"
28#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 AArch64LowerHomogeneousPE {
46public:
47 const AArch64InstrInfo *TII;
48
49 AArch64LowerHomogeneousPE(Module *M, MachineModuleInfo *MMI)
50 : M(M), MMI(MMI) {}
51
52 bool run();
53 bool runOnMachineFunction(MachineFunction &Fn);
54
55private:
56 Module *M;
58
59 bool runOnMBB(MachineBasicBlock &MBB);
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.
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.
73};
74
75class AArch64LowerHomogeneousPrologEpilog : public ModulePass {
76public:
77 static char ID;
78
79 AArch64LowerHomogeneousPrologEpilog() : ModulePass(ID) {
82 }
83 void getAnalysisUsage(AnalysisUsage &AU) const override {
86 AU.setPreservesAll();
88 }
89 bool runOnModule(Module &M) override;
90
91 StringRef getPassName() const override {
93 }
94};
95
96} // end anonymous namespace
97
98char AArch64LowerHomogeneousPrologEpilog::ID = 0;
99
100INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilog,
101 "aarch64-lower-homogeneous-prolog-epilog",
103
104bool AArch64LowerHomogeneousPrologEpilog::runOnModule(Module &M) {
105 if (skipModule(M))
106 return false;
107
108 MachineModuleInfo *MMI =
109 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
110 return AArch64LowerHomogeneousPE(&M, MMI).run();
111}
112
113bool AArch64LowerHomogeneousPE::run() {
114 bool Changed = false;
115 for (auto &F : *M) {
116 if (F.empty())
117 continue;
118
119 MachineFunction *MF = MMI->getMachineFunction(F);
120 if (!MF)
121 continue;
122 Changed |= runOnMachineFunction(*MF);
123 }
124
125 return Changed;
126}
128
129/// Return a frame helper name with the given CSRs and the helper type.
130/// For instance, a prolog helper that saves x19 and x20 is named as
131/// OUTLINED_FUNCTION_PROLOG_x19x20.
133 FrameHelperType Type, unsigned FpOffset) {
134 std::ostringstream RegStream;
135 switch (Type) {
137 RegStream << "OUTLINED_FUNCTION_PROLOG_";
138 break;
140 RegStream << "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset << "_";
141 break;
143 RegStream << "OUTLINED_FUNCTION_EPILOG_";
144 break;
146 RegStream << "OUTLINED_FUNCTION_EPILOG_TAIL_";
147 break;
148 }
149
150 for (auto Reg : Regs) {
151 if (Reg == AArch64::NoRegister)
152 continue;
153 RegStream << AArch64InstPrinter::getRegisterName(Reg);
154 }
155
156 return RegStream.str();
157}
158
159/// Create a Function for the unique frame helper with the given name.
160/// Return a newly created MachineFunction with an empty MachineBasicBlock.
163 StringRef Name) {
164 LLVMContext &C = M->getContext();
165 Function *F = M->getFunction(Name);
166 assert(F == nullptr && "Function has been created before");
167 F = Function::Create(FunctionType::get(Type::getVoidTy(C), false),
168 Function::ExternalLinkage, Name, M);
169 assert(F && "Function was null!");
170
171 // Use ODR linkage to avoid duplication.
173 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
174
175 // Set no-opt/minsize, so we don't insert padding between outlined
176 // functions.
177 F->addFnAttr(Attribute::OptimizeNone);
178 F->addFnAttr(Attribute::NoInline);
179 F->addFnAttr(Attribute::MinSize);
180 F->addFnAttr(Attribute::Naked);
181
183 // Remove unnecessary register liveness and set NoVRegs.
184 MF.getProperties().reset(MachineFunctionProperties::Property::TracksLiveness);
185 MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA);
186 MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
188
189 // Create entry block.
190 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
191 IRBuilder<> Builder(EntryBB);
192 Builder.CreateRetVoid();
193
194 // Insert the new block into the function.
196 MF.insert(MF.begin(), MBB);
197
198 return MF;
199}
200
201/// Emit a store-pair instruction for frame-setup.
202/// If Reg2 is AArch64::NoRegister, emit STR instead.
205 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
206 int Offset, bool IsPreDec) {
207 assert(Reg1 != AArch64::NoRegister);
208 const bool IsPaired = Reg2 != AArch64::NoRegister;
209 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
210 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
211 unsigned Opc;
212 if (IsPreDec) {
213 if (IsFloat)
214 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
215 else
216 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
217 } else {
218 if (IsFloat)
219 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
220 else
221 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
222 }
223 // The implicit scale for Offset is 8.
224 TypeSize Scale(0U, false), Width(0U, false);
225 int64_t MinOffset, MaxOffset;
226 [[maybe_unused]] bool Success =
227 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
228 assert(Success && "Invalid Opcode");
229 Offset *= (8 / (int)Scale);
230
231 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
232 if (IsPreDec)
233 MIB.addDef(AArch64::SP);
234 if (IsPaired)
235 MIB.addReg(Reg2);
236 MIB.addReg(Reg1)
237 .addReg(AArch64::SP)
238 .addImm(Offset)
240}
241
242/// Emit a load-pair instruction for frame-destroy.
243/// If Reg2 is AArch64::NoRegister, emit LDR instead.
246 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
247 int Offset, bool IsPostDec) {
248 assert(Reg1 != AArch64::NoRegister);
249 const bool IsPaired = Reg2 != AArch64::NoRegister;
250 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
251 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
252 unsigned Opc;
253 if (IsPostDec) {
254 if (IsFloat)
255 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
256 else
257 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
258 } else {
259 if (IsFloat)
260 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
261 else
262 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
263 }
264 // The implicit scale for Offset is 8.
265 TypeSize Scale(0U, false), Width(0U, false);
266 int64_t MinOffset, MaxOffset;
267 [[maybe_unused]] bool Success =
268 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
269 assert(Success && "Invalid Opcode");
270 Offset *= (8 / (int)Scale);
271
272 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
273 if (IsPostDec)
274 MIB.addDef(AArch64::SP);
275 if (IsPaired)
276 MIB.addReg(Reg2, getDefRegState(true));
277 MIB.addReg(Reg1, getDefRegState(true))
278 .addReg(AArch64::SP)
279 .addImm(Offset)
281}
282
283/// Return a unique function if a helper can be formed with the given Regs
284/// and frame type.
285/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
286/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
287/// stp x20, x19, [sp, #16]
288/// ret
289///
290/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
291/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
292/// stp x20, x19, [sp, #16]
293/// add fp, sp, #32
294/// ret
295///
296/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
297/// mov x16, x30
298/// ldp x29, x30, [sp, #32]
299/// ldp x20, x19, [sp, #16]
300/// ldp x22, x21, [sp], #48
301/// ret x16
302///
303/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
304/// ldp x29, x30, [sp, #32]
305/// ldp x20, x19, [sp, #16]
306/// ldp x22, x21, [sp], #48
307/// ret
308/// @param M module
309/// @param MMI machine module info
310/// @param Regs callee save regs that the helper will handle
311/// @param Type frame helper type
312/// @return a helper function
316 unsigned FpOffset = 0) {
317 assert(Regs.size() >= 2);
318 auto Name = getFrameHelperName(Regs, Type, FpOffset);
319 auto *F = M->getFunction(Name);
320 if (F)
321 return F;
322
323 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
324 MachineBasicBlock &MBB = *MF.begin();
325 const TargetSubtargetInfo &STI = MF.getSubtarget();
326 const TargetInstrInfo &TII = *STI.getInstrInfo();
327
328 int Size = (int)Regs.size();
329 switch (Type) {
332 // Compute the remaining SP adjust beyond FP/LR.
333 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
334
335 // If the register stored to the lowest address is not LR, we must subtract
336 // more from SP here.
337 if (LRIdx != Size - 2) {
338 assert(Regs[Size - 2] != AArch64::LR);
339 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
340 LRIdx - Size + 2, true);
341 }
342
343 // Store CSRs in the reverse order.
344 for (int I = Size - 3; I >= 0; I -= 2) {
345 // FP/LR has been stored at call-site.
346 if (Regs[I - 1] == AArch64::LR)
347 continue;
348 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
349 false);
350 }
352 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
353 .addDef(AArch64::FP)
354 .addUse(AArch64::SP)
355 .addImm(FpOffset)
356 .addImm(0)
358
359 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
360 .addReg(AArch64::LR);
361 break;
362 }
366 // Stash LR to X16
367 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
368 .addDef(AArch64::X16)
369 .addReg(AArch64::XZR)
370 .addUse(AArch64::LR)
371 .addImm(0);
372
373 for (int I = 0; I < Size - 2; I += 2)
374 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
375 false);
376 // Restore the last CSR with post-increment of SP.
377 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
378 true);
379
380 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
381 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
382 break;
383 }
384
385 return M->getFunction(Name);
386}
387
388/// This function checks if a frame helper should be used for
389/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
390/// @param MBB machine basic block
391/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
392/// @param Regs callee save registers that are saved or restored.
393/// @param Type frame helper type
394/// @return True if a use of helper is qualified.
399 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
400 auto RegCount = Regs.size();
401 assert(RegCount > 0 && (RegCount % 2 == 0));
402 // # of instructions that will be outlined.
403 int InstCount = RegCount / 2;
404
405 // Do not use a helper call when not saving LR.
406 if (!llvm::is_contained(Regs, AArch64::LR))
407 return false;
408
409 switch (Type) {
411 // Prolog helper cannot save FP/LR.
412 InstCount--;
413 break;
415 // Effecitvely no change in InstCount since FpAdjusment is included.
416 break;
417 }
419 // Bail-out if X16 is live across the epilog helper because it is used in
420 // the helper to handle X30.
421 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
422 if (NextMI->readsRegister(AArch64::W16, TRI))
423 return false;
424 }
425 // Epilog may not be in the last block. Check the liveness in successors.
426 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
427 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
428 return false;
429 }
430 // No change in InstCount for the regular epilog case.
431 break;
433 // EpilogTail helper includes the caller's return.
434 if (NextMBBI == MBB.end())
435 return false;
436 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
437 return false;
438 InstCount++;
439 break;
440 }
441 }
442
443 return InstCount >= FrameHelperSizeThreshold;
444}
445
446/// Lower a HOM_Epilog pseudo instruction into a helper call while
447/// creating the helper on demand. Or emit a sequence of loads in place when not
448/// using a helper call.
449///
450/// 1. With a helper including ret
451/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
452/// ret ; NextMBBI
453/// =>
454/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
455/// ... ; NextMBBI
456///
457/// 2. With a helper
458/// HOM_Epilog x30, x29, x19, x20, x21, x22
459/// =>
460/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
461///
462/// 3. Without a helper
463/// HOM_Epilog x30, x29, x19, x20, x21, x22
464/// =>
465/// ldp x29, x30, [sp, #32]
466/// ldp x20, x19, [sp, #16]
467/// ldp x22, x21, [sp], #48
468bool AArch64LowerHomogeneousPE::lowerEpilog(
470 MachineBasicBlock::iterator &NextMBBI) {
471 auto &MF = *MBB.getParent();
472 MachineInstr &MI = *MBBI;
473
474 DebugLoc DL = MI.getDebugLoc();
476 bool HasUnpairedReg = false;
477 for (auto &MO : MI.operands())
478 if (MO.isReg()) {
479 if (!MO.getReg().isValid()) {
480 // For now we are only expecting unpaired GP registers which should
481 // occur exactly once.
482 assert(!HasUnpairedReg);
483 HasUnpairedReg = true;
484 }
485 Regs.push_back(MO.getReg());
486 }
487 (void)HasUnpairedReg;
488 int Size = (int)Regs.size();
489 if (Size == 0)
490 return false;
491 // Registers are in pair.
492 assert(Size % 2 == 0);
493 assert(MI.getOpcode() == AArch64::HOM_Epilog);
494
495 auto Return = NextMBBI;
497 // When MBB ends with a return, emit a tail-call to the epilog helper
498 auto *EpilogTailHelper =
500 BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
501 .addGlobalAddress(EpilogTailHelper)
502 .addImm(0)
505 .copyImplicitOps(*Return);
506 NextMBBI = std::next(Return);
507 Return->removeFromParent();
508 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
510 // The default epilog helper case.
511 auto *EpilogHelper =
513 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
514 .addGlobalAddress(EpilogHelper)
517 } else {
518 // Fall back to no-helper.
519 for (int I = 0; I < Size - 2; I += 2)
520 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
521 // Restore the last CSR with post-increment of SP.
522 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
523 }
524
526 return true;
527}
528
529/// Lower a HOM_Prolog pseudo instruction into a helper call while
530/// creating the helper on demand. Or emit a sequence of stores in place when
531/// not using a helper call.
532///
533/// 1. With a helper including frame-setup
534/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
535/// =>
536/// stp x29, x30, [sp, #-16]!
537/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
538///
539/// 2. With a helper
540/// HOM_Prolog x30, x29, x19, x20, x21, x22
541/// =>
542/// stp x29, x30, [sp, #-16]!
543/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
544///
545/// 3. Without a helper
546/// HOM_Prolog x30, x29, x19, x20, x21, x22
547/// =>
548/// stp x22, x21, [sp, #-48]!
549/// stp x20, x19, [sp, #16]
550/// stp x29, x30, [sp, #32]
551bool AArch64LowerHomogeneousPE::lowerProlog(
553 MachineBasicBlock::iterator &NextMBBI) {
554 auto &MF = *MBB.getParent();
555 MachineInstr &MI = *MBBI;
556
557 DebugLoc DL = MI.getDebugLoc();
559 bool HasUnpairedReg = false;
560 int LRIdx = 0;
561 std::optional<int> FpOffset;
562 for (auto &MO : MI.operands()) {
563 if (MO.isReg()) {
564 if (MO.getReg().isValid()) {
565 if (MO.getReg() == AArch64::LR)
566 LRIdx = Regs.size();
567 } else {
568 // For now we are only expecting unpaired GP registers which should
569 // occur exactly once.
570 assert(!HasUnpairedReg);
571 HasUnpairedReg = true;
572 }
573 Regs.push_back(MO.getReg());
574 } else if (MO.isImm()) {
575 FpOffset = MO.getImm();
576 }
577 }
578 (void)HasUnpairedReg;
579 int Size = (int)Regs.size();
580 if (Size == 0)
581 return false;
582 // Allow compact unwind case only for oww.
583 assert(Size % 2 == 0);
584 assert(MI.getOpcode() == AArch64::HOM_Prolog);
585
586 if (FpOffset &&
588 // FP/LR is stored at the top of stack before the prolog helper call.
589 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
590 auto *PrologFrameHelper = getOrCreateFrameHelper(
591 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
592 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
593 .addGlobalAddress(PrologFrameHelper)
597 .addReg(AArch64::SP, RegState::Implicit);
598 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
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 *PrologHelper =
604 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
605 .addGlobalAddress(PrologHelper)
608 } else {
609 // Fall back to no-helper.
610 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
611 for (int I = Size - 3; I >= 0; I -= 2)
612 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
613 if (FpOffset) {
614 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
615 .addDef(AArch64::FP)
616 .addUse(AArch64::SP)
617 .addImm(*FpOffset)
618 .addImm(0)
620 }
621 }
622
624 return true;
625}
626
627/// Process each machine instruction
628/// @param MBB machine basic block
629/// @param MBBI current instruction iterator
630/// @param NextMBBI next instruction iterator which can be updated
631/// @return True when IR is changed.
632bool AArch64LowerHomogeneousPE::runOnMI(MachineBasicBlock &MBB,
634 MachineBasicBlock::iterator &NextMBBI) {
635 MachineInstr &MI = *MBBI;
636 unsigned Opcode = MI.getOpcode();
637 switch (Opcode) {
638 default:
639 break;
640 case AArch64::HOM_Prolog:
641 return lowerProlog(MBB, MBBI, NextMBBI);
642 case AArch64::HOM_Epilog:
643 return lowerEpilog(MBB, MBBI, NextMBBI);
644 }
645 return false;
646}
647
648bool AArch64LowerHomogeneousPE::runOnMBB(MachineBasicBlock &MBB) {
649 bool Modified = false;
650
652 while (MBBI != E) {
653 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
654 Modified |= runOnMI(MBB, MBBI, NMBBI);
655 MBBI = NMBBI;
656 }
657
658 return Modified;
659}
660
661bool AArch64LowerHomogeneousPE::runOnMachineFunction(MachineFunction &MF) {
662 TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
663
664 bool Modified = false;
665 for (auto &MBB : MF)
666 Modified |= runOnMBB(MBB);
667 return Modified;
668}
669
671 return new AArch64LowerHomogeneousPrologEpilog();
672}
#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
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.
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
std::string Name
uint64_t Size
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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.
Represent the analysis usage information of a pass.
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:61
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:202
A debug info location.
Definition: DebugLoc.h:33
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:165
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:55
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition: IRBuilder.h:1095
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2671
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
MachineBasicBlock * removeFromParent()
This method unlinks 'this' from the containing function, and returns it, but does not delete it.
MachineFunctionProperties & set(Property P)
MachineFunctionProperties & reset(Property P)
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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.
Representation of each machine instruction.
Definition: MachineInstr.h:69
This class contains meta information specific to a module.
MachineFunction & getOrCreateMachineFunction(Function &F)
Returns the MachineFunction constructed for the IR function F.
void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetInstrInfo - Interface to description of machine instruction set.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
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 Type * getVoidTy(LLVMContext &C)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ 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)
Definition: CommandLine.h:443
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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:1742
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeAArch64LowerHomogeneousPrologEpilogPass(PassRegistry &)
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:1879