164#define DEBUG_TYPE "arm-frame-lowering"
170 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
174 unsigned NumAlignedDPRCS2Regs);
233 if (CFSize >= ((1 << 12) - 1) / 2)
256 bool IsTailCallReturn =
false;
258 unsigned RetOpcode =
MBBI->getOpcode();
259 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
260 RetOpcode == ARM::TCRETURNri;
264 int ArgumentPopSize = 0;
265 if (IsTailCallReturn) {
271 ArgumentPopSize = StackAdjust.
getImm();
280 return ArgumentPopSize;
286 F.needsUnwindTableEntry();
294 unsigned Opc =
MBBI->getOpcode();
320 case ARM::t2MOVi16: {
321 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
325 NewInstr.
add(
MBBI->getOperand(0));
327 for (
unsigned i = 1, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i)
328 NewInstr.
add(
MBBI->getOperand(i));
343 case ARM::t2MOVi32imm:
360 case ARM::t2LDMIA_RET:
361 case ARM::t2LDMIA_UPD:
362 case ARM::t2STMDB_UPD: {
365 for (
unsigned i = 4, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i) {
372 if (Reg >= 8 && Reg <= 13)
374 else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)
381 case ARM::t2LDMIA_RET:
382 NewOpc = ARM::tPOP_RET;
384 case ARM::t2LDMIA_UPD:
387 case ARM::t2STMDB_UPD:
395 for (
unsigned i = 2, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i)
396 NewInstr.
add(
MBBI->getOperand(i));
402 (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
409 case ARM::VSTMDDB_UPD:
410 case ARM::VLDMDIA_UPD: {
411 int First = -1,
Last = 0;
412 for (
unsigned i = 4, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i) {
432 case ARM::t2SUBspImm:
433 case ARM::t2SUBspImm12:
434 case ARM::t2ADDspImm:
435 case ARM::t2ADDspImm12:
443 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
445 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
449 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
451 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
461 case ARM::TCRETURNri:
467 case ARM::TCRETURNdi:
480 return std::prev(
MBBI);
488 Start = std::next(Start);
492 for (
auto MI = Start;
MI != End;) {
493 auto Next = std::next(
MI);
497 MI = std::next(Next);
514 Pred, PredReg,
TII, MIFlags);
517 Pred, PredReg,
TII, MIFlags);
525 unsigned PredReg = 0) {
527 MIFlags, Pred, PredReg);
532 switch (
MI.getOpcode()) {
533 case ARM::VSTMDDB_UPD:
537 case ARM::t2STMDB_UPD:
541 case ARM::STR_PRE_IMM:
550 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
556 size_t StackSizeInBytes) {
562 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
563 return (StackSizeInBytes >= StackProbeSize) &&
564 !
F.hasFnAttribute(
"no-stack-arg-probe");
569struct StackAdjustingInsts {
579 bool BeforeFPSet =
false) {
580 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
587 assert(
Info != Insts.
end() &&
"invalid sp adjusting instruction");
588 Info->SPAdjust += ExtraBytes;
594 unsigned CFAOffset = 0;
595 for (
auto &
Info : Insts) {
596 if (HasFP && !
Info.BeforeFPSet)
599 CFAOffset +=
Info.SPAdjust;
603 TII.get(TargetOpcode::CFI_INSTRUCTION))
624 const Align Alignment,
625 const bool MustBeSingleInstruction) {
627 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
628 const unsigned AlignMask = Alignment.
value() - 1U;
629 const unsigned NrBitsToZero =
Log2(Alignment);
646 }
else if (AlignMask <= 255) {
653 assert(!MustBeSingleInstruction &&
654 "Shouldn't call emitAligningInstructions demanding a single "
655 "instruction to be emitted for large stack alignment for a target "
693 int MaxRegBytes = 8 * 4;
697 MaxRegBytes = 11 * 4 + 8 * 8;
716 "This emitPrologue does not support Thumb1!");
722 int FPCXTSaveSize = 0;
733 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
734 int FramePtrSpillFI = 0;
742 StackAdjustingInsts DefCFAOffsetCandidates;
743 bool HasFP =
hasFP(MF);
750 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
753 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
767 int FI =
I.getFrameIdx();
772 FramePtrSpillFI = FI;
803 int FI =
I.getFrameIdx();
825 FramePtrSpillFI = FI;
848 if (FPCXTSaveSize > 0) {
850 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize,
true);
854 if (ArgRegsSaveSize) {
857 LastPush = std::prev(
MBBI);
858 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize,
true);
862 if (GPRCS1Size > 0) {
863 GPRCS1Push = LastPush =
MBBI++;
864 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size,
true);
868 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
869 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
870 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
872 unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize;
874 DPRGapSize += GPRCS2Size;
876 DPRGapSize %= DPRAlign.
value();
878 unsigned DPRCSOffset;
880 DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize;
881 GPRCS2Offset = DPRCSOffset - GPRCS2Size;
883 DPRCSOffset = GPRCS2Offset - DPRGapSize - DPRCSSize;
885 int FramePtrOffsetInPush = 0;
889 "Max FP estimation is wrong");
890 FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize;
900 GPRCS2Push = LastPush =
MBBI++;
901 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
907 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
908 if (LastPush !=
MBB.
end() &&
910 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
914 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize);
922 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
937 NumBytes = DPRCSOffset;
940 GPRCS2Push = LastPush =
MBBI++;
941 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
944 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
946 NeedsWinCFIStackAlloc =
false;
951 if (NumWords < 65536) {
961 .
addImm(NumWords & 0xffff)
971 switch (
TM.getCodeModel()) {
1003 if (NeedsWinCFIStackAlloc) {
1004 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1017 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1021 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1047 AfterPush = std::next(GPRCS1Push);
1049 int FPOffset = PushSize + FramePtrOffsetInPush;
1051 AfterPush = std::next(GPRCS2Push);
1060 if (FramePtrOffsetInPush + PushSize != 0) {
1063 FPCXTSaveSize + ArgRegsSaveSize - FramePtrOffsetInPush));
1064 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1071 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1093 if (GPRCS1Size > 0 && !NeedsWinCFI) {
1096 for (
const auto &Entry : CSI) {
1098 int FI = Entry.getFrameIdx();
1119 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1127 if (GPRCS2Size > 0 && !NeedsWinCFI) {
1129 for (
const auto &Entry : CSI) {
1131 int FI = Entry.getFrameIdx();
1139 unsigned DwarfReg =
MRI->getDwarfRegNum(
1140 Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
true);
1144 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1153 if (DPRCSSize > 0 && !NeedsWinCFI) {
1157 for (
const auto &Entry : CSI) {
1159 int FI = Entry.getFrameIdx();
1160 if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
1162 unsigned DwarfReg =
MRI->getDwarfRegNum(Reg,
true);
1166 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1178 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
1253 "This emitEpilogue does not support Thumb1!");
1283 if (NumBytes + IncomingArgStackToRestore != 0)
1285 NumBytes + IncomingArgStackToRestore,
1305 NumBytes -= (ReservedArgStack +
1330 "No scratch register to restore SP from FP!");
1352 }
else if (NumBytes &&
1365 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1370 "unexpected DPR alignment gap");
1379 if (ReservedArgStack || IncomingArgStackToRestore) {
1380 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1381 "attempting to restore negative stack amount");
1383 ReservedArgStack + IncomingArgStackToRestore,
1432 if (RegInfo->hasStackRealignment(MF)) {
1433 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1437 }
else if (hasMovingSP) {
1439 "VLAs and dynamic stack alignment, but missing base pointer!");
1453 }
else if (hasMovingSP) {
1459 if (FPOffset >= -255 && FPOffset < 0) {
1478 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1497 unsigned StmOpc,
unsigned StrOpc,
1498 bool NoGap,
bool (*Func)(
unsigned,
bool),
1499 unsigned NumAlignedDPRCS2Regs,
1500 unsigned MIFlags)
const {
1507 using RegAndKill = std::pair<unsigned, bool>;
1510 unsigned i = CSI.
size();
1512 unsigned LastReg = 0;
1513 for (; i != 0; --i) {
1518 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
1522 bool isLiveIn =
MRI.isLiveIn(Reg);
1523 if (!isLiveIn && !
MRI.isReserved(Reg))
1528 if (NoGap && LastReg && LastReg != Reg-1)
1536 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1542 llvm::sort(Regs, [&](
const RegAndKill &LHS,
const RegAndKill &RHS) {
1543 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1546 if (Regs.
size() > 1 || StrOpc== 0) {
1551 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
1553 }
else if (Regs.
size() == 1) {
1574 unsigned LdmOpc,
unsigned LdrOpc,
1575 bool isVarArg,
bool NoGap,
1576 bool (*Func)(
unsigned,
bool),
1577 unsigned NumAlignedDPRCS2Regs)
const {
1584 bool isTailCall =
false;
1585 bool isInterrupt =
false;
1586 bool isTrap =
false;
1587 bool isCmseEntry =
false;
1589 DL =
MI->getDebugLoc();
1590 unsigned RetOpcode =
MI->getOpcode();
1591 isTailCall = (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri);
1593 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1595 RetOpcode == ARM::TRAP || RetOpcode == ARM::TRAPNaCl ||
1596 RetOpcode == ARM::tTRAP;
1597 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1601 unsigned i = CSI.
size();
1603 unsigned LastReg = 0;
1604 bool DeleteRet =
false;
1605 for (; i != 0; --i) {
1611 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
1613 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1623 Info.setRestored(
false);
1629 if (NoGap && LastReg && LastReg != Reg-1)
1639 llvm::sort(Regs, [&](
unsigned LHS,
unsigned RHS) {
1640 return TRI.getEncodingValue(LHS) <
TRI.getEncodingValue(RHS);
1643 if (Regs.
size() > 1 || LdrOpc == 0) {
1648 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
1653 MI->eraseFromParent();
1657 }
else if (Regs.
size() == 1) {
1660 if (Regs[0] == ARM::PC)
1669 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1690 unsigned NumAlignedDPRCS2Regs,
1703 unsigned DNum =
I.getReg() - ARM::D8;
1704 if (DNum > NumAlignedDPRCS2Regs - 1)
1706 int FI =
I.getFrameIdx();
1734 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
1737 .
addImm(8 * NumAlignedDPRCS2Regs)
1753 Opc =
isThumb ? ARM::tMOVr : ARM::MOVr;
1762 unsigned NextReg = ARM::D8;
1766 if (NumAlignedDPRCS2Regs >= 6) {
1767 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1768 &ARM::QQPRRegClass);
1777 NumAlignedDPRCS2Regs -= 4;
1782 unsigned R4BaseReg = NextReg;
1785 if (NumAlignedDPRCS2Regs >= 4) {
1786 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1787 &ARM::QQPRRegClass);
1796 NumAlignedDPRCS2Regs -= 4;
1800 if (NumAlignedDPRCS2Regs >= 2) {
1801 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1810 NumAlignedDPRCS2Regs -= 2;
1814 if (NumAlignedDPRCS2Regs) {
1820 .
addImm((NextReg - R4BaseReg) * 2)
1832 unsigned NumAlignedDPRCS2Regs) {
1837 assert(
MI->mayStore() &&
"Expecting spill instruction");
1840 switch(NumAlignedDPRCS2Regs) {
1843 assert(
MI->mayStore() &&
"Expecting spill instruction");
1847 assert(
MI->mayStore() &&
"Expecting spill instruction");
1852 assert(
MI->killsRegister(ARM::R4) &&
"Missed kill flag");
1863 unsigned NumAlignedDPRCS2Regs,
1874 if (
I.getReg() == ARM::D8) {
1875 D8SpillFI =
I.getFrameIdx();
1887 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
1895 unsigned NextReg = ARM::D8;
1898 if (NumAlignedDPRCS2Regs >= 6) {
1899 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1900 &ARM::QQPRRegClass);
1908 NumAlignedDPRCS2Regs -= 4;
1913 unsigned R4BaseReg = NextReg;
1916 if (NumAlignedDPRCS2Regs >= 4) {
1917 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1918 &ARM::QQPRRegClass);
1925 NumAlignedDPRCS2Regs -= 4;
1929 if (NumAlignedDPRCS2Regs >= 2) {
1930 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1937 NumAlignedDPRCS2Regs -= 2;
1941 if (NumAlignedDPRCS2Regs)
1944 .
addImm(2 * (NextReg - R4BaseReg))
1960 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
1962 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
1963 unsigned FltOpc = ARM::VSTMDDB_UPD;
1972 return C.getReg() == ARM::FPCXTNS;
1981 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false,
1985 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false,
1999 if (NumAlignedDPRCS2Regs)
2018 if (NumAlignedDPRCS2Regs)
2021 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2024 unsigned FltOpc = ARM::VLDMDIA_UPD;
2026 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2029 NumAlignedDPRCS2Regs);
2030 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2034 NumAlignedDPRCS2Regs);
2035 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2037 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2047 unsigned FnSize = 0;
2048 for (
auto &
MBB : MF) {
2049 for (
auto &
MI :
MBB)
2050 FnSize +=
TII.getInstSizeInBytes(
MI);
2054 FnSize += Table.MBBs.size() * 4;
2065 bool &HasNonSPFrameIndex) {
2070 unsigned Limit = (1 << 12) - 1;
2071 for (
auto &
MBB : MF) {
2072 for (
auto &
MI :
MBB) {
2073 if (
MI.isDebugInstr())
2075 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2076 if (!
MI.getOperand(i).isFI())
2081 if (
MI.getOpcode() == ARM::ADDri) {
2082 Limit = std::min(Limit, (1U << 8) - 1);
2087 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2092 if (RegClass && !RegClass->
contains(ARM::SP))
2093 HasNonSPFrameIndex =
true;
2103 Limit = std::min(Limit, (1U << 8) - 1);
2106 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2111 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2117 Limit = std::min(Limit, (1U << 8) - 1);
2125 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2128 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2131 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2134 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2175 unsigned NumSpills = 0;
2176 for (; NumSpills < 8; ++NumSpills)
2177 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2188 SavedRegs.
set(ARM::R4);
2194 if (
STI.hasV8_1MMainlineOps() &&
2210 return Subtarget.createAAPCSFrameChainLeaf() ||
2223 for (
const auto &
MBB : MF)
2224 for (
const auto &
MI :
MBB)
2225 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi)
2226 for (
const auto &Op :
MI.operands())
2230 if (ARM::hGPRRegClass.
contains(Reg) && Reg != ARM::SP)
2245 bool CS1Spilled =
false;
2246 bool LRSpilled =
false;
2247 unsigned NumGPRSpills = 0;
2248 unsigned NumFPRSpills = 0;
2268 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2269 SavedRegs.
set(ARM::R4);
2278 SavedRegs.
set(ARM::R4);
2279 SavedRegs.
set(ARM::LR);
2285 SavedRegs.
set(ARM::LR);
2293 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2294 MFI.estimateStackSize(MF) > 508)
2295 SavedRegs.
set(ARM::R4);
2307 CanEliminateFrame =
false;
2312 for (
unsigned i = 0; CSRegs[i]; ++i) {
2313 unsigned Reg = CSRegs[i];
2314 bool Spilled =
false;
2315 if (SavedRegs.
test(Reg)) {
2317 CanEliminateFrame =
false;
2320 if (!ARM::GPRRegClass.
contains(Reg)) {
2322 if (ARM::SPRRegClass.
contains(Reg))
2324 else if (ARM::DPRRegClass.
contains(Reg))
2326 else if (ARM::QPRRegClass.
contains(Reg))
2347 case ARM::R0:
case ARM::R1:
2348 case ARM::R2:
case ARM::R3:
2349 case ARM::R4:
case ARM::R5:
2350 case ARM::R6:
case ARM::R7:
2363 case ARM::R0:
case ARM::R1:
2364 case ARM::R2:
case ARM::R3:
2365 case ARM::R4:
case ARM::R5:
2366 case ARM::R6:
case ARM::R7:
2377 bool ForceLRSpill =
false;
2382 if (FnSize >= (1 << 11)) {
2383 CanEliminateFrame =
false;
2384 ForceLRSpill =
true;
2402 unsigned EstimatedStackSize =
2403 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2406 int MaxFixedOffset = 0;
2407 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2408 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2409 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2412 bool HasFP =
hasFP(MF);
2415 EstimatedStackSize += 4;
2419 EstimatedStackSize += MaxFixedOffset;
2421 EstimatedStackSize += 16;
2423 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2424 bool HasNonSPFrameIndex =
false;
2445 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2447 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2448 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2450 EstimatedRSStackSizeLimit =
2452 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2456 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2462 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2464 bool HasBPOrFixedSP = RegInfo->
hasBasePointer(MF) || !HasMovingSP;
2473 bool HasLargeArgumentList =
2474 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2476 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2477 HasLargeArgumentList || HasNonSPFrameIndex;
2478 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2479 <<
"; EstimatedStack: " << EstimatedStackSize
2480 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2481 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2482 if (BigFrameOffsets ||
2493 SavedRegs.
set(ARM::LR);
2496 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2497 if (LRPos != UnspilledCS1GPRs.
end())
2498 UnspilledCS1GPRs.
erase(LRPos);
2501 if (FPPos != UnspilledCS1GPRs.
end())
2502 UnspilledCS1GPRs.
erase(FPPos);
2519 bool ExtraCSSpill =
false;
2536 int EntryRegDeficit = 0;
2537 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2542 <<
" is unused argument register, EntryRegDeficit = "
2543 << EntryRegDeficit <<
"\n");
2550 <<
" return regs used, ExitRegDeficit = "
2551 << ExitRegDeficit <<
"\n");
2553 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2558 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2559 if (SavedRegs.
test(Reg)) {
2562 <<
" is saved low register, RegDeficit = "
2563 << RegDeficit <<
"\n");
2569 <<
" is non-saved low register, adding to AvailableRegs\n");
2574 if (!HasFP ||
FramePtr != ARM::R7) {
2575 if (SavedRegs.
test(ARM::R7)) {
2578 << RegDeficit <<
"\n");
2583 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2588 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2589 if (SavedRegs.
test(Reg)) {
2592 <<
" is saved high register, RegDeficit = "
2593 << RegDeficit <<
"\n");
2600 if ((EntryRegDeficit > ExitRegDeficit) &&
2603 if (SavedRegs.
test(ARM::LR)) {
2606 << RegDeficit <<
"\n");
2609 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2618 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2619 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2622 <<
" to make up reg deficit\n");
2626 assert(!
MRI.isReserved(Reg) &&
"Should not be reserved");
2627 if (Reg != ARM::LR && !
MRI.isPhysRegUsed(Reg))
2628 ExtraCSSpill =
true;
2633 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2643 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2644 SavedRegs.
set(ARM::LR);
2647 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2648 if (LRPos != UnspilledCS1GPRs.
end())
2649 UnspilledCS1GPRs.
erase(LRPos);
2651 ForceLRSpill =
false;
2652 if (!
MRI.isReserved(ARM::LR) && !
MRI.isPhysRegUsed(ARM::LR) &&
2654 ExtraCSSpill =
true;
2662 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2663 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
2664 for (
unsigned i = 0, e = UnspilledCS1GPRs.
size(); i != e; ++i) {
2665 unsigned Reg = UnspilledCS1GPRs[i];
2671 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2674 <<
" to make up alignment\n");
2675 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg) &&
2677 ExtraCSSpill =
true;
2682 unsigned Reg = UnspilledCS2GPRs.
front();
2685 <<
" to make up alignment\n");
2686 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg))
2687 ExtraCSSpill =
true;
2697 if (!ExtraCSSpill &&
2701 unsigned NumExtras = TargetAlign.
value() / 4;
2703 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
2705 if (!
MRI.isReserved(Reg) &&
2713 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
2715 if (!
MRI.isReserved(Reg)) {
2721 if (NumExtras == 0) {
2722 for (
unsigned Reg : Extras) {
2724 if (!
MRI.isPhysRegUsed(Reg))
2725 ExtraCSSpill =
true;
2728 if (!ExtraCSSpill && RS) {
2732 unsigned Size =
TRI->getSpillSize(RC);
2733 Align Alignment =
TRI->getSpillAlign(RC);
2735 MFI.CreateStackObject(
Size, Alignment,
false));
2741 SavedRegs.
set(ARM::LR);
2754 SavedRegs.
set(ARM::R0);
2759 std::vector<CalleeSavedInfo> &CSI)
const {
2762 if (
STI.hasV8_1MMainlineOps() &&
2764 CSI.emplace_back(ARM::FPCXTNS);
2765 CSI.back().setRestored(
false);
2779 [=](
const auto &CS) {
2781 return Reg == ARM::R10 || Reg == ARM::R11 ||
2782 Reg == ARM::R8 || Reg == ARM::R9 ||
2783 ARM::DPRRegClass.contains(Reg);
2793 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
2794 NumEntries = std::size(FixedSpillOffsets);
2795 return FixedSpillOffsets;
2806 unsigned Opc =
I->getOpcode();
2807 bool IsDestroy = Opc ==
TII.getCallFrameDestroyOpcode();
2808 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
2811 "This eliminateCallFramePseudoInstr does not support Thumb1!");
2813 int PIdx =
I->findFirstPredOperandIdx();
2817 unsigned PredReg =
TII.getFramePred(*
I);
2821 if (IsDestroy && CalleePopAmount != -1U)
2827 unsigned Amount =
TII.getFrameSize(*
I);
2834 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
2838 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
2843 }
else if (CalleePopAmount != -1U) {
2857 unsigned Shifted = 0;
2862 while (!(
Value & 0xC0000000)) {
2867 bool Carry = (
Value & 0x00FFFFFF);
2868 Value = ((
Value & 0xFF000000) >> 24) + Carry;
2870 if (
Value & 0x0000100)
2914 bool Thumb = ST->isThumb();
2915 bool Thumb2 = ST->isThumb2();
2921 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
2940 unsigned ScratchReg0 = ARM::R4;
2941 unsigned ScratchReg1 = ARM::R5;
2958 if (BeforePrologueRegion.
insert(PredBB).second)
2961 }
while (!WalkList.
empty());
2971 BeforePrologueRegion.
insert(
B);
2973 for (
const auto &LI : PrologueMBB.
liveins()) {
2975 PredBB->addLiveIn(LI);
2981 BeforePrologueRegion.
erase(
B);
3026 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3029 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true), -4));
3030 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3033 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true), -8));
3034 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3043 }
else if (CompareStackPointer) {
3051 if (!CompareStackPointer && Thumb) {
3052 if (AlignedStackSize < 256) {
3056 .
addImm(AlignedStackSize)
3060 BuildMI(McrMBB,
DL,
TII.get(ARM::t2MOVi32imm), ScratchReg0)
3061 .
addImm(AlignedStackSize);
3074 }
else if (!CompareStackPointer) {
3075 if (AlignedStackSize < 256) {
3078 .
addImm(AlignedStackSize)
3094 if (Thumb && ST->isThumb1Only()) {
3102 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3114 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3124 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3125 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3129 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3138 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3145 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3158 if (AlignedStackSize < 256) {
3159 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3161 .
addImm(AlignedStackSize)
3165 BuildMI(AllocMBB,
DL,
TII.get(ARM::t2MOVi32imm), ScratchReg0)
3166 .
addImm(AlignedStackSize);
3175 if (AlignedStackSize < 256) {
3177 .
addImm(AlignedStackSize)
3192 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3198 BuildMI(AllocMBB,
DL,
TII.get(ARM::t2MOVi32imm), ScratchReg1)
3204 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3218 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3240 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3243 nullptr,
MRI->getDwarfRegNum(ARM::LR,
true), -12));
3244 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3260 if (ST->isThumb1Only()) {
3304 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3330 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3336 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true)));
3337 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3340 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true)));
3341 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3357#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...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
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)
static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI)
static bool requiresAAPCSFrameRecord(const MachineFunction &MF)
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)
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
const char LLVMTargetMachineRef TM
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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...
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
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.
bool keepFramePointer(const MachineFunction &MF) const override
Return true if the target wants to keep the frame pointer regardless of the function attribute "frame...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
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...
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...
void setDPRCalleeSavedAreaSize(unsigned s)
bool hasStackFrame() const
bool isThumb2Function() const
unsigned getFPCXTSaveAreaSize() const
unsigned getGPRCalleeSavedArea1Size() const
unsigned getDPRCalleeSavedGapSize() const
unsigned createPICLabelUId()
void setLRIsSpilled(bool s)
void setGPRCalleeSavedArea2Size(unsigned s)
bool isThumb1OnlyFunction() const
void setHasStackFrame(bool s)
void setDPRCalleeSavedAreaOffset(unsigned o)
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 getDPRCalleeSavedAreaSize() const
unsigned getFramePtrSpillOffset() const
bool shouldRestoreSPFromFP() const
unsigned getArgRegsSaveSize() const
void setGPRCalleeSavedArea2Offset(unsigned o)
void setGPRCalleeSavedArea1Offset(unsigned o)
void setDPRCalleeSavedGapSize(unsigned s)
unsigned getArgumentStackSize() const
void setShouldRestoreSPFromFP(bool s)
unsigned getReturnRegsCount() const
bool getPreservesR0() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isTargetWindows() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool splitFramePushPop(const MachineFunction &MF) const
Returns true if the frame setup is split into two separate pushes (first r0-r7,lr then r8-r11),...
bool splitFramePointerPush(const MachineFunction &MF) const
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...
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 cfiDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register)
.cfi_same_value Current value of Register is the same as in the previous frame.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset)
.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, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Context object for machine code objects.
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 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 hasCalls() const
Return true if the current function has any function calls.
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...
int getStackProtectorIndex() const
Return the index for the stack protector object.
int getOffsetAdjustment() const
Return the correction for frame offsets.
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
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.
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
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.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
MachineModuleInfo & getMMI() const
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.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
void insert(iterator MBBI, MachineBasicBlock *MBB)
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.
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
This class contains meta information specific to a module.
const MCContext & getContext() 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)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false.
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.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
virtual bool hasFP(const MachineFunction &MF) const =0
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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 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.
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)
@ 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)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find 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 isSplitFPArea1Register(unsigned Reg, bool SplitFramePushPop)
static bool isARMArea2Register(unsigned Reg, bool SplitFramePushPop)
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.
static bool isARMArea3Register(unsigned Reg, bool SplitFramePushPop)
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...
static bool isARMLowRegister(unsigned Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
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.
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 bool isARMArea1Register(unsigned Reg, bool SplitFramePushPop)
isARMArea1Register - Returns true if the register is a low register (r0-r7) or a stack/pc register th...
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...
static bool isSplitFPArea2Register(unsigned Reg, bool SplitFramePushPop)
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.