160#define DEBUG_TYPE "arm-frame-lowering"
166 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
170 unsigned NumAlignedDPRCS2Regs);
185 unsigned NumAlignedDPRCS2Regs,
284 if (
Reg >= ARM::D8 &&
Reg < ARM::D8 + NumAlignedDPRCS2Regs)
370 if (CFSize >= ((1 << 12) - 1) / 2)
393 bool IsTailCallReturn =
false;
395 unsigned RetOpcode =
MBBI->getOpcode();
396 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
397 RetOpcode == ARM::TCRETURNri ||
398 RetOpcode == ARM::TCRETURNrinotr12;
402 int ArgumentPopSize = 0;
403 if (IsTailCallReturn) {
409 ArgumentPopSize = StackAdjust.
getImm();
418 return ArgumentPopSize;
424 F.needsUnwindTableEntry();
432 unsigned Opc =
MBBI->getOpcode();
458 case ARM::t2MOVi16: {
459 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
463 NewInstr.
add(
MBBI->getOperand(0));
481 case ARM::t2MOVi32imm:
499 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
500 MBBI->getOperand(2).getReg() == ARM::SP &&
501 MBBI->getOperand(3).getImm() == -4) {
502 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
512 case ARM::t2LDR_POST:
513 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
514 MBBI->getOperand(2).getReg() == ARM::SP &&
515 MBBI->getOperand(3).getImm() == 4) {
516 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
526 case ARM::t2LDMIA_RET:
527 case ARM::t2LDMIA_UPD:
528 case ARM::t2STMDB_UPD: {
538 if (
Reg >= 8 &&
Reg <= 13)
540 else if (
Opc == ARM::t2LDMIA_UPD &&
Reg == 14)
547 case ARM::t2LDMIA_RET:
548 NewOpc = ARM::tPOP_RET;
550 case ARM::t2LDMIA_UPD:
553 case ARM::t2STMDB_UPD:
562 NewInstr.
add(
MBBI->getOperand(i));
568 (
Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
575 case ARM::VSTMDDB_UPD:
576 case ARM::VLDMDIA_UPD: {
579 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
597 case ARM::t2SUBspImm:
598 case ARM::t2SUBspImm12:
599 case ARM::t2ADDspImm:
600 case ARM::t2ADDspImm12:
608 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
610 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
614 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
616 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
626 case ARM::t2BXAUT_RET:
627 case ARM::TCRETURNri:
628 case ARM::TCRETURNrinotr12:
634 case ARM::TCRETURNdi:
640 return MBB->insertAfter(
MBBI, MIB);
647 return std::prev(
MBBI);
655 Start = std::next(Start);
659 for (
auto MI = Start;
MI != End;) {
660 auto Next = std::next(
MI);
681 Pred, PredReg,
TII, MIFlags);
684 Pred, PredReg,
TII, MIFlags);
692 unsigned PredReg = 0) {
694 MIFlags, Pred, PredReg);
699 switch (
MI.getOpcode()) {
700 case ARM::VSTMDDB_UPD:
704 case ARM::t2STMDB_UPD:
708 case ARM::STR_PRE_IMM:
717 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
723 size_t StackSizeInBytes) {
729 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
730 return (StackSizeInBytes >= StackProbeSize) &&
731 !
F.hasFnAttribute(
"no-stack-arg-probe");
736struct StackAdjustingInsts {
742#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
744 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
745 <<
"sp-adjust=" << SPAdjust;
754 bool BeforeFPSet =
false) {
755 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
762 assert(Info != Insts.
end() &&
"invalid sp adjusting instruction");
763 Info->SPAdjust += ExtraBytes;
766 void emitDefCFAOffsets(MachineBasicBlock &
MBB,
bool HasFP) {
768 unsigned CFAOffset = 0;
769 for (
auto &Info : Insts) {
770 if (HasFP && !
Info.BeforeFPSet)
773 CFAOffset +=
Info.SPAdjust;
774 CFIBuilder.setInsertPoint(std::next(
Info.I));
775 CFIBuilder.buildDefCFAOffset(CFAOffset);
779#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
781 dbgs() <<
"StackAdjustingInsts:\n";
782 for (
auto &Info : Insts)
802 const Align Alignment,
803 const bool MustBeSingleInstruction) {
805 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
806 const unsigned AlignMask = Alignment.
value() - 1U;
807 const unsigned NrBitsToZero =
Log2(Alignment);
824 }
else if (AlignMask <= 255) {
831 assert(!MustBeSingleInstruction &&
832 "Shouldn't call emitAligningInstructions demanding a single "
833 "instruction to be emitted for large stack alignment for a target "
873 int MaxRegBytes = 8 * 4;
876 MaxRegBytes = 11 * 4;
879 MaxRegBytes = 11 * 4 + 8 * 8;
895 "This emitPrologue does not support Thumb1!");
897 Align Alignment =
STI.getFrameLowering()->getStackAlign();
901 int FPCXTSaveSize = 0;
904 STI.getPushPopSplitVariation(MF);
916 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
917 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
918 int FramePtrSpillFI = 0;
926 StackAdjustingInsts DefCFAOffsetCandidates;
927 bool HasFP =
hasFP(MF);
934 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
937 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
938 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
949 bool BeforeFPPush =
true;
952 int FI =
I.getFrameIdx();
958 FramePtrSpillFI = FI;
959 FramePtrSpillArea = Area;
990 DPRCS1Push, GPRCS3Push;
997 if (FPCXTSaveSize > 0) {
999 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
1003 if (ArgRegsSaveSize) {
1006 LastPush = std::prev(
MBBI);
1007 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1011 if (GPRCS1Size > 0) {
1012 GPRCS1Push = LastPush =
MBBI++;
1013 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1015 BeforeFPPush =
false;
1022 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1023 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1024 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1025 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1027 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1028 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1029 GPRCS2Size + FPStatusSize) %
1032 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1038 <<
", FPOffset: " << FPOffset <<
"\n");
1040 "Max FP estimation is wrong");
1049 if (GPRCS2Size > 0) {
1051 GPRCS2Push = LastPush =
MBBI++;
1052 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1054 BeforeFPPush =
false;
1058 if (FPStatusSize > 0) {
1060 unsigned Opc =
MBBI->getOpcode();
1061 if (
Opc == ARM::VMRS ||
Opc == ARM::VMRS_FPEXC)
1067 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1073 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1074 if (LastPush !=
MBB.end() &&
1076 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1080 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1085 if (DPRCS1Size > 0) {
1088 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1091 DPRCS1Push = LastPush =
MBBI++;
1096 if (DPRCS2Size > 0) {
1104 NumBytes = DPRCS1Offset;
1107 if (GPRCS3Size > 0) {
1109 GPRCS3Push = LastPush =
MBBI++;
1110 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1112 BeforeFPPush =
false;
1115 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1117 NeedsWinCFIStackAlloc =
false;
1122 if (NumWords < 65536) {
1132 .
addImm(NumWords & 0xffff)
1143 RTLIB::LibcallImpl ChkStkLibcall = TLI->
getLibcallImpl(RTLIB::STACK_PROBE);
1144 if (ChkStkLibcall == RTLIB::Unsupported)
1148 switch (TM.getCodeModel()) {
1180 if (NeedsWinCFIStackAlloc) {
1181 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1185 MBB.insertAfter(Instr, SEH);
1194 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1198 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1224 int64_t FPOffsetAfterPush;
1225 switch (FramePtrSpillArea) {
1227 FPPushInst = GPRCS1Push;
1229 ArgRegsSaveSize + FPCXTSaveSize +
1232 << FPOffsetAfterPush <<
" after that push\n");
1235 FPPushInst = GPRCS2Push;
1237 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1240 << FPOffsetAfterPush <<
" after that push\n");
1243 FPPushInst = GPRCS3Push;
1245 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1246 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1249 << FPOffsetAfterPush <<
" after that push\n");
1255 AfterPush = std::next(FPPushInst);
1257 assert(FPOffsetAfterPush == 0);
1261 FramePtr, ARM::SP, FPOffsetAfterPush,
1268 if (FPOffsetAfterPush != 0)
1277 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
1291 for (
const auto &Entry :
reverse(CSI)) {
1293 int FI = Entry.getFrameIdx();
1298 CFIPos = std::next(GPRCS1Push);
1301 CFIPos = std::next(GPRCS2Push);
1304 CFIPos = std::next(DPRCS1Push);
1307 CFIPos = std::next(GPRCS3Push);
1318 .
buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1330 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
1333 if (
STI.isTargetELF() &&
hasFP(MF))
1381 if (RegInfo->hasBasePointer(MF)) {
1408 "This emitEpilogue does not support Thumb1!");
1411 STI.getPushPopSplitVariation(MF);
1442 if (NumBytes + IncomingArgStackToRestore != 0)
1444 NumBytes + IncomingArgStackToRestore,
1451 }
while (
MBBI !=
MBB.begin() &&
1488 "No scratch register to restore SP from FP!");
1510 }
else if (NumBytes &&
1526 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1531 "unexpected DPR alignment gap");
1543 if (ReservedArgStack || IncomingArgStackToRestore) {
1544 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1545 "attempting to restore negative stack amount");
1547 ReservedArgStack + IncomingArgStackToRestore,
1557 STI.isThumb() &&
STI.hasV8_1MMainlineOps() &&
STI.hasPACBTI();
1558 auto TMBBI =
MBB.getFirstTerminator();
1560 TMBBI !=
MBB.end() && TMBBI->getOpcode() == ARM::tBX_RET;
1561 if (IsBXReturn && CanUseBXAut)
1562 TMBBI->setDesc(
STI.getInstrInfo()->get(ARM::t2BXAUT_RET));
1605 if (RegInfo->hasStackRealignment(MF)) {
1606 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1608 FrameReg = RegInfo->getFrameRegister(MF);
1610 }
else if (hasMovingSP) {
1611 assert(RegInfo->hasBasePointer(MF) &&
1612 "VLAs and dynamic stack alignment, but missing base pointer!");
1613 FrameReg = RegInfo->getBaseRegister();
1623 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1624 FrameReg = RegInfo->getFrameRegister(MF);
1626 }
else if (hasMovingSP) {
1627 assert(RegInfo->hasBasePointer(MF) &&
"missing base pointer!");
1632 if (FPOffset >= -255 && FPOffset < 0) {
1633 FrameReg = RegInfo->getFrameRegister(MF);
1648 FrameReg = RegInfo->getFrameRegister(MF);
1651 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1653 FrameReg = RegInfo->getFrameRegister(MF);
1660 if (RegInfo->hasBasePointer(MF)) {
1661 FrameReg = RegInfo->getBaseRegister();
1670 unsigned StmOpc,
unsigned StrOpc,
1679 using RegAndKill = std::pair<unsigned, bool>;
1682 unsigned i = CSI.
size();
1684 unsigned LastReg = 0;
1685 for (; i != 0; --i) {
1697 if (NoGap && LastReg && LastReg != Reg-1)
1705 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1712 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1715 if (Regs.
size() > 1 || StrOpc== 0) {
1720 for (
const auto &[
Reg,
Kill] : Regs)
1722 }
else if (Regs.size() == 1) {
1743 unsigned LdmOpc,
unsigned LdrOpc,
1744 bool isVarArg,
bool NoGap,
1748 const TargetRegisterInfo &
TRI = *
STI.getRegisterInfo();
1749 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
1752 bool isTailCall =
false;
1753 bool isInterrupt =
false;
1754 bool isTrap =
false;
1755 bool isCmseEntry =
false;
1757 STI.getPushPopSplitVariation(MF);
1759 DL =
MI->getDebugLoc();
1760 unsigned RetOpcode =
MI->getOpcode();
1762 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1763 RetOpcode == ARM::TCRETURNrinotr12);
1765 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1766 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1767 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1770 SmallVector<unsigned, 4> Regs;
1771 unsigned i = CSI.
size();
1773 unsigned LastReg = 0;
1774 bool DeleteRet =
false;
1775 for (; i != 0; --i) {
1776 CalleeSavedInfo &
Info = CSI[i-1];
1777 MCRegister
Reg =
Info.getReg();
1781 if (
Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1795 if (NoGap && LastReg && LastReg !=
Reg-1)
1806 return TRI.getEncodingValue(
LHS) <
TRI.getEncodingValue(
RHS);
1809 if (Regs.
size() > 1 || LdrOpc == 0) {
1814 for (
unsigned Reg : Regs)
1819 MI->eraseFromParent();
1823 }
else if (Regs.size() == 1) {
1826 if (Regs[0] == ARM::PC)
1828 MachineInstrBuilder MIB =
1835 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1854 unsigned PushOpc)
const {
1859 auto RegPresent = [&CSI](MCRegister
Reg) {
1861 return C.getReg() ==
Reg;
1867 if (RegPresent(ARM::FPSCR)) {
1877 if (RegPresent(ARM::FPEXC)) {
1886 if (Regs.
size() == 0)
1890 MachineInstrBuilder MIB =
1901void ARMFrameLowering::emitFPStatusRestores(
1907 auto RegPresent = [&CSI](MCRegister
Reg) {
1909 return C.getReg() ==
Reg;
1914 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1918 MachineInstrBuilder MIB =
1925 if (RegPresent(ARM::FPSCR)) {
1930 if (RegPresent(ARM::FPEXC)) {
1935 if (RegPresent(ARM::FPSCR)) {
1944 if (RegPresent(ARM::FPEXC)) {
1957 unsigned NumAlignedDPRCS2Regs,
1970 unsigned DNum =
I.getReg() - ARM::D8;
1971 if (DNum > NumAlignedDPRCS2Regs - 1)
1973 int FI =
I.getFrameIdx();
2001 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
2004 .
addImm(8 * NumAlignedDPRCS2Regs)
2029 unsigned NextReg = ARM::D8;
2033 if (NumAlignedDPRCS2Regs >= 6) {
2035 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2036 MBB.addLiveIn(SupReg);
2044 NumAlignedDPRCS2Regs -= 4;
2049 unsigned R4BaseReg = NextReg;
2052 if (NumAlignedDPRCS2Regs >= 4) {
2054 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2055 MBB.addLiveIn(SupReg);
2063 NumAlignedDPRCS2Regs -= 4;
2067 if (NumAlignedDPRCS2Regs >= 2) {
2069 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2070 MBB.addLiveIn(SupReg);
2077 NumAlignedDPRCS2Regs -= 2;
2081 if (NumAlignedDPRCS2Regs) {
2082 MBB.addLiveIn(NextReg);
2087 .
addImm((NextReg - R4BaseReg) * 2)
2092 std::prev(
MI)->addRegisterKilled(ARM::R4,
TRI);
2099 unsigned NumAlignedDPRCS2Regs) {
2104 assert(
MI->mayStore() &&
"Expecting spill instruction");
2107 switch(NumAlignedDPRCS2Regs) {
2110 assert(
MI->mayStore() &&
"Expecting spill instruction");
2114 assert(
MI->mayStore() &&
"Expecting spill instruction");
2119 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2130 unsigned NumAlignedDPRCS2Regs,
2141 if (
I.getReg() == ARM::D8) {
2142 D8SpillFI =
I.getFrameIdx();
2154 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2162 unsigned NextReg = ARM::D8;
2165 if (NumAlignedDPRCS2Regs >= 6) {
2167 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2175 NumAlignedDPRCS2Regs -= 4;
2180 unsigned R4BaseReg = NextReg;
2183 if (NumAlignedDPRCS2Regs >= 4) {
2185 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2192 NumAlignedDPRCS2Regs -= 4;
2196 if (NumAlignedDPRCS2Regs >= 2) {
2198 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2204 NumAlignedDPRCS2Regs -= 2;
2208 if (NumAlignedDPRCS2Regs)
2211 .
addImm(2 * (NextReg - R4BaseReg))
2227 STI.getPushPopSplitVariation(MF);
2230 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2232 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2233 unsigned FltOpc = ARM::VSTMDDB_UPD;
2242 return C.getReg() == ARM::FPCXTNS;
2251 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2252 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2253 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2256 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2259 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2262 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2265 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2269 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2270 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2271 emitFPStatusSaves(
MBB,
MI, CSI, PushOpc);
2272 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2273 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2278 if (NumAlignedDPRCS2Regs)
2297 STI.getPushPopSplitVariation(MF);
2301 if (NumAlignedDPRCS2Regs)
2304 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2307 unsigned FltOpc = ARM::VLDMDIA_UPD;
2309 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2310 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2311 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2314 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2317 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2320 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2323 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2327 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2328 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2329 emitFPStatusRestores(
MBB,
MI, CSI, PopOpc);
2330 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2331 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2339 unsigned FnSize = 0;
2340 for (
auto &
MBB : MF) {
2341 for (
auto &
MI :
MBB)
2342 FnSize +=
TII.getInstSizeInBytes(
MI);
2346 FnSize += Table.MBBs.size() * 4;
2349 << FnSize <<
" bytes\n");
2359 bool &HasNonSPFrameIndex) {
2363 unsigned Limit = (1 << 12) - 1;
2364 for (
auto &
MBB : MF) {
2365 for (
auto &
MI :
MBB) {
2366 if (
MI.isDebugInstr())
2368 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2369 if (!
MI.getOperand(i).isFI())
2374 if (
MI.getOpcode() == ARM::ADDri) {
2375 Limit = std::min(Limit, (1U << 8) - 1);
2380 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2385 if (RegClass && !RegClass->
contains(ARM::SP))
2386 HasNonSPFrameIndex =
true;
2396 Limit = std::min(Limit, (1U << 8) - 1);
2399 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2404 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2410 Limit = std::min(Limit, (1U << 8) - 1);
2418 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2421 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2424 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2427 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2468 unsigned NumSpills = 0;
2469 for (; NumSpills < 8; ++NumSpills)
2470 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2481 SavedRegs.
set(ARM::R4);
2487 if (
STI.hasV8_1MMainlineOps() &&
2504 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2517 for (
const auto &
MBB : MF)
2518 for (
const auto &
MI :
MBB)
2519 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2520 STI.genExecuteOnly())
2521 for (
const auto &
Op :
MI.operands())
2541 bool CS1Spilled =
false;
2542 bool LRSpilled =
false;
2543 unsigned NumGPRSpills = 0;
2544 unsigned NumFPRSpills = 0;
2559 STI.getPushPopSplitVariation(MF);
2563 if (
F.hasFnAttribute(
"interrupt") &&
F.hasFnAttribute(
"save-fp")) {
2564 SavedRegs.
set(ARM::FPSCR);
2565 SavedRegs.
set(ARM::R4);
2568 if (
STI.isMClass()) {
2569 SavedRegs.
reset(ARM::FPEXC);
2571 SavedRegs.
set(ARM::FPEXC);
2572 SavedRegs.
set(ARM::R5);
2582 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2583 SavedRegs.
set(ARM::R4);
2590 if (
STI.isTargetWindows() &&
2592 SavedRegs.
set(ARM::R4);
2593 SavedRegs.
set(ARM::LR);
2599 SavedRegs.
set(ARM::LR);
2607 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2608 MFI.estimateStackSize(MF) > 508)
2609 SavedRegs.
set(ARM::R4);
2616 if (RegInfo->hasBasePointer(MF))
2617 SavedRegs.
set(RegInfo->getBaseRegister());
2621 CanEliminateFrame =
false;
2625 CanEliminateFrame =
false;
2629 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2630 for (
unsigned i = 0; CSRegs[i]; ++i) {
2631 unsigned Reg = CSRegs[i];
2632 bool Spilled =
false;
2633 if (SavedRegs.
test(Reg)) {
2635 CanEliminateFrame =
false;
2638 if (!ARM::GPRRegClass.
contains(Reg)) {
2640 if (ARM::SPRRegClass.
contains(Reg))
2642 else if (ARM::DPRRegClass.
contains(Reg))
2644 else if (ARM::QPRRegClass.
contains(Reg))
2665 case ARM::R0:
case ARM::R1:
2666 case ARM::R2:
case ARM::R3:
2667 case ARM::R4:
case ARM::R5:
2668 case ARM::R6:
case ARM::R7:
2681 case ARM::R0:
case ARM::R1:
2682 case ARM::R2:
case ARM::R3:
2683 case ARM::R4:
case ARM::R5:
2684 case ARM::R6:
case ARM::R7:
2695 bool ForceLRSpill =
false;
2700 if (FnSize >= (1 << 11)) {
2701 CanEliminateFrame =
false;
2702 ForceLRSpill =
true;
2720 unsigned EstimatedStackSize =
2721 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2724 int MaxFixedOffset = 0;
2725 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2726 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2727 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2730 bool HasFP =
hasFP(MF);
2733 EstimatedStackSize += 4;
2737 EstimatedStackSize += MaxFixedOffset;
2739 EstimatedStackSize += 16;
2741 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2742 bool HasNonSPFrameIndex =
false;
2762 if (RegInfo->hasBasePointer(MF))
2763 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2765 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2766 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2768 EstimatedRSStackSizeLimit =
2770 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2774 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2780 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2782 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
2791 bool HasLargeArgumentList =
2792 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2794 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2795 HasLargeArgumentList || HasNonSPFrameIndex;
2796 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2797 <<
"; EstimatedStack: " << EstimatedStackSize
2798 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2799 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2800 if (BigFrameOffsets ||
2801 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
2815 SavedRegs.
set(ARM::LR);
2818 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2819 if (LRPos != UnspilledCS1GPRs.
end())
2820 UnspilledCS1GPRs.
erase(LRPos);
2823 if (FPPos != UnspilledCS1GPRs.
end())
2824 UnspilledCS1GPRs.
erase(FPPos);
2842 unsigned NumExtraCSSpill = 0;
2859 int EntryRegDeficit = 0;
2860 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2865 <<
" is unused argument register, EntryRegDeficit = "
2866 << EntryRegDeficit <<
"\n");
2873 <<
" return regs used, ExitRegDeficit = "
2874 << ExitRegDeficit <<
"\n");
2876 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2881 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2882 if (SavedRegs.
test(Reg)) {
2885 <<
" is saved low register, RegDeficit = "
2886 << RegDeficit <<
"\n");
2892 <<
" is non-saved low register, adding to AvailableRegs\n");
2897 if (!HasFP ||
FramePtr != ARM::R7) {
2898 if (SavedRegs.
test(ARM::R7)) {
2901 << RegDeficit <<
"\n");
2906 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2911 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2912 if (SavedRegs.
test(Reg)) {
2915 <<
" is saved high register, RegDeficit = "
2916 << RegDeficit <<
"\n");
2923 if ((EntryRegDeficit > ExitRegDeficit) &&
2926 if (SavedRegs.
test(ARM::LR)) {
2929 << RegDeficit <<
"\n");
2932 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2941 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2942 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2945 <<
" to make up reg deficit\n");
2956 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2966 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2967 SavedRegs.
set(ARM::LR);
2970 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2971 if (LRPos != UnspilledCS1GPRs.
end())
2972 UnspilledCS1GPRs.
erase(LRPos);
2974 ForceLRSpill =
false;
2985 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2986 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
2987 for (
unsigned Reg : UnspilledCS1GPRs) {
2991 (
STI.isTargetWindows() && Reg == ARM::R11) ||
2993 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2996 <<
" to make up alignment\n");
3004 unsigned Reg = UnspilledCS2GPRs.
front();
3007 <<
" to make up alignment\n");
3019 unsigned RegsNeeded = 0;
3028 if (RegsNeeded > NumExtraCSSpill) {
3031 unsigned NumExtras = TargetAlign.
value() / 4;
3033 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
3043 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
3051 if (NumExtras == 0) {
3052 for (
unsigned Reg : Extras) {
3058 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3062 unsigned Size =
TRI->getSpillSize(RC);
3063 Align Alignment =
TRI->getSpillAlign(RC);
3064 RS->addScavengingFrameIndex(
3065 MFI.CreateSpillStackObject(
Size, Alignment));
3072 SavedRegs.
set(ARM::LR);
3085 if (Info.getReg() != ARM::LR)
3089 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3090 Term.getOpcode() == ARM::t2LDMIA_RET ||
3091 Term.getOpcode() == ARM::tPOP_RET;
3094 Info.setRestored(
false);
3115 SavedRegs.
set(ARM::R0);
3120 std::vector<CalleeSavedInfo> &CSI)
const {
3123 if (
STI.hasV8_1MMainlineOps() &&
3125 CSI.emplace_back(ARM::FPCXTNS);
3126 CSI.back().setRestored(
false);
3138 switch (
STI.getPushPopSplitVariation(MF)) {
3142 [=](
const auto &CS) {
3144 return Reg == ARM::R10 || Reg == ARM::R11 ||
3145 Reg == ARM::R8 || Reg == ARM::R9 ||
3146 ARM::DPRRegClass.contains(Reg);
3157 "ABI-required frame pointers need a CSR split when signing return "
3160 [=](
const auto &CS) {
3162 return Reg != ARM::LR;
3176 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3177 NumEntries = std::size(FixedSpillOffsets);
3178 return FixedSpillOffsets;
3189 unsigned Opc =
I->getOpcode();
3190 bool IsDestroy =
Opc ==
TII.getCallFrameDestroyOpcode();
3191 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3194 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3196 int PIdx =
I->findFirstPredOperandIdx();
3200 unsigned PredReg =
TII.getFramePred(*
I);
3204 if (IsDestroy && CalleePopAmount != -1U)
3205 return MBB.erase(
I);
3210 unsigned Amount =
TII.getFrameSize(*
I);
3217 if (
Opc == ARM::ADJCALLSTACKDOWN ||
Opc == ARM::tADJCALLSTACKDOWN) {
3221 assert(
Opc == ARM::ADJCALLSTACKUP ||
Opc == ARM::tADJCALLSTACKUP);
3226 }
else if (CalleePopAmount != -1U) {
3240 unsigned Shifted = 0;
3245 while (!(
Value & 0xC0000000)) {
3250 bool Carry = (
Value & 0x00FFFFFF);
3251 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3253 if (
Value & 0x0000100)
3296 bool Thumb = ST->isThumb();
3297 bool Thumb2 = ST->isThumb2();
3303 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3319 unsigned ScratchReg0 = ARM::R4;
3320 unsigned ScratchReg1 = ARM::R5;
3321 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3338 if (BeforePrologueRegion.
insert(PredBB).second)
3341 }
while (!WalkList.
empty());
3352 for (
const auto &LI : PrologueMBB.
liveins()) {
3354 PredBB->addLiveIn(LI);
3360 BeforePrologueRegion.
erase(
B);
3366 MBB->sortUniqueLiveIns();
3369 if (
MBB->isSuccessor(&PrologueMBB))
3370 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3415 }
else if (CompareStackPointer) {
3423 if (!CompareStackPointer && Thumb) {
3424 if (AlignedStackSize < 256) {
3428 .
addImm(AlignedStackSize)
3431 if (Thumb2 || ST->genExecuteOnly()) {
3433 .
addImm(AlignedStackSize);
3436 auto RegInfo =
STI.getRegisterInfo();
3437 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3446 }
else if (!CompareStackPointer) {
3447 if (AlignedStackSize < 256) {
3450 .
addImm(AlignedStackSize)
3455 auto RegInfo =
STI.getRegisterInfo();
3456 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3466 if (Thumb && ST->isThumb1Only()) {
3467 if (ST->genExecuteOnly()) {
3478 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3491 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3501 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3502 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3506 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3515 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3522 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3535 if (AlignedStackSize < 256) {
3536 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3538 .
addImm(AlignedStackSize)
3541 if (Thumb2 || ST->genExecuteOnly()) {
3543 .
addImm(AlignedStackSize);
3546 auto RegInfo =
STI.getRegisterInfo();
3547 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3552 if (AlignedStackSize < 256) {
3554 .
addImm(AlignedStackSize)
3559 auto RegInfo =
STI.getRegisterInfo();
3560 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3569 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3574 if (Thumb2 || ST->genExecuteOnly()) {
3579 auto RegInfo =
STI.getRegisterInfo();
3580 RegInfo->emitLoadConstPool(
3581 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3593 auto RegInfo =
STI.getRegisterInfo();
3594 RegInfo->emitLoadConstPool(
3595 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3633 if (ST->isThumb1Only()) {
3720#ifdef EXPENSIVE_CHECKS
static unsigned estimateRSStackSizeLimit(MachineFunction &MF)
Look at each instruction that references stack frames and return the stack size limit beyond which so...
static bool needsWinCFI(const MachineFunction *MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isThumb(const MCSubtargetInfo &STI)
static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)
Skip past the code inserted by emitAlignedDPRCS2Spills, and return an iterator to the following instr...
static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const unsigned Reg, const Align Alignment, const bool MustBeSingleInstruction)
Emit an instruction sequence that will align the address in register Reg by zero-ing out the lower bi...
static uint32_t alignToARMConstant(uint32_t Value)
Get the minimum constant for ARM that is greater than or equal to the argument.
static void checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs)
static void insertSEHRange(MachineBasicBlock &MBB, MachineBasicBlock::iterator Start, const MachineBasicBlock::iterator &End, const ARMBaseInstrInfo &TII, unsigned MIFlags)
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
static int getArgumentStackToRestore(MachineFunction &MF, MachineBasicBlock &MBB)
static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)
static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, const TargetInstrInfo &TII, unsigned Flags)
SpillArea getSpillArea(Register Reg, ARMSubtarget::PushPopSplitVariation Variation, unsigned NumAlignedDPRCS2Regs, const ARMBaseRegisterInfo *RegInfo)
Get the spill area that Reg should be saved into in the prologue.
static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI)
static bool WindowsRequiresStackProbe(const MachineFunction &MF, size_t StackSizeInBytes)
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, const MachineFunction &MF)
We need the offset of the frame pointer relative to other MachineFrameInfo offsets which are encoded ...
static MachineBasicBlock::iterator initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI)
static int sizeOfSPAdjustment(const MachineInstr &MI)
static const uint64_t kSplitStackAvailable
static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))
static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const unsigned FramePtr
bool canRealignStack(const MachineFunction &MF) const override
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
bool keepFramePointer(const MachineFunction &MF) const
static void updateLRRestored(MachineFunction &MF)
Update the IsRestored flag on LR if it is spilled, based on the return instructions.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
ARMFrameLowering(const ARMSubtarget &sti)
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool requiresAAPCSFrameRecord(const MachineFunction &MF) const
bool isFPReserved(const MachineFunction &MF) const
isFPReserved - Return true if the frame pointer register should be considered a reserved register on ...
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &MBB) const override
Adjust the prologue to have the function use segmented stacks.
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override
getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs, that contains an entry...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool hasFPImpl(const MachineFunction &MF) const override
hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.
int ResolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, int SPAdj) const
void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const override
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool enableCalleeSaveSkip(const MachineFunction &MF) const override
Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functi...
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool hasStackFrame() const
bool isThumb2Function() const
unsigned getFPCXTSaveAreaSize() const
unsigned getGPRCalleeSavedArea1Size() const
unsigned getDPRCalleeSavedGapSize() const
unsigned getDPRCalleeSavedArea1Size() const
unsigned createPICLabelUId()
void setLRIsSpilled(bool s)
void setDPRCalleeSavedArea1Offset(unsigned o)
void setGPRCalleeSavedArea2Size(unsigned s)
bool isThumb1OnlyFunction() const
void setHasStackFrame(bool s)
bool isThumbFunction() const
void setFramePtrSpillOffset(unsigned o)
unsigned getGPRCalleeSavedArea2Size() const
unsigned getNumAlignedDPRCS2Regs() const
bool shouldSignReturnAddress() const
void setGPRCalleeSavedArea1Size(unsigned s)
unsigned getArgumentStackToRestore() const
void setFPCXTSaveAreaSize(unsigned s)
bool isCmseNSEntryFunction() const
unsigned getGPRCalleeSavedArea3Size() const
unsigned getFramePtrSpillOffset() const
bool shouldRestoreSPFromFP() const
unsigned getArgRegsSaveSize() const
void setGPRCalleeSavedArea2Offset(unsigned o)
void setGPRCalleeSavedArea1Offset(unsigned o)
void setDPRCalleeSavedArea1Size(unsigned s)
void setDPRCalleeSavedGapSize(unsigned s)
void setFPStatusSavesSize(unsigned s)
unsigned getArgumentStackSize() const
void setShouldRestoreSPFromFP(bool s)
unsigned getReturnRegsCount() const
void setGPRCalleeSavedArea3Size(unsigned s)
bool getPreservesR0() const
unsigned getFPStatusSavesSize() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
enum PushPopSplitVariation getPushPopSplitVariation(const MachineFunction &MF) const
PushPopSplitVariation
How the push and pop instructions of callee saved general-purpose registers should be split.
@ SplitR11WindowsSEH
When the stack frame size is not known (because of variable-sized objects or realignment),...
@ SplitR7
R7 and LR must be adjacent, because R7 is the frame pointer, and must point to a frame record consist...
@ SplitR11AAPCSSignRA
When generating AAPCS-compilant frame chains, R11 is the frame pointer, and must be pushed adjacent t...
@ NoSplit
All GPRs can be pushed in a single instruction.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
bool test(unsigned Idx) const
Helper class for creating CFI instructions and inserting them into MIR.
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void buildDefCFARegister(MCRegister Reg) const
void buildSameValue(MCRegister Reg) const
void buildOffset(MCRegister Reg, int64_t Offset) const
void buildDefCFA(MCRegister Reg, int64_t Offset) const
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool usesWindowsCFI() const
Describe properties that are true of each instruction in the target description file.
Wrapper class representing physical registers. Should be passed by value.
iterator_range< livein_iterator > liveins() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool needsSplitStackProlog() const
Return true if this function requires a split stack prolog, even if it uses no stack space.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int getStackProtectorIndex() const
Return the index for the stack protector object.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
void setHasWinCFI(bool v)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
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 & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
bool isValid() const
Check for null.
Representation of each machine instruction.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Wrapper class representing virtual and physical registers.
bool erase(PtrType Ptr)
Remove pointer from the set.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
iterator erase(const_iterator CI)
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Information about stack frame layout on the target.
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
virtual void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetInstrInfo - Interface to description of machine instruction set.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
Primary interface to the complete machine description for the target machine.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
LLVM_ABI bool FramePointerIsReserved(const MachineFunction &MF) const
FramePointerIsReserved - This returns true if the frame pointer must always either point to a new fra...
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
@ D16
Only 16 D registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of 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).
@ Kill
The last use of a register.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isSEHInstruction(const MachineInstr &MI)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
unsigned Log2(Align A)
Returns the log2 of the alignment.
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.