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
38namespace {
39
40class AArch64LowerHomogeneousPrologEpilogImpl {
41public:
42 const AArch64InstrInfo *TII;
43
44 AArch64LowerHomogeneousPrologEpilogImpl(Module *M, MachineModuleInfo *MMI)
45 : M(M), MMI(MMI) {}
46
47 bool run();
48 bool runOnMachineFunction(MachineFunction &Fn);
49
50private:
51 Module *M;
53
54 bool runOnMBB(MachineBasicBlock &MBB);
57
58 /// Lower a HOM_Prolog pseudo instruction into a helper call
59 /// or a sequence of homogeneous stores.
60 /// When a fp setup follows, it can be optimized.
63 /// Lower a HOM_Epilog pseudo instruction into a helper call
64 /// or a sequence of homogeneous loads.
65 /// When a return follow, it can be optimized.
68};
69
70class AArch64LowerHomogeneousPrologEpilogLegacy : public ModulePass {
71public:
72 static char ID;
73
74 AArch64LowerHomogeneousPrologEpilogLegacy() : ModulePass(ID) {}
75 void getAnalysisUsage(AnalysisUsage &AU) const override {
78 AU.setPreservesAll();
80 }
81 bool runOnModule(Module &M) override;
82
83 StringRef getPassName() const override {
85 }
86};
87
88} // end anonymous namespace
89
90char AArch64LowerHomogeneousPrologEpilogLegacy::ID = 0;
91
92INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilogLegacy,
93 "aarch64-lower-homogeneous-prolog-epilog",
95
96bool AArch64LowerHomogeneousPrologEpilogLegacy::runOnModule(Module &M) {
97 if (skipModule(M))
98 return false;
99
100 MachineModuleInfo *MMI =
101 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
102 return AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
103}
104
108 MachineModuleInfo *MMI = &MAM.getResult<MachineModuleAnalysis>(M).getMMI();
109 bool Changed = AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
110 if (!Changed)
111 return PreservedAnalyses::all();
114 return PA;
115}
116
117bool AArch64LowerHomogeneousPrologEpilogImpl::run() {
118 bool Changed = false;
119 for (auto &F : *M) {
120 if (F.empty())
121 continue;
122
123 MachineFunction *MF = MMI->getMachineFunction(F);
124 if (!MF)
125 continue;
126 Changed |= runOnMachineFunction(*MF);
127 }
128
129 return Changed;
130}
132
133/// Return a frame helper name with the given CSRs and the helper type.
134/// For instance, a prolog helper that saves x19 and x20 is named as
135/// OUTLINED_FUNCTION_PROLOG_x19x20.
137 FrameHelperType Type, unsigned FpOffset) {
138 std::ostringstream RegStream;
139 switch (Type) {
141 RegStream << "OUTLINED_FUNCTION_PROLOG_";
142 break;
144 RegStream << "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset << "_";
145 break;
147 RegStream << "OUTLINED_FUNCTION_EPILOG_";
148 break;
150 RegStream << "OUTLINED_FUNCTION_EPILOG_TAIL_";
151 break;
152 }
153
154 for (auto Reg : Regs) {
155 if (Reg == AArch64::NoRegister)
156 continue;
158 }
159
160 return RegStream.str();
161}
162
163/// Create a Function for the unique frame helper with the given name.
164/// Return a newly created MachineFunction with an empty MachineBasicBlock.
167 StringRef Name) {
168 LLVMContext &C = M->getContext();
169 Function *F = M->getFunction(Name);
170 assert(F == nullptr && "Function has been created before");
173 assert(F && "Function was null!");
174
175 // Use ODR linkage to avoid duplication.
177 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
178
179 // Set minsize, so we don't insert padding between outlined functions.
180 F->addFnAttr(Attribute::NoInline);
181 F->addFnAttr(Attribute::MinSize);
182 F->addFnAttr(Attribute::Naked);
183
185 // Remove unnecessary register liveness and set NoVRegs.
186 MF.getProperties()
187 .resetTracksLiveness()
188 .resetIsSSA()
189 .setNoVRegs()
190 .setNoPHIs();
192
193 // Create entry block.
194 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
195 IRBuilder<> Builder(EntryBB);
196 Builder.CreateRetVoid();
197
198 // Insert the new block into the function.
200 MF.insert(MF.begin(), MBB);
201
202 return MF;
203}
204
205/// Emit a store-pair instruction for frame-setup.
206/// If Reg2 is AArch64::NoRegister, emit STR instead.
209 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
210 int Offset, bool IsPreDec) {
211 assert(Reg1 != AArch64::NoRegister);
212 const bool IsPaired = Reg2 != AArch64::NoRegister;
213 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
214 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
215 unsigned Opc;
216 if (IsPreDec) {
217 if (IsFloat)
218 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
219 else
220 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
221 } else {
222 if (IsFloat)
223 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
224 else
225 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
226 }
227 // The implicit scale for Offset is 8.
228 TypeSize Scale(0U, false), Width(0U, false);
229 int64_t MinOffset, MaxOffset;
230 [[maybe_unused]] bool Success =
231 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
232 assert(Success && "Invalid Opcode");
233 Offset *= (8 / (int)Scale);
234
235 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
236 if (IsPreDec)
237 MIB.addDef(AArch64::SP);
238 if (IsPaired)
239 MIB.addReg(Reg2);
240 MIB.addReg(Reg1)
241 .addReg(AArch64::SP)
242 .addImm(Offset)
244}
245
246/// Emit a load-pair instruction for frame-destroy.
247/// If Reg2 is AArch64::NoRegister, emit LDR instead.
250 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
251 int Offset, bool IsPostDec) {
252 assert(Reg1 != AArch64::NoRegister);
253 const bool IsPaired = Reg2 != AArch64::NoRegister;
254 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
255 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
256 unsigned Opc;
257 if (IsPostDec) {
258 if (IsFloat)
259 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
260 else
261 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
262 } else {
263 if (IsFloat)
264 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
265 else
266 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
267 }
268 // The implicit scale for Offset is 8.
269 TypeSize Scale(0U, false), Width(0U, false);
270 int64_t MinOffset, MaxOffset;
271 [[maybe_unused]] bool Success =
272 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
273 assert(Success && "Invalid Opcode");
274 Offset *= (8 / (int)Scale);
275
276 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
277 if (IsPostDec)
278 MIB.addDef(AArch64::SP);
279 if (IsPaired)
280 MIB.addReg(Reg2, getDefRegState(true));
281 MIB.addReg(Reg1, getDefRegState(true))
282 .addReg(AArch64::SP)
283 .addImm(Offset)
285}
286
287/// Return a unique function if a helper can be formed with the given Regs
288/// and frame type.
289/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
290/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
291/// stp x20, x19, [sp, #16]
292/// ret
293///
294/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
295/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
296/// stp x20, x19, [sp, #16]
297/// add fp, sp, #32
298/// ret
299///
300/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
301/// mov x16, x30
302/// ldp x29, x30, [sp, #32]
303/// ldp x20, x19, [sp, #16]
304/// ldp x22, x21, [sp], #48
305/// ret x16
306///
307/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
308/// ldp x29, x30, [sp, #32]
309/// ldp x20, x19, [sp, #16]
310/// ldp x22, x21, [sp], #48
311/// ret
312/// @param M module
313/// @param MMI machine module info
314/// @param Regs callee save regs that the helper will handle
315/// @param Type frame helper type
316/// @return a helper function
320 unsigned FpOffset = 0) {
321 assert(Regs.size() >= 2);
322 auto Name = getFrameHelperName(Regs, Type, FpOffset);
323 auto *F = M->getFunction(Name);
324 if (F)
325 return F;
326
327 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
328 MachineBasicBlock &MBB = *MF.begin();
329 const TargetSubtargetInfo &STI = MF.getSubtarget();
330 const TargetInstrInfo &TII = *STI.getInstrInfo();
331
332 int Size = (int)Regs.size();
333 switch (Type) {
336 // Compute the remaining SP adjust beyond FP/LR.
337 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
338
339 // If the register stored to the lowest address is not LR, we must subtract
340 // more from SP here.
341 if (LRIdx != Size - 2) {
342 assert(Regs[Size - 2] != AArch64::LR);
343 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
344 LRIdx - Size + 2, true);
345 }
346
347 // Store CSRs in the reverse order.
348 for (int I = Size - 3; I >= 0; I -= 2) {
349 // FP/LR has been stored at call-site.
350 if (Regs[I - 1] == AArch64::LR)
351 continue;
352 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
353 false);
354 }
356 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
357 .addDef(AArch64::FP)
358 .addUse(AArch64::SP)
359 .addImm(FpOffset)
360 .addImm(0)
362
363 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
364 .addReg(AArch64::LR);
365 break;
366 }
370 // Stash LR to X16
371 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
372 .addDef(AArch64::X16)
373 .addReg(AArch64::XZR)
374 .addUse(AArch64::LR)
375 .addImm(0);
376
377 for (int I = 0; I < Size - 2; I += 2)
378 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
379 false);
380 // Restore the last CSR with post-increment of SP.
381 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
382 true);
383
384 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
385 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
386 break;
387 }
388
389 return M->getFunction(Name);
390}
391
392/// This function checks if a frame helper should be used for
393/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
394/// @param MBB machine basic block
395/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
396/// @param Regs callee save registers that are saved or restored.
397/// @param Type frame helper type
398/// @return True if a use of helper is qualified.
403 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
404 auto RegCount = Regs.size();
405 assert(RegCount > 0 && (RegCount % 2 == 0));
406 // # of instructions that will be outlined.
407 int InstCount = RegCount / 2;
408
409 // Do not use a helper call when not saving LR.
410 if (!llvm::is_contained(Regs, AArch64::LR))
411 return false;
412
413 switch (Type) {
415 // Prolog helper cannot save FP/LR.
416 InstCount--;
417 break;
419 // Effectively no change in InstCount since FpAdjustment is included.
420 break;
421 }
423 // Bail-out if X16 is live across the epilog helper because it is used in
424 // the helper to handle X30.
425 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
426 if (NextMI->readsRegister(AArch64::W16, TRI))
427 return false;
428 }
429 // Epilog may not be in the last block. Check the liveness in successors.
430 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
431 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
432 return false;
433 }
434 // No change in InstCount for the regular epilog case.
435 break;
437 // EpilogTail helper includes the caller's return.
438 if (NextMBBI == MBB.end())
439 return false;
440 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
441 return false;
442 InstCount++;
443 break;
444 }
445 }
446
447 return InstCount >= MBB.getParent()
448 ->getSubtarget<AArch64Subtarget>()
449 .getCLOpts()
450 .frame_helper_size_threshold;
451}
452
453/// Lower a HOM_Epilog pseudo instruction into a helper call while
454/// creating the helper on demand. Or emit a sequence of loads in place when not
455/// using a helper call.
456///
457/// 1. With a helper including ret
458/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
459/// ret ; NextMBBI
460/// =>
461/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
462/// ... ; NextMBBI
463///
464/// 2. With a helper
465/// HOM_Epilog x30, x29, x19, x20, x21, x22
466/// =>
467/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
468///
469/// 3. Without a helper
470/// HOM_Epilog x30, x29, x19, x20, x21, x22
471/// =>
472/// ldp x29, x30, [sp, #32]
473/// ldp x20, x19, [sp, #16]
474/// ldp x22, x21, [sp], #48
475bool AArch64LowerHomogeneousPrologEpilogImpl::lowerEpilog(
477 MachineBasicBlock::iterator &NextMBBI) {
478 auto &MF = *MBB.getParent();
479 MachineInstr &MI = *MBBI;
480
481 DebugLoc DL = MI.getDebugLoc();
483 bool HasUnpairedReg = false;
484 for (auto &MO : MI.operands())
485 if (MO.isReg()) {
486 if (!MO.getReg().isValid()) {
487 // For now we are only expecting unpaired GP registers which should
488 // occur exactly once.
489 assert(!HasUnpairedReg);
490 HasUnpairedReg = true;
491 }
492 Regs.push_back(MO.getReg());
493 }
494 (void)HasUnpairedReg;
495 int Size = (int)Regs.size();
496 if (Size == 0)
497 return false;
498 // Registers are in pair.
499 assert(Size % 2 == 0);
500 assert(MI.getOpcode() == AArch64::HOM_Epilog);
501
502 auto Return = NextMBBI;
503 MachineInstr *HelperCall = nullptr;
505 // When MBB ends with a return, emit a tail-call to the epilog helper
506 auto *EpilogTailHelper =
508 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
509 .addGlobalAddress(EpilogTailHelper)
510 .addImm(0)
513 .copyImplicitOps(*Return);
514 NextMBBI = std::next(Return);
515 Return->removeFromParent();
516 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
518 // The default epilog helper case.
519 auto *EpilogHelper =
521 HelperCall = BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
522 .addGlobalAddress(EpilogHelper)
525 } else {
526 // Fall back to no-helper.
527 for (int I = 0; I < Size - 2; I += 2)
528 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
529 // Restore the last CSR with post-increment of SP.
530 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
531 }
532
533 // Make sure all explicit definitions are preserved in the helper call;
534 // implicit ones are already handled by copyImplicitOps.
535 if (HelperCall)
536 for (auto &Def : MBBI->defs())
537 HelperCall->addRegisterDefined(Def.getReg(),
540 return true;
541}
542
543/// Lower a HOM_Prolog pseudo instruction into a helper call while
544/// creating the helper on demand. Or emit a sequence of stores in place when
545/// not using a helper call.
546///
547/// 1. With a helper including frame-setup
548/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
549/// =>
550/// stp x29, x30, [sp, #-16]!
551/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
552///
553/// 2. With a helper
554/// HOM_Prolog x30, x29, x19, x20, x21, x22
555/// =>
556/// stp x29, x30, [sp, #-16]!
557/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
558///
559/// 3. Without a helper
560/// HOM_Prolog x30, x29, x19, x20, x21, x22
561/// =>
562/// stp x22, x21, [sp, #-48]!
563/// stp x20, x19, [sp, #16]
564/// stp x29, x30, [sp, #32]
565bool AArch64LowerHomogeneousPrologEpilogImpl::lowerProlog(
567 MachineBasicBlock::iterator &NextMBBI) {
568 auto &MF = *MBB.getParent();
569 MachineInstr &MI = *MBBI;
570
571 DebugLoc DL = MI.getDebugLoc();
573 bool HasUnpairedReg = false;
574 int LRIdx = 0;
575 std::optional<int> FpOffset;
576 for (auto &MO : MI.operands()) {
577 if (MO.isReg()) {
578 if (MO.getReg().isValid()) {
579 if (MO.getReg() == AArch64::LR)
580 LRIdx = Regs.size();
581 } else {
582 // For now we are only expecting unpaired GP registers which should
583 // occur exactly once.
584 assert(!HasUnpairedReg);
585 HasUnpairedReg = true;
586 }
587 Regs.push_back(MO.getReg());
588 } else if (MO.isImm()) {
589 FpOffset = MO.getImm();
590 }
591 }
592 (void)HasUnpairedReg;
593 int Size = (int)Regs.size();
594 if (Size == 0)
595 return false;
596 // Allow compact unwind case only for oww.
597 assert(Size % 2 == 0);
598 assert(MI.getOpcode() == AArch64::HOM_Prolog);
599
600 if (FpOffset &&
602 // FP/LR is stored at the top of stack before the prolog helper call.
603 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
604 auto *PrologFrameHelper = getOrCreateFrameHelper(
605 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
606 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
607 .addGlobalAddress(PrologFrameHelper)
611 .addReg(AArch64::SP, RegState::Implicit);
612 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
614 // FP/LR is stored at the top of stack before the prolog helper call.
615 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
616 auto *PrologHelper =
618 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
619 .addGlobalAddress(PrologHelper)
622 } else {
623 // Fall back to no-helper.
624 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
625 for (int I = Size - 3; I >= 0; I -= 2)
626 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
627 if (FpOffset) {
628 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
629 .addDef(AArch64::FP)
630 .addUse(AArch64::SP)
631 .addImm(*FpOffset)
632 .addImm(0)
634 }
635 }
636
638 return true;
639}
640
641/// Process each machine instruction
642/// @param MBB machine basic block
643/// @param MBBI current instruction iterator
644/// @param NextMBBI next instruction iterator which can be updated
645/// @return True when IR is changed.
646bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMI(
648 MachineBasicBlock::iterator &NextMBBI) {
649 MachineInstr &MI = *MBBI;
650 unsigned Opcode = MI.getOpcode();
651 switch (Opcode) {
652 default:
653 break;
654 case AArch64::HOM_Prolog:
655 return lowerProlog(MBB, MBBI, NextMBBI);
656 case AArch64::HOM_Epilog:
657 return lowerEpilog(MBB, MBBI, NextMBBI);
658 }
659 return false;
660}
661
662bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMBB(MachineBasicBlock &MBB) {
663 bool Modified = false;
664
666 while (MBBI != E) {
667 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
668 Modified |= runOnMI(MBB, MBBI, NMBBI);
669 MBBI = NMBBI;
670 }
671
672 return Modified;
673}
674
675bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMachineFunction(
676 MachineFunction &MF) {
677 TII = MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
678
679 bool Modified = false;
680 for (auto &MBB : MF)
681 Modified |= runOnMBB(MBB);
682 return Modified;
683}
684
686 return new AArch64LowerHomogeneousPrologEpilogLegacy();
687}
#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 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
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)
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: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:169
@ 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:2918
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:68
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition Pass.cpp:113
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:272
Changed
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:1781
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:1963
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39