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/Pass.h"
29#include <optional>
30#include <sstream>
31
32using namespace llvm;
33
34#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME \
35 "AArch64 homogeneous prolog/epilog lowering pass"
36
38 "frame-helper-size-threshold", cl::init(2), cl::Hidden,
39 cl::desc("The minimum number of instructions that are outlined in a frame "
40 "helper (default = 2)"));
41
42namespace {
43
44class AArch64LowerHomogeneousPE {
45public:
46 const AArch64InstrInfo *TII;
47
48 AArch64LowerHomogeneousPE(Module *M, MachineModuleInfo *MMI)
49 : M(M), MMI(MMI) {}
50
51 bool run();
52 bool runOnMachineFunction(MachineFunction &Fn);
53
54private:
55 Module *M;
57
58 bool runOnMBB(MachineBasicBlock &MBB);
61
62 /// Lower a HOM_Prolog pseudo instruction into a helper call
63 /// or a sequence of homogeneous stores.
64 /// When a fp setup follows, it can be optimized.
67 /// Lower a HOM_Epilog pseudo instruction into a helper call
68 /// or a sequence of homogeneous loads.
69 /// When a return follow, it can be optimized.
72};
73
74class AArch64LowerHomogeneousPrologEpilog : public ModulePass {
75public:
76 static char ID;
77
78 AArch64LowerHomogeneousPrologEpilog() : ModulePass(ID) {
81 }
82 void getAnalysisUsage(AnalysisUsage &AU) const override {
85 AU.setPreservesAll();
87 }
88 bool runOnModule(Module &M) override;
89
90 StringRef getPassName() const override {
92 }
93};
94
95} // end anonymous namespace
96
97char AArch64LowerHomogeneousPrologEpilog::ID = 0;
98
99INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilog,
100 "aarch64-lower-homogeneous-prolog-epilog",
102
103bool AArch64LowerHomogeneousPrologEpilog::runOnModule(Module &M) {
104 if (skipModule(M))
105 return false;
106
107 MachineModuleInfo *MMI =
108 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
109 return AArch64LowerHomogeneousPE(&M, MMI).run();
110}
111
112bool AArch64LowerHomogeneousPE::run() {
113 bool Changed = false;
114 for (auto &F : *M) {
115 if (F.empty())
116 continue;
117
118 MachineFunction *MF = MMI->getMachineFunction(F);
119 if (!MF)
120 continue;
121 Changed |= runOnMachineFunction(*MF);
122 }
123
124 return Changed;
125}
127
128/// Return a frame helper name with the given CSRs and the helper type.
129/// For instance, a prolog helper that saves x19 and x20 is named as
130/// OUTLINED_FUNCTION_PROLOG_x19x20.
132 FrameHelperType Type, unsigned FpOffset) {
133 std::ostringstream RegStream;
134 switch (Type) {
136 RegStream << "OUTLINED_FUNCTION_PROLOG_";
137 break;
139 RegStream << "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset << "_";
140 break;
142 RegStream << "OUTLINED_FUNCTION_EPILOG_";
143 break;
145 RegStream << "OUTLINED_FUNCTION_EPILOG_TAIL_";
146 break;
147 }
148
149 for (auto Reg : Regs) {
150 if (Reg == AArch64::NoRegister)
151 continue;
152 RegStream << AArch64InstPrinter::getRegisterName(Reg);
153 }
154
155 return RegStream.str();
156}
157
158/// Create a Function for the unique frame helper with the given name.
159/// Return a newly created MachineFunction with an empty MachineBasicBlock.
162 StringRef Name) {
163 LLVMContext &C = M->getContext();
164 Function *F = M->getFunction(Name);
165 assert(F == nullptr && "Function has been created before");
166 F = Function::Create(FunctionType::get(Type::getVoidTy(C), false),
167 Function::ExternalLinkage, Name, M);
168 assert(F && "Function was null!");
169
170 // Use ODR linkage to avoid duplication.
172 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
173
174 // Set no-opt/minsize, so we don't insert padding between outlined
175 // functions.
176 F->addFnAttr(Attribute::OptimizeNone);
177 F->addFnAttr(Attribute::NoInline);
178 F->addFnAttr(Attribute::MinSize);
179 F->addFnAttr(Attribute::Naked);
180
182 // Remove unnecessary register liveness and set NoVRegs.
183 MF.getProperties().reset(MachineFunctionProperties::Property::TracksLiveness);
184 MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA);
185 MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
187
188 // Create entry block.
189 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
190 IRBuilder<> Builder(EntryBB);
191 Builder.CreateRetVoid();
192
193 // Insert the new block into the function.
195 MF.insert(MF.begin(), MBB);
196
197 return MF;
198}
199
200/// Emit a store-pair instruction for frame-setup.
201/// If Reg2 is AArch64::NoRegister, emit STR instead.
204 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
205 int Offset, bool IsPreDec) {
206 assert(Reg1 != AArch64::NoRegister);
207 const bool IsPaired = Reg2 != AArch64::NoRegister;
208 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
209 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
210 unsigned Opc;
211 if (IsPreDec) {
212 if (IsFloat)
213 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
214 else
215 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
216 } else {
217 if (IsFloat)
218 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
219 else
220 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
221 }
222 // The implicit scale for Offset is 8.
223 TypeSize Scale(0U, false), Width(0U, false);
224 int64_t MinOffset, MaxOffset;
225 [[maybe_unused]] bool Success =
226 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
227 assert(Success && "Invalid Opcode");
228 Offset *= (8 / (int)Scale);
229
230 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
231 if (IsPreDec)
232 MIB.addDef(AArch64::SP);
233 if (IsPaired)
234 MIB.addReg(Reg2);
235 MIB.addReg(Reg1)
236 .addReg(AArch64::SP)
237 .addImm(Offset)
239}
240
241/// Emit a load-pair instruction for frame-destroy.
242/// If Reg2 is AArch64::NoRegister, emit LDR instead.
245 const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2,
246 int Offset, bool IsPostDec) {
247 assert(Reg1 != AArch64::NoRegister);
248 const bool IsPaired = Reg2 != AArch64::NoRegister;
249 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
250 assert(!(IsFloat ^ AArch64::FPR64RegClass.contains(Reg2)));
251 unsigned Opc;
252 if (IsPostDec) {
253 if (IsFloat)
254 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
255 else
256 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
257 } else {
258 if (IsFloat)
259 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
260 else
261 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
262 }
263 // The implicit scale for Offset is 8.
264 TypeSize Scale(0U, false), Width(0U, false);
265 int64_t MinOffset, MaxOffset;
266 [[maybe_unused]] bool Success =
267 AArch64InstrInfo::getMemOpInfo(Opc, Scale, Width, MinOffset, MaxOffset);
268 assert(Success && "Invalid Opcode");
269 Offset *= (8 / (int)Scale);
270
271 MachineInstrBuilder MIB = BuildMI(MBB, Pos, DebugLoc(), TII.get(Opc));
272 if (IsPostDec)
273 MIB.addDef(AArch64::SP);
274 if (IsPaired)
275 MIB.addReg(Reg2, getDefRegState(true));
276 MIB.addReg(Reg1, getDefRegState(true))
277 .addReg(AArch64::SP)
278 .addImm(Offset)
280}
281
282/// Return a unique function if a helper can be formed with the given Regs
283/// and frame type.
284/// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
285/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
286/// stp x20, x19, [sp, #16]
287/// ret
288///
289/// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
290/// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
291/// stp x20, x19, [sp, #16]
292/// add fp, sp, #32
293/// ret
294///
295/// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
296/// mov x16, x30
297/// ldp x29, x30, [sp, #32]
298/// ldp x20, x19, [sp, #16]
299/// ldp x22, x21, [sp], #48
300/// ret x16
301///
302/// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
303/// ldp x29, x30, [sp, #32]
304/// ldp x20, x19, [sp, #16]
305/// ldp x22, x21, [sp], #48
306/// ret
307/// @param M module
308/// @param MMI machine module info
309/// @param Regs callee save regs that the helper will handle
310/// @param Type frame helper type
311/// @return a helper function
315 unsigned FpOffset = 0) {
316 assert(Regs.size() >= 2);
317 auto Name = getFrameHelperName(Regs, Type, FpOffset);
318 auto *F = M->getFunction(Name);
319 if (F)
320 return F;
321
322 auto &MF = createFrameHelperMachineFunction(M, MMI, Name);
323 MachineBasicBlock &MBB = *MF.begin();
324 const TargetSubtargetInfo &STI = MF.getSubtarget();
325 const TargetInstrInfo &TII = *STI.getInstrInfo();
326
327 int Size = (int)Regs.size();
328 switch (Type) {
331 // Compute the remaining SP adjust beyond FP/LR.
332 auto LRIdx = std::distance(Regs.begin(), llvm::find(Regs, AArch64::LR));
333
334 // If the register stored to the lowest address is not LR, we must subtract
335 // more from SP here.
336 if (LRIdx != Size - 2) {
337 assert(Regs[Size - 2] != AArch64::LR);
338 emitStore(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1],
339 LRIdx - Size + 2, true);
340 }
341
342 // Store CSRs in the reverse order.
343 for (int I = Size - 3; I >= 0; I -= 2) {
344 // FP/LR has been stored at call-site.
345 if (Regs[I - 1] == AArch64::LR)
346 continue;
347 emitStore(MF, MBB, MBB.end(), TII, Regs[I - 1], Regs[I], Size - I - 1,
348 false);
349 }
351 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ADDXri))
352 .addDef(AArch64::FP)
353 .addUse(AArch64::SP)
354 .addImm(FpOffset)
355 .addImm(0)
357
358 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
359 .addReg(AArch64::LR);
360 break;
361 }
365 // Stash LR to X16
366 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::ORRXrs))
367 .addDef(AArch64::X16)
368 .addReg(AArch64::XZR)
369 .addUse(AArch64::LR)
370 .addImm(0);
371
372 for (int I = 0; I < Size - 2; I += 2)
373 emitLoad(MF, MBB, MBB.end(), TII, Regs[I], Regs[I + 1], Size - I - 2,
374 false);
375 // Restore the last CSR with post-increment of SP.
376 emitLoad(MF, MBB, MBB.end(), TII, Regs[Size - 2], Regs[Size - 1], Size,
377 true);
378
379 BuildMI(MBB, MBB.end(), DebugLoc(), TII.get(AArch64::RET))
380 .addReg(Type == FrameHelperType::Epilog ? AArch64::X16 : AArch64::LR);
381 break;
382 }
383
384 return M->getFunction(Name);
385}
386
387/// This function checks if a frame helper should be used for
388/// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
389/// @param MBB machine basic block
390/// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
391/// @param Regs callee save registers that are saved or restored.
392/// @param Type frame helper type
393/// @return True if a use of helper is qualified.
398 const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
399 auto RegCount = Regs.size();
400 assert(RegCount > 0 && (RegCount % 2 == 0));
401 // # of instructions that will be outlined.
402 int InstCount = RegCount / 2;
403
404 // Do not use a helper call when not saving LR.
405 if (!llvm::is_contained(Regs, AArch64::LR))
406 return false;
407
408 switch (Type) {
410 // Prolog helper cannot save FP/LR.
411 InstCount--;
412 break;
414 // Effecitvely no change in InstCount since FpAdjusment is included.
415 break;
416 }
418 // Bail-out if X16 is live across the epilog helper because it is used in
419 // the helper to handle X30.
420 for (auto NextMI = NextMBBI; NextMI != MBB.end(); NextMI++) {
421 if (NextMI->readsRegister(AArch64::W16, TRI))
422 return false;
423 }
424 // Epilog may not be in the last block. Check the liveness in successors.
425 for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
426 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
427 return false;
428 }
429 // No change in InstCount for the regular epilog case.
430 break;
432 // EpilogTail helper includes the caller's return.
433 if (NextMBBI == MBB.end())
434 return false;
435 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
436 return false;
437 InstCount++;
438 break;
439 }
440 }
441
442 return InstCount >= FrameHelperSizeThreshold;
443}
444
445/// Lower a HOM_Epilog pseudo instruction into a helper call while
446/// creating the helper on demand. Or emit a sequence of loads in place when not
447/// using a helper call.
448///
449/// 1. With a helper including ret
450/// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
451/// ret ; NextMBBI
452/// =>
453/// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
454/// ... ; NextMBBI
455///
456/// 2. With a helper
457/// HOM_Epilog x30, x29, x19, x20, x21, x22
458/// =>
459/// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
460///
461/// 3. Without a helper
462/// HOM_Epilog x30, x29, x19, x20, x21, x22
463/// =>
464/// ldp x29, x30, [sp, #32]
465/// ldp x20, x19, [sp, #16]
466/// ldp x22, x21, [sp], #48
467bool AArch64LowerHomogeneousPE::lowerEpilog(
469 MachineBasicBlock::iterator &NextMBBI) {
470 auto &MF = *MBB.getParent();
471 MachineInstr &MI = *MBBI;
472
473 DebugLoc DL = MI.getDebugLoc();
475 bool HasUnpairedReg = false;
476 for (auto &MO : MI.operands())
477 if (MO.isReg()) {
478 if (!MO.getReg().isValid()) {
479 // For now we are only expecting unpaired GP registers which should
480 // occur exactly once.
481 assert(!HasUnpairedReg);
482 HasUnpairedReg = true;
483 }
484 Regs.push_back(MO.getReg());
485 }
486 (void)HasUnpairedReg;
487 int Size = (int)Regs.size();
488 if (Size == 0)
489 return false;
490 // Registers are in pair.
491 assert(Size % 2 == 0);
492 assert(MI.getOpcode() == AArch64::HOM_Epilog);
493
494 auto Return = NextMBBI;
496 // When MBB ends with a return, emit a tail-call to the epilog helper
497 auto *EpilogTailHelper =
499 BuildMI(MBB, MBBI, DL, TII->get(AArch64::TCRETURNdi))
500 .addGlobalAddress(EpilogTailHelper)
501 .addImm(0)
504 .copyImplicitOps(*Return);
505 NextMBBI = std::next(Return);
506 Return->removeFromParent();
507 } else if (shouldUseFrameHelper(MBB, NextMBBI, Regs,
509 // The default epilog helper case.
510 auto *EpilogHelper =
512 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
513 .addGlobalAddress(EpilogHelper)
516 } else {
517 // Fall back to no-helper.
518 for (int I = 0; I < Size - 2; I += 2)
519 emitLoad(MF, MBB, MBBI, *TII, Regs[I], Regs[I + 1], Size - I - 2, false);
520 // Restore the last CSR with post-increment of SP.
521 emitLoad(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], Size, true);
522 }
523
525 return true;
526}
527
528/// Lower a HOM_Prolog pseudo instruction into a helper call while
529/// creating the helper on demand. Or emit a sequence of stores in place when
530/// not using a helper call.
531///
532/// 1. With a helper including frame-setup
533/// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
534/// =>
535/// stp x29, x30, [sp, #-16]!
536/// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
537///
538/// 2. With a helper
539/// HOM_Prolog x30, x29, x19, x20, x21, x22
540/// =>
541/// stp x29, x30, [sp, #-16]!
542/// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
543///
544/// 3. Without a helper
545/// HOM_Prolog x30, x29, x19, x20, x21, x22
546/// =>
547/// stp x22, x21, [sp, #-48]!
548/// stp x20, x19, [sp, #16]
549/// stp x29, x30, [sp, #32]
550bool AArch64LowerHomogeneousPE::lowerProlog(
552 MachineBasicBlock::iterator &NextMBBI) {
553 auto &MF = *MBB.getParent();
554 MachineInstr &MI = *MBBI;
555
556 DebugLoc DL = MI.getDebugLoc();
558 bool HasUnpairedReg = false;
559 int LRIdx = 0;
560 std::optional<int> FpOffset;
561 for (auto &MO : MI.operands()) {
562 if (MO.isReg()) {
563 if (MO.getReg().isValid()) {
564 if (MO.getReg() == AArch64::LR)
565 LRIdx = Regs.size();
566 } else {
567 // For now we are only expecting unpaired GP registers which should
568 // occur exactly once.
569 assert(!HasUnpairedReg);
570 HasUnpairedReg = true;
571 }
572 Regs.push_back(MO.getReg());
573 } else if (MO.isImm()) {
574 FpOffset = MO.getImm();
575 }
576 }
577 (void)HasUnpairedReg;
578 int Size = (int)Regs.size();
579 if (Size == 0)
580 return false;
581 // Allow compact unwind case only for oww.
582 assert(Size % 2 == 0);
583 assert(MI.getOpcode() == AArch64::HOM_Prolog);
584
585 if (FpOffset &&
587 // FP/LR is stored at the top of stack before the prolog helper call.
588 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
589 auto *PrologFrameHelper = getOrCreateFrameHelper(
590 M, MMI, Regs, FrameHelperType::PrologFrame, *FpOffset);
591 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
592 .addGlobalAddress(PrologFrameHelper)
596 .addReg(AArch64::SP, RegState::Implicit);
597 } else if (!FpOffset && shouldUseFrameHelper(MBB, NextMBBI, Regs,
599 // FP/LR is stored at the top of stack before the prolog helper call.
600 emitStore(MF, MBB, MBBI, *TII, AArch64::LR, AArch64::FP, -LRIdx - 2, true);
601 auto *PrologHelper =
603 BuildMI(MBB, MBBI, DL, TII->get(AArch64::BL))
604 .addGlobalAddress(PrologHelper)
607 } else {
608 // Fall back to no-helper.
609 emitStore(MF, MBB, MBBI, *TII, Regs[Size - 2], Regs[Size - 1], -Size, true);
610 for (int I = Size - 3; I >= 0; I -= 2)
611 emitStore(MF, MBB, MBBI, *TII, Regs[I - 1], Regs[I], Size - I - 1, false);
612 if (FpOffset) {
613 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri))
614 .addDef(AArch64::FP)
615 .addUse(AArch64::SP)
616 .addImm(*FpOffset)
617 .addImm(0)
619 }
620 }
621
623 return true;
624}
625
626/// Process each machine instruction
627/// @param MBB machine basic block
628/// @param MBBI current instruction iterator
629/// @param NextMBBI next instruction iterator which can be updated
630/// @return True when IR is changed.
631bool AArch64LowerHomogeneousPE::runOnMI(MachineBasicBlock &MBB,
633 MachineBasicBlock::iterator &NextMBBI) {
634 MachineInstr &MI = *MBBI;
635 unsigned Opcode = MI.getOpcode();
636 switch (Opcode) {
637 default:
638 break;
639 case AArch64::HOM_Prolog:
640 return lowerProlog(MBB, MBBI, NextMBBI);
641 case AArch64::HOM_Epilog:
642 return lowerEpilog(MBB, MBBI, NextMBBI);
643 }
644 return false;
645}
646
647bool AArch64LowerHomogeneousPE::runOnMBB(MachineBasicBlock &MBB) {
648 bool Modified = false;
649
651 while (MBBI != E) {
652 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
653 Modified |= runOnMI(MBB, MBBI, NMBBI);
654 MBBI = NMBBI;
655 }
656
657 return Modified;
658}
659
660bool AArch64LowerHomogeneousPE::runOnMachineFunction(MachineFunction &MF) {
661 TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
662
663 bool Modified = false;
664 for (auto &MBB : MF)
665 Modified |= runOnMBB(MBB);
666 return Modified;
667}
668
670 return new AArch64LowerHomogeneousPrologEpilog();
671}
#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
#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:60
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:198
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:162
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:55
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition: IRBuilder.h:1084
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2644
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:450
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:456
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:1751
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:1888