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::TCRETURNri:
627 case ARM::TCRETURNrinotr12:
633 case ARM::TCRETURNdi:
639 return MBB->insertAfter(
MBBI, MIB);
646 return std::prev(
MBBI);
654 Start = std::next(Start);
658 for (
auto MI = Start;
MI != End;) {
659 auto Next = std::next(
MI);
680 Pred, PredReg,
TII, MIFlags);
683 Pred, PredReg,
TII, MIFlags);
691 unsigned PredReg = 0) {
693 MIFlags, Pred, PredReg);
698 switch (
MI.getOpcode()) {
699 case ARM::VSTMDDB_UPD:
703 case ARM::t2STMDB_UPD:
707 case ARM::STR_PRE_IMM:
716 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
722 size_t StackSizeInBytes) {
728 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
729 return (StackSizeInBytes >= StackProbeSize) &&
730 !
F.hasFnAttribute(
"no-stack-arg-probe");
735struct StackAdjustingInsts {
741#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
743 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
744 <<
"sp-adjust=" << SPAdjust;
753 bool BeforeFPSet =
false) {
754 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
761 assert(Info != Insts.
end() &&
"invalid sp adjusting instruction");
762 Info->SPAdjust += ExtraBytes;
765 void emitDefCFAOffsets(MachineBasicBlock &
MBB,
bool HasFP) {
767 unsigned CFAOffset = 0;
768 for (
auto &Info : Insts) {
769 if (HasFP && !
Info.BeforeFPSet)
772 CFAOffset +=
Info.SPAdjust;
773 CFIBuilder.setInsertPoint(std::next(
Info.I));
774 CFIBuilder.buildDefCFAOffset(CFAOffset);
778#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
780 dbgs() <<
"StackAdjustingInsts:\n";
781 for (
auto &Info : Insts)
801 const Align Alignment,
802 const bool MustBeSingleInstruction) {
804 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
805 const unsigned AlignMask = Alignment.
value() - 1U;
806 const unsigned NrBitsToZero =
Log2(Alignment);
823 }
else if (AlignMask <= 255) {
830 assert(!MustBeSingleInstruction &&
831 "Shouldn't call emitAligningInstructions demanding a single "
832 "instruction to be emitted for large stack alignment for a target "
872 int MaxRegBytes = 8 * 4;
875 MaxRegBytes = 11 * 4;
878 MaxRegBytes = 11 * 4 + 8 * 8;
894 "This emitPrologue does not support Thumb1!");
896 Align Alignment =
STI.getFrameLowering()->getStackAlign();
900 int FPCXTSaveSize = 0;
903 STI.getPushPopSplitVariation(MF);
915 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
916 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
917 int FramePtrSpillFI = 0;
925 StackAdjustingInsts DefCFAOffsetCandidates;
926 bool HasFP =
hasFP(MF);
933 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
936 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
937 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
948 bool BeforeFPPush =
true;
951 int FI =
I.getFrameIdx();
957 FramePtrSpillFI = FI;
958 FramePtrSpillArea = Area;
989 DPRCS1Push, GPRCS3Push;
996 if (FPCXTSaveSize > 0) {
998 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
1002 if (ArgRegsSaveSize) {
1005 LastPush = std::prev(
MBBI);
1006 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1010 if (GPRCS1Size > 0) {
1011 GPRCS1Push = LastPush =
MBBI++;
1012 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1014 BeforeFPPush =
false;
1021 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1022 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1023 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1024 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1026 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1027 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1028 GPRCS2Size + FPStatusSize) %
1031 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1037 <<
", FPOffset: " << FPOffset <<
"\n");
1039 "Max FP estimation is wrong");
1048 if (GPRCS2Size > 0) {
1050 GPRCS2Push = LastPush =
MBBI++;
1051 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1053 BeforeFPPush =
false;
1057 if (FPStatusSize > 0) {
1059 unsigned Opc =
MBBI->getOpcode();
1060 if (
Opc == ARM::VMRS ||
Opc == ARM::VMRS_FPEXC)
1066 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1072 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1073 if (LastPush !=
MBB.end() &&
1075 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1079 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1084 if (DPRCS1Size > 0) {
1087 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1090 DPRCS1Push = LastPush =
MBBI++;
1095 if (DPRCS2Size > 0) {
1103 NumBytes = DPRCS1Offset;
1106 if (GPRCS3Size > 0) {
1108 GPRCS3Push = LastPush =
MBBI++;
1109 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1111 BeforeFPPush =
false;
1114 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1116 NeedsWinCFIStackAlloc =
false;
1121 if (NumWords < 65536) {
1131 .
addImm(NumWords & 0xffff)
1142 RTLIB::LibcallImpl ChkStkLibcall = TLI->
getLibcallImpl(RTLIB::STACK_PROBE);
1143 if (ChkStkLibcall == RTLIB::Unsupported)
1147 switch (TM.getCodeModel()) {
1179 if (NeedsWinCFIStackAlloc) {
1180 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1184 MBB.insertAfter(Instr, SEH);
1193 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1197 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1223 int64_t FPOffsetAfterPush;
1224 switch (FramePtrSpillArea) {
1226 FPPushInst = GPRCS1Push;
1228 ArgRegsSaveSize + FPCXTSaveSize +
1231 << FPOffsetAfterPush <<
" after that push\n");
1234 FPPushInst = GPRCS2Push;
1236 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1239 << FPOffsetAfterPush <<
" after that push\n");
1242 FPPushInst = GPRCS3Push;
1244 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1245 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1248 << FPOffsetAfterPush <<
" after that push\n");
1254 AfterPush = std::next(FPPushInst);
1256 assert(FPOffsetAfterPush == 0);
1260 FramePtr, ARM::SP, FPOffsetAfterPush,
1267 if (FPOffsetAfterPush != 0)
1276 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
1290 for (
const auto &Entry :
reverse(CSI)) {
1292 int FI = Entry.getFrameIdx();
1297 CFIPos = std::next(GPRCS1Push);
1300 CFIPos = std::next(GPRCS2Push);
1303 CFIPos = std::next(DPRCS1Push);
1306 CFIPos = std::next(GPRCS3Push);
1317 .
buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1329 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
1332 if (
STI.isTargetELF() &&
hasFP(MF))
1380 if (RegInfo->hasBasePointer(MF)) {
1407 "This emitEpilogue does not support Thumb1!");
1410 STI.getPushPopSplitVariation(MF);
1441 if (NumBytes + IncomingArgStackToRestore != 0)
1443 NumBytes + IncomingArgStackToRestore,
1450 }
while (
MBBI !=
MBB.begin() &&
1487 "No scratch register to restore SP from FP!");
1509 }
else if (NumBytes &&
1525 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1530 "unexpected DPR alignment gap");
1542 if (ReservedArgStack || IncomingArgStackToRestore) {
1543 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1544 "attempting to restore negative stack amount");
1546 ReservedArgStack + IncomingArgStackToRestore,
1595 if (RegInfo->hasStackRealignment(MF)) {
1596 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1598 FrameReg = RegInfo->getFrameRegister(MF);
1600 }
else if (hasMovingSP) {
1601 assert(RegInfo->hasBasePointer(MF) &&
1602 "VLAs and dynamic stack alignment, but missing base pointer!");
1603 FrameReg = RegInfo->getBaseRegister();
1613 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1614 FrameReg = RegInfo->getFrameRegister(MF);
1616 }
else if (hasMovingSP) {
1617 assert(RegInfo->hasBasePointer(MF) &&
"missing base pointer!");
1622 if (FPOffset >= -255 && FPOffset < 0) {
1623 FrameReg = RegInfo->getFrameRegister(MF);
1638 FrameReg = RegInfo->getFrameRegister(MF);
1641 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1643 FrameReg = RegInfo->getFrameRegister(MF);
1650 if (RegInfo->hasBasePointer(MF)) {
1651 FrameReg = RegInfo->getBaseRegister();
1660 unsigned StmOpc,
unsigned StrOpc,
1669 using RegAndKill = std::pair<unsigned, bool>;
1672 unsigned i = CSI.
size();
1674 unsigned LastReg = 0;
1675 for (; i != 0; --i) {
1681 bool isLiveIn =
MRI.isLiveIn(Reg);
1682 if (!isLiveIn && !
MRI.isReserved(Reg))
1687 if (NoGap && LastReg && LastReg != Reg-1)
1695 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1702 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1705 if (Regs.
size() > 1 || StrOpc== 0) {
1710 for (
const auto &[
Reg,
Kill] : Regs)
1712 }
else if (Regs.size() == 1) {
1733 unsigned LdmOpc,
unsigned LdrOpc,
1734 bool isVarArg,
bool NoGap,
1738 const TargetRegisterInfo &
TRI = *
STI.getRegisterInfo();
1739 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
1742 bool isTailCall =
false;
1743 bool isInterrupt =
false;
1744 bool isTrap =
false;
1745 bool isCmseEntry =
false;
1747 STI.getPushPopSplitVariation(MF);
1749 DL =
MI->getDebugLoc();
1750 unsigned RetOpcode =
MI->getOpcode();
1752 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1753 RetOpcode == ARM::TCRETURNrinotr12);
1755 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1756 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1757 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1760 SmallVector<unsigned, 4> Regs;
1761 unsigned i = CSI.
size();
1763 unsigned LastReg = 0;
1764 bool DeleteRet =
false;
1765 for (; i != 0; --i) {
1766 CalleeSavedInfo &
Info = CSI[i-1];
1767 MCRegister
Reg =
Info.getReg();
1771 if (
Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1785 if (NoGap && LastReg && LastReg !=
Reg-1)
1796 return TRI.getEncodingValue(
LHS) <
TRI.getEncodingValue(
RHS);
1799 if (Regs.
size() > 1 || LdrOpc == 0) {
1804 for (
unsigned Reg : Regs)
1809 MI->eraseFromParent();
1813 }
else if (Regs.size() == 1) {
1816 if (Regs[0] == ARM::PC)
1818 MachineInstrBuilder MIB =
1825 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1844 unsigned PushOpc)
const {
1849 auto RegPresent = [&CSI](MCRegister
Reg) {
1851 return C.getReg() ==
Reg;
1857 if (RegPresent(ARM::FPSCR)) {
1867 if (RegPresent(ARM::FPEXC)) {
1876 if (Regs.
size() == 0)
1880 MachineInstrBuilder MIB =
1891void ARMFrameLowering::emitFPStatusRestores(
1897 auto RegPresent = [&CSI](MCRegister
Reg) {
1899 return C.getReg() ==
Reg;
1904 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1908 MachineInstrBuilder MIB =
1915 if (RegPresent(ARM::FPSCR)) {
1920 if (RegPresent(ARM::FPEXC)) {
1925 if (RegPresent(ARM::FPSCR)) {
1934 if (RegPresent(ARM::FPEXC)) {
1947 unsigned NumAlignedDPRCS2Regs,
1960 unsigned DNum =
I.getReg() - ARM::D8;
1961 if (DNum > NumAlignedDPRCS2Regs - 1)
1963 int FI =
I.getFrameIdx();
1991 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
1994 .
addImm(8 * NumAlignedDPRCS2Regs)
2019 unsigned NextReg = ARM::D8;
2023 if (NumAlignedDPRCS2Regs >= 6) {
2025 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2026 MBB.addLiveIn(SupReg);
2034 NumAlignedDPRCS2Regs -= 4;
2039 unsigned R4BaseReg = NextReg;
2042 if (NumAlignedDPRCS2Regs >= 4) {
2044 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2045 MBB.addLiveIn(SupReg);
2053 NumAlignedDPRCS2Regs -= 4;
2057 if (NumAlignedDPRCS2Regs >= 2) {
2059 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2060 MBB.addLiveIn(SupReg);
2067 NumAlignedDPRCS2Regs -= 2;
2071 if (NumAlignedDPRCS2Regs) {
2072 MBB.addLiveIn(NextReg);
2077 .
addImm((NextReg - R4BaseReg) * 2)
2082 std::prev(
MI)->addRegisterKilled(ARM::R4,
TRI);
2089 unsigned NumAlignedDPRCS2Regs) {
2094 assert(
MI->mayStore() &&
"Expecting spill instruction");
2097 switch(NumAlignedDPRCS2Regs) {
2100 assert(
MI->mayStore() &&
"Expecting spill instruction");
2104 assert(
MI->mayStore() &&
"Expecting spill instruction");
2109 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2120 unsigned NumAlignedDPRCS2Regs,
2131 if (
I.getReg() == ARM::D8) {
2132 D8SpillFI =
I.getFrameIdx();
2144 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2152 unsigned NextReg = ARM::D8;
2155 if (NumAlignedDPRCS2Regs >= 6) {
2157 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2165 NumAlignedDPRCS2Regs -= 4;
2170 unsigned R4BaseReg = NextReg;
2173 if (NumAlignedDPRCS2Regs >= 4) {
2175 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2182 NumAlignedDPRCS2Regs -= 4;
2186 if (NumAlignedDPRCS2Regs >= 2) {
2188 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2194 NumAlignedDPRCS2Regs -= 2;
2198 if (NumAlignedDPRCS2Regs)
2201 .
addImm(2 * (NextReg - R4BaseReg))
2217 STI.getPushPopSplitVariation(MF);
2220 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2222 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2223 unsigned FltOpc = ARM::VSTMDDB_UPD;
2232 return C.getReg() == ARM::FPCXTNS;
2241 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2242 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2243 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2246 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2249 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2252 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2255 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2259 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2260 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2261 emitFPStatusSaves(
MBB,
MI, CSI, PushOpc);
2262 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2263 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2268 if (NumAlignedDPRCS2Regs)
2287 STI.getPushPopSplitVariation(MF);
2291 if (NumAlignedDPRCS2Regs)
2294 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2297 unsigned FltOpc = ARM::VLDMDIA_UPD;
2299 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2300 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2301 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2304 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2307 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2310 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2313 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2317 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2318 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2319 emitFPStatusRestores(
MBB,
MI, CSI, PopOpc);
2320 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2321 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2329 unsigned FnSize = 0;
2330 for (
auto &
MBB : MF) {
2331 for (
auto &
MI :
MBB)
2332 FnSize +=
TII.getInstSizeInBytes(
MI);
2336 FnSize += Table.MBBs.size() * 4;
2339 << FnSize <<
" bytes\n");
2349 bool &HasNonSPFrameIndex) {
2353 unsigned Limit = (1 << 12) - 1;
2354 for (
auto &
MBB : MF) {
2355 for (
auto &
MI :
MBB) {
2356 if (
MI.isDebugInstr())
2358 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2359 if (!
MI.getOperand(i).isFI())
2364 if (
MI.getOpcode() == ARM::ADDri) {
2365 Limit = std::min(Limit, (1U << 8) - 1);
2370 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2375 if (RegClass && !RegClass->
contains(ARM::SP))
2376 HasNonSPFrameIndex =
true;
2386 Limit = std::min(Limit, (1U << 8) - 1);
2389 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2394 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2400 Limit = std::min(Limit, (1U << 8) - 1);
2408 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2411 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2414 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2417 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2458 unsigned NumSpills = 0;
2459 for (; NumSpills < 8; ++NumSpills)
2460 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2471 SavedRegs.
set(ARM::R4);
2477 if (
STI.hasV8_1MMainlineOps() &&
2494 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2507 for (
const auto &
MBB : MF)
2508 for (
const auto &
MI :
MBB)
2509 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2510 STI.genExecuteOnly())
2511 for (
const auto &
Op :
MI.operands())
2531 bool CS1Spilled =
false;
2532 bool LRSpilled =
false;
2533 unsigned NumGPRSpills = 0;
2534 unsigned NumFPRSpills = 0;
2549 STI.getPushPopSplitVariation(MF);
2553 if (
F.hasFnAttribute(
"interrupt") &&
F.hasFnAttribute(
"save-fp")) {
2554 SavedRegs.
set(ARM::FPSCR);
2555 SavedRegs.
set(ARM::R4);
2558 if (
STI.isMClass()) {
2559 SavedRegs.
reset(ARM::FPEXC);
2561 SavedRegs.
set(ARM::FPEXC);
2562 SavedRegs.
set(ARM::R5);
2572 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2573 SavedRegs.
set(ARM::R4);
2580 if (
STI.isTargetWindows() &&
2582 SavedRegs.
set(ARM::R4);
2583 SavedRegs.
set(ARM::LR);
2589 SavedRegs.
set(ARM::LR);
2597 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2598 MFI.estimateStackSize(MF) > 508)
2599 SavedRegs.
set(ARM::R4);
2606 if (RegInfo->hasBasePointer(MF))
2607 SavedRegs.
set(RegInfo->getBaseRegister());
2611 CanEliminateFrame =
false;
2615 CanEliminateFrame =
false;
2619 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2620 for (
unsigned i = 0; CSRegs[i]; ++i) {
2621 unsigned Reg = CSRegs[i];
2622 bool Spilled =
false;
2623 if (SavedRegs.
test(Reg)) {
2625 CanEliminateFrame =
false;
2628 if (!ARM::GPRRegClass.
contains(Reg)) {
2630 if (ARM::SPRRegClass.
contains(Reg))
2632 else if (ARM::DPRRegClass.
contains(Reg))
2634 else if (ARM::QPRRegClass.
contains(Reg))
2655 case ARM::R0:
case ARM::R1:
2656 case ARM::R2:
case ARM::R3:
2657 case ARM::R4:
case ARM::R5:
2658 case ARM::R6:
case ARM::R7:
2671 case ARM::R0:
case ARM::R1:
2672 case ARM::R2:
case ARM::R3:
2673 case ARM::R4:
case ARM::R5:
2674 case ARM::R6:
case ARM::R7:
2685 bool ForceLRSpill =
false;
2690 if (FnSize >= (1 << 11)) {
2691 CanEliminateFrame =
false;
2692 ForceLRSpill =
true;
2710 unsigned EstimatedStackSize =
2711 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2714 int MaxFixedOffset = 0;
2715 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2716 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2717 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2720 bool HasFP =
hasFP(MF);
2723 EstimatedStackSize += 4;
2727 EstimatedStackSize += MaxFixedOffset;
2729 EstimatedStackSize += 16;
2731 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2732 bool HasNonSPFrameIndex =
false;
2752 if (RegInfo->hasBasePointer(MF))
2753 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2755 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2756 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2758 EstimatedRSStackSizeLimit =
2760 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2764 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2770 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2772 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
2781 bool HasLargeArgumentList =
2782 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2784 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2785 HasLargeArgumentList || HasNonSPFrameIndex;
2786 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2787 <<
"; EstimatedStack: " << EstimatedStackSize
2788 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2789 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2790 if (BigFrameOffsets ||
2791 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
2805 SavedRegs.
set(ARM::LR);
2808 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2809 if (LRPos != UnspilledCS1GPRs.
end())
2810 UnspilledCS1GPRs.
erase(LRPos);
2813 if (FPPos != UnspilledCS1GPRs.
end())
2814 UnspilledCS1GPRs.
erase(FPPos);
2832 unsigned NumExtraCSSpill = 0;
2849 int EntryRegDeficit = 0;
2850 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2855 <<
" is unused argument register, EntryRegDeficit = "
2856 << EntryRegDeficit <<
"\n");
2863 <<
" return regs used, ExitRegDeficit = "
2864 << ExitRegDeficit <<
"\n");
2866 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2871 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2872 if (SavedRegs.
test(Reg)) {
2875 <<
" is saved low register, RegDeficit = "
2876 << RegDeficit <<
"\n");
2882 <<
" is non-saved low register, adding to AvailableRegs\n");
2887 if (!HasFP ||
FramePtr != ARM::R7) {
2888 if (SavedRegs.
test(ARM::R7)) {
2891 << RegDeficit <<
"\n");
2896 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2901 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2902 if (SavedRegs.
test(Reg)) {
2905 <<
" is saved high register, RegDeficit = "
2906 << RegDeficit <<
"\n");
2913 if ((EntryRegDeficit > ExitRegDeficit) &&
2916 if (SavedRegs.
test(ARM::LR)) {
2919 << RegDeficit <<
"\n");
2922 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2931 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2932 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2935 <<
" to make up reg deficit\n");
2939 assert(!
MRI.isReserved(Reg) &&
"Should not be reserved");
2940 if (Reg != ARM::LR && !
MRI.isPhysRegUsed(Reg))
2946 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2956 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2957 SavedRegs.
set(ARM::LR);
2960 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2961 if (LRPos != UnspilledCS1GPRs.
end())
2962 UnspilledCS1GPRs.
erase(LRPos);
2964 ForceLRSpill =
false;
2965 if (!
MRI.isReserved(ARM::LR) && !
MRI.isPhysRegUsed(ARM::LR) &&
2975 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2976 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
2977 for (
unsigned Reg : UnspilledCS1GPRs) {
2981 (
STI.isTargetWindows() && Reg == ARM::R11) ||
2983 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2986 <<
" to make up alignment\n");
2987 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg) &&
2994 unsigned Reg = UnspilledCS2GPRs.
front();
2997 <<
" to make up alignment\n");
2998 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg))
3009 unsigned RegsNeeded = 0;
3018 if (RegsNeeded > NumExtraCSSpill) {
3021 unsigned NumExtras = TargetAlign.
value() / 4;
3023 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
3025 if (!
MRI.isReserved(Reg) &&
3033 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
3035 if (!
MRI.isReserved(Reg)) {
3041 if (NumExtras == 0) {
3042 for (
unsigned Reg : Extras) {
3044 if (!
MRI.isPhysRegUsed(Reg))
3048 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3052 unsigned Size =
TRI->getSpillSize(RC);
3053 Align Alignment =
TRI->getSpillAlign(RC);
3054 RS->addScavengingFrameIndex(
3055 MFI.CreateSpillStackObject(
Size, Alignment));
3062 SavedRegs.
set(ARM::LR);
3075 if (Info.getReg() != ARM::LR)
3079 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3080 Term.getOpcode() == ARM::t2LDMIA_RET ||
3081 Term.getOpcode() == ARM::tPOP_RET;
3084 Info.setRestored(
false);
3105 SavedRegs.
set(ARM::R0);
3110 std::vector<CalleeSavedInfo> &CSI)
const {
3113 if (
STI.hasV8_1MMainlineOps() &&
3115 CSI.emplace_back(ARM::FPCXTNS);
3116 CSI.back().setRestored(
false);
3128 switch (
STI.getPushPopSplitVariation(MF)) {
3132 [=](
const auto &CS) {
3134 return Reg == ARM::R10 || Reg == ARM::R11 ||
3135 Reg == ARM::R8 || Reg == ARM::R9 ||
3136 ARM::DPRRegClass.contains(Reg);
3147 "ABI-required frame pointers need a CSR split when signing return "
3150 [=](
const auto &CS) {
3152 return Reg != ARM::LR;
3166 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3167 NumEntries = std::size(FixedSpillOffsets);
3168 return FixedSpillOffsets;
3179 unsigned Opc =
I->getOpcode();
3180 bool IsDestroy =
Opc ==
TII.getCallFrameDestroyOpcode();
3181 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3184 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3186 int PIdx =
I->findFirstPredOperandIdx();
3190 unsigned PredReg =
TII.getFramePred(*
I);
3194 if (IsDestroy && CalleePopAmount != -1U)
3195 return MBB.erase(
I);
3200 unsigned Amount =
TII.getFrameSize(*
I);
3207 if (
Opc == ARM::ADJCALLSTACKDOWN ||
Opc == ARM::tADJCALLSTACKDOWN) {
3211 assert(
Opc == ARM::ADJCALLSTACKUP ||
Opc == ARM::tADJCALLSTACKUP);
3216 }
else if (CalleePopAmount != -1U) {
3230 unsigned Shifted = 0;
3235 while (!(
Value & 0xC0000000)) {
3240 bool Carry = (
Value & 0x00FFFFFF);
3241 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3243 if (
Value & 0x0000100)
3286 bool Thumb = ST->isThumb();
3287 bool Thumb2 = ST->isThumb2();
3293 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3309 unsigned ScratchReg0 = ARM::R4;
3310 unsigned ScratchReg1 = ARM::R5;
3311 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3328 if (BeforePrologueRegion.
insert(PredBB).second)
3331 }
while (!WalkList.
empty());
3342 for (
const auto &LI : PrologueMBB.
liveins()) {
3344 PredBB->addLiveIn(LI);
3350 BeforePrologueRegion.
erase(
B);
3356 MBB->sortUniqueLiveIns();
3359 if (
MBB->isSuccessor(&PrologueMBB))
3360 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3405 }
else if (CompareStackPointer) {
3413 if (!CompareStackPointer && Thumb) {
3414 if (AlignedStackSize < 256) {
3418 .
addImm(AlignedStackSize)
3421 if (Thumb2 || ST->genExecuteOnly()) {
3423 .
addImm(AlignedStackSize);
3426 auto RegInfo =
STI.getRegisterInfo();
3427 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3436 }
else if (!CompareStackPointer) {
3437 if (AlignedStackSize < 256) {
3440 .
addImm(AlignedStackSize)
3445 auto RegInfo =
STI.getRegisterInfo();
3446 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3456 if (Thumb && ST->isThumb1Only()) {
3457 if (ST->genExecuteOnly()) {
3468 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3481 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3491 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3492 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3496 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3505 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3512 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3525 if (AlignedStackSize < 256) {
3526 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3528 .
addImm(AlignedStackSize)
3531 if (Thumb2 || ST->genExecuteOnly()) {
3533 .
addImm(AlignedStackSize);
3536 auto RegInfo =
STI.getRegisterInfo();
3537 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3542 if (AlignedStackSize < 256) {
3544 .
addImm(AlignedStackSize)
3549 auto RegInfo =
STI.getRegisterInfo();
3550 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3559 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3564 if (Thumb2 || ST->genExecuteOnly()) {
3569 auto RegInfo =
STI.getRegisterInfo();
3570 RegInfo->emitLoadConstPool(
3571 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3583 auto RegInfo =
STI.getRegisterInfo();
3584 RegInfo->emitLoadConstPool(
3585 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3623 if (ST->isThumb1Only()) {
3710#ifdef EXPENSIVE_CHECKS
unsigned const MachineRegisterInfo * MRI
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,...
LLVM_ABI bool isLiveIn(Register Reg) const
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.