161#define DEBUG_TYPE "arm-frame-lowering"
167 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
171 unsigned NumAlignedDPRCS2Regs);
186 unsigned NumAlignedDPRCS2Regs,
285 if (
Reg >= ARM::D8 &&
Reg < ARM::D8 + NumAlignedDPRCS2Regs)
371 if (CFSize >= ((1 << 12) - 1) / 2)
394 bool IsTailCallReturn =
false;
396 unsigned RetOpcode =
MBBI->getOpcode();
397 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
398 RetOpcode == ARM::TCRETURNri ||
399 RetOpcode == ARM::TCRETURNrinotr12;
403 int ArgumentPopSize = 0;
404 if (IsTailCallReturn) {
410 ArgumentPopSize = StackAdjust.
getImm();
419 return ArgumentPopSize;
425 F.needsUnwindTableEntry();
433 unsigned Opc =
MBBI->getOpcode();
459 case ARM::t2MOVi16: {
460 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
464 NewInstr.
add(
MBBI->getOperand(0));
482 case ARM::t2MOVi32imm:
500 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
501 MBBI->getOperand(2).getReg() == ARM::SP &&
502 MBBI->getOperand(3).getImm() == -4) {
503 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
513 case ARM::t2LDR_POST:
514 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
515 MBBI->getOperand(2).getReg() == ARM::SP &&
516 MBBI->getOperand(3).getImm() == 4) {
517 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
527 case ARM::t2LDMIA_RET:
528 case ARM::t2LDMIA_UPD:
529 case ARM::t2STMDB_UPD: {
539 if (
Reg >= 8 &&
Reg <= 13)
541 else if (
Opc == ARM::t2LDMIA_UPD &&
Reg == 14)
548 case ARM::t2LDMIA_RET:
549 NewOpc = ARM::tPOP_RET;
551 case ARM::t2LDMIA_UPD:
554 case ARM::t2STMDB_UPD:
563 NewInstr.
add(
MBBI->getOperand(i));
569 (
Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
576 case ARM::VSTMDDB_UPD:
577 case ARM::VLDMDIA_UPD: {
580 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
598 case ARM::t2SUBspImm:
599 case ARM::t2SUBspImm12:
600 case ARM::t2ADDspImm:
601 case ARM::t2ADDspImm12:
609 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
611 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
615 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
617 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
627 case ARM::t2BXAUT_RET:
628 case ARM::CLEANUPRET:
630 case ARM::TCRETURNri:
631 case ARM::TCRETURNrinotr12:
637 case ARM::TCRETURNdi:
643 return MBB->insertAfter(
MBBI, MIB);
650 return std::prev(
MBBI);
658 Start = std::next(Start);
662 for (
auto MI = Start;
MI != End;) {
663 auto Next = std::next(
MI);
684 Pred, PredReg,
TII, MIFlags);
687 Pred, PredReg,
TII, MIFlags);
695 unsigned PredReg = 0) {
697 MIFlags, Pred, PredReg);
702 switch (
MI.getOpcode()) {
703 case ARM::VSTMDDB_UPD:
707 case ARM::t2STMDB_UPD:
711 case ARM::STR_PRE_IMM:
720 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
726 size_t StackSizeInBytes) {
732 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
733 return (StackSizeInBytes >= StackProbeSize) &&
734 !
F.hasFnAttribute(
"no-stack-arg-probe");
739struct StackAdjustingInsts {
745#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
747 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
748 <<
"sp-adjust=" << SPAdjust;
757 bool BeforeFPSet =
false) {
758 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
765 assert(Info != Insts.
end() &&
"invalid sp adjusting instruction");
766 Info->SPAdjust += ExtraBytes;
769 void emitDefCFAOffsets(MachineBasicBlock &
MBB,
bool HasFP) {
771 unsigned CFAOffset = 0;
772 for (
auto &Info : Insts) {
773 if (HasFP && !
Info.BeforeFPSet)
776 CFAOffset +=
Info.SPAdjust;
777 CFIBuilder.setInsertPoint(std::next(
Info.I));
778 CFIBuilder.buildDefCFAOffset(CFAOffset);
782#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
784 dbgs() <<
"StackAdjustingInsts:\n";
785 for (
auto &Info : Insts)
805 const Align Alignment,
806 const bool MustBeSingleInstruction) {
808 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
809 const unsigned AlignMask = Alignment.
value() - 1U;
810 const unsigned NrBitsToZero =
Log2(Alignment);
827 }
else if (AlignMask <= 255) {
834 assert(!MustBeSingleInstruction &&
835 "Shouldn't call emitAligningInstructions demanding a single "
836 "instruction to be emitted for large stack alignment for a target "
876 int MaxRegBytes = 8 * 4;
879 MaxRegBytes = 11 * 4;
882 MaxRegBytes = 11 * 4 + 8 * 8;
898 "This emitPrologue does not support Thumb1!");
900 Align Alignment =
STI.getFrameLowering()->getStackAlign();
904 int FPCXTSaveSize = 0;
907 STI.getPushPopSplitVariation(MF);
919 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
920 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
921 int FramePtrSpillFI = 0;
929 StackAdjustingInsts DefCFAOffsetCandidates;
930 bool HasFP =
hasFP(MF);
937 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
940 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
941 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
952 bool BeforeFPPush =
true;
955 int FI =
I.getFrameIdx();
961 FramePtrSpillFI = FI;
962 FramePtrSpillArea = Area;
993 DPRCS1Push, GPRCS3Push;
1000 if (FPCXTSaveSize > 0) {
1002 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
1006 if (ArgRegsSaveSize) {
1009 LastPush = std::prev(
MBBI);
1010 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1014 if (GPRCS1Size > 0) {
1015 GPRCS1Push = LastPush =
MBBI++;
1016 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1018 BeforeFPPush =
false;
1025 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1026 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1027 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1028 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1030 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1031 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1032 GPRCS2Size + FPStatusSize) %
1035 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1041 <<
", FPOffset: " << FPOffset <<
"\n");
1043 "Max FP estimation is wrong");
1052 if (GPRCS2Size > 0) {
1054 GPRCS2Push = LastPush =
MBBI++;
1055 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1057 BeforeFPPush =
false;
1061 if (FPStatusSize > 0) {
1063 unsigned Opc =
MBBI->getOpcode();
1064 if (
Opc == ARM::VMRS ||
Opc == ARM::VMRS_FPEXC)
1070 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1076 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1077 if (LastPush !=
MBB.end() &&
1079 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1083 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1088 if (DPRCS1Size > 0) {
1091 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1094 DPRCS1Push = LastPush =
MBBI++;
1099 if (DPRCS2Size > 0) {
1107 NumBytes = DPRCS1Offset;
1110 if (GPRCS3Size > 0) {
1112 GPRCS3Push = LastPush =
MBBI++;
1113 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1115 BeforeFPPush =
false;
1116 NumBytes -= GPRCS3Size;
1119 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1121 NeedsWinCFIStackAlloc =
false;
1126 if (NumWords < 65536) {
1136 .
addImm(NumWords & 0xffff)
1147 RTLIB::LibcallImpl ChkStkLibcall = TLI->
getLibcallImpl(RTLIB::STACK_PROBE);
1148 if (ChkStkLibcall == RTLIB::Unsupported)
1152 switch (TM.getCodeModel()) {
1184 if (NeedsWinCFIStackAlloc) {
1185 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1189 MBB.insertAfter(Instr, SEH);
1198 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1202 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1228 int64_t FPOffsetAfterPush;
1229 switch (FramePtrSpillArea) {
1231 FPPushInst = GPRCS1Push;
1233 ArgRegsSaveSize + FPCXTSaveSize +
1236 << FPOffsetAfterPush <<
" after that push\n");
1239 FPPushInst = GPRCS2Push;
1241 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1244 << FPOffsetAfterPush <<
" after that push\n");
1247 FPPushInst = GPRCS3Push;
1249 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1250 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1253 << FPOffsetAfterPush <<
" after that push\n");
1259 AfterPush = std::next(FPPushInst);
1261 assert(FPOffsetAfterPush == 0);
1265 FramePtr, ARM::SP, FPOffsetAfterPush,
1272 if (FPOffsetAfterPush != 0)
1281 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
1295 for (
const auto &Entry :
reverse(CSI)) {
1297 int FI = Entry.getFrameIdx();
1302 CFIPos = std::next(GPRCS1Push);
1305 CFIPos = std::next(GPRCS2Push);
1308 CFIPos = std::next(DPRCS1Push);
1311 CFIPos = std::next(GPRCS3Push);
1322 .
buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1334 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
1337 if (
STI.isTargetELF() &&
hasFP(MF))
1385 if (RegInfo->hasBasePointer(MF) && !
MBB.isEHFuncletEntry()) {
1412 "This emitEpilogue does not support Thumb1!");
1415 STI.getPushPopSplitVariation(MF);
1446 if (NumBytes + IncomingArgStackToRestore != 0)
1448 NumBytes + IncomingArgStackToRestore,
1455 }
while (
MBBI !=
MBB.begin() &&
1492 "No scratch register to restore SP from FP!");
1514 }
else if (NumBytes &&
1530 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1535 "unexpected DPR alignment gap");
1547 if (ReservedArgStack || IncomingArgStackToRestore) {
1548 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1549 "attempting to restore negative stack amount");
1551 ReservedArgStack + IncomingArgStackToRestore,
1561 STI.isThumb() &&
STI.hasV8_1MMainlineOps() &&
STI.hasPACBTI();
1562 auto TMBBI =
MBB.getFirstTerminator();
1564 TMBBI !=
MBB.end() && TMBBI->getOpcode() == ARM::tBX_RET;
1565 if (IsBXReturn && CanUseBXAut)
1566 TMBBI->setDesc(
STI.getInstrInfo()->get(ARM::t2BXAUT_RET));
1617 if (RegInfo->hasStackRealignment(MF)) {
1618 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1620 FrameReg = RegInfo->getFrameRegister(MF);
1622 }
else if (hasMovingSP) {
1623 assert(RegInfo->hasBasePointer(MF) &&
1624 "VLAs and dynamic stack alignment, but missing base pointer!");
1625 FrameReg = RegInfo->getBaseRegister();
1635 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1636 FrameReg = RegInfo->getFrameRegister(MF);
1638 }
else if (hasMovingSP) {
1639 assert(RegInfo->hasBasePointer(MF) &&
"missing base pointer!");
1644 if (FPOffset >= -255 && FPOffset < 0) {
1645 FrameReg = RegInfo->getFrameRegister(MF);
1660 FrameReg = RegInfo->getFrameRegister(MF);
1663 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1665 FrameReg = RegInfo->getFrameRegister(MF);
1672 if (RegInfo->hasBasePointer(MF)) {
1673 FrameReg = RegInfo->getBaseRegister();
1682 unsigned StmOpc,
unsigned StrOpc,
1691 using RegAndKill = std::pair<unsigned, bool>;
1694 unsigned i = CSI.
size();
1696 unsigned LastReg = 0;
1697 for (; i != 0; --i) {
1709 if (NoGap && LastReg && LastReg != Reg-1)
1717 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1724 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1727 if (Regs.
size() > 1 || StrOpc== 0) {
1732 for (
const auto &[
Reg,
Kill] : Regs)
1734 }
else if (Regs.size() == 1) {
1755 unsigned LdmOpc,
unsigned LdrOpc,
1756 bool isVarArg,
bool NoGap,
1760 const TargetRegisterInfo &
TRI = *
STI.getRegisterInfo();
1761 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
1764 bool isTailCall =
false;
1765 bool isInterrupt =
false;
1766 bool isTrap =
false;
1767 bool isCmseEntry =
false;
1769 STI.getPushPopSplitVariation(MF);
1771 DL =
MI->getDebugLoc();
1772 unsigned RetOpcode =
MI->getOpcode();
1774 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1775 RetOpcode == ARM::TCRETURNrinotr12);
1777 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1778 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1779 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1782 SmallVector<unsigned, 4> Regs;
1783 unsigned i = CSI.
size();
1785 unsigned LastReg = 0;
1786 bool DeleteRet =
false;
1787 for (; i != 0; --i) {
1788 CalleeSavedInfo &
Info = CSI[i-1];
1789 MCRegister
Reg =
Info.getReg();
1793 if (
Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1807 if (NoGap && LastReg && LastReg !=
Reg-1)
1818 return TRI.getEncodingValue(
LHS) <
TRI.getEncodingValue(
RHS);
1821 if (Regs.
size() > 1 || LdrOpc == 0) {
1826 for (
unsigned Reg : Regs)
1831 MI->eraseFromParent();
1835 }
else if (Regs.size() == 1) {
1838 if (Regs[0] == ARM::PC)
1840 MachineInstrBuilder MIB =
1847 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1866 unsigned PushOpc)
const {
1871 auto RegPresent = [&CSI](MCRegister
Reg) {
1873 return C.getReg() ==
Reg;
1879 if (RegPresent(ARM::FPSCR)) {
1889 if (RegPresent(ARM::FPEXC)) {
1898 if (Regs.
size() == 0)
1902 MachineInstrBuilder MIB =
1913void ARMFrameLowering::emitFPStatusRestores(
1919 auto RegPresent = [&CSI](MCRegister
Reg) {
1921 return C.getReg() ==
Reg;
1926 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1930 MachineInstrBuilder MIB =
1937 if (RegPresent(ARM::FPSCR)) {
1942 if (RegPresent(ARM::FPEXC)) {
1947 if (RegPresent(ARM::FPSCR)) {
1956 if (RegPresent(ARM::FPEXC)) {
1969 unsigned NumAlignedDPRCS2Regs,
1982 unsigned DNum =
I.getReg() - ARM::D8;
1983 if (DNum > NumAlignedDPRCS2Regs - 1)
1985 int FI =
I.getFrameIdx();
2013 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
2016 .
addImm(8 * NumAlignedDPRCS2Regs)
2041 unsigned NextReg = ARM::D8;
2045 if (NumAlignedDPRCS2Regs >= 6) {
2047 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2048 MBB.addLiveIn(SupReg);
2056 NumAlignedDPRCS2Regs -= 4;
2061 unsigned R4BaseReg = NextReg;
2064 if (NumAlignedDPRCS2Regs >= 4) {
2066 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2067 MBB.addLiveIn(SupReg);
2075 NumAlignedDPRCS2Regs -= 4;
2079 if (NumAlignedDPRCS2Regs >= 2) {
2081 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2082 MBB.addLiveIn(SupReg);
2089 NumAlignedDPRCS2Regs -= 2;
2093 if (NumAlignedDPRCS2Regs) {
2094 MBB.addLiveIn(NextReg);
2099 .
addImm((NextReg - R4BaseReg) * 2)
2104 std::prev(
MI)->addRegisterKilled(ARM::R4,
TRI);
2111 unsigned NumAlignedDPRCS2Regs) {
2116 assert(
MI->mayStore() &&
"Expecting spill instruction");
2119 switch(NumAlignedDPRCS2Regs) {
2122 assert(
MI->mayStore() &&
"Expecting spill instruction");
2126 assert(
MI->mayStore() &&
"Expecting spill instruction");
2131 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2142 unsigned NumAlignedDPRCS2Regs,
2153 if (
I.getReg() == ARM::D8) {
2154 D8SpillFI =
I.getFrameIdx();
2166 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2174 unsigned NextReg = ARM::D8;
2177 if (NumAlignedDPRCS2Regs >= 6) {
2179 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2187 NumAlignedDPRCS2Regs -= 4;
2192 unsigned R4BaseReg = NextReg;
2195 if (NumAlignedDPRCS2Regs >= 4) {
2197 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2204 NumAlignedDPRCS2Regs -= 4;
2208 if (NumAlignedDPRCS2Regs >= 2) {
2210 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2216 NumAlignedDPRCS2Regs -= 2;
2220 if (NumAlignedDPRCS2Regs)
2223 .
addImm(2 * (NextReg - R4BaseReg))
2239 STI.getPushPopSplitVariation(MF);
2242 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2244 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2245 unsigned FltOpc = ARM::VSTMDDB_UPD;
2254 return C.getReg() == ARM::FPCXTNS;
2263 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2264 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2265 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2268 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2271 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2274 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2277 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2281 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2282 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2283 emitFPStatusSaves(
MBB,
MI, CSI, PushOpc);
2284 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2285 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2290 if (NumAlignedDPRCS2Regs)
2309 STI.getPushPopSplitVariation(MF);
2313 if (NumAlignedDPRCS2Regs)
2316 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2319 unsigned FltOpc = ARM::VLDMDIA_UPD;
2321 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2322 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2323 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2326 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2329 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2332 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2335 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2339 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2340 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2341 emitFPStatusRestores(
MBB,
MI, CSI, PopOpc);
2342 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2343 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2354 bool BigFrameOffsets) {
2355 unsigned FnSize = 0;
2368 unsigned SavedHighRegs = 0;
2369 for (
auto Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11, ARM::R12})
2382 unsigned PrologueSize = 2 + 4 * SavedHighRegs + 6 + 12 + 2;
2383 if (
RegInfo->hasStackRealignment(MF))
2385 FnSize += PrologueSize;
2394 unsigned EpilogueSize = 6 + 2 + 4 * SavedHighRegs + 4 + 2 + 2;
2396 bool FirstBlock =
true;
2397 for (
auto &
MBB : MF) {
2401 unsigned Alignment =
MBB.getMaxBytesForAlignment();
2402 FnSize += Alignment;
2405 unsigned SizeBeforeThisBB = FnSize;
2407 bool seenBranch =
false, seenConstantLoad =
false;
2408 for (
auto &
MI :
MBB) {
2410 switch (
MI.getOpcode()) {
2411 case ARM::tADDframe:
2412 if (BigFrameOffsets)
2423 if (BigFrameOffsets)
2433 case TargetOpcode::COPY:
2444 case ARM::Int_eh_sjlj_dispatchsetup:
2449 case ARM::tLDRpci_pic:
2453 case ARM::ADJCALLSTACKDOWN:
2454 case ARM::ADJCALLSTACKUP:
2458 case ARM::tBLXNS_CALL:
2463 InstSize = 2 + 2 * 4 + 2;
2478 InstSize += 2 + 2 * 4 + 2;
2481 case ARM::tBXNS_RET:
2485 InstSize = 5 * 2 + 4 + 2;
2488 case TargetOpcode::LOAD_STACK_GUARD:
2489 if (STI.genExecuteOnly())
2495 InstSize = 7 * 2 + 2 * 4 + 8;
2500 InstSize = 2 * 2 + 4;
2504 InstSize =
TII.getInstSizeInBytes(
MI);
2515 MO->getPointerInfo().V);
2517 unsigned ConstSize = MO->getType().getSizeInBytes();
2518 FnSize += ConstSize;
2519 seenConstantLoad =
true;
2526 if (
MI.isReturn() ||
TII.isTailCall(
MI)) {
2527 FnSize += EpilogueSize;
2532 if (KCFI &&
MI.isCall() &&
MI.getCFIType()) {
2534 FnSize +=
MCID.getSize();
2537 if (
MI.isUnconditionalBranch())
2544 if (seenConstantLoad && !seenBranch) {
2555 unsigned BBSize = FnSize - SizeBeforeThisBB;
2556 FnSize += 4 * BBSize / 512;
2560 unsigned TableLen = Table.MBBs.size();
2561 unsigned TableSizeBytes = TableLen * 4;
2562 FnSize += TableSizeBytes;
2566 << FnSize <<
" bytes\n");
2576 bool &HasNonSPFrameIndex) {
2580 unsigned Limit = (1 << 12) - 1;
2581 for (
auto &
MBB : MF) {
2582 for (
auto &
MI :
MBB) {
2583 if (
MI.isDebugInstr())
2585 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
2587 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2588 if (!
MI.getOperand(i).isFI())
2593 if (
MI.getOpcode() == ARM::ADDri) {
2594 Limit = std::min(Limit, (1U << 8) - 1);
2599 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2604 if (RegClass && !RegClass->
contains(ARM::SP))
2605 HasNonSPFrameIndex =
true;
2615 Limit = std::min(Limit, (1U << 8) - 1);
2618 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2623 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2629 Limit = std::min(Limit, (1U << 8) - 1);
2637 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2640 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2643 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2646 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2687 unsigned NumSpills = 0;
2688 for (; NumSpills < 8; ++NumSpills)
2689 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2700 SavedRegs.
set(ARM::R4);
2706 if (
STI.hasV8_1MMainlineOps() &&
2723 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2736 for (
const auto &
MBB : MF)
2737 for (
const auto &
MI :
MBB)
2738 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2739 STI.genExecuteOnly())
2740 for (
const auto &
Op :
MI.operands())
2760 bool CS1Spilled =
false;
2761 bool LRSpilled =
false;
2762 unsigned NumGPRSpills = 0;
2763 unsigned NumFPRSpills = 0;
2778 STI.getPushPopSplitVariation(MF);
2782 if (
F.hasFnAttribute(
"interrupt") &&
F.hasFnAttribute(
"save-fp")) {
2783 SavedRegs.
set(ARM::FPSCR);
2784 SavedRegs.
set(ARM::R4);
2787 if (
STI.isMClass()) {
2788 SavedRegs.
reset(ARM::FPEXC);
2790 SavedRegs.
set(ARM::FPEXC);
2791 SavedRegs.
set(ARM::R5);
2801 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2802 SavedRegs.
set(ARM::R4);
2809 if (
STI.isTargetWindows() &&
2811 SavedRegs.
set(ARM::R4);
2812 SavedRegs.
set(ARM::LR);
2818 SavedRegs.
set(ARM::LR);
2826 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2827 MFI.estimateStackSize(MF) > 508)
2828 SavedRegs.
set(ARM::R4);
2835 if (RegInfo->hasBasePointer(MF))
2836 SavedRegs.
set(RegInfo->getBaseRegister());
2840 CanEliminateFrame =
false;
2844 CanEliminateFrame =
false;
2848 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2849 for (
unsigned i = 0; CSRegs[i]; ++i) {
2850 unsigned Reg = CSRegs[i];
2851 bool Spilled =
false;
2852 if (SavedRegs.
test(Reg)) {
2854 CanEliminateFrame =
false;
2857 if (!ARM::GPRRegClass.
contains(Reg)) {
2859 if (ARM::SPRRegClass.
contains(Reg))
2861 else if (ARM::DPRRegClass.
contains(Reg))
2863 else if (ARM::QPRRegClass.
contains(Reg))
2884 case ARM::R0:
case ARM::R1:
2885 case ARM::R2:
case ARM::R3:
2886 case ARM::R4:
case ARM::R5:
2887 case ARM::R6:
case ARM::R7:
2900 case ARM::R0:
case ARM::R1:
2901 case ARM::R2:
case ARM::R3:
2902 case ARM::R4:
case ARM::R5:
2903 case ARM::R6:
case ARM::R7:
2914 bool ForceLRSpill =
false;
2930 unsigned EstimatedStackSize =
2931 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2934 int MaxFixedOffset = 0;
2935 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2936 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2937 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2940 bool HasFP =
hasFP(MF);
2943 EstimatedStackSize += 4;
2947 EstimatedStackSize += MaxFixedOffset;
2949 EstimatedStackSize += 16;
2951 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2952 bool HasNonSPFrameIndex =
false;
2972 if (RegInfo->hasBasePointer(MF))
2973 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2975 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2976 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2978 EstimatedRSStackSizeLimit =
2980 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2984 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2990 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2992 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
3001 bool HasLargeArgumentList =
3002 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
3004 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
3005 HasLargeArgumentList || HasNonSPFrameIndex;
3006 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
3007 <<
"; EstimatedStack: " << EstimatedStackSize
3008 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
3009 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
3013 SavedRegs, BigFrameOffsets);
3015 if (FnSize >= (1 << 11)) {
3018 CanEliminateFrame =
false;
3019 ForceLRSpill =
true;
3023 if (BigFrameOffsets ||
3024 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
3038 SavedRegs.
set(ARM::LR);
3041 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
3042 if (LRPos != UnspilledCS1GPRs.
end())
3043 UnspilledCS1GPRs.
erase(LRPos);
3046 if (FPPos != UnspilledCS1GPRs.
end())
3047 UnspilledCS1GPRs.
erase(FPPos);
3065 unsigned NumExtraCSSpill = 0;
3082 int EntryRegDeficit = 0;
3083 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
3088 <<
" is unused argument register, EntryRegDeficit = "
3089 << EntryRegDeficit <<
"\n");
3096 <<
" return regs used, ExitRegDeficit = "
3097 << ExitRegDeficit <<
"\n");
3099 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
3104 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
3105 if (SavedRegs.
test(Reg)) {
3108 <<
" is saved low register, RegDeficit = "
3109 << RegDeficit <<
"\n");
3115 <<
" is non-saved low register, adding to AvailableRegs\n");
3120 if (!HasFP ||
FramePtr != ARM::R7) {
3121 if (SavedRegs.
test(ARM::R7)) {
3124 << RegDeficit <<
"\n");
3129 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
3134 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
3135 if (SavedRegs.
test(Reg)) {
3138 <<
" is saved high register, RegDeficit = "
3139 << RegDeficit <<
"\n");
3146 if ((EntryRegDeficit > ExitRegDeficit) &&
3149 if (SavedRegs.
test(ARM::LR)) {
3152 << RegDeficit <<
"\n");
3155 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
3164 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
3165 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
3168 <<
" to make up reg deficit\n");
3179 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
3189 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
3190 SavedRegs.
set(ARM::LR);
3193 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
3194 if (LRPos != UnspilledCS1GPRs.
end())
3195 UnspilledCS1GPRs.
erase(LRPos);
3197 ForceLRSpill =
false;
3208 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
3209 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
3210 for (
unsigned Reg : UnspilledCS1GPRs) {
3214 (
STI.isTargetWindows() && Reg == ARM::R11) ||
3216 (Reg == ARM::LR && !ExpensiveLRRestore)) {
3219 <<
" to make up alignment\n");
3227 unsigned Reg = UnspilledCS2GPRs.
front();
3230 <<
" to make up alignment\n");
3242 unsigned RegsNeeded = 0;
3251 if (RegsNeeded > NumExtraCSSpill) {
3254 unsigned NumExtras = TargetAlign.
value() / 4;
3256 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
3266 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
3274 if (NumExtras == 0) {
3275 for (
unsigned Reg : Extras) {
3281 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3285 unsigned Size =
TRI->getSpillSize(RC);
3286 Align Alignment =
TRI->getSpillAlign(RC);
3287 RS->addScavengingFrameIndex(
3288 MFI.CreateSpillStackObject(
Size, Alignment));
3295 SavedRegs.
set(ARM::LR);
3308 if (Info.getReg() != ARM::LR)
3312 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3313 Term.getOpcode() == ARM::t2LDMIA_RET ||
3314 Term.getOpcode() == ARM::tPOP_RET;
3317 Info.setRestored(
false);
3338 SavedRegs.
set(ARM::R0);
3343 std::vector<CalleeSavedInfo> &CSI)
const {
3346 if (
STI.hasV8_1MMainlineOps() &&
3348 CSI.emplace_back(ARM::FPCXTNS);
3349 CSI.back().setRestored(
false);
3361 switch (
STI.getPushPopSplitVariation(MF)) {
3365 [=](
const auto &CS) {
3367 return Reg == ARM::R10 || Reg == ARM::R11 ||
3368 Reg == ARM::R8 || Reg == ARM::R9 ||
3369 ARM::DPRRegClass.contains(Reg);
3380 "ABI-required frame pointers need a CSR split when signing return "
3383 [=](
const auto &CS) {
3385 return Reg != ARM::LR;
3399 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3400 NumEntries = std::size(FixedSpillOffsets);
3401 return FixedSpillOffsets;
3412 unsigned Opc =
I->getOpcode();
3413 bool IsDestroy =
Opc ==
TII.getCallFrameDestroyOpcode();
3414 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3417 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3419 int PIdx =
I->findFirstPredOperandIdx();
3423 unsigned PredReg =
TII.getFramePred(*
I);
3427 if (IsDestroy && CalleePopAmount != -1U)
3428 return MBB.erase(
I);
3433 unsigned Amount =
TII.getFrameSize(*
I);
3440 if (
Opc == ARM::ADJCALLSTACKDOWN ||
Opc == ARM::tADJCALLSTACKDOWN) {
3444 assert(
Opc == ARM::ADJCALLSTACKUP ||
Opc == ARM::tADJCALLSTACKUP);
3449 }
else if (CalleePopAmount != -1U) {
3463 unsigned Shifted = 0;
3468 while (!(
Value & 0xC0000000)) {
3473 bool Carry = (
Value & 0x00FFFFFF);
3474 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3476 if (
Value & 0x0000100)
3519 bool Thumb = ST->isThumb();
3520 bool Thumb2 = ST->isThumb2();
3526 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3542 unsigned ScratchReg0 = ARM::R4;
3543 unsigned ScratchReg1 = ARM::R5;
3544 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3561 if (BeforePrologueRegion.
insert(PredBB).second)
3564 }
while (!WalkList.
empty());
3575 for (
const auto &LI : PrologueMBB.
liveins()) {
3577 PredBB->addLiveIn(LI);
3583 BeforePrologueRegion.
erase(
B);
3589 MBB->sortUniqueLiveIns();
3592 if (
MBB->isSuccessor(&PrologueMBB))
3593 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3638 }
else if (CompareStackPointer) {
3646 if (!CompareStackPointer && Thumb) {
3647 if (AlignedStackSize < 256) {
3651 .
addImm(AlignedStackSize)
3654 if (Thumb2 || ST->genExecuteOnly()) {
3656 .
addImm(AlignedStackSize);
3659 auto RegInfo =
STI.getRegisterInfo();
3660 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3669 }
else if (!CompareStackPointer) {
3670 if (AlignedStackSize < 256) {
3673 .
addImm(AlignedStackSize)
3678 auto RegInfo =
STI.getRegisterInfo();
3679 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3689 if (Thumb && ST->isThumb1Only()) {
3690 if (ST->genExecuteOnly()) {
3701 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3714 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3724 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3725 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3729 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3738 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3745 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3758 if (AlignedStackSize < 256) {
3759 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3761 .
addImm(AlignedStackSize)
3764 if (Thumb2 || ST->genExecuteOnly()) {
3766 .
addImm(AlignedStackSize);
3769 auto RegInfo =
STI.getRegisterInfo();
3770 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3775 if (AlignedStackSize < 256) {
3777 .
addImm(AlignedStackSize)
3782 auto RegInfo =
STI.getRegisterInfo();
3783 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3792 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3797 if (Thumb2 || ST->genExecuteOnly()) {
3802 auto RegInfo =
STI.getRegisterInfo();
3803 RegInfo->emitLoadConstPool(
3804 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3816 auto RegInfo =
STI.getRegisterInfo();
3817 RegInfo->emitLoadConstPool(
3818 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3856 if (ST->isThumb1Only()) {
3943#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 unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII, const ARMSubtarget &STI, const ARMBaseRegisterInfo *RegInfo, BitVector &SavedRegs, bool BigFrameOffsets)
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 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
Module.h This file contains the declarations for the Module class.
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 getNonLocalFrameIndexReference(const MachineFunction &MF, int FI) const override
getNonLocalFrameIndexReference - This method returns the offset used to reference a frame index locat...
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
BitVector & reset()
Reset all bits in the bitvector.
BitVector & set()
Set all bits in the bitvector.
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.
Module * getParent()
Get the module that this global value is contained inside of...
bool usesWindowsCFI() const
Describe properties that are true of each instruction in the target description file.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
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...
LLVM_ABI 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.
bool shouldSplitStack() const
Should we be emitting segmented stack stuff for the function.
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
A description of a memory reference used in the backend.
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.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Special value supplied for machine level alias analysis.
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
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...
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).
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
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...
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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)
MCRegisterClass TargetRegisterClass
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.