163#define DEBUG_TYPE "arm-frame-lowering"
169 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
173 unsigned NumAlignedDPRCS2Regs);
187 unsigned NumAlignedDPRCS2Regs,
282 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
368 if (CFSize >= ((1 << 12) - 1) / 2)
391 bool IsTailCallReturn =
false;
393 unsigned RetOpcode =
MBBI->getOpcode();
394 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
395 RetOpcode == ARM::TCRETURNri ||
396 RetOpcode == ARM::TCRETURNrinotr12;
400 int ArgumentPopSize = 0;
401 if (IsTailCallReturn) {
407 ArgumentPopSize = StackAdjust.
getImm();
416 return ArgumentPopSize;
422 F.needsUnwindTableEntry();
430 unsigned Opc =
MBBI->getOpcode();
456 case ARM::t2MOVi16: {
457 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
461 NewInstr.
add(
MBBI->getOperand(0));
479 case ARM::t2MOVi32imm:
497 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
498 MBBI->getOperand(2).getReg() == ARM::SP &&
499 MBBI->getOperand(3).getImm() == -4) {
500 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
510 case ARM::t2LDR_POST:
511 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
512 MBBI->getOperand(2).getReg() == ARM::SP &&
513 MBBI->getOperand(3).getImm() == 4) {
514 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
524 case ARM::t2LDMIA_RET:
525 case ARM::t2LDMIA_UPD:
526 case ARM::t2STMDB_UPD: {
529 for (
unsigned i = 4, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i) {
536 if (Reg >= 8 && Reg <= 13)
538 else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)
545 case ARM::t2LDMIA_RET:
546 NewOpc = ARM::tPOP_RET;
548 case ARM::t2LDMIA_UPD:
551 case ARM::t2STMDB_UPD:
559 for (
unsigned i = 2, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i)
560 NewInstr.
add(
MBBI->getOperand(i));
566 (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
573 case ARM::VSTMDDB_UPD:
574 case ARM::VLDMDIA_UPD: {
577 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
595 case ARM::t2SUBspImm:
596 case ARM::t2SUBspImm12:
597 case ARM::t2ADDspImm:
598 case ARM::t2ADDspImm12:
606 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
608 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
612 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
614 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
624 case ARM::TCRETURNri:
625 case ARM::TCRETURNrinotr12:
631 case ARM::TCRETURNdi:
644 return std::prev(
MBBI);
652 Start = std::next(Start);
656 for (
auto MI = Start;
MI !=
End;) {
657 auto Next = std::next(
MI);
661 MI = std::next(Next);
678 Pred, PredReg,
TII, MIFlags);
681 Pred, PredReg,
TII, MIFlags);
689 unsigned PredReg = 0) {
691 MIFlags, Pred, PredReg);
696 switch (
MI.getOpcode()) {
697 case ARM::VSTMDDB_UPD:
701 case ARM::t2STMDB_UPD:
705 case ARM::STR_PRE_IMM:
714 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
720 size_t StackSizeInBytes) {
726 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
727 return (StackSizeInBytes >= StackProbeSize) &&
728 !
F.hasFnAttribute(
"no-stack-arg-probe");
733struct StackAdjustingInsts {
739#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
741 dbgs() <<
" " << (BeforeFPSet ?
"before-fp " :
" ")
742 <<
"sp-adjust=" << SPAdjust;
751 bool BeforeFPSet =
false) {
752 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
759 assert(
Info != Insts.
end() &&
"invalid sp adjusting instruction");
760 Info->SPAdjust += ExtraBytes;
766 unsigned CFAOffset = 0;
767 for (
auto &
Info : Insts) {
768 if (HasFP && !
Info.BeforeFPSet)
771 CFAOffset +=
Info.SPAdjust;
775 TII.get(TargetOpcode::CFI_INSTRUCTION))
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;
899 "This emitPrologue does not support Thumb1!");
905 int FPCXTSaveSize = 0;
920 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCS1Size = 0, GPRCS3Size = 0,
922 int FramePtrSpillFI = 0;
930 StackAdjustingInsts DefCFAOffsetCandidates;
931 bool HasFP =
hasFP(MF);
938 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
941 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
952 SpillArea FramePtrSpillArea = SpillArea::GPRCS1;
953 bool BeforeFPPush =
true;
956 int FI =
I.getFrameIdx();
962 FramePtrSpillFI = FI;
963 FramePtrSpillArea = Area;
969 case SpillArea::FPCXT:
972 case SpillArea::GPRCS1:
975 case SpillArea::GPRCS2:
978 case SpillArea::DPRCS1:
981 case SpillArea::GPRCS3:
984 case SpillArea::DPRCS2:
991 DPRCS1Push, GPRCS3Push;
998 if (FPCXTSaveSize > 0) {
1000 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
1004 if (ArgRegsSaveSize) {
1007 LastPush = std::prev(
MBBI);
1008 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1012 if (GPRCS1Size > 0) {
1013 GPRCS1Push = LastPush =
MBBI++;
1014 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1015 if (FramePtrSpillArea == SpillArea::GPRCS1)
1016 BeforeFPPush =
false;
1023 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1024 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1025 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1027 Align DPRAlign = DPRCS1Size ? std::min(
Align(8), Alignment) :
Align(4);
1028 unsigned DPRGapSize =
1029 (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size + GPRCS2Size) %
1032 unsigned DPRCS1Offset = GPRCS2Offset - DPRGapSize - DPRCS1Size;
1038 <<
", FPOffset: " << FPOffset <<
"\n");
1040 "Max FP estimation is wrong");
1049 if (GPRCS2Size > 0) {
1051 GPRCS2Push = LastPush =
MBBI++;
1052 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1053 if (FramePtrSpillArea == SpillArea::GPRCS2)
1054 BeforeFPPush =
false;
1060 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
1061 if (LastPush !=
MBB.
end() &&
1063 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1067 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize, BeforeFPPush);
1072 if (DPRCS1Size > 0) {
1075 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1078 DPRCS1Push = LastPush =
MBBI++;
1083 if (DPRCS2Size > 0) {
1091 NumBytes = DPRCS1Offset;
1094 if (GPRCS3Size > 0) {
1096 GPRCS3Push = LastPush =
MBBI++;
1097 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1098 if (FramePtrSpillArea == SpillArea::GPRCS3)
1099 BeforeFPPush =
false;
1102 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1104 NeedsWinCFIStackAlloc =
false;
1109 if (NumWords < 65536) {
1119 .
addImm(NumWords & 0xffff)
1129 switch (TM.getCodeModel()) {
1161 if (NeedsWinCFIStackAlloc) {
1162 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1175 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1179 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1205 int64_t FPOffsetAfterPush;
1206 switch (FramePtrSpillArea) {
1207 case SpillArea::GPRCS1:
1208 FPPushInst = GPRCS1Push;
1210 ArgRegsSaveSize + FPCXTSaveSize +
1213 << FPOffsetAfterPush <<
" after that push\n");
1215 case SpillArea::GPRCS2:
1216 FPPushInst = GPRCS2Push;
1218 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1221 << FPOffsetAfterPush <<
" after that push\n");
1223 case SpillArea::GPRCS3:
1224 FPPushInst = GPRCS3Push;
1226 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1227 GPRCS2Size + DPRCS1Size + DPRGapSize +
1230 << FPOffsetAfterPush <<
" after that push\n");
1236 AfterPush = std::next(FPPushInst);
1238 assert(FPOffsetAfterPush == 0);
1242 FramePtr, ARM::SP, FPOffsetAfterPush,
1248 if (FPOffsetAfterPush != 0) {
1252 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1259 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1282 for (
const auto &Entry :
reverse(CSI)) {
1284 int FI = Entry.getFrameIdx();
1288 case SpillArea::GPRCS1:
1289 CFIPos = std::next(GPRCS1Push);
1291 case SpillArea::GPRCS2:
1292 CFIPos = std::next(GPRCS2Push);
1294 case SpillArea::DPRCS1:
1295 CFIPos = std::next(DPRCS1Push);
1297 case SpillArea::GPRCS3:
1298 CFIPos = std::next(GPRCS3Push);
1300 case SpillArea::FPCXT:
1301 case SpillArea::DPRCS2:
1309 MRI->getDwarfRegNum(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1312 BuildMI(
MBB, CFIPos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1325 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
1402 "This emitEpilogue does not support Thumb1!");
1436 if (NumBytes + IncomingArgStackToRestore != 0)
1438 NumBytes + IncomingArgStackToRestore,
1482 "No scratch register to restore SP from FP!");
1504 }
else if (NumBytes &&
1520 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1525 "unexpected DPR alignment gap");
1537 if (ReservedArgStack || IncomingArgStackToRestore) {
1538 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1539 "attempting to restore negative stack amount");
1541 ReservedArgStack + IncomingArgStackToRestore,
1590 if (RegInfo->hasStackRealignment(MF)) {
1591 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1595 }
else if (hasMovingSP) {
1597 "VLAs and dynamic stack alignment, but missing base pointer!");
1611 }
else if (hasMovingSP) {
1617 if (FPOffset >= -255 && FPOffset < 0) {
1636 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1655 unsigned StmOpc,
unsigned StrOpc,
1664 using RegAndKill = std::pair<unsigned, bool>;
1667 unsigned i = CSI.
size();
1669 unsigned LastReg = 0;
1670 for (; i != 0; --i) {
1676 bool isLiveIn =
MRI.isLiveIn(Reg);
1677 if (!isLiveIn && !
MRI.isReserved(Reg))
1682 if (NoGap && LastReg && LastReg != Reg-1)
1690 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1696 llvm::sort(Regs, [&](
const RegAndKill &LHS,
const RegAndKill &RHS) {
1697 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1700 if (Regs.
size() > 1 || StrOpc== 0) {
1705 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
1707 }
else if (Regs.
size() == 1) {
1728 unsigned LdmOpc,
unsigned LdrOpc,
1729 bool isVarArg,
bool NoGap,
1737 bool isTailCall =
false;
1738 bool isInterrupt =
false;
1739 bool isTrap =
false;
1740 bool isCmseEntry =
false;
1744 DL =
MI->getDebugLoc();
1745 unsigned RetOpcode =
MI->getOpcode();
1747 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1748 RetOpcode == ARM::TCRETURNrinotr12);
1750 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1752 RetOpcode == ARM::TRAP || RetOpcode == ARM::TRAPNaCl ||
1753 RetOpcode == ARM::tTRAP;
1754 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1758 unsigned i = CSI.
size();
1760 unsigned LastReg = 0;
1761 bool DeleteRet =
false;
1762 for (; i != 0; --i) {
1768 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1782 if (NoGap && LastReg && LastReg != Reg-1)
1792 llvm::sort(Regs, [&](
unsigned LHS,
unsigned RHS) {
1793 return TRI.getEncodingValue(LHS) <
TRI.getEncodingValue(RHS);
1796 if (Regs.
size() > 1 || LdrOpc == 0) {
1801 for (
unsigned Reg : Regs)
1806 MI->eraseFromParent();
1810 }
else if (Regs.size() == 1) {
1813 if (Regs[0] == ARM::PC)
1822 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1843 unsigned NumAlignedDPRCS2Regs,
1856 unsigned DNum =
I.getReg() - ARM::D8;
1857 if (DNum > NumAlignedDPRCS2Regs - 1)
1859 int FI =
I.getFrameIdx();
1887 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
1890 .
addImm(8 * NumAlignedDPRCS2Regs)
1906 Opc =
isThumb ? ARM::tMOVr : ARM::MOVr;
1915 unsigned NextReg = ARM::D8;
1919 if (NumAlignedDPRCS2Regs >= 6) {
1920 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1921 &ARM::QQPRRegClass);
1930 NumAlignedDPRCS2Regs -= 4;
1935 unsigned R4BaseReg = NextReg;
1938 if (NumAlignedDPRCS2Regs >= 4) {
1939 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1940 &ARM::QQPRRegClass);
1949 NumAlignedDPRCS2Regs -= 4;
1953 if (NumAlignedDPRCS2Regs >= 2) {
1954 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1963 NumAlignedDPRCS2Regs -= 2;
1967 if (NumAlignedDPRCS2Regs) {
1973 .
addImm((NextReg - R4BaseReg) * 2)
1985 unsigned NumAlignedDPRCS2Regs) {
1990 assert(
MI->mayStore() &&
"Expecting spill instruction");
1993 switch(NumAlignedDPRCS2Regs) {
1996 assert(
MI->mayStore() &&
"Expecting spill instruction");
2000 assert(
MI->mayStore() &&
"Expecting spill instruction");
2005 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
2016 unsigned NumAlignedDPRCS2Regs,
2027 if (
I.getReg() == ARM::D8) {
2028 D8SpillFI =
I.getFrameIdx();
2040 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
2048 unsigned NextReg = ARM::D8;
2051 if (NumAlignedDPRCS2Regs >= 6) {
2052 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
2053 &ARM::QQPRRegClass);
2061 NumAlignedDPRCS2Regs -= 4;
2066 unsigned R4BaseReg = NextReg;
2069 if (NumAlignedDPRCS2Regs >= 4) {
2070 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
2071 &ARM::QQPRRegClass);
2078 NumAlignedDPRCS2Regs -= 4;
2082 if (NumAlignedDPRCS2Regs >= 2) {
2083 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
2090 NumAlignedDPRCS2Regs -= 2;
2094 if (NumAlignedDPRCS2Regs)
2097 .
addImm(2 * (NextReg - R4BaseReg))
2116 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2118 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2119 unsigned FltOpc = ARM::VSTMDDB_UPD;
2128 return C.getReg() == ARM::FPCXTNS;
2137 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2138 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2139 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2142 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2143 return CheckRegArea(Reg, SpillArea::GPRCS1);
2145 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2146 return CheckRegArea(Reg, SpillArea::GPRCS2);
2148 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2149 return CheckRegArea(Reg, SpillArea::DPRCS1);
2151 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2152 return CheckRegArea(Reg, SpillArea::GPRCS3);
2155 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS1);
2156 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS2);
2157 emitPushInst(
MBB,
MI, CSI, FltOpc, 0,
true, IsDPRCS1);
2158 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false, IsGPRCS3);
2163 if (NumAlignedDPRCS2Regs)
2186 if (NumAlignedDPRCS2Regs)
2189 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2192 unsigned FltOpc = ARM::VLDMDIA_UPD;
2194 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2195 RegInfo](
unsigned Reg,
SpillArea TestArea) {
2196 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2199 auto IsGPRCS1 = [&CheckRegArea](
unsigned Reg) {
2200 return CheckRegArea(Reg, SpillArea::GPRCS1);
2202 auto IsGPRCS2 = [&CheckRegArea](
unsigned Reg) {
2203 return CheckRegArea(Reg, SpillArea::GPRCS2);
2205 auto IsDPRCS1 = [&CheckRegArea](
unsigned Reg) {
2206 return CheckRegArea(Reg, SpillArea::DPRCS1);
2208 auto IsGPRCS3 = [&CheckRegArea](
unsigned Reg) {
2209 return CheckRegArea(Reg, SpillArea::GPRCS3);
2212 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS3);
2213 emitPopInst(
MBB,
MI, CSI, FltOpc, 0, isVarArg,
true, IsDPRCS1);
2214 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS2);
2215 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false, IsGPRCS1);
2223 unsigned FnSize = 0;
2224 for (
auto &
MBB : MF) {
2225 for (
auto &
MI :
MBB)
2226 FnSize +=
TII.getInstSizeInBytes(
MI);
2230 FnSize += Table.MBBs.size() * 4;
2241 bool &HasNonSPFrameIndex) {
2246 unsigned Limit = (1 << 12) - 1;
2247 for (
auto &
MBB : MF) {
2248 for (
auto &
MI :
MBB) {
2249 if (
MI.isDebugInstr())
2251 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2252 if (!
MI.getOperand(i).isFI())
2257 if (
MI.getOpcode() == ARM::ADDri) {
2258 Limit = std::min(Limit, (1U << 8) - 1);
2263 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2268 if (RegClass && !RegClass->
contains(ARM::SP))
2269 HasNonSPFrameIndex =
true;
2279 Limit = std::min(Limit, (1U << 8) - 1);
2282 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2287 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2293 Limit = std::min(Limit, (1U << 8) - 1);
2301 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2304 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2307 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2310 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2351 unsigned NumSpills = 0;
2352 for (; NumSpills < 8; ++NumSpills)
2353 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2364 SavedRegs.
set(ARM::R4);
2370 if (
STI.hasV8_1MMainlineOps() &&
2387 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2400 for (
const auto &
MBB : MF)
2401 for (
const auto &
MI :
MBB)
2402 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2403 STI.genExecuteOnly())
2404 for (
const auto &
Op :
MI.operands())
2408 if (ARM::hGPRRegClass.
contains(Reg) && Reg != ARM::SP)
2424 bool CS1Spilled =
false;
2425 bool LRSpilled =
false;
2426 unsigned NumGPRSpills = 0;
2427 unsigned NumFPRSpills = 0;
2449 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2450 SavedRegs.
set(ARM::R4);
2459 SavedRegs.
set(ARM::R4);
2460 SavedRegs.
set(ARM::LR);
2466 SavedRegs.
set(ARM::LR);
2474 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2475 MFI.estimateStackSize(MF) > 508)
2476 SavedRegs.
set(ARM::R4);
2488 CanEliminateFrame =
false;
2492 CanEliminateFrame =
false;
2497 for (
unsigned i = 0; CSRegs[i]; ++i) {
2498 unsigned Reg = CSRegs[i];
2499 bool Spilled =
false;
2500 if (SavedRegs.
test(Reg)) {
2502 CanEliminateFrame =
false;
2505 if (!ARM::GPRRegClass.
contains(Reg)) {
2507 if (ARM::SPRRegClass.
contains(Reg))
2509 else if (ARM::DPRRegClass.
contains(Reg))
2511 else if (ARM::QPRRegClass.
contains(Reg))
2532 case ARM::R0:
case ARM::R1:
2533 case ARM::R2:
case ARM::R3:
2534 case ARM::R4:
case ARM::R5:
2535 case ARM::R6:
case ARM::R7:
2548 case ARM::R0:
case ARM::R1:
2549 case ARM::R2:
case ARM::R3:
2550 case ARM::R4:
case ARM::R5:
2551 case ARM::R6:
case ARM::R7:
2562 bool ForceLRSpill =
false;
2567 if (FnSize >= (1 << 11)) {
2568 CanEliminateFrame =
false;
2569 ForceLRSpill =
true;
2587 unsigned EstimatedStackSize =
2588 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2591 int MaxFixedOffset = 0;
2592 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2593 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2594 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2597 bool HasFP =
hasFP(MF);
2600 EstimatedStackSize += 4;
2604 EstimatedStackSize += MaxFixedOffset;
2606 EstimatedStackSize += 16;
2608 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2609 bool HasNonSPFrameIndex =
false;
2630 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2632 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2633 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2635 EstimatedRSStackSizeLimit =
2637 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2641 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2647 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2649 bool HasBPOrFixedSP = RegInfo->
hasBasePointer(MF) || !HasMovingSP;
2658 bool HasLargeArgumentList =
2659 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2661 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2662 HasLargeArgumentList || HasNonSPFrameIndex;
2663 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2664 <<
"; EstimatedStack: " << EstimatedStackSize
2665 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2666 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2667 if (BigFrameOffsets ||
2678 SavedRegs.
set(ARM::LR);
2681 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2682 if (LRPos != UnspilledCS1GPRs.
end())
2683 UnspilledCS1GPRs.
erase(LRPos);
2686 if (FPPos != UnspilledCS1GPRs.
end())
2687 UnspilledCS1GPRs.
erase(FPPos);
2705 unsigned NumExtraCSSpill = 0;
2722 int EntryRegDeficit = 0;
2723 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2728 <<
" is unused argument register, EntryRegDeficit = "
2729 << EntryRegDeficit <<
"\n");
2736 <<
" return regs used, ExitRegDeficit = "
2737 << ExitRegDeficit <<
"\n");
2739 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2744 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2745 if (SavedRegs.
test(Reg)) {
2748 <<
" is saved low register, RegDeficit = "
2749 << RegDeficit <<
"\n");
2755 <<
" is non-saved low register, adding to AvailableRegs\n");
2760 if (!HasFP ||
FramePtr != ARM::R7) {
2761 if (SavedRegs.
test(ARM::R7)) {
2764 << RegDeficit <<
"\n");
2769 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2774 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2775 if (SavedRegs.
test(Reg)) {
2778 <<
" is saved high register, RegDeficit = "
2779 << RegDeficit <<
"\n");
2786 if ((EntryRegDeficit > ExitRegDeficit) &&
2789 if (SavedRegs.
test(ARM::LR)) {
2792 << RegDeficit <<
"\n");
2795 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2804 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2805 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2808 <<
" to make up reg deficit\n");
2812 assert(!
MRI.isReserved(Reg) &&
"Should not be reserved");
2813 if (Reg != ARM::LR && !
MRI.isPhysRegUsed(Reg))
2819 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2829 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2830 SavedRegs.
set(ARM::LR);
2833 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2834 if (LRPos != UnspilledCS1GPRs.
end())
2835 UnspilledCS1GPRs.
erase(LRPos);
2837 ForceLRSpill =
false;
2838 if (!
MRI.isReserved(ARM::LR) && !
MRI.isPhysRegUsed(ARM::LR) &&
2848 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2849 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
2850 for (
unsigned Reg : UnspilledCS1GPRs) {
2856 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2859 <<
" to make up alignment\n");
2860 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg) &&
2867 unsigned Reg = UnspilledCS2GPRs.
front();
2870 <<
" to make up alignment\n");
2871 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg))
2882 unsigned RegsNeeded = 0;
2891 if (RegsNeeded > NumExtraCSSpill) {
2894 unsigned NumExtras = TargetAlign.
value() / 4;
2896 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
2898 if (!
MRI.isReserved(Reg) &&
2906 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
2908 if (!
MRI.isReserved(Reg)) {
2914 if (NumExtras == 0) {
2915 for (
unsigned Reg : Extras) {
2917 if (!
MRI.isPhysRegUsed(Reg))
2921 while ((RegsNeeded > NumExtraCSSpill) && RS) {
2925 unsigned Size =
TRI->getSpillSize(RC);
2926 Align Alignment =
TRI->getSpillAlign(RC);
2928 MFI.CreateStackObject(
Size, Alignment,
false));
2935 SavedRegs.
set(ARM::LR);
2948 if (
Info.getReg() != ARM::LR)
2952 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
2953 Term.getOpcode() == ARM::t2LDMIA_RET ||
2954 Term.getOpcode() == ARM::tPOP_RET;
2957 Info.setRestored(
false);
2978 SavedRegs.
set(ARM::R0);
2983 std::vector<CalleeSavedInfo> &CSI)
const {
2986 if (
STI.hasV8_1MMainlineOps() &&
2988 CSI.emplace_back(ARM::FPCXTNS);
2989 CSI.back().setRestored(
false);
3005 [=](
const auto &CS) {
3007 return Reg == ARM::R10 || Reg == ARM::R11 ||
3008 Reg == ARM::R8 || Reg == ARM::R9 ||
3009 ARM::DPRRegClass.contains(Reg);
3020 "ABI-required frame pointers need a CSR split when signing return "
3023 [=](
const auto &CS) {
3025 return Reg != ARM::LR;
3039 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3040 NumEntries = std::size(FixedSpillOffsets);
3041 return FixedSpillOffsets;
3052 unsigned Opc =
I->getOpcode();
3053 bool IsDestroy = Opc ==
TII.getCallFrameDestroyOpcode();
3054 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
3057 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3059 int PIdx =
I->findFirstPredOperandIdx();
3063 unsigned PredReg =
TII.getFramePred(*
I);
3067 if (IsDestroy && CalleePopAmount != -1U)
3073 unsigned Amount =
TII.getFrameSize(*
I);
3080 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
3084 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
3089 }
else if (CalleePopAmount != -1U) {
3103 unsigned Shifted = 0;
3108 while (!(
Value & 0xC0000000)) {
3113 bool Carry = (
Value & 0x00FFFFFF);
3114 Value = ((
Value & 0xFF000000) >> 24) + Carry;
3116 if (
Value & 0x0000100)
3160 bool Thumb = ST->isThumb();
3161 bool Thumb2 = ST->isThumb2();
3167 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3185 unsigned ScratchReg0 = ARM::R4;
3186 unsigned ScratchReg1 = ARM::R5;
3187 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3204 if (BeforePrologueRegion.
insert(PredBB).second)
3207 }
while (!WalkList.
empty());
3217 BeforePrologueRegion.
insert(
B);
3219 for (
const auto &LI : PrologueMBB.
liveins()) {
3221 PredBB->addLiveIn(LI);
3227 BeforePrologueRegion.
erase(
B);
3272 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3275 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true), -4));
3276 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3279 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true), -8));
3280 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3289 }
else if (CompareStackPointer) {
3297 if (!CompareStackPointer && Thumb) {
3298 if (AlignedStackSize < 256) {
3302 .
addImm(AlignedStackSize)
3305 if (Thumb2 || ST->genExecuteOnly()) {
3307 .
addImm(AlignedStackSize);
3320 }
else if (!CompareStackPointer) {
3321 if (AlignedStackSize < 256) {
3324 .
addImm(AlignedStackSize)
3340 if (Thumb && ST->isThumb1Only()) {
3341 if (ST->genExecuteOnly()) {
3352 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3365 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3375 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3376 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3380 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3389 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3396 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3409 if (AlignedStackSize < 256) {
3410 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3412 .
addImm(AlignedStackSize)
3415 if (Thumb2 || ST->genExecuteOnly()) {
3417 .
addImm(AlignedStackSize);
3426 if (AlignedStackSize < 256) {
3428 .
addImm(AlignedStackSize)
3443 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3448 if (Thumb2 || ST->genExecuteOnly()) {
3455 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3469 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3491 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3494 nullptr,
MRI->getDwarfRegNum(ARM::LR,
true), -12));
3495 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3511 if (ST->isThumb1Only()) {
3555 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3581 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3587 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true)));
3588 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3591 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true)));
3592 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3608#ifdef EXPENSIVE_CHECKS
unsigned const MachineRegisterInfo * MRI
static int64_t getArgumentStackToRestore(MachineFunction &MF, MachineBasicBlock &MBB)
Returns how much of the incoming argument stack area (in bytes) we should clean up in an epilogue.
static bool needsWinCFI(const MachineFunction &MF)
static unsigned estimateRSStackSizeLimit(MachineFunction &MF)
Look at each instruction that references stack frames and return the stack size limit beyond which so...
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 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")
Analysis containing CSE Info
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 hasBasePointer(const MachineFunction &MF) const
virtual void emitLoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred=ARMCC::AL, Register PredReg=Register(), unsigned MIFlags=MachineInstr::NoFlags) const
emitLoadConstPool - Emits a load from constpool to materialize the specified immediate.
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
bool cannotEliminateFrame(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
bool canRealignStack(const MachineFunction &MF) const override
Register getBaseRegister() const
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
bool keepFramePointer(const MachineFunction &MF) const
static void updateLRRestored(MachineFunction &MF)
Update the IsRestored flag on LR if it is spilled, based on the return instructions.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
ARMFrameLowering(const ARMSubtarget &sti)
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool requiresAAPCSFrameRecord(const MachineFunction &MF) const
bool isFPReserved(const MachineFunction &MF) const
isFPReserved - Return true if the frame pointer register should be considered a reserved register on ...
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &MBB) const override
Adjust the prologue to have the function use segmented stacks.
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override
getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs, that contains an entry...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool hasFPImpl(const MachineFunction &MF) const override
hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.
int ResolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, int SPAdj) const
void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const override
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool enableCalleeSaveSkip(const MachineFunction &MF) const override
Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functi...
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
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)
unsigned getArgumentStackSize() const
void setShouldRestoreSPFromFP(bool s)
unsigned getReturnRegsCount() const
void setGPRCalleeSavedArea3Size(unsigned s)
bool getPreservesR0() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isTargetWindows() 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.
const ARMFrameLowering * getFrameLowering() const override
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
bool test(unsigned Idx) const
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
This class represents an Operation in the Expression.
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
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_same_value Current value of Register is the same as in the previous frame.
Context object for machine code objects.
const MCRegisterInfo * getRegisterInfo() const
Describe properties that are true of each instruction in the target description file.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
iterator_range< livein_iterator > liveins() const
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New)
Given a machine basic block that branched to 'Old', change the code and CFG so that it branches to 'N...
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< iterator > terminators()
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
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?
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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
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.
MCContext & getContext() const
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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 & addCFIIndex(unsigned CFIIndex) const
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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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.
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 isLiveIn(Register Reg) const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
bool erase(PtrType Ptr)
Remove pointer from the set.
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.
Information about stack frame layout on the target.
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.
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.
Primary interface to the complete machine description for the target machine.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
bool FramePointerIsReserved(const MachineFunction &MF) const
FramePointerIsReserved - This returns true if the frame pointer must always either point to a new fra...
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...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
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.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
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.
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)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
unsigned getDefRegState(bool B)
unsigned getKillRegState(bool B)
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...
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...
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)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.