160#define DEBUG_TYPE "arm-frame-lowering"
166 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
170 unsigned NumAlignedDPRCS2Regs);
185 unsigned NumAlignedDPRCS2Regs,
284 if (
Reg >= ARM::D8 &&
Reg < ARM::D8 + NumAlignedDPRCS2Regs)
370 if (CFSize >= ((1 << 12) - 1) / 2)
393 bool IsTailCallReturn =
false;
395 unsigned RetOpcode =
MBBI->getOpcode();
396 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
397 RetOpcode == ARM::TCRETURNri ||
398 RetOpcode == ARM::TCRETURNrinotr12;
402 int ArgumentPopSize = 0;
403 if (IsTailCallReturn) {
409 ArgumentPopSize = StackAdjust.
getImm();
418 return ArgumentPopSize;
424 F.needsUnwindTableEntry();
432 unsigned Opc =
MBBI->getOpcode();
458 case ARM::t2MOVi16: {
459 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
463 NewInstr.
add(
MBBI->getOperand(0));
481 case ARM::t2MOVi32imm:
499 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
500 MBBI->getOperand(2).getReg() == ARM::SP &&
501 MBBI->getOperand(3).getImm() == -4) {
502 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
512 case ARM::t2LDR_POST:
513 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
514 MBBI->getOperand(2).getReg() == ARM::SP &&
515 MBBI->getOperand(3).getImm() == 4) {
516 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
526 case ARM::t2LDMIA_RET:
527 case ARM::t2LDMIA_UPD:
528 case ARM::t2STMDB_UPD: {
538 if (
Reg >= 8 &&
Reg <= 13)
540 else if (
Opc == ARM::t2LDMIA_UPD &&
Reg == 14)
547 case ARM::t2LDMIA_RET:
548 NewOpc = ARM::tPOP_RET;
550 case ARM::t2LDMIA_UPD:
553 case ARM::t2STMDB_UPD:
562 NewInstr.
add(
MBBI->getOperand(i));
568 (
Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
575 case ARM::VSTMDDB_UPD:
576 case ARM::VLDMDIA_UPD: {
579 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
597 case ARM::t2SUBspImm:
598 case ARM::t2SUBspImm12:
599 case ARM::t2ADDspImm:
600 case ARM::t2ADDspImm12:
608 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
610 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
614 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
616 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
626 case ARM::t2BXAUT_RET:
627 case ARM::CLEANUPRET:
629 case ARM::TCRETURNri:
630 case ARM::TCRETURNrinotr12:
636 case ARM::TCRETURNdi:
642 return MBB->insertAfter(
MBBI, MIB);
649 return std::prev(
MBBI);
657 Start = std::next(Start);
661 for (
auto MI = Start;
MI != End;) {
662 auto Next = std::next(
MI);
683 Pred, PredReg,
TII, MIFlags);
686 Pred, PredReg,
TII, MIFlags);
694 unsigned PredReg = 0) {
696 MIFlags, Pred, PredReg);
701 switch (
MI.getOpcode()) {
702 case ARM::VSTMDDB_UPD:
706 case ARM::t2STMDB_UPD:
710 case ARM::STR_PRE_IMM:
719 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
725 size_t StackSizeInBytes) {
731 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
732 return (StackSizeInBytes >= StackProbeSize) &&
733 !
F.hasFnAttribute(
"no-stack-arg-probe");
738struct StackAdjustingInsts {
744#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
746 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
747 <<
"sp-adjust=" << SPAdjust;
756 bool BeforeFPSet =
false) {
757 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
764 assert(Info != Insts.
end() &&
"invalid sp adjusting instruction");
765 Info->SPAdjust += ExtraBytes;
768 void emitDefCFAOffsets(MachineBasicBlock &
MBB,
bool HasFP) {
770 unsigned CFAOffset = 0;
771 for (
auto &Info : Insts) {
772 if (HasFP && !
Info.BeforeFPSet)
775 CFAOffset +=
Info.SPAdjust;
776 CFIBuilder.setInsertPoint(std::next(
Info.I));
777 CFIBuilder.buildDefCFAOffset(CFAOffset);
781#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
783 dbgs() <<
"StackAdjustingInsts:\n";
784 for (
auto &Info : Insts)
804 const Align Alignment,
805 const bool MustBeSingleInstruction) {
807 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
808 const unsigned AlignMask = Alignment.
value() - 1U;
809 const unsigned NrBitsToZero =
Log2(Alignment);
826 }
else if (AlignMask <= 255) {
833 assert(!MustBeSingleInstruction &&
834 "Shouldn't call emitAligningInstructions demanding a single "
835 "instruction to be emitted for large stack alignment for a target "
875 int MaxRegBytes = 8 * 4;
878 MaxRegBytes = 11 * 4;
881 MaxRegBytes = 11 * 4 + 8 * 8;
897 "This emitPrologue does not support Thumb1!");
899 Align Alignment =
STI.getFrameLowering()->getStackAlign();
903 int FPCXTSaveSize = 0;
906 STI.getPushPopSplitVariation(MF);
918 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
919 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
920 int FramePtrSpillFI = 0;
928 StackAdjustingInsts DefCFAOffsetCandidates;
929 bool HasFP =
hasFP(MF);
936 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
939 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
940 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
951 bool BeforeFPPush =
true;
954 int FI =
I.getFrameIdx();
960 FramePtrSpillFI = FI;
961 FramePtrSpillArea = Area;
992 DPRCS1Push, GPRCS3Push;
999 if (FPCXTSaveSize > 0) {
1001 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
1005 if (ArgRegsSaveSize) {
1008 LastPush = std::prev(
MBBI);
1009 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1013 if (GPRCS1Size > 0) {
1014 GPRCS1Push = LastPush =
MBBI++;
1015 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1017 BeforeFPPush =
false;
1024 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1025 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1026 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1027 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1029 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1030 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1031 GPRCS2Size + FPStatusSize) %
1034 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1040 <<
", FPOffset: " << FPOffset <<
"\n");
1042 "Max FP estimation is wrong");
1051 if (GPRCS2Size > 0) {
1053 GPRCS2Push = LastPush =
MBBI++;
1054 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1056 BeforeFPPush =
false;
1060 if (FPStatusSize > 0) {
1062 unsigned Opc =
MBBI->getOpcode();
1063 if (
Opc == ARM::VMRS ||
Opc == ARM::VMRS_FPEXC)
1069 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1075 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1076 if (LastPush !=
MBB.end() &&
1078 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1082 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1087 if (DPRCS1Size > 0) {
1090 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1093 DPRCS1Push = LastPush =
MBBI++;
1098 if (DPRCS2Size > 0) {
1106 NumBytes = DPRCS1Offset;
1109 if (GPRCS3Size > 0) {
1111 GPRCS3Push = LastPush =
MBBI++;
1112 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1114 BeforeFPPush =
false;
1115 NumBytes -= GPRCS3Size;
1118 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1120 NeedsWinCFIStackAlloc =
false;
1125 if (NumWords < 65536) {
1135 .
addImm(NumWords & 0xffff)
1146 RTLIB::LibcallImpl ChkStkLibcall = TLI->
getLibcallImpl(RTLIB::STACK_PROBE);
1147 if (ChkStkLibcall == RTLIB::Unsupported)
1151 switch (TM.getCodeModel()) {
1183 if (NeedsWinCFIStackAlloc) {
1184 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1188 MBB.insertAfter(Instr, SEH);
1197 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1201 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1227 int64_t FPOffsetAfterPush;
1228 switch (FramePtrSpillArea) {
1230 FPPushInst = GPRCS1Push;
1232 ArgRegsSaveSize + FPCXTSaveSize +
1235 << FPOffsetAfterPush <<
" after that push\n");
1238 FPPushInst = GPRCS2Push;
1240 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1243 << FPOffsetAfterPush <<
" after that push\n");
1246 FPPushInst = GPRCS3Push;
1248 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1249 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1252 << FPOffsetAfterPush <<
" after that push\n");
1258 AfterPush = std::next(FPPushInst);
1260 assert(FPOffsetAfterPush == 0);
1264 FramePtr, ARM::SP, FPOffsetAfterPush,
1271 if (FPOffsetAfterPush != 0)
1280 if (NeedsWinCFI &&
MBBI !=
MBB.begin()) {
1294 for (
const auto &Entry :
reverse(CSI)) {
1296 int FI = Entry.getFrameIdx();
1301 CFIPos = std::next(GPRCS1Push);
1304 CFIPos = std::next(GPRCS2Push);
1307 CFIPos = std::next(DPRCS1Push);
1310 CFIPos = std::next(GPRCS3Push);
1321 .
buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1333 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, HasFP);
1336 if (
STI.isTargetELF() &&
hasFP(MF))
1384 if (RegInfo->hasBasePointer(MF) && !
MBB.isEHFuncletEntry()) {
1411 "This emitEpilogue does not support Thumb1!");
1414 STI.getPushPopSplitVariation(MF);
1445 if (NumBytes + IncomingArgStackToRestore != 0)
1447 NumBytes + IncomingArgStackToRestore,
1454 }
while (
MBBI !=
MBB.begin() &&
1491 "No scratch register to restore SP from FP!");
1513 }
else if (NumBytes &&
1529 while (
MBBI !=
MBB.end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1534 "unexpected DPR alignment gap");
1546 if (ReservedArgStack || IncomingArgStackToRestore) {
1547 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1548 "attempting to restore negative stack amount");
1550 ReservedArgStack + IncomingArgStackToRestore,
1560 STI.isThumb() &&
STI.hasV8_1MMainlineOps() &&
STI.hasPACBTI();
1561 auto TMBBI =
MBB.getFirstTerminator();
1563 TMBBI !=
MBB.end() && TMBBI->getOpcode() == ARM::tBX_RET;
1564 if (IsBXReturn && CanUseBXAut)
1565 TMBBI->setDesc(
STI.getInstrInfo()->get(ARM::t2BXAUT_RET));
1616 if (RegInfo->hasStackRealignment(MF)) {
1617 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1619 FrameReg = RegInfo->getFrameRegister(MF);
1621 }
else if (hasMovingSP) {
1622 assert(RegInfo->hasBasePointer(MF) &&
1623 "VLAs and dynamic stack alignment, but missing base pointer!");
1624 FrameReg = RegInfo->getBaseRegister();
1634 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1635 FrameReg = RegInfo->getFrameRegister(MF);
1637 }
else if (hasMovingSP) {
1638 assert(RegInfo->hasBasePointer(MF) &&
"missing base pointer!");
1643 if (FPOffset >= -255 && FPOffset < 0) {
1644 FrameReg = RegInfo->getFrameRegister(MF);
1659 FrameReg = RegInfo->getFrameRegister(MF);
1662 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1664 FrameReg = RegInfo->getFrameRegister(MF);
1671 if (RegInfo->hasBasePointer(MF)) {
1672 FrameReg = RegInfo->getBaseRegister();
1681 unsigned StmOpc,
unsigned StrOpc,
1690 using RegAndKill = std::pair<unsigned, bool>;
1693 unsigned i = CSI.
size();
1695 unsigned LastReg = 0;
1696 for (; i != 0; --i) {
1708 if (NoGap && LastReg && LastReg != Reg-1)
1716 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1723 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1726 if (Regs.
size() > 1 || StrOpc== 0) {
1731 for (
const auto &[
Reg,
Kill] : Regs)
1733 }
else if (Regs.size() == 1) {
1754 unsigned LdmOpc,
unsigned LdrOpc,
1755 bool isVarArg,
bool NoGap,
1759 const TargetRegisterInfo &
TRI = *
STI.getRegisterInfo();
1760 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
1763 bool isTailCall =
false;
1764 bool isInterrupt =
false;
1765 bool isTrap =
false;
1766 bool isCmseEntry =
false;
1768 STI.getPushPopSplitVariation(MF);
1770 DL =
MI->getDebugLoc();
1771 unsigned RetOpcode =
MI->getOpcode();
1773 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1774 RetOpcode == ARM::TCRETURNrinotr12);
1776 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1777 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1778 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1781 SmallVector<unsigned, 4> Regs;
1782 unsigned i = CSI.
size();
1784 unsigned LastReg = 0;
1785 bool DeleteRet =
false;
1786 for (; i != 0; --i) {
1787 CalleeSavedInfo &
Info = CSI[i-1];
1788 MCRegister
Reg =
Info.getReg();
1792 if (
Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1806 if (NoGap && LastReg && LastReg !=
Reg-1)
1817 return TRI.getEncodingValue(
LHS) <
TRI.getEncodingValue(
RHS);
1820 if (Regs.
size() > 1 || LdrOpc == 0) {
1825 for (
unsigned Reg : Regs)
1830 MI->eraseFromParent();
1834 }
else if (Regs.size() == 1) {
1837 if (Regs[0] == ARM::PC)
1839 MachineInstrBuilder MIB =
1846 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1865 unsigned PushOpc)
const {
1870 auto RegPresent = [&CSI](MCRegister
Reg) {
1872 return C.getReg() ==
Reg;
1878 if (RegPresent(ARM::FPSCR)) {
1888 if (RegPresent(ARM::FPEXC)) {
1897 if (Regs.
size() == 0)
1901 MachineInstrBuilder MIB =
1912void ARMFrameLowering::emitFPStatusRestores(
1918 auto RegPresent = [&CSI](MCRegister
Reg) {
1920 return C.getReg() ==
Reg;
1925 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1929 MachineInstrBuilder MIB =
1936 if (RegPresent(ARM::FPSCR)) {
1941 if (RegPresent(ARM::FPEXC)) {
1946 if (RegPresent(ARM::FPSCR)) {
1955 if (RegPresent(ARM::FPEXC)) {
1968 unsigned NumAlignedDPRCS2Regs,
1981 unsigned DNum =
I.getReg() - ARM::D8;
1982 if (DNum > NumAlignedDPRCS2Regs - 1)
1984 int FI =
I.getFrameIdx();
2012 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
2015 .
addImm(8 * NumAlignedDPRCS2Regs)
2040 unsigned NextReg = ARM::D8;
2044 if (NumAlignedDPRCS2Regs >= 6) {
2046 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2047 MBB.addLiveIn(SupReg);
2055 NumAlignedDPRCS2Regs -= 4;
2060 unsigned R4BaseReg = NextReg;
2063 if (NumAlignedDPRCS2Regs >= 4) {
2065 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2066 MBB.addLiveIn(SupReg);
2074 NumAlignedDPRCS2Regs -= 4;
2078 if (NumAlignedDPRCS2Regs >= 2) {
2080 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2081 MBB.addLiveIn(SupReg);
2088 NumAlignedDPRCS2Regs -= 2;
2092 if (NumAlignedDPRCS2Regs) {
2093 MBB.addLiveIn(NextReg);
2098 .
addImm((NextReg - R4BaseReg) * 2)
2103 std::prev(
MI)->addRegisterKilled(ARM::R4,
TRI);
2110 unsigned NumAlignedDPRCS2Regs) {
2115 assert(
MI->mayStore() &&
"Expecting spill instruction");
2118 switch(NumAlignedDPRCS2Regs) {
2121 assert(
MI->mayStore() &&
"Expecting spill instruction");
2125 assert(
MI->mayStore() &&
"Expecting spill instruction");
2130 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2141 unsigned NumAlignedDPRCS2Regs,
2152 if (
I.getReg() == ARM::D8) {
2153 D8SpillFI =
I.getFrameIdx();
2165 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2173 unsigned NextReg = ARM::D8;
2176 if (NumAlignedDPRCS2Regs >= 6) {
2178 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2186 NumAlignedDPRCS2Regs -= 4;
2191 unsigned R4BaseReg = NextReg;
2194 if (NumAlignedDPRCS2Regs >= 4) {
2196 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2203 NumAlignedDPRCS2Regs -= 4;
2207 if (NumAlignedDPRCS2Regs >= 2) {
2209 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2215 NumAlignedDPRCS2Regs -= 2;
2219 if (NumAlignedDPRCS2Regs)
2222 .
addImm(2 * (NextReg - R4BaseReg))
2238 STI.getPushPopSplitVariation(MF);
2241 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2243 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2244 unsigned FltOpc = ARM::VSTMDDB_UPD;
2253 return C.getReg() == ARM::FPCXTNS;
2262 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2263 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2264 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2267 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2270 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2273 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2276 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2280 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2281 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2282 emitFPStatusSaves(
MBB,
MI, CSI, PushOpc);
2283 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2284 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2289 if (NumAlignedDPRCS2Regs)
2308 STI.getPushPopSplitVariation(MF);
2312 if (NumAlignedDPRCS2Regs)
2315 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2318 unsigned FltOpc = ARM::VLDMDIA_UPD;
2320 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2321 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2322 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2325 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2328 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2331 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2334 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2338 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2339 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2340 emitFPStatusRestores(
MBB,
MI, CSI, PopOpc);
2341 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2342 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2350 unsigned FnSize = 0;
2351 for (
auto &
MBB : MF) {
2352 for (
auto &
MI :
MBB)
2353 FnSize +=
TII.getInstSizeInBytes(
MI);
2357 FnSize += Table.MBBs.size() * 4;
2360 << FnSize <<
" bytes\n");
2370 bool &HasNonSPFrameIndex) {
2374 unsigned Limit = (1 << 12) - 1;
2375 for (
auto &
MBB : MF) {
2376 for (
auto &
MI :
MBB) {
2377 if (
MI.isDebugInstr())
2379 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
2381 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2382 if (!
MI.getOperand(i).isFI())
2387 if (
MI.getOpcode() == ARM::ADDri) {
2388 Limit = std::min(Limit, (1U << 8) - 1);
2393 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2398 if (RegClass && !RegClass->
contains(ARM::SP))
2399 HasNonSPFrameIndex =
true;
2409 Limit = std::min(Limit, (1U << 8) - 1);
2412 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2417 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2423 Limit = std::min(Limit, (1U << 8) - 1);
2431 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2434 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2437 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2440 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2481 unsigned NumSpills = 0;
2482 for (; NumSpills < 8; ++NumSpills)
2483 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2494 SavedRegs.
set(ARM::R4);
2500 if (
STI.hasV8_1MMainlineOps() &&
2517 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2530 for (
const auto &
MBB : MF)
2531 for (
const auto &
MI :
MBB)
2532 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2533 STI.genExecuteOnly())
2534 for (
const auto &
Op :
MI.operands())
2554 bool CS1Spilled =
false;
2555 bool LRSpilled =
false;
2556 unsigned NumGPRSpills = 0;
2557 unsigned NumFPRSpills = 0;
2572 STI.getPushPopSplitVariation(MF);
2576 if (
F.hasFnAttribute(
"interrupt") &&
F.hasFnAttribute(
"save-fp")) {
2577 SavedRegs.
set(ARM::FPSCR);
2578 SavedRegs.
set(ARM::R4);
2581 if (
STI.isMClass()) {
2582 SavedRegs.
reset(ARM::FPEXC);
2584 SavedRegs.
set(ARM::FPEXC);
2585 SavedRegs.
set(ARM::R5);
2595 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2596 SavedRegs.
set(ARM::R4);
2603 if (
STI.isTargetWindows() &&
2605 SavedRegs.
set(ARM::R4);
2606 SavedRegs.
set(ARM::LR);
2612 SavedRegs.
set(ARM::LR);
2620 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2621 MFI.estimateStackSize(MF) > 508)
2622 SavedRegs.
set(ARM::R4);
2629 if (RegInfo->hasBasePointer(MF))
2630 SavedRegs.
set(RegInfo->getBaseRegister());
2634 CanEliminateFrame =
false;
2638 CanEliminateFrame =
false;
2642 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2643 for (
unsigned i = 0; CSRegs[i]; ++i) {
2644 unsigned Reg = CSRegs[i];
2645 bool Spilled =
false;
2646 if (SavedRegs.
test(Reg)) {
2648 CanEliminateFrame =
false;
2651 if (!ARM::GPRRegClass.
contains(Reg)) {
2653 if (ARM::SPRRegClass.
contains(Reg))
2655 else if (ARM::DPRRegClass.
contains(Reg))
2657 else if (ARM::QPRRegClass.
contains(Reg))
2678 case ARM::R0:
case ARM::R1:
2679 case ARM::R2:
case ARM::R3:
2680 case ARM::R4:
case ARM::R5:
2681 case ARM::R6:
case ARM::R7:
2694 case ARM::R0:
case ARM::R1:
2695 case ARM::R2:
case ARM::R3:
2696 case ARM::R4:
case ARM::R5:
2697 case ARM::R6:
case ARM::R7:
2708 bool ForceLRSpill =
false;
2713 if (FnSize >= (1 << 11)) {
2714 CanEliminateFrame =
false;
2715 ForceLRSpill =
true;
2733 unsigned EstimatedStackSize =
2734 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2737 int MaxFixedOffset = 0;
2738 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2739 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2740 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2743 bool HasFP =
hasFP(MF);
2746 EstimatedStackSize += 4;
2750 EstimatedStackSize += MaxFixedOffset;
2752 EstimatedStackSize += 16;
2754 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2755 bool HasNonSPFrameIndex =
false;
2775 if (RegInfo->hasBasePointer(MF))
2776 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2778 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2779 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2781 EstimatedRSStackSizeLimit =
2783 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2787 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2793 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2795 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
2804 bool HasLargeArgumentList =
2805 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2807 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2808 HasLargeArgumentList || HasNonSPFrameIndex;
2809 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2810 <<
"; EstimatedStack: " << EstimatedStackSize
2811 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2812 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2813 if (BigFrameOffsets ||
2814 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
2828 SavedRegs.
set(ARM::LR);
2831 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2832 if (LRPos != UnspilledCS1GPRs.
end())
2833 UnspilledCS1GPRs.
erase(LRPos);
2836 if (FPPos != UnspilledCS1GPRs.
end())
2837 UnspilledCS1GPRs.
erase(FPPos);
2855 unsigned NumExtraCSSpill = 0;
2872 int EntryRegDeficit = 0;
2873 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2878 <<
" is unused argument register, EntryRegDeficit = "
2879 << EntryRegDeficit <<
"\n");
2886 <<
" return regs used, ExitRegDeficit = "
2887 << ExitRegDeficit <<
"\n");
2889 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2894 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2895 if (SavedRegs.
test(Reg)) {
2898 <<
" is saved low register, RegDeficit = "
2899 << RegDeficit <<
"\n");
2905 <<
" is non-saved low register, adding to AvailableRegs\n");
2910 if (!HasFP ||
FramePtr != ARM::R7) {
2911 if (SavedRegs.
test(ARM::R7)) {
2914 << RegDeficit <<
"\n");
2919 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2924 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2925 if (SavedRegs.
test(Reg)) {
2928 <<
" is saved high register, RegDeficit = "
2929 << RegDeficit <<
"\n");
2936 if ((EntryRegDeficit > ExitRegDeficit) &&
2939 if (SavedRegs.
test(ARM::LR)) {
2942 << RegDeficit <<
"\n");
2945 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2954 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2955 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2958 <<
" to make up reg deficit\n");
2969 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2979 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2980 SavedRegs.
set(ARM::LR);
2983 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2984 if (LRPos != UnspilledCS1GPRs.
end())
2985 UnspilledCS1GPRs.
erase(LRPos);
2987 ForceLRSpill =
false;
2998 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2999 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
3000 for (
unsigned Reg : UnspilledCS1GPRs) {
3004 (
STI.isTargetWindows() && Reg == ARM::R11) ||
3006 (Reg == ARM::LR && !ExpensiveLRRestore)) {
3009 <<
" to make up alignment\n");
3017 unsigned Reg = UnspilledCS2GPRs.
front();
3020 <<
" to make up alignment\n");
3032 unsigned RegsNeeded = 0;
3041 if (RegsNeeded > NumExtraCSSpill) {
3044 unsigned NumExtras = TargetAlign.
value() / 4;
3046 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
3056 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
3064 if (NumExtras == 0) {
3065 for (
unsigned Reg : Extras) {
3071 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3075 unsigned Size =
TRI->getSpillSize(RC);
3076 Align Alignment =
TRI->getSpillAlign(RC);
3077 RS->addScavengingFrameIndex(
3078 MFI.CreateSpillStackObject(
Size, Alignment));
3085 SavedRegs.
set(ARM::LR);
3098 if (Info.getReg() != ARM::LR)
3102 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3103 Term.getOpcode() == ARM::t2LDMIA_RET ||
3104 Term.getOpcode() == ARM::tPOP_RET;
3107 Info.setRestored(
false);
3128 SavedRegs.
set(ARM::R0);
3133 std::vector<CalleeSavedInfo> &CSI)
const {
3136 if (
STI.hasV8_1MMainlineOps() &&
3138 CSI.emplace_back(ARM::FPCXTNS);
3139 CSI.back().setRestored(
false);
3151 switch (
STI.getPushPopSplitVariation(MF)) {
3155 [=](
const auto &CS) {
3157 return Reg == ARM::R10 || Reg == ARM::R11 ||
3158 Reg == ARM::R8 || Reg == ARM::R9 ||
3159 ARM::DPRRegClass.contains(Reg);
3170 "ABI-required frame pointers need a CSR split when signing return "
3173 [=](
const auto &CS) {
3175 return Reg != ARM::LR;
3189 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3190 NumEntries = std::size(FixedSpillOffsets);
3191 return FixedSpillOffsets;
3202 unsigned Opc =
I->getOpcode();
3203 bool IsDestroy =
Opc ==
TII.getCallFrameDestroyOpcode();
3204 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3207 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3209 int PIdx =
I->findFirstPredOperandIdx();
3213 unsigned PredReg =
TII.getFramePred(*
I);
3217 if (IsDestroy && CalleePopAmount != -1U)
3218 return MBB.erase(
I);
3223 unsigned Amount =
TII.getFrameSize(*
I);
3230 if (
Opc == ARM::ADJCALLSTACKDOWN ||
Opc == ARM::tADJCALLSTACKDOWN) {
3234 assert(
Opc == ARM::ADJCALLSTACKUP ||
Opc == ARM::tADJCALLSTACKUP);
3239 }
else if (CalleePopAmount != -1U) {
3253 unsigned Shifted = 0;
3258 while (!(
Value & 0xC0000000)) {
3263 bool Carry = (
Value & 0x00FFFFFF);
3264 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3266 if (
Value & 0x0000100)
3309 bool Thumb = ST->isThumb();
3310 bool Thumb2 = ST->isThumb2();
3316 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3332 unsigned ScratchReg0 = ARM::R4;
3333 unsigned ScratchReg1 = ARM::R5;
3334 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3351 if (BeforePrologueRegion.
insert(PredBB).second)
3354 }
while (!WalkList.
empty());
3365 for (
const auto &LI : PrologueMBB.
liveins()) {
3367 PredBB->addLiveIn(LI);
3373 BeforePrologueRegion.
erase(
B);
3379 MBB->sortUniqueLiveIns();
3382 if (
MBB->isSuccessor(&PrologueMBB))
3383 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3428 }
else if (CompareStackPointer) {
3436 if (!CompareStackPointer && Thumb) {
3437 if (AlignedStackSize < 256) {
3441 .
addImm(AlignedStackSize)
3444 if (Thumb2 || ST->genExecuteOnly()) {
3446 .
addImm(AlignedStackSize);
3449 auto RegInfo =
STI.getRegisterInfo();
3450 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3459 }
else if (!CompareStackPointer) {
3460 if (AlignedStackSize < 256) {
3463 .
addImm(AlignedStackSize)
3468 auto RegInfo =
STI.getRegisterInfo();
3469 RegInfo->emitLoadConstPool(*McrMBB,
MBBI,
DL, ScratchReg0, 0,
3479 if (Thumb && ST->isThumb1Only()) {
3480 if (ST->genExecuteOnly()) {
3491 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3504 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3514 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3515 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3519 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3528 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3535 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3548 if (AlignedStackSize < 256) {
3549 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3551 .
addImm(AlignedStackSize)
3554 if (Thumb2 || ST->genExecuteOnly()) {
3556 .
addImm(AlignedStackSize);
3559 auto RegInfo =
STI.getRegisterInfo();
3560 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3565 if (AlignedStackSize < 256) {
3567 .
addImm(AlignedStackSize)
3572 auto RegInfo =
STI.getRegisterInfo();
3573 RegInfo->emitLoadConstPool(*AllocMBB,
MBBI,
DL, ScratchReg0, 0,
3582 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3587 if (Thumb2 || ST->genExecuteOnly()) {
3592 auto RegInfo =
STI.getRegisterInfo();
3593 RegInfo->emitLoadConstPool(
3594 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3606 auto RegInfo =
STI.getRegisterInfo();
3607 RegInfo->emitLoadConstPool(
3608 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3646 if (ST->isThumb1Only()) {
3733#ifdef EXPENSIVE_CHECKS
static unsigned estimateRSStackSizeLimit(MachineFunction &MF)
Look at each instruction that references stack frames and return the stack size limit beyond which so...
static bool needsWinCFI(const MachineFunction *MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isThumb(const MCSubtargetInfo &STI)
static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)
Skip past the code inserted by emitAlignedDPRCS2Spills, and return an iterator to the following instr...
static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const unsigned Reg, const Align Alignment, const bool MustBeSingleInstruction)
Emit an instruction sequence that will align the address in register Reg by zero-ing out the lower bi...
static uint32_t alignToARMConstant(uint32_t Value)
Get the minimum constant for ARM that is greater than or equal to the argument.
static void checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs)
static void insertSEHRange(MachineBasicBlock &MBB, MachineBasicBlock::iterator Start, const MachineBasicBlock::iterator &End, const ARMBaseInstrInfo &TII, unsigned MIFlags)
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
static int getArgumentStackToRestore(MachineFunction &MF, MachineBasicBlock &MBB)
static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)
static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, const TargetInstrInfo &TII, unsigned Flags)
SpillArea getSpillArea(Register Reg, ARMSubtarget::PushPopSplitVariation Variation, unsigned NumAlignedDPRCS2Regs, const ARMBaseRegisterInfo *RegInfo)
Get the spill area that Reg should be saved into in the prologue.
static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI)
static bool WindowsRequiresStackProbe(const MachineFunction &MF, size_t StackSizeInBytes)
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, const MachineFunction &MF)
We need the offset of the frame pointer relative to other MachineFrameInfo offsets which are encoded ...
static MachineBasicBlock::iterator initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI)
static int sizeOfSPAdjustment(const MachineInstr &MI)
static const uint64_t kSplitStackAvailable
static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))
static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const unsigned FramePtr
bool canRealignStack(const MachineFunction &MF) const override
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
StackOffset 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.
bool usesWindowsCFI() const
Describe properties that are true of each instruction in the target description file.
Wrapper class representing physical registers. Should be passed by value.
iterator_range< livein_iterator > liveins() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool needsSplitStackProlog() const
Return true if this function requires a split stack prolog, even if it uses no stack space.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int getStackProtectorIndex() const
Return the index for the stack protector object.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
void setHasWinCFI(bool v)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
bool isValid() const
Check for null.
Representation of each machine instruction.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
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...
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
@ D16
Only 16 D registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isSEHInstruction(const MachineInstr &MI)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
unsigned Log2(Align A)
Returns the log2 of the alignment.
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.