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;
426 unsigned Opc =
MBBI->getOpcode();
452 case ARM::t2MOVi16: {
453 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
457 NewInstr.
add(
MBBI->getOperand(0));
475 case ARM::t2MOVi32imm:
493 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
494 MBBI->getOperand(2).getReg() == ARM::SP &&
495 MBBI->getOperand(3).getImm() == -4) {
496 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
506 case ARM::t2LDR_POST:
507 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
508 MBBI->getOperand(2).getReg() == ARM::SP &&
509 MBBI->getOperand(3).getImm() == 4) {
510 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
520 case ARM::t2LDMIA_RET:
521 case ARM::t2LDMIA_UPD:
522 case ARM::t2STMDB_UPD: {
532 if (
Reg >= 8 &&
Reg <= 13)
534 else if (
Opc == ARM::t2LDMIA_UPD &&
Reg == 14)
541 case ARM::t2LDMIA_RET:
542 NewOpc = ARM::tPOP_RET;
544 case ARM::t2LDMIA_UPD:
547 case ARM::t2STMDB_UPD:
556 NewInstr.
add(
MBBI->getOperand(i));
562 (
Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
569 case ARM::VSTMDDB_UPD:
570 case ARM::VLDMDIA_UPD: {
573 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
591 case ARM::t2SUBspImm:
592 case ARM::t2SUBspImm12:
593 case ARM::t2ADDspImm:
594 case ARM::t2ADDspImm12:
602 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
604 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
608 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
610 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
620 case ARM::t2BXAUT_RET:
621 case ARM::CLEANUPRET:
623 case ARM::TCRETURNri:
624 case ARM::TCRETURNrinotr12:
630 case ARM::TCRETURNdi:
636 return MBB->insertAfter(
MBBI, MIB);
643 return std::prev(
MBBI);
651 Start = std::next(Start);
655 for (
auto MI = Start;
MI !=
End;) {
656 auto Next = std::next(
MI);
677 Pred, PredReg,
TII, MIFlags);
680 Pred, PredReg,
TII, MIFlags);
688 unsigned PredReg = 0) {
690 MIFlags, Pred, PredReg);
695 switch (
MI.getOpcode()) {
696 case ARM::VSTMDDB_UPD:
700 case ARM::t2STMDB_UPD:
704 case ARM::STR_PRE_IMM:
713 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
719 size_t StackSizeInBytes) {
725 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
726 return (StackSizeInBytes >= StackProbeSize) &&
727 !
F.hasFnAttribute(
"no-stack-arg-probe");
732struct StackAdjustingInsts {
738#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
740 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
741 <<
"sp-adjust=" << SPAdjust;
750 bool BeforeFPSet =
false) {
751 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
758 assert(Info != Insts.
end() &&
"invalid sp adjusting instruction");
759 Info->SPAdjust += ExtraBytes;
762 void emitDefCFAOffsets(MachineBasicBlock &
MBB,
bool HasFP) {
764 unsigned CFAOffset = 0;
765 for (
auto &Info : Insts) {
766 if (HasFP && !
Info.BeforeFPSet)
769 CFAOffset +=
Info.SPAdjust;
770 CFIBuilder.setInsertPoint(std::next(
Info.I));
771 CFIBuilder.buildDefCFAOffset(CFAOffset);
775#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
777 dbgs() <<
"StackAdjustingInsts:\n";
778 for (
auto &Info : Insts)
798 const Align Alignment,
799 const bool MustBeSingleInstruction) {
801 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
802 const unsigned AlignMask = Alignment.value() - 1U;
803 const unsigned NrBitsToZero =
Log2(Alignment);
820 }
else if (AlignMask <= 255) {
827 assert(!MustBeSingleInstruction &&
828 "Shouldn't call emitAligningInstructions demanding a single "
829 "instruction to be emitted for large stack alignment for a target "
869 int MaxRegBytes = 8 * 4;
872 MaxRegBytes = 11 * 4;
875 MaxRegBytes = 11 * 4 + 8 * 8;
891 "This emitPrologue does not support Thumb1!");
893 Align Alignment =
STI.getFrameLowering()->getStackAlign();
897 int FPCXTSaveSize = 0;
900 STI.getPushPopSplitVariation(MF);
912 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
913 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
914 int FramePtrSpillFI = 0;
922 StackAdjustingInsts DefCFAOffsetCandidates;
923 bool HasFP =
hasFP(MF);
930 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
933 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
934 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
945 bool BeforeFPPush =
true;
948 int FI =
I.getFrameIdx();
954 FramePtrSpillFI = FI;
955 FramePtrSpillArea = Area;
986 DPRCS1Push, GPRCS3Push;
993 if (FPCXTSaveSize > 0) {
995 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
999 if (ArgRegsSaveSize) {
1002 LastPush = std::prev(
MBBI);
1003 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1007 if (GPRCS1Size > 0) {
1008 GPRCS1Push = LastPush =
MBBI++;
1009 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1011 BeforeFPPush =
false;
1018 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1019 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1020 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1021 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1023 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1024 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1025 GPRCS2Size + FPStatusSize) %
1028 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1034 <<
", FPOffset: " << FPOffset <<
"\n");
1036 "Max FP estimation is wrong");
1045 if (GPRCS2Size > 0) {
1047 GPRCS2Push = LastPush =
MBBI++;
1048 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1050 BeforeFPPush =
false;
1054 if (FPStatusSize > 0) {
1056 unsigned Opc =
MBBI->getOpcode();
1057 if (
Opc == ARM::VMRS ||
Opc == ARM::VMRS_FPEXC)
1063 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1069 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1070 if (LastPush !=
MBB.end() &&
1072 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1076 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1081 if (DPRCS1Size > 0) {
1084 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1087 DPRCS1Push = LastPush =
MBBI++;
1092 if (DPRCS2Size > 0) {
1100 NumBytes = DPRCS1Offset;
1103 if (GPRCS3Size > 0) {
1105 GPRCS3Push = LastPush =
MBBI++;
1106 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1108 BeforeFPPush =
false;
1109 NumBytes -= GPRCS3Size;
1112 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1114 NeedsWinCFIStackAlloc =
false;
1119 if (NumWords < 65536) {
1129 .
addImm(NumWords & 0xffff)
1140 RTLIB::LibcallImpl ChkStkLibcall = TLI->
getLibcallImpl(RTLIB::STACK_PROBE);
1141 if (ChkStkLibcall == RTLIB::Unsupported)
1145 switch (TM.getCodeModel()) {
1177 if (NeedsWinCFIStackAlloc) {
1178 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1182 MBB.insertAfter(Instr, SEH);
1191 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1195 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1221 int64_t FPOffsetAfterPush;
1222 switch (FramePtrSpillArea) {
1224 FPPushInst = GPRCS1Push;
1226 ArgRegsSaveSize + FPCXTSaveSize +
1229 << FPOffsetAfterPush <<
" after that push\n");
1232 FPPushInst = GPRCS2Push;
1234 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1237 << FPOffsetAfterPush <<
" after that push\n");
1240 FPPushInst = GPRCS3Push;
1242 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1243 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1246 << FPOffsetAfterPush <<
" after that push\n");
1252 AfterPush = std::next(FPPushInst);
1254 assert(FPOffsetAfterPush == 0);
1258 FramePtr, ARM::SP, FPOffsetAfterPush,
1265 if (FPOffsetAfterPush != 0)
1274 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
1288 for (
const auto &Entry :
reverse(CSI)) {
1290 int FI = Entry.getFrameIdx();
1295 CFIPos = std::next(GPRCS1Push);
1298 CFIPos = std::next(GPRCS2Push);
1301 CFIPos = std::next(DPRCS1Push);
1304 CFIPos = std::next(GPRCS3Push);
1315 .
buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1327 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
1330 if (
STI.isTargetELF() &&
hasFP(MF))
1378 if (RegInfo->hasBasePointer(MF) && !
MBB.isEHFuncletEntry()) {
1405 "This emitEpilogue does not support Thumb1!");
1408 STI.getPushPopSplitVariation(MF);
1439 if (NumBytes + IncomingArgStackToRestore != 0)
1441 NumBytes + IncomingArgStackToRestore,
1448 }
while (
MBBI !=
MBB.begin() &&
1485 "No scratch register to restore SP from FP!");
1507 }
else if (NumBytes &&
1523 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1528 "unexpected DPR alignment gap");
1540 if (ReservedArgStack || IncomingArgStackToRestore) {
1541 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1542 "attempting to restore negative stack amount");
1544 ReservedArgStack + IncomingArgStackToRestore,
1554 STI.isThumb() &&
STI.hasV8_1MMainlineOps() &&
STI.hasPACBTI();
1555 auto TMBBI =
MBB.getFirstTerminator();
1557 TMBBI !=
MBB.end() && TMBBI->getOpcode() == ARM::tBX_RET;
1558 if (IsBXReturn && CanUseBXAut)
1559 TMBBI->setDesc(
STI.getInstrInfo()->get(ARM::t2BXAUT_RET));
1610 if (RegInfo->hasStackRealignment(MF)) {
1611 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1613 FrameReg = RegInfo->getFrameRegister(MF);
1615 }
else if (hasMovingSP) {
1616 assert(RegInfo->hasBasePointer(MF) &&
1617 "VLAs and dynamic stack alignment, but missing base pointer!");
1618 FrameReg = RegInfo->getBaseRegister();
1628 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1629 FrameReg = RegInfo->getFrameRegister(MF);
1631 }
else if (hasMovingSP) {
1632 assert(RegInfo->hasBasePointer(MF) &&
"missing base pointer!");
1637 if (FPOffset >= -255 && FPOffset < 0) {
1638 FrameReg = RegInfo->getFrameRegister(MF);
1653 FrameReg = RegInfo->getFrameRegister(MF);
1656 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1658 FrameReg = RegInfo->getFrameRegister(MF);
1665 if (RegInfo->hasBasePointer(MF)) {
1666 FrameReg = RegInfo->getBaseRegister();
1675 unsigned StmOpc,
unsigned StrOpc,
1684 using RegAndKill = std::pair<unsigned, bool>;
1687 unsigned i = CSI.
size();
1689 unsigned LastReg = 0;
1690 for (; i != 0; --i) {
1702 if (NoGap && LastReg && LastReg != Reg-1)
1710 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1717 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1720 if (Regs.
size() > 1 || StrOpc== 0) {
1725 for (
const auto &[
Reg,
Kill] : Regs)
1727 }
else if (Regs.size() == 1) {
1748 unsigned LdmOpc,
unsigned LdrOpc,
1749 bool isVarArg,
bool NoGap,
1753 const TargetRegisterInfo &
TRI = *
STI.getRegisterInfo();
1754 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
1757 bool isTailCall =
false;
1758 bool isInterrupt =
false;
1759 bool isTrap =
false;
1760 bool isCmseEntry =
false;
1762 STI.getPushPopSplitVariation(MF);
1764 DL =
MI->getDebugLoc();
1765 unsigned RetOpcode =
MI->getOpcode();
1767 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1768 RetOpcode == ARM::TCRETURNrinotr12);
1770 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1771 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1772 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1775 SmallVector<unsigned, 4> Regs;
1776 unsigned i = CSI.
size();
1778 unsigned LastReg = 0;
1779 bool DeleteRet =
false;
1780 for (; i != 0; --i) {
1781 CalleeSavedInfo &
Info = CSI[i-1];
1782 MCRegister
Reg =
Info.getReg();
1786 if (
Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1800 if (NoGap && LastReg && LastReg !=
Reg-1)
1811 return TRI.getEncodingValue(
LHS) <
TRI.getEncodingValue(
RHS);
1814 if (Regs.
size() > 1 || LdrOpc == 0) {
1819 for (
unsigned Reg : Regs)
1828 }
else if (Regs.size() == 1) {
1831 if (Regs[0] == ARM::PC)
1833 MachineInstrBuilder MIB =
1840 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1859 unsigned PushOpc)
const {
1864 auto RegPresent = [&CSI](MCRegister
Reg) {
1866 return C.getReg() ==
Reg;
1872 if (RegPresent(ARM::FPSCR)) {
1882 if (RegPresent(ARM::FPEXC)) {
1891 if (Regs.
size() == 0)
1895 MachineInstrBuilder MIB =
1906void ARMFrameLowering::emitFPStatusRestores(
1912 auto RegPresent = [&CSI](MCRegister
Reg) {
1914 return C.getReg() ==
Reg;
1919 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1923 MachineInstrBuilder MIB =
1930 if (RegPresent(ARM::FPSCR)) {
1935 if (RegPresent(ARM::FPEXC)) {
1940 if (RegPresent(ARM::FPSCR)) {
1949 if (RegPresent(ARM::FPEXC)) {
1962 unsigned NumAlignedDPRCS2Regs,
1975 unsigned DNum =
I.getReg() - ARM::D8;
1976 if (DNum > NumAlignedDPRCS2Regs - 1)
1978 int FI =
I.getFrameIdx();
2006 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
2009 .
addImm(8 * NumAlignedDPRCS2Regs)
2034 unsigned NextReg = ARM::D8;
2038 if (NumAlignedDPRCS2Regs >= 6) {
2040 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2041 MBB.addLiveIn(SupReg);
2049 NumAlignedDPRCS2Regs -= 4;
2054 unsigned R4BaseReg = NextReg;
2057 if (NumAlignedDPRCS2Regs >= 4) {
2059 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2060 MBB.addLiveIn(SupReg);
2068 NumAlignedDPRCS2Regs -= 4;
2072 if (NumAlignedDPRCS2Regs >= 2) {
2074 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2075 MBB.addLiveIn(SupReg);
2082 NumAlignedDPRCS2Regs -= 2;
2086 if (NumAlignedDPRCS2Regs) {
2087 MBB.addLiveIn(NextReg);
2092 .
addImm((NextReg - R4BaseReg) * 2)
2097 std::prev(
MI)->addRegisterKilled(ARM::R4,
TRI);
2104 unsigned NumAlignedDPRCS2Regs) {
2109 assert(
MI->mayStore() &&
"Expecting spill instruction");
2112 switch(NumAlignedDPRCS2Regs) {
2115 assert(
MI->mayStore() &&
"Expecting spill instruction");
2119 assert(
MI->mayStore() &&
"Expecting spill instruction");
2124 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2135 unsigned NumAlignedDPRCS2Regs,
2146 if (
I.getReg() == ARM::D8) {
2147 D8SpillFI =
I.getFrameIdx();
2159 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2167 unsigned NextReg = ARM::D8;
2170 if (NumAlignedDPRCS2Regs >= 6) {
2172 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2180 NumAlignedDPRCS2Regs -= 4;
2185 unsigned R4BaseReg = NextReg;
2188 if (NumAlignedDPRCS2Regs >= 4) {
2190 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2197 NumAlignedDPRCS2Regs -= 4;
2201 if (NumAlignedDPRCS2Regs >= 2) {
2203 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2209 NumAlignedDPRCS2Regs -= 2;
2213 if (NumAlignedDPRCS2Regs)
2216 .
addImm(2 * (NextReg - R4BaseReg))
2232 STI.getPushPopSplitVariation(MF);
2235 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2237 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2238 unsigned FltOpc = ARM::VSTMDDB_UPD;
2247 return C.getReg() == ARM::FPCXTNS;
2256 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2257 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2258 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2261 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2264 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2267 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2270 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2274 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2275 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2276 emitFPStatusSaves(
MBB,
MI, CSI, PushOpc);
2277 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2278 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2283 if (NumAlignedDPRCS2Regs)
2302 STI.getPushPopSplitVariation(MF);
2306 if (NumAlignedDPRCS2Regs)
2309 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2312 unsigned FltOpc = ARM::VLDMDIA_UPD;
2314 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2315 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2316 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2319 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2322 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2325 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2328 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2332 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2333 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2334 emitFPStatusRestores(
MBB,
MI, CSI, PopOpc);
2335 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2336 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2347 bool BigFrameOffsets) {
2348 unsigned FnSize = 0;
2361 unsigned SavedHighRegs = 0;
2362 for (
auto Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11, ARM::R12})
2375 unsigned PrologueSize = 2 + 4 * SavedHighRegs + 6 + 12 + 2;
2376 if (
RegInfo->hasStackRealignment(MF))
2378 FnSize += PrologueSize;
2387 unsigned EpilogueSize = 6 + 2 + 4 * SavedHighRegs + 4 + 2 + 2;
2389 bool FirstBlock =
true;
2390 for (
auto &
MBB : MF) {
2394 unsigned Alignment =
MBB.getMaxBytesForAlignment();
2395 FnSize += Alignment;
2398 unsigned SizeBeforeThisBB = FnSize;
2400 bool seenBranch =
false, seenConstantLoad =
false;
2401 for (
auto &
MI :
MBB) {
2403 switch (
MI.getOpcode()) {
2404 case ARM::tADDframe:
2405 if (BigFrameOffsets)
2416 if (BigFrameOffsets)
2426 case TargetOpcode::COPY:
2437 case ARM::Int_eh_sjlj_dispatchsetup:
2442 case ARM::tLDRpci_pic:
2446 case ARM::ADJCALLSTACKDOWN:
2447 case ARM::ADJCALLSTACKUP:
2451 case ARM::tBLXNS_CALL:
2456 InstSize = 2 + 2 * 4 + 2;
2471 InstSize += 2 + 2 * 4 + 2;
2474 case ARM::tBXNS_RET:
2478 InstSize = 5 * 2 + 4 + 2;
2481 case TargetOpcode::LOAD_STACK_GUARD:
2482 if (STI.genExecuteOnly())
2488 InstSize = 7 * 2 + 2 * 4 + 8;
2493 InstSize = 2 * 2 + 4;
2497 InstSize =
TII.getInstSizeInBytes(
MI);
2508 MO->getPointerInfo().V);
2510 unsigned ConstSize = MO->getType().getSizeInBytes();
2511 FnSize += ConstSize;
2512 seenConstantLoad =
true;
2519 if (
MI.isReturn() ||
TII.isTailCall(
MI)) {
2520 FnSize += EpilogueSize;
2525 if (KCFI &&
MI.isCall() &&
MI.getCFIType()) {
2527 FnSize +=
MCID.getSize();
2530 if (
MI.isUnconditionalBranch())
2537 if (seenConstantLoad && !seenBranch) {
2548 unsigned BBSize = FnSize - SizeBeforeThisBB;
2549 FnSize += 4 * BBSize / 512;
2553 unsigned TableLen =
Table.MBBs.size();
2554 unsigned TableSizeBytes = TableLen * 4;
2555 FnSize += TableSizeBytes;
2559 << FnSize <<
" bytes\n");
2569 bool &HasNonSPFrameIndex) {
2573 unsigned Limit = (1 << 12) - 1;
2574 for (
auto &
MBB : MF) {
2575 for (
auto &
MI :
MBB) {
2576 if (
MI.isDebugInstr())
2578 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
2580 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2581 if (!
MI.getOperand(i).isFI())
2586 if (
MI.getOpcode() == ARM::ADDri) {
2587 Limit = std::min(Limit, (1U << 8) - 1);
2592 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2597 if (RegClass && !RegClass->
contains(ARM::SP))
2598 HasNonSPFrameIndex =
true;
2608 Limit = std::min(Limit, (1U << 8) - 1);
2611 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2616 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2622 Limit = std::min(Limit, (1U << 8) - 1);
2630 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2633 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2636 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2639 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2680 unsigned NumSpills = 0;
2681 for (; NumSpills < 8; ++NumSpills)
2682 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2693 SavedRegs.
set(ARM::R4);
2699 if (
STI.hasV8_1MMainlineOps() &&
2716 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2729 for (
const auto &
MBB : MF)
2730 for (
const auto &
MI :
MBB)
2731 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2732 STI.genExecuteOnly())
2733 for (
const auto &
Op :
MI.operands())
2753 bool CS1Spilled =
false;
2754 bool LRSpilled =
false;
2755 unsigned NumGPRSpills = 0;
2756 unsigned NumFPRSpills = 0;
2771 STI.getPushPopSplitVariation(MF);
2775 if (
F.hasFnAttribute(
"interrupt") &&
F.hasFnAttribute(
"save-fp")) {
2776 SavedRegs.
set(ARM::FPSCR);
2777 SavedRegs.
set(ARM::R4);
2780 if (
STI.isMClass()) {
2781 SavedRegs.
reset(ARM::FPEXC);
2783 SavedRegs.
set(ARM::FPEXC);
2784 SavedRegs.
set(ARM::R5);
2794 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2795 SavedRegs.
set(ARM::R4);
2802 if (
STI.isTargetWindows() &&
2804 SavedRegs.
set(ARM::R4);
2805 SavedRegs.
set(ARM::LR);
2811 SavedRegs.
set(ARM::LR);
2819 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2820 MFI.estimateStackSize(MF) > 508)
2821 SavedRegs.
set(ARM::R4);
2828 if (RegInfo->hasBasePointer(MF))
2829 SavedRegs.
set(RegInfo->getBaseRegister());
2833 CanEliminateFrame =
false;
2837 CanEliminateFrame =
false;
2841 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2842 for (
unsigned i = 0; CSRegs[i]; ++i) {
2843 unsigned Reg = CSRegs[i];
2844 bool Spilled =
false;
2845 if (SavedRegs.
test(Reg)) {
2847 CanEliminateFrame =
false;
2850 if (!ARM::GPRRegClass.
contains(Reg)) {
2852 if (ARM::SPRRegClass.
contains(Reg))
2854 else if (ARM::DPRRegClass.
contains(Reg))
2856 else if (ARM::QPRRegClass.
contains(Reg))
2877 case ARM::R0:
case ARM::R1:
2878 case ARM::R2:
case ARM::R3:
2879 case ARM::R4:
case ARM::R5:
2880 case ARM::R6:
case ARM::R7:
2893 case ARM::R0:
case ARM::R1:
2894 case ARM::R2:
case ARM::R3:
2895 case ARM::R4:
case ARM::R5:
2896 case ARM::R6:
case ARM::R7:
2907 bool ForceLRSpill =
false;
2923 unsigned EstimatedStackSize =
2924 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2927 int MaxFixedOffset = 0;
2928 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2929 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2930 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2933 bool HasFP =
hasFP(MF);
2936 EstimatedStackSize += 4;
2940 EstimatedStackSize += MaxFixedOffset;
2942 EstimatedStackSize += 16;
2944 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2945 bool HasNonSPFrameIndex =
false;
2965 if (RegInfo->hasBasePointer(MF))
2966 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2968 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2969 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2971 EstimatedRSStackSizeLimit =
2973 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2977 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2983 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2985 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
2994 bool HasLargeArgumentList =
2995 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2997 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2998 HasLargeArgumentList || HasNonSPFrameIndex;
2999 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
3000 <<
"; EstimatedStack: " << EstimatedStackSize
3001 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
3002 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
3006 SavedRegs, BigFrameOffsets);
3008 if (FnSize >= (1 << 11)) {
3011 CanEliminateFrame =
false;
3012 ForceLRSpill =
true;
3016 if (BigFrameOffsets ||
3017 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
3030 SavedRegs.
set(ARM::LR);
3033 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
3034 if (LRPos != UnspilledCS1GPRs.
end())
3035 UnspilledCS1GPRs.
erase(LRPos);
3038 if (FPPos != UnspilledCS1GPRs.
end())
3039 UnspilledCS1GPRs.
erase(FPPos);
3057 unsigned NumExtraCSSpill = 0;
3074 int EntryRegDeficit = 0;
3075 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
3080 <<
" is unused argument register, EntryRegDeficit = "
3081 << EntryRegDeficit <<
"\n");
3088 <<
" return regs used, ExitRegDeficit = "
3089 << ExitRegDeficit <<
"\n");
3091 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
3096 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
3097 if (SavedRegs.
test(Reg)) {
3100 <<
" is saved low register, RegDeficit = "
3101 << RegDeficit <<
"\n");
3107 <<
" is non-saved low register, adding to AvailableRegs\n");
3112 if (!HasFP ||
FramePtr != ARM::R7) {
3113 if (SavedRegs.
test(ARM::R7)) {
3116 << RegDeficit <<
"\n");
3121 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
3126 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
3127 if (SavedRegs.
test(Reg)) {
3130 <<
" is saved high register, RegDeficit = "
3131 << RegDeficit <<
"\n");
3138 if ((EntryRegDeficit > ExitRegDeficit) &&
3141 if (SavedRegs.
test(ARM::LR)) {
3144 << RegDeficit <<
"\n");
3147 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
3156 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
3157 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
3160 <<
" to make up reg deficit\n");
3171 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
3181 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
3182 SavedRegs.
set(ARM::LR);
3185 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
3186 if (LRPos != UnspilledCS1GPRs.
end())
3187 UnspilledCS1GPRs.
erase(LRPos);
3189 ForceLRSpill =
false;
3200 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
3201 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
3202 for (
unsigned Reg : UnspilledCS1GPRs) {
3206 (
STI.isTargetWindows() && Reg == ARM::R11) ||
3208 (Reg == ARM::LR && !ExpensiveLRRestore)) {
3211 <<
" to make up alignment\n");
3219 unsigned Reg = UnspilledCS2GPRs.
front();
3222 <<
" to make up alignment\n");
3234 unsigned RegsNeeded = 0;
3243 if (RegsNeeded > NumExtraCSSpill) {
3246 unsigned NumExtras = TargetAlign.
value() / 4;
3248 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
3258 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
3266 if (NumExtras == 0) {
3267 for (
unsigned Reg : Extras) {
3273 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3277 unsigned Size =
TRI->getSpillSize(RC);
3278 Align Alignment =
TRI->getSpillAlign(RC);
3279 RS->addScavengingFrameIndex(
3280 MFI.CreateSpillStackObject(
Size, Alignment));
3287 SavedRegs.
set(ARM::LR);
3300 if (Info.getReg() != ARM::LR)
3304 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3305 Term.getOpcode() == ARM::t2LDMIA_RET ||
3306 Term.getOpcode() == ARM::tPOP_RET;
3309 Info.setRestored(
false);
3330 SavedRegs.
set(ARM::R0);
3335 std::vector<CalleeSavedInfo> &CSI)
const {
3338 if (
STI.hasV8_1MMainlineOps() &&
3340 CSI.emplace_back(ARM::FPCXTNS);
3341 CSI.back().setRestored(
false);
3353 switch (
STI.getPushPopSplitVariation(MF)) {
3357 [=](
const auto &CS) {
3359 return Reg == ARM::R10 || Reg == ARM::R11 ||
3360 Reg == ARM::R8 || Reg == ARM::R9 ||
3361 ARM::DPRRegClass.contains(Reg);
3372 "ABI-required frame pointers need a CSR split when signing return "
3375 [=](
const auto &CS) {
3377 return Reg != ARM::LR;
3391 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3392 NumEntries = std::size(FixedSpillOffsets);
3393 return FixedSpillOffsets;
3404 unsigned Opc =
I->getOpcode();
3405 bool IsDestroy =
Opc ==
TII.getCallFrameDestroyOpcode();
3406 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3409 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3411 int PIdx =
I->findFirstPredOperandIdx();
3415 unsigned PredReg =
TII.getFramePred(*
I);
3419 if (IsDestroy && CalleePopAmount != -1U)
3420 return MBB.erase(
I);
3425 unsigned Amount =
TII.getFrameSize(*
I);
3432 if (
Opc == ARM::ADJCALLSTACKDOWN ||
Opc == ARM::tADJCALLSTACKDOWN) {
3436 assert(
Opc == ARM::ADJCALLSTACKUP ||
Opc == ARM::tADJCALLSTACKUP);
3441 }
else if (CalleePopAmount != -1U) {
3455 unsigned Shifted = 0;
3460 while (!(
Value & 0xC0000000)) {
3465 bool Carry = (
Value & 0x00FFFFFF);
3466 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3468 if (
Value & 0x0000100)
3511 bool Thumb = ST->isThumb();
3512 bool Thumb2 = ST->isThumb2();
3518 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3534 unsigned ScratchReg0 = ARM::R4;
3535 unsigned ScratchReg1 = ARM::R5;
3536 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3537 uint64_t AlignedStackSize;
3553 if (BeforePrologueRegion.
insert(PredBB).second)
3556 }
while (!WalkList.
empty());
3567 for (
const auto &LI : PrologueMBB.
liveins()) {
3569 PredBB->addLiveIn(LI);
3575 BeforePrologueRegion.
erase(
B);
3581 MBB->sortUniqueLiveIns();
3584 if (
MBB->isSuccessor(&PrologueMBB))
3585 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3630 }
else if (CompareStackPointer) {
3638 if (!CompareStackPointer && Thumb) {
3639 if (AlignedStackSize < 256) {
3643 .
addImm(AlignedStackSize)
3646 if (Thumb2 || ST->genExecuteOnly()) {
3648 .
addImm(AlignedStackSize);
3651 auto RegInfo =
STI.getRegisterInfo();
3652 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3661 }
else if (!CompareStackPointer) {
3662 if (AlignedStackSize < 256) {
3665 .
addImm(AlignedStackSize)
3670 auto RegInfo =
STI.getRegisterInfo();
3671 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3681 if (Thumb && ST->isThumb1Only()) {
3682 if (ST->genExecuteOnly()) {
3693 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3706 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3716 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3717 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3721 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3730 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3737 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3750 if (AlignedStackSize < 256) {
3751 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3753 .
addImm(AlignedStackSize)
3756 if (Thumb2 || ST->genExecuteOnly()) {
3758 .
addImm(AlignedStackSize);
3761 auto RegInfo =
STI.getRegisterInfo();
3762 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3767 if (AlignedStackSize < 256) {
3769 .
addImm(AlignedStackSize)
3774 auto RegInfo =
STI.getRegisterInfo();
3775 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3784 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3789 if (Thumb2 || ST->genExecuteOnly()) {
3794 auto RegInfo =
STI.getRegisterInfo();
3795 RegInfo->emitLoadConstPool(
3796 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3808 auto RegInfo =
STI.getRegisterInfo();
3809 RegInfo->emitLoadConstPool(
3810 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3848 if (ST->isThumb1Only()) {
3935#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...
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
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...
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 alignment of this function's frame.
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.
bool framePointerIsReserved() const
Returns true if the frame pointer must always either point to a new frame record or be un-modified in...
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.
bool needsWinCFI() const
True if this function uses SEH unwind opcodes and needs an unwind table entry.
Function & getFunction()
Return the LLVM function that this machine code represents.
bool usesWindowsUnwindInfo() const
True if this function describes its unwind information with Windows SEH unwind opcodes (....
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
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.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
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).
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.
@ End
Run the machine verifier once, at the end of the pipeline.
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.