1 //===- AArch64LowerHomogeneousPrologEpilog.cpp ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains a pass that lowers homogeneous prolog/epilog instructions.
11 //===----------------------------------------------------------------------===//
13 #include "AArch64InstrInfo.h"
14 #include "AArch64Subtarget.h"
15 #include "MCTargetDesc/AArch64InstPrinter.h"
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineModuleInfo.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/TargetSubtargetInfo.h"
25 #include "llvm/IR/DebugLoc.h"
26 #include "llvm/IR/IRBuilder.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Support/raw_ostream.h"
33 #define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME \
34 "AArch64 homogeneous prolog/epilog lowering pass"
36 cl::opt
<int> FrameHelperSizeThreshold(
37 "frame-helper-size-threshold", cl::init(2), cl::Hidden
,
38 cl::desc("The minimum number of instructions that are outlined in a frame "
39 "helper (default = 2)"));
43 class AArch64LowerHomogeneousPE
{
45 const AArch64InstrInfo
*TII
;
47 AArch64LowerHomogeneousPE(Module
*M
, MachineModuleInfo
*MMI
)
51 bool runOnMachineFunction(MachineFunction
&Fn
);
55 MachineModuleInfo
*MMI
;
57 bool runOnMBB(MachineBasicBlock
&MBB
);
58 bool runOnMI(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
59 MachineBasicBlock::iterator
&NextMBBI
);
61 /// Lower a HOM_Prolog pseudo instruction into a helper call
62 /// or a sequence of homogeneous stores.
63 /// When a a fp setup follows, it can be optimized.
64 bool lowerProlog(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
65 MachineBasicBlock::iterator
&NextMBBI
);
66 /// Lower a HOM_Epilog pseudo instruction into a helper call
67 /// or a sequence of homogeneous loads.
68 /// When a return follow, it can be optimized.
69 bool lowerEpilog(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
70 MachineBasicBlock::iterator
&NextMBBI
);
73 class AArch64LowerHomogeneousPrologEpilog
: public ModulePass
{
77 AArch64LowerHomogeneousPrologEpilog() : ModulePass(ID
) {
78 initializeAArch64LowerHomogeneousPrologEpilogPass(
79 *PassRegistry::getPassRegistry());
81 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
82 AU
.addRequired
<MachineModuleInfoWrapperPass
>();
83 AU
.addPreserved
<MachineModuleInfoWrapperPass
>();
85 ModulePass::getAnalysisUsage(AU
);
87 bool runOnModule(Module
&M
) override
;
89 StringRef
getPassName() const override
{
90 return AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME
;
94 } // end anonymous namespace
96 char AArch64LowerHomogeneousPrologEpilog::ID
= 0;
98 INITIALIZE_PASS(AArch64LowerHomogeneousPrologEpilog
,
99 "aarch64-lower-homogeneous-prolog-epilog",
100 AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME
, false, false)
102 bool AArch64LowerHomogeneousPrologEpilog::runOnModule(Module
&M
) {
106 MachineModuleInfo
*MMI
=
107 &getAnalysis
<MachineModuleInfoWrapperPass
>().getMMI();
108 return AArch64LowerHomogeneousPE(&M
, MMI
).run();
111 bool AArch64LowerHomogeneousPE::run() {
112 bool Changed
= false;
117 MachineFunction
*MF
= MMI
->getMachineFunction(F
);
120 Changed
|= runOnMachineFunction(*MF
);
125 enum FrameHelperType
{ Prolog
, PrologFrame
, Epilog
, EpilogTail
};
127 /// Return a frame helper name with the given CSRs and the helper type.
128 /// For instance, a prolog helper that saves x19 and x20 is named as
129 /// OUTLINED_FUNCTION_PROLOG_x19x20.
130 static std::string
getFrameHelperName(SmallVectorImpl
<unsigned> &Regs
,
131 FrameHelperType Type
, unsigned FpOffset
) {
132 std::ostringstream RegStream
;
134 case FrameHelperType::Prolog
:
135 RegStream
<< "OUTLINED_FUNCTION_PROLOG_";
137 case FrameHelperType::PrologFrame
:
138 RegStream
<< "OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset
<< "_";
140 case FrameHelperType::Epilog
:
141 RegStream
<< "OUTLINED_FUNCTION_EPILOG_";
143 case FrameHelperType::EpilogTail
:
144 RegStream
<< "OUTLINED_FUNCTION_EPILOG_TAIL_";
148 for (auto Reg
: Regs
)
149 RegStream
<< AArch64InstPrinter::getRegisterName(Reg
);
151 return RegStream
.str();
154 /// Create a Function for the unique frame helper with the given name.
155 /// Return a newly created MachineFunction with an empty MachineBasicBlock.
156 static MachineFunction
&createFrameHelperMachineFunction(Module
*M
,
157 MachineModuleInfo
*MMI
,
159 LLVMContext
&C
= M
->getContext();
160 Function
*F
= M
->getFunction(Name
);
161 assert(F
== nullptr && "Function has been created before");
162 F
= Function::Create(FunctionType::get(Type::getVoidTy(C
), false),
163 Function::ExternalLinkage
, Name
, M
);
164 assert(F
&& "Function was null!");
166 // Use ODR linkage to avoid duplication.
167 F
->setLinkage(GlobalValue::LinkOnceODRLinkage
);
168 F
->setUnnamedAddr(GlobalValue::UnnamedAddr::Global
);
170 // Set no-opt/minsize, so we don't insert padding between outlined
172 F
->addFnAttr(Attribute::OptimizeNone
);
173 F
->addFnAttr(Attribute::NoInline
);
174 F
->addFnAttr(Attribute::MinSize
);
175 F
->addFnAttr(Attribute::Naked
);
177 MachineFunction
&MF
= MMI
->getOrCreateMachineFunction(*F
);
178 // Remove unnecessary register liveness and set NoVRegs.
179 MF
.getProperties().reset(MachineFunctionProperties::Property::TracksLiveness
);
180 MF
.getProperties().reset(MachineFunctionProperties::Property::IsSSA
);
181 MF
.getProperties().set(MachineFunctionProperties::Property::NoVRegs
);
182 MF
.getRegInfo().freezeReservedRegs(MF
);
184 // Create entry block.
185 BasicBlock
*EntryBB
= BasicBlock::Create(C
, "entry", F
);
186 IRBuilder
<> Builder(EntryBB
);
187 Builder
.CreateRetVoid();
189 // Insert the new block into the function.
190 MachineBasicBlock
*MBB
= MF
.CreateMachineBasicBlock();
191 MF
.insert(MF
.begin(), MBB
);
196 /// Emit a store-pair instruction for frame-setup.
197 static void emitStore(MachineFunction
&MF
, MachineBasicBlock
&MBB
,
198 MachineBasicBlock::iterator Pos
,
199 const TargetInstrInfo
&TII
, unsigned Reg1
, unsigned Reg2
,
200 int Offset
, bool IsPreDec
) {
201 bool IsFloat
= AArch64::FPR64RegClass
.contains(Reg1
);
202 assert(!(IsFloat
^ AArch64::FPR64RegClass
.contains(Reg2
)));
205 Opc
= IsFloat
? AArch64::STPDpre
: AArch64::STPXpre
;
207 Opc
= IsFloat
? AArch64::STPDi
: AArch64::STPXi
;
209 MachineInstrBuilder MIB
= BuildMI(MBB
, Pos
, DebugLoc(), TII
.get(Opc
));
211 MIB
.addDef(AArch64::SP
);
216 .setMIFlag(MachineInstr::FrameSetup
);
219 /// Emit a load-pair instruction for frame-destroy.
220 static void emitLoad(MachineFunction
&MF
, MachineBasicBlock
&MBB
,
221 MachineBasicBlock::iterator Pos
,
222 const TargetInstrInfo
&TII
, unsigned Reg1
, unsigned Reg2
,
223 int Offset
, bool IsPostDec
) {
224 bool IsFloat
= AArch64::FPR64RegClass
.contains(Reg1
);
225 assert(!(IsFloat
^ AArch64::FPR64RegClass
.contains(Reg2
)));
228 Opc
= IsFloat
? AArch64::LDPDpost
: AArch64::LDPXpost
;
230 Opc
= IsFloat
? AArch64::LDPDi
: AArch64::LDPXi
;
232 MachineInstrBuilder MIB
= BuildMI(MBB
, Pos
, DebugLoc(), TII
.get(Opc
));
234 MIB
.addDef(AArch64::SP
);
235 MIB
.addReg(Reg2
, getDefRegState(true))
236 .addReg(Reg1
, getDefRegState(true))
239 .setMIFlag(MachineInstr::FrameDestroy
);
242 /// Return a unique function if a helper can be formed with the given Regs
244 /// 1) _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22:
245 /// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
246 /// stp x20, x19, [sp, #16]
249 /// 2) _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22:
250 /// stp x22, x21, [sp, #-32]! ; x29/x30 has been stored at the caller
251 /// stp x20, x19, [sp, #16]
255 /// 3) _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22:
257 /// ldp x29, x30, [sp, #32]
258 /// ldp x20, x19, [sp, #16]
259 /// ldp x22, x21, [sp], #48
262 /// 4) _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22:
263 /// ldp x29, x30, [sp, #32]
264 /// ldp x20, x19, [sp, #16]
265 /// ldp x22, x21, [sp], #48
268 /// @param MMI machine module info
269 /// @param Regs callee save regs that the helper will handle
270 /// @param Type frame helper type
271 /// @return a helper function
272 static Function
*getOrCreateFrameHelper(Module
*M
, MachineModuleInfo
*MMI
,
273 SmallVectorImpl
<unsigned> &Regs
,
274 FrameHelperType Type
,
275 unsigned FpOffset
= 0) {
276 assert(Regs
.size() >= 2);
277 auto Name
= getFrameHelperName(Regs
, Type
, FpOffset
);
278 auto *F
= M
->getFunction(Name
);
282 auto &MF
= createFrameHelperMachineFunction(M
, MMI
, Name
);
283 MachineBasicBlock
&MBB
= *MF
.begin();
284 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
285 const TargetInstrInfo
&TII
= *STI
.getInstrInfo();
287 int Size
= (int)Regs
.size();
289 case FrameHelperType::Prolog
:
290 case FrameHelperType::PrologFrame
: {
291 // Compute the remaining SP adjust beyond FP/LR.
292 auto LRIdx
= std::distance(
293 Regs
.begin(), std::find(Regs
.begin(), Regs
.end(), AArch64::LR
));
295 // If the register stored to the lowest address is not LR, we must subtract
296 // more from SP here.
297 if (LRIdx
!= Size
- 2) {
298 assert(Regs
[Size
- 2] != AArch64::LR
);
299 emitStore(MF
, MBB
, MBB
.end(), TII
, Regs
[Size
- 2], Regs
[Size
- 1],
300 LRIdx
- Size
+ 2, true);
303 // Store CSRs in the reverse order.
304 for (int I
= Size
- 3; I
>= 0; I
-= 2) {
305 // FP/LR has been stored at call-site.
306 if (Regs
[I
- 1] == AArch64::LR
)
308 emitStore(MF
, MBB
, MBB
.end(), TII
, Regs
[I
- 1], Regs
[I
], Size
- I
- 1,
311 if (Type
== FrameHelperType::PrologFrame
)
312 BuildMI(MBB
, MBB
.end(), DebugLoc(), TII
.get(AArch64::ADDXri
))
317 .setMIFlag(MachineInstr::FrameSetup
);
319 BuildMI(MBB
, MBB
.end(), DebugLoc(), TII
.get(AArch64::RET
))
320 .addReg(AArch64::LR
);
323 case FrameHelperType::Epilog
:
324 case FrameHelperType::EpilogTail
:
325 if (Type
== FrameHelperType::Epilog
)
327 BuildMI(MBB
, MBB
.end(), DebugLoc(), TII
.get(AArch64::ORRXrs
))
328 .addDef(AArch64::X16
)
329 .addReg(AArch64::XZR
)
333 for (int I
= 0; I
< Size
- 2; I
+= 2)
334 emitLoad(MF
, MBB
, MBB
.end(), TII
, Regs
[I
], Regs
[I
+ 1], Size
- I
- 2,
336 // Restore the last CSR with post-increment of SP.
337 emitLoad(MF
, MBB
, MBB
.end(), TII
, Regs
[Size
- 2], Regs
[Size
- 1], Size
,
340 BuildMI(MBB
, MBB
.end(), DebugLoc(), TII
.get(AArch64::RET
))
341 .addReg(Type
== FrameHelperType::Epilog
? AArch64::X16
: AArch64::LR
);
345 return M
->getFunction(Name
);
348 /// This function checks if a frame helper should be used for
349 /// HOM_Prolog/HOM_Epilog pseudo instruction expansion.
350 /// @param MBB machine basic block
351 /// @param NextMBBI next instruction following HOM_Prolog/HOM_Epilog
352 /// @param Regs callee save registers that are saved or restored.
353 /// @param Type frame helper type
354 /// @return True if a use of helper is qualified.
355 static bool shouldUseFrameHelper(MachineBasicBlock
&MBB
,
356 MachineBasicBlock::iterator
&NextMBBI
,
357 SmallVectorImpl
<unsigned> &Regs
,
358 FrameHelperType Type
) {
359 const auto *TRI
= MBB
.getParent()->getSubtarget().getRegisterInfo();
360 auto RegCount
= Regs
.size();
361 assert(RegCount
> 0 && (RegCount
% 2 == 0));
362 // # of instructions that will be outlined.
363 int InstCount
= RegCount
/ 2;
365 // Do not use a helper call when not saving LR.
366 if (std::find(Regs
.begin(), Regs
.end(), AArch64::LR
) == Regs
.end())
370 case FrameHelperType::Prolog
:
371 // Prolog helper cannot save FP/LR.
374 case FrameHelperType::PrologFrame
: {
375 // Effecitvely no change in InstCount since FpAdjusment is included.
378 case FrameHelperType::Epilog
:
379 // Bail-out if X16 is live across the epilog helper because it is used in
380 // the helper to handle X30.
381 for (auto NextMI
= NextMBBI
; NextMI
!= MBB
.end(); NextMI
++) {
382 if (NextMI
->readsRegister(AArch64::W16
, TRI
))
385 // Epilog may not be in the last block. Check the liveness in successors.
386 for (const MachineBasicBlock
*SuccMBB
: MBB
.successors()) {
387 if (SuccMBB
->isLiveIn(AArch64::W16
) || SuccMBB
->isLiveIn(AArch64::X16
))
390 // No change in InstCount for the regular epilog case.
392 case FrameHelperType::EpilogTail
: {
393 // EpilogTail helper includes the caller's return.
394 if (NextMBBI
== MBB
.end())
396 if (NextMBBI
->getOpcode() != AArch64::RET_ReallyLR
)
403 return InstCount
>= FrameHelperSizeThreshold
;
406 /// Lower a HOM_Epilog pseudo instruction into a helper call while
407 /// creating the helper on demand. Or emit a sequence of loads in place when not
408 /// using a helper call.
410 /// 1. With a helper including ret
411 /// HOM_Epilog x30, x29, x19, x20, x21, x22 ; MBBI
414 /// b _OUTLINED_FUNCTION_EPILOG_TAIL_x30x29x19x20x21x22
418 /// HOM_Epilog x30, x29, x19, x20, x21, x22
420 /// bl _OUTLINED_FUNCTION_EPILOG_x30x29x19x20x21x22
422 /// 3. Without a helper
423 /// HOM_Epilog x30, x29, x19, x20, x21, x22
425 /// ldp x29, x30, [sp, #32]
426 /// ldp x20, x19, [sp, #16]
427 /// ldp x22, x21, [sp], #48
428 bool AArch64LowerHomogeneousPE::lowerEpilog(
429 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
430 MachineBasicBlock::iterator
&NextMBBI
) {
431 auto &MF
= *MBB
.getParent();
432 MachineInstr
&MI
= *MBBI
;
434 DebugLoc DL
= MI
.getDebugLoc();
435 SmallVector
<unsigned, 8> Regs
;
436 for (auto &MO
: MI
.operands())
438 Regs
.push_back(MO
.getReg());
439 int Size
= (int)Regs
.size();
442 // Registers are in pair.
443 assert(Size
% 2 == 0);
444 assert(MI
.getOpcode() == AArch64::HOM_Epilog
);
446 auto Return
= NextMBBI
;
447 if (shouldUseFrameHelper(MBB
, NextMBBI
, Regs
, FrameHelperType::EpilogTail
)) {
448 // When MBB ends with a return, emit a tail-call to the epilog helper
449 auto *EpilogTailHelper
=
450 getOrCreateFrameHelper(M
, MMI
, Regs
, FrameHelperType::EpilogTail
);
451 BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::TCRETURNdi
))
452 .addGlobalAddress(EpilogTailHelper
)
454 .setMIFlag(MachineInstr::FrameDestroy
)
456 .copyImplicitOps(*Return
);
457 NextMBBI
= std::next(Return
);
458 Return
->removeFromParent();
459 } else if (shouldUseFrameHelper(MBB
, NextMBBI
, Regs
,
460 FrameHelperType::Epilog
)) {
461 // The default epilog helper case.
463 getOrCreateFrameHelper(M
, MMI
, Regs
, FrameHelperType::Epilog
);
464 BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::BL
))
465 .addGlobalAddress(EpilogHelper
)
466 .setMIFlag(MachineInstr::FrameDestroy
)
467 .copyImplicitOps(MI
);
469 // Fall back to no-helper.
470 for (int I
= 0; I
< Size
- 2; I
+= 2)
471 emitLoad(MF
, MBB
, MBBI
, *TII
, Regs
[I
], Regs
[I
+ 1], Size
- I
- 2, false);
472 // Restore the last CSR with post-increment of SP.
473 emitLoad(MF
, MBB
, MBBI
, *TII
, Regs
[Size
- 2], Regs
[Size
- 1], Size
, true);
476 MBBI
->removeFromParent();
480 /// Lower a HOM_Prolog pseudo instruction into a helper call while
481 /// creating the helper on demand. Or emit a sequence of stores in place when
482 /// not using a helper call.
484 /// 1. With a helper including frame-setup
485 /// HOM_Prolog x30, x29, x19, x20, x21, x22, 32
487 /// stp x29, x30, [sp, #-16]!
488 /// bl _OUTLINED_FUNCTION_PROLOG_FRAME32_x30x29x19x20x21x22
491 /// HOM_Prolog x30, x29, x19, x20, x21, x22
493 /// stp x29, x30, [sp, #-16]!
494 /// bl _OUTLINED_FUNCTION_PROLOG_x30x29x19x20x21x22
496 /// 3. Without a helper
497 /// HOM_Prolog x30, x29, x19, x20, x21, x22
499 /// stp x22, x21, [sp, #-48]!
500 /// stp x20, x19, [sp, #16]
501 /// stp x29, x30, [sp, #32]
502 bool AArch64LowerHomogeneousPE::lowerProlog(
503 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
504 MachineBasicBlock::iterator
&NextMBBI
) {
505 auto &MF
= *MBB
.getParent();
506 MachineInstr
&MI
= *MBBI
;
508 DebugLoc DL
= MI
.getDebugLoc();
509 SmallVector
<unsigned, 8> Regs
;
511 Optional
<int> FpOffset
;
512 for (auto &MO
: MI
.operands()) {
514 if (MO
.getReg() == AArch64::LR
)
516 Regs
.push_back(MO
.getReg());
517 } else if (MO
.isImm()) {
518 FpOffset
= MO
.getImm();
521 int Size
= (int)Regs
.size();
524 // Allow compact unwind case only for oww.
525 assert(Size
% 2 == 0);
526 assert(MI
.getOpcode() == AArch64::HOM_Prolog
);
529 shouldUseFrameHelper(MBB
, NextMBBI
, Regs
, FrameHelperType::PrologFrame
)) {
530 // FP/LR is stored at the top of stack before the prolog helper call.
531 emitStore(MF
, MBB
, MBBI
, *TII
, AArch64::LR
, AArch64::FP
, -LRIdx
- 2, true);
532 auto *PrologFrameHelper
= getOrCreateFrameHelper(
533 M
, MMI
, Regs
, FrameHelperType::PrologFrame
, *FpOffset
);
534 BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::BL
))
535 .addGlobalAddress(PrologFrameHelper
)
536 .setMIFlag(MachineInstr::FrameSetup
)
538 .addReg(AArch64::FP
, RegState::Implicit
| RegState::Define
)
539 .addReg(AArch64::SP
, RegState::Implicit
);
540 } else if (!FpOffset
&& shouldUseFrameHelper(MBB
, NextMBBI
, Regs
,
541 FrameHelperType::Prolog
)) {
542 // FP/LR is stored at the top of stack before the prolog helper call.
543 emitStore(MF
, MBB
, MBBI
, *TII
, AArch64::LR
, AArch64::FP
, -LRIdx
- 2, true);
545 getOrCreateFrameHelper(M
, MMI
, Regs
, FrameHelperType::Prolog
);
546 BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::BL
))
547 .addGlobalAddress(PrologHelper
)
548 .setMIFlag(MachineInstr::FrameSetup
)
549 .copyImplicitOps(MI
);
551 // Fall back to no-helper.
552 emitStore(MF
, MBB
, MBBI
, *TII
, Regs
[Size
- 2], Regs
[Size
- 1], -Size
, true);
553 for (int I
= Size
- 3; I
>= 0; I
-= 2)
554 emitStore(MF
, MBB
, MBBI
, *TII
, Regs
[I
- 1], Regs
[I
], Size
- I
- 1, false);
556 BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::ADDXri
))
561 .setMIFlag(MachineInstr::FrameSetup
);
565 MBBI
->removeFromParent();
569 /// Process each machine instruction
570 /// @param MBB machine basic block
571 /// @param MBBI current instruction iterator
572 /// @param NextMBBI next instruction iterator which can be updated
573 /// @return True when IR is changed.
574 bool AArch64LowerHomogeneousPE::runOnMI(MachineBasicBlock
&MBB
,
575 MachineBasicBlock::iterator MBBI
,
576 MachineBasicBlock::iterator
&NextMBBI
) {
577 MachineInstr
&MI
= *MBBI
;
578 unsigned Opcode
= MI
.getOpcode();
582 case AArch64::HOM_Prolog
:
583 return lowerProlog(MBB
, MBBI
, NextMBBI
);
584 case AArch64::HOM_Epilog
:
585 return lowerEpilog(MBB
, MBBI
, NextMBBI
);
590 bool AArch64LowerHomogeneousPE::runOnMBB(MachineBasicBlock
&MBB
) {
591 bool Modified
= false;
593 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
595 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
596 Modified
|= runOnMI(MBB
, MBBI
, NMBBI
);
603 bool AArch64LowerHomogeneousPE::runOnMachineFunction(MachineFunction
&MF
) {
604 TII
= static_cast<const AArch64InstrInfo
*>(MF
.getSubtarget().getInstrInfo());
606 bool Modified
= false;
608 Modified
|= runOnMBB(MBB
);
612 ModulePass
*llvm::createAArch64LowerHomogeneousPrologEpilogPass() {
613 return new AArch64LowerHomogeneousPrologEpilog();