35#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME \
36 "AArch64 homogeneous prolog/epilog lowering pass"
40 cl::desc(
"The minimum number of instructions that are outlined in a frame "
41 "helper (default = 2)"));
45class AArch64LowerHomogeneousPrologEpilogImpl {
53 bool runOnMachineFunction(MachineFunction &Fn);
57 MachineModuleInfo *MMI;
59 bool runOnMBB(MachineBasicBlock &
MBB);
75class AArch64LowerHomogeneousPrologEpilogLegacy :
public ModulePass {
79 AArch64LowerHomogeneousPrologEpilogLegacy() : ModulePass(ID) {}
80 void getAnalysisUsage(AnalysisUsage &AU)
const override {
84 ModulePass::getAnalysisUsage(AU);
86 bool runOnModule(
Module &M)
override;
88 StringRef getPassName()
const override {
95char AArch64LowerHomogeneousPrologEpilogLegacy::ID = 0;
98 "aarch64-lower-homogeneous-prolog-epilog",
101bool AArch64LowerHomogeneousPrologEpilogLegacy::runOnModule(
Module &M) {
106 &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
107 return AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
114 bool Changed = AArch64LowerHomogeneousPrologEpilogImpl(&M, MMI).run();
122bool AArch64LowerHomogeneousPrologEpilogImpl::run() {
131 Changed |= runOnMachineFunction(*MF);
143 std::ostringstream RegStream;
146 RegStream <<
"OUTLINED_FUNCTION_PROLOG_";
149 RegStream <<
"OUTLINED_FUNCTION_PROLOG_FRAME" << FpOffset <<
"_";
152 RegStream <<
"OUTLINED_FUNCTION_EPILOG_";
155 RegStream <<
"OUTLINED_FUNCTION_EPILOG_TAIL_";
159 for (
auto Reg : Regs) {
160 if (
Reg == AArch64::NoRegister)
165 return RegStream.str();
175 assert(
F ==
nullptr &&
"Function has been created before");
178 assert(
F &&
"Function was null!");
185 F->addFnAttr(Attribute::NoInline);
186 F->addFnAttr(Attribute::MinSize);
187 F->addFnAttr(Attribute::Naked);
191 MF.
getProperties().resetTracksLiveness().resetIsSSA().setNoVRegs();
197 Builder.CreateRetVoid();
211 int Offset,
bool IsPreDec) {
212 assert(Reg1 != AArch64::NoRegister);
213 const bool IsPaired = Reg2 != AArch64::NoRegister;
214 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
219 Opc = IsPaired ? AArch64::STPDpre : AArch64::STRDpre;
221 Opc = IsPaired ? AArch64::STPXpre : AArch64::STRXpre;
224 Opc = IsPaired ? AArch64::STPDi : AArch64::STRDui;
226 Opc = IsPaired ? AArch64::STPXi : AArch64::STRXui;
229 TypeSize Scale(0U,
false), Width(0U,
false);
230 int64_t MinOffset, MaxOffset;
231 [[maybe_unused]]
bool Success =
234 Offset *= (8 / (int)Scale);
252 int Offset,
bool IsPostDec) {
253 assert(Reg1 != AArch64::NoRegister);
254 const bool IsPaired = Reg2 != AArch64::NoRegister;
255 bool IsFloat = AArch64::FPR64RegClass.contains(Reg1);
260 Opc = IsPaired ? AArch64::LDPDpost : AArch64::LDRDpost;
262 Opc = IsPaired ? AArch64::LDPXpost : AArch64::LDRXpost;
265 Opc = IsPaired ? AArch64::LDPDi : AArch64::LDRDui;
267 Opc = IsPaired ? AArch64::LDPXi : AArch64::LDRXui;
270 TypeSize Scale(0U,
false), Width(0U,
false);
271 int64_t MinOffset, MaxOffset;
272 [[maybe_unused]]
bool Success =
275 Offset *= (8 / (int)Scale);
321 unsigned FpOffset = 0) {
324 auto *
F = M->getFunction(Name);
338 auto LRIdx = std::distance(Regs.
begin(),
llvm::find(Regs, AArch64::LR));
342 if (LRIdx !=
Size - 2) {
345 LRIdx -
Size + 2,
true);
349 for (
int I =
Size - 3;
I >= 0;
I -= 2) {
351 if (Regs[
I - 1] == AArch64::LR)
378 for (
int I = 0;
I <
Size - 2;
I += 2)
390 return M->getFunction(Name);
404 const auto *
TRI =
MBB.getParent()->getSubtarget().getRegisterInfo();
405 auto RegCount = Regs.
size();
406 assert(RegCount > 0 && (RegCount % 2 == 0));
408 int InstCount = RegCount / 2;
426 for (
auto NextMI = NextMBBI; NextMI !=
MBB.end(); NextMI++) {
427 if (NextMI->readsRegister(AArch64::W16,
TRI))
432 if (SuccMBB->isLiveIn(AArch64::W16) || SuccMBB->isLiveIn(AArch64::X16))
439 if (NextMBBI ==
MBB.end())
441 if (NextMBBI->getOpcode() != AArch64::RET_ReallyLR)
473bool AArch64LowerHomogeneousPrologEpilogImpl::lowerEpilog(
481 bool HasUnpairedReg =
false;
482 for (
auto &MO :
MI.operands())
484 if (!MO.getReg().isValid()) {
488 HasUnpairedReg =
true;
492 (void)HasUnpairedReg;
498 assert(
MI.getOpcode() == AArch64::HOM_Epilog);
504 auto *EpilogTailHelper =
512 NextMBBI = std::next(Return);
513 Return->removeFromParent();
525 for (
int I = 0;
I <
Size - 2;
I += 2)
534 for (
auto &Def :
MBBI->defs())
563bool AArch64LowerHomogeneousPrologEpilogImpl::lowerProlog(
571 bool HasUnpairedReg =
false;
573 std::optional<int> FpOffset;
574 for (
auto &MO :
MI.operands()) {
576 if (MO.getReg().isValid()) {
577 if (MO.getReg() == AArch64::LR)
583 HasUnpairedReg =
true;
586 }
else if (MO.isImm()) {
587 FpOffset = MO.getImm();
590 (void)HasUnpairedReg;
596 assert(
MI.getOpcode() == AArch64::HOM_Prolog);
623 for (
int I =
Size - 3;
I >= 0;
I -= 2)
644bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMI(
648 unsigned Opcode =
MI.getOpcode();
652 case AArch64::HOM_Prolog:
653 return lowerProlog(
MBB,
MBBI, NextMBBI);
654 case AArch64::HOM_Epilog:
655 return lowerEpilog(
MBB,
MBBI, NextMBBI);
673bool AArch64LowerHomogeneousPrologEpilogImpl::runOnMachineFunction(
684 return new AArch64LowerHomogeneousPrologEpilogLegacy();
static Function * getOrCreateFrameHelper(Module *M, MachineModuleInfo *MMI, SmallVectorImpl< unsigned > &Regs, FrameHelperType Type, unsigned FpOffset=0)
Return a unique function if a helper can be formed with the given Regs and frame type.
static bool shouldUseFrameHelper(MachineBasicBlock &MBB, MachineBasicBlock::iterator &NextMBBI, SmallVectorImpl< unsigned > &Regs, FrameHelperType Type)
This function checks if a frame helper should be used for HOM_Prolog/HOM_Epilog pseudo instruction ex...
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
#define AARCH64_LOWER_HOMOGENEOUS_PROLOG_EPILOG_NAME
static cl::opt< int > FrameHelperSizeThreshold("frame-helper-size-threshold", cl::init(2), cl::Hidden, cl::desc("The minimum number of instructions that are outlined in a frame " "helper (default = 2)"))
static std::string getFrameHelperName(SmallVectorImpl< unsigned > &Regs, FrameHelperType Type, unsigned FpOffset)
Return a frame helper name with the given CSRs and the helper type.
static void emitStore(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPreDec)
Emit a store-pair instruction for frame-setup.
static MachineFunction & createFrameHelperMachineFunction(Module *M, MachineModuleInfo *MMI, StringRef Name)
Create a Function for the unique frame helper with the given name.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
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)
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This is an important class for using LLVM in a threaded context.
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...
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
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.
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.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
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.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.