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 ||
261 RetOpcode == ARM::TCRETURNrinotr12;
265 int ArgumentPopSize = 0;
266 if (IsTailCallReturn) {
272 ArgumentPopSize = StackAdjust.
getImm();
281 return ArgumentPopSize;
287 F.needsUnwindTableEntry();
295 unsigned Opc =
MBBI->getOpcode();
321 case ARM::t2MOVi16: {
322 bool Wide =
MBBI->getOperand(1).getImm() >= 256;
326 NewInstr.
add(
MBBI->getOperand(0));
344 case ARM::t2MOVi32imm:
362 if (
MBBI->getOperand(0).getReg() == ARM::SP &&
363 MBBI->getOperand(2).getReg() == ARM::SP &&
364 MBBI->getOperand(3).getImm() == -4) {
365 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
375 case ARM::t2LDR_POST:
376 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
377 MBBI->getOperand(2).getReg() == ARM::SP &&
378 MBBI->getOperand(3).getImm() == 4) {
379 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
389 case ARM::t2LDMIA_RET:
390 case ARM::t2LDMIA_UPD:
391 case ARM::t2STMDB_UPD: {
394 for (
unsigned i = 4, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i) {
401 if (Reg >= 8 && Reg <= 13)
403 else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)
410 case ARM::t2LDMIA_RET:
411 NewOpc = ARM::tPOP_RET;
413 case ARM::t2LDMIA_UPD:
416 case ARM::t2STMDB_UPD:
424 for (
unsigned i = 2, NumOps =
MBBI->getNumOperands(); i != NumOps; ++i)
425 NewInstr.
add(
MBBI->getOperand(i));
431 (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
438 case ARM::VSTMDDB_UPD:
439 case ARM::VLDMDIA_UPD: {
442 unsigned Reg =
RegInfo->getSEHRegNum(MO.getReg());
460 case ARM::t2SUBspImm:
461 case ARM::t2SUBspImm12:
462 case ARM::t2ADDspImm:
463 case ARM::t2ADDspImm12:
471 if (
MBBI->getOperand(1).getReg() == ARM::SP &&
473 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(0).getReg());
477 }
else if (
MBBI->getOperand(0).getReg() == ARM::SP &&
479 unsigned Reg =
RegInfo->getSEHRegNum(
MBBI->getOperand(1).getReg());
489 case ARM::TCRETURNri:
490 case ARM::TCRETURNrinotr12:
496 case ARM::TCRETURNdi:
509 return std::prev(
MBBI);
517 Start = std::next(Start);
521 for (
auto MI = Start;
MI !=
End;) {
522 auto Next = std::next(
MI);
526 MI = std::next(Next);
543 Pred, PredReg,
TII, MIFlags);
546 Pred, PredReg,
TII, MIFlags);
554 unsigned PredReg = 0) {
556 MIFlags, Pred, PredReg);
561 switch (
MI.getOpcode()) {
562 case ARM::VSTMDDB_UPD:
566 case ARM::t2STMDB_UPD:
570 case ARM::STR_PRE_IMM:
579 for (
int i =
MI.getNumOperands() - 1; i >= 4; --i)
585 size_t StackSizeInBytes) {
591 F.getFnAttributeAsParsedInteger(
"stack-probe-size", StackProbeSize);
592 return (StackSizeInBytes >= StackProbeSize) &&
593 !
F.hasFnAttribute(
"no-stack-arg-probe");
598struct StackAdjustingInsts {
608 bool BeforeFPSet =
false) {
609 InstInfo
Info = {
I, SPAdjust, BeforeFPSet};
616 assert(
Info != Insts.
end() &&
"invalid sp adjusting instruction");
617 Info->SPAdjust += ExtraBytes;
623 unsigned CFAOffset = 0;
624 for (
auto &
Info : Insts) {
625 if (HasFP && !
Info.BeforeFPSet)
628 CFAOffset +=
Info.SPAdjust;
632 TII.get(TargetOpcode::CFI_INSTRUCTION))
653 const Align Alignment,
654 const bool MustBeSingleInstruction) {
656 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
657 const unsigned AlignMask = Alignment.
value() - 1U;
658 const unsigned NrBitsToZero =
Log2(Alignment);
675 }
else if (AlignMask <= 255) {
682 assert(!MustBeSingleInstruction &&
683 "Shouldn't call emitAligningInstructions demanding a single "
684 "instruction to be emitted for large stack alignment for a target "
722 int MaxRegBytes = 8 * 4;
726 MaxRegBytes = 11 * 4 + 8 * 8;
744 "This emitPrologue does not support Thumb1!");
750 int FPCXTSaveSize = 0;
761 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
762 int FramePtrSpillFI = 0;
770 StackAdjustingInsts DefCFAOffsetCandidates;
771 bool HasFP =
hasFP(MF);
778 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes,
true);
781 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
795 int FI =
I.getFrameIdx();
800 FramePtrSpillFI = FI;
831 int FI =
I.getFrameIdx();
853 FramePtrSpillFI = FI;
876 if (FPCXTSaveSize > 0) {
878 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize,
true);
882 if (ArgRegsSaveSize) {
885 LastPush = std::prev(
MBBI);
886 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize,
true);
890 if (GPRCS1Size > 0) {
891 GPRCS1Push = LastPush =
MBBI++;
892 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size,
true);
896 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
897 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
898 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
900 unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize;
902 DPRGapSize += GPRCS2Size;
904 DPRGapSize %= DPRAlign.
value();
906 unsigned DPRCSOffset;
908 DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize;
909 GPRCS2Offset = DPRCSOffset - GPRCS2Size;
911 DPRCSOffset = GPRCS2Offset - DPRGapSize - DPRCSSize;
913 int FramePtrOffsetInPush = 0;
917 "Max FP estimation is wrong");
918 FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize;
928 GPRCS2Push = LastPush =
MBBI++;
929 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
935 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
936 if (LastPush !=
MBB.
end() &&
938 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
942 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), DPRGapSize);
950 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
965 NumBytes = DPRCSOffset;
968 GPRCS2Push = LastPush =
MBBI++;
969 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
972 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
974 NeedsWinCFIStackAlloc =
false;
979 if (NumWords < 65536) {
989 .
addImm(NumWords & 0xffff)
999 switch (TM.getCodeModel()) {
1031 if (NeedsWinCFIStackAlloc) {
1032 SEH =
BuildMI(MF, dl,
TII.get(ARM::SEH_StackAlloc))
1045 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1049 DefCFAOffsetCandidates.addInst(std::prev(
MBBI), NumBytes);
1075 AfterPush = std::next(GPRCS1Push);
1077 int FPOffset = PushSize + FramePtrOffsetInPush;
1079 AfterPush = std::next(GPRCS2Push);
1088 if (FramePtrOffsetInPush + PushSize != 0) {
1091 FPCXTSaveSize + ArgRegsSaveSize - FramePtrOffsetInPush));
1092 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1099 BuildMI(
MBB, AfterPush, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1121 if (GPRCS1Size > 0 && !NeedsWinCFI) {
1124 for (
const auto &Entry : CSI) {
1126 int FI = Entry.getFrameIdx();
1147 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1155 if (GPRCS2Size > 0 && !NeedsWinCFI) {
1157 for (
const auto &Entry : CSI) {
1159 int FI = Entry.getFrameIdx();
1167 unsigned DwarfReg =
MRI->getDwarfRegNum(
1168 Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
true);
1172 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1181 if (DPRCSSize > 0 && !NeedsWinCFI) {
1185 for (
const auto &Entry : CSI) {
1187 int FI = Entry.getFrameIdx();
1188 if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
1190 unsigned DwarfReg =
MRI->getDwarfRegNum(Reg,
true);
1194 BuildMI(
MBB, Pos, dl,
TII.get(TargetOpcode::CFI_INSTRUCTION))
1206 DefCFAOffsetCandidates.emitDefCFAOffsets(
MBB, dl,
TII, HasFP);
1281 "This emitEpilogue does not support Thumb1!");
1311 if (NumBytes + IncomingArgStackToRestore != 0)
1313 NumBytes + IncomingArgStackToRestore,
1333 NumBytes -= (ReservedArgStack +
1358 "No scratch register to restore SP from FP!");
1380 }
else if (NumBytes &&
1393 while (
MBBI !=
MBB.
end() &&
MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1398 "unexpected DPR alignment gap");
1407 if (ReservedArgStack || IncomingArgStackToRestore) {
1408 assert((
int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1409 "attempting to restore negative stack amount");
1411 ReservedArgStack + IncomingArgStackToRestore,
1460 if (RegInfo->hasStackRealignment(MF)) {
1461 assert(
hasFP(MF) &&
"dynamic stack realignment without a FP!");
1465 }
else if (hasMovingSP) {
1467 "VLAs and dynamic stack alignment, but missing base pointer!");
1481 }
else if (hasMovingSP) {
1487 if (FPOffset >= -255 && FPOffset < 0) {
1506 }
else if (
Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1525 unsigned StmOpc,
unsigned StrOpc,
1526 bool NoGap,
bool (*Func)(
unsigned,
bool),
1527 unsigned NumAlignedDPRCS2Regs,
1528 unsigned MIFlags)
const {
1535 using RegAndKill = std::pair<unsigned, bool>;
1538 unsigned i = CSI.
size();
1540 unsigned LastReg = 0;
1541 for (; i != 0; --i) {
1546 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
1550 bool isLiveIn =
MRI.isLiveIn(Reg);
1551 if (!isLiveIn && !
MRI.isReserved(Reg))
1556 if (NoGap && LastReg && LastReg != Reg-1)
1564 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
1570 llvm::sort(Regs, [&](
const RegAndKill &LHS,
const RegAndKill &RHS) {
1571 return TRI.getEncodingValue(
LHS.first) <
TRI.getEncodingValue(
RHS.first);
1574 if (Regs.
size() > 1 || StrOpc== 0) {
1579 for (
unsigned i = 0, e = Regs.
size(); i < e; ++i)
1581 }
else if (Regs.
size() == 1) {
1602 unsigned LdmOpc,
unsigned LdrOpc,
1603 bool isVarArg,
bool NoGap,
1604 bool (*Func)(
unsigned,
bool),
1605 unsigned NumAlignedDPRCS2Regs)
const {
1612 bool isTailCall =
false;
1613 bool isInterrupt =
false;
1614 bool isTrap =
false;
1615 bool isCmseEntry =
false;
1617 DL =
MI->getDebugLoc();
1618 unsigned RetOpcode =
MI->getOpcode();
1620 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1621 RetOpcode == ARM::TCRETURNrinotr12);
1623 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1625 RetOpcode == ARM::TRAP || RetOpcode == ARM::TRAPNaCl ||
1626 RetOpcode == ARM::tTRAP;
1627 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1631 unsigned i = CSI.
size();
1633 unsigned LastReg = 0;
1634 bool DeleteRet =
false;
1635 for (; i != 0; --i) {
1641 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
1643 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1656 if (NoGap && LastReg && LastReg != Reg-1)
1666 llvm::sort(Regs, [&](
unsigned LHS,
unsigned RHS) {
1667 return TRI.getEncodingValue(LHS) <
TRI.getEncodingValue(RHS);
1670 if (Regs.
size() > 1 || LdrOpc == 0) {
1675 for (
unsigned Reg : Regs)
1680 MI->eraseFromParent();
1684 }
else if (Regs.size() == 1) {
1687 if (Regs[0] == ARM::PC)
1696 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1717 unsigned NumAlignedDPRCS2Regs,
1730 unsigned DNum =
I.getReg() - ARM::D8;
1731 if (DNum > NumAlignedDPRCS2Regs - 1)
1733 int FI =
I.getFrameIdx();
1761 unsigned Opc =
isThumb ? ARM::t2SUBri : ARM::SUBri;
1764 .
addImm(8 * NumAlignedDPRCS2Regs)
1780 Opc =
isThumb ? ARM::tMOVr : ARM::MOVr;
1789 unsigned NextReg = ARM::D8;
1793 if (NumAlignedDPRCS2Regs >= 6) {
1794 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1795 &ARM::QQPRRegClass);
1804 NumAlignedDPRCS2Regs -= 4;
1809 unsigned R4BaseReg = NextReg;
1812 if (NumAlignedDPRCS2Regs >= 4) {
1813 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1814 &ARM::QQPRRegClass);
1823 NumAlignedDPRCS2Regs -= 4;
1827 if (NumAlignedDPRCS2Regs >= 2) {
1828 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1837 NumAlignedDPRCS2Regs -= 2;
1841 if (NumAlignedDPRCS2Regs) {
1847 .
addImm((NextReg - R4BaseReg) * 2)
1859 unsigned NumAlignedDPRCS2Regs) {
1864 assert(
MI->mayStore() &&
"Expecting spill instruction");
1867 switch(NumAlignedDPRCS2Regs) {
1870 assert(
MI->mayStore() &&
"Expecting spill instruction");
1874 assert(
MI->mayStore() &&
"Expecting spill instruction");
1879 assert(
MI->killsRegister(ARM::R4,
nullptr) &&
"Missed kill flag");
1890 unsigned NumAlignedDPRCS2Regs,
1901 if (
I.getReg() == ARM::D8) {
1902 D8SpillFI =
I.getFrameIdx();
1914 unsigned Opc =
isThumb ? ARM::t2ADDri : ARM::ADDri;
1922 unsigned NextReg = ARM::D8;
1925 if (NumAlignedDPRCS2Regs >= 6) {
1926 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1927 &ARM::QQPRRegClass);
1935 NumAlignedDPRCS2Regs -= 4;
1940 unsigned R4BaseReg = NextReg;
1943 if (NumAlignedDPRCS2Regs >= 4) {
1944 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1945 &ARM::QQPRRegClass);
1952 NumAlignedDPRCS2Regs -= 4;
1956 if (NumAlignedDPRCS2Regs >= 2) {
1957 unsigned SupReg =
TRI->getMatchingSuperReg(NextReg, ARM::dsub_0,
1964 NumAlignedDPRCS2Regs -= 2;
1968 if (NumAlignedDPRCS2Regs)
1971 .
addImm(2 * (NextReg - R4BaseReg))
1987 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
1989 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
1990 unsigned FltOpc = ARM::VSTMDDB_UPD;
1999 return C.getReg() == ARM::FPCXTNS;
2008 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false,
2012 emitPushInst(
MBB,
MI, CSI, PushOpc, PushOneOpc,
false,
2026 if (NumAlignedDPRCS2Regs)
2045 if (NumAlignedDPRCS2Regs)
2048 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2051 unsigned FltOpc = ARM::VLDMDIA_UPD;
2053 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2056 NumAlignedDPRCS2Regs);
2057 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2061 NumAlignedDPRCS2Regs);
2062 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2064 emitPopInst(
MBB,
MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
2074 unsigned FnSize = 0;
2075 for (
auto &
MBB : MF) {
2076 for (
auto &
MI :
MBB)
2077 FnSize +=
TII.getInstSizeInBytes(
MI);
2081 FnSize += Table.MBBs.size() * 4;
2092 bool &HasNonSPFrameIndex) {
2097 unsigned Limit = (1 << 12) - 1;
2098 for (
auto &
MBB : MF) {
2099 for (
auto &
MI :
MBB) {
2100 if (
MI.isDebugInstr())
2102 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
2103 if (!
MI.getOperand(i).isFI())
2108 if (
MI.getOpcode() == ARM::ADDri) {
2109 Limit = std::min(Limit, (1U << 8) - 1);
2114 if (
MI.getOpcode() == ARM::t2ADDri ||
MI.getOpcode() == ARM::t2ADDri12)
2119 if (RegClass && !RegClass->
contains(ARM::SP))
2120 HasNonSPFrameIndex =
true;
2130 Limit = std::min(Limit, (1U << 8) - 1);
2133 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2138 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2144 Limit = std::min(Limit, (1U << 8) - 1);
2152 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2155 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2158 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2161 llvm_unreachable(
"Unhandled addressing mode in stack size limit calculation");
2202 unsigned NumSpills = 0;
2203 for (; NumSpills < 8; ++NumSpills)
2204 if (!SavedRegs.
test(ARM::D8 + NumSpills))
2215 SavedRegs.
set(ARM::R4);
2221 if (
STI.hasV8_1MMainlineOps() &&
2238 return Subtarget.createAAPCSFrameChain() &&
hasFP(MF);
2251 for (
const auto &
MBB : MF)
2252 for (
const auto &
MI :
MBB)
2253 if (
MI.getOpcode() == ARM::tSTRspi ||
MI.getOpcode() == ARM::tSTRi ||
2254 STI.genExecuteOnly())
2255 for (
const auto &
Op :
MI.operands())
2259 if (ARM::hGPRRegClass.
contains(Reg) && Reg != ARM::SP)
2274 bool CS1Spilled =
false;
2275 bool LRSpilled =
false;
2276 unsigned NumGPRSpills = 0;
2277 unsigned NumFPRSpills = 0;
2297 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2298 SavedRegs.
set(ARM::R4);
2307 SavedRegs.
set(ARM::R4);
2308 SavedRegs.
set(ARM::LR);
2314 SavedRegs.
set(ARM::LR);
2322 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2323 MFI.estimateStackSize(MF) > 508)
2324 SavedRegs.
set(ARM::R4);
2336 CanEliminateFrame =
false;
2340 CanEliminateFrame =
false;
2345 for (
unsigned i = 0; CSRegs[i]; ++i) {
2346 unsigned Reg = CSRegs[i];
2347 bool Spilled =
false;
2348 if (SavedRegs.
test(Reg)) {
2350 CanEliminateFrame =
false;
2353 if (!ARM::GPRRegClass.
contains(Reg)) {
2355 if (ARM::SPRRegClass.
contains(Reg))
2357 else if (ARM::DPRRegClass.
contains(Reg))
2359 else if (ARM::QPRRegClass.
contains(Reg))
2380 case ARM::R0:
case ARM::R1:
2381 case ARM::R2:
case ARM::R3:
2382 case ARM::R4:
case ARM::R5:
2383 case ARM::R6:
case ARM::R7:
2396 case ARM::R0:
case ARM::R1:
2397 case ARM::R2:
case ARM::R3:
2398 case ARM::R4:
case ARM::R5:
2399 case ARM::R6:
case ARM::R7:
2410 bool ForceLRSpill =
false;
2415 if (FnSize >= (1 << 11)) {
2416 CanEliminateFrame =
false;
2417 ForceLRSpill =
true;
2435 unsigned EstimatedStackSize =
2436 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2439 int MaxFixedOffset = 0;
2440 for (
int I = MFI.getObjectIndexBegin();
I < 0; ++
I) {
2441 int MaxObjectOffset = MFI.getObjectOffset(
I) + MFI.getObjectSize(
I);
2442 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2445 bool HasFP =
hasFP(MF);
2448 EstimatedStackSize += 4;
2452 EstimatedStackSize += MaxFixedOffset;
2454 EstimatedStackSize += 16;
2456 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2457 bool HasNonSPFrameIndex =
false;
2478 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2480 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2481 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2483 EstimatedRSStackSizeLimit =
2485 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2489 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2495 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2497 bool HasBPOrFixedSP = RegInfo->
hasBasePointer(MF) || !HasMovingSP;
2506 bool HasLargeArgumentList =
2507 HasFP && (MaxFixedOffset - MaxFPOffset) > (
int)EstimatedRSFixedSizeLimit;
2509 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2510 HasLargeArgumentList || HasNonSPFrameIndex;
2511 LLVM_DEBUG(
dbgs() <<
"EstimatedLimit: " << EstimatedRSStackSizeLimit
2512 <<
"; EstimatedStack: " << EstimatedStackSize
2513 <<
"; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2514 <<
"; BigFrameOffsets: " << BigFrameOffsets <<
"\n");
2515 if (BigFrameOffsets ||
2526 SavedRegs.
set(ARM::LR);
2529 auto LRPos =
llvm::find(UnspilledCS1GPRs, ARM::LR);
2530 if (LRPos != UnspilledCS1GPRs.
end())
2531 UnspilledCS1GPRs.
erase(LRPos);
2534 if (FPPos != UnspilledCS1GPRs.
end())
2535 UnspilledCS1GPRs.
erase(FPPos);
2553 unsigned NumExtraCSSpill = 0;
2570 int EntryRegDeficit = 0;
2571 for (
unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2576 <<
" is unused argument register, EntryRegDeficit = "
2577 << EntryRegDeficit <<
"\n");
2584 <<
" return regs used, ExitRegDeficit = "
2585 << ExitRegDeficit <<
"\n");
2587 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2592 for (
unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2593 if (SavedRegs.
test(Reg)) {
2596 <<
" is saved low register, RegDeficit = "
2597 << RegDeficit <<
"\n");
2603 <<
" is non-saved low register, adding to AvailableRegs\n");
2608 if (!HasFP ||
FramePtr != ARM::R7) {
2609 if (SavedRegs.
test(ARM::R7)) {
2612 << RegDeficit <<
"\n");
2617 <<
"%r7 is non-saved low register, adding to AvailableRegs\n");
2622 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2623 if (SavedRegs.
test(Reg)) {
2626 <<
" is saved high register, RegDeficit = "
2627 << RegDeficit <<
"\n");
2634 if ((EntryRegDeficit > ExitRegDeficit) &&
2637 if (SavedRegs.
test(ARM::LR)) {
2640 << RegDeficit <<
"\n");
2643 LLVM_DEBUG(
dbgs() <<
"%lr is not saved, adding to AvailableRegs\n");
2652 LLVM_DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
2653 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
2656 <<
" to make up reg deficit\n");
2660 assert(!
MRI.isReserved(Reg) &&
"Should not be reserved");
2661 if (Reg != ARM::LR && !
MRI.isPhysRegUsed(Reg))
2667 LLVM_DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit
2677 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2678 SavedRegs.
set(ARM::LR);
2681 LRPos =
llvm::find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
2682 if (LRPos != UnspilledCS1GPRs.
end())
2683 UnspilledCS1GPRs.
erase(LRPos);
2685 ForceLRSpill =
false;
2686 if (!
MRI.isReserved(ARM::LR) && !
MRI.isPhysRegUsed(ARM::LR) &&
2696 if (TargetAlign >=
Align(8) && (NumGPRSpills & 1)) {
2697 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
2698 for (
unsigned Reg : UnspilledCS1GPRs) {
2704 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2707 <<
" to make up alignment\n");
2708 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg) &&
2715 unsigned Reg = UnspilledCS2GPRs.
front();
2718 <<
" to make up alignment\n");
2719 if (!
MRI.isReserved(Reg) && !
MRI.isPhysRegUsed(Reg))
2730 unsigned RegsNeeded = 0;
2739 if (RegsNeeded > NumExtraCSSpill) {
2742 unsigned NumExtras = TargetAlign.
value() / 4;
2744 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
2746 if (!
MRI.isReserved(Reg) &&
2754 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
2756 if (!
MRI.isReserved(Reg)) {
2762 if (NumExtras == 0) {
2763 for (
unsigned Reg : Extras) {
2765 if (!
MRI.isPhysRegUsed(Reg))
2769 while ((RegsNeeded > NumExtraCSSpill) && RS) {
2773 unsigned Size =
TRI->getSpillSize(RC);
2774 Align Alignment =
TRI->getSpillAlign(RC);
2776 MFI.CreateStackObject(
Size, Alignment,
false));
2783 SavedRegs.
set(ARM::LR);
2796 if (
Info.getReg() != ARM::LR)
2800 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
2801 Term.getOpcode() == ARM::t2LDMIA_RET ||
2802 Term.getOpcode() == ARM::tPOP_RET;
2805 Info.setRestored(
false);
2826 SavedRegs.
set(ARM::R0);
2831 std::vector<CalleeSavedInfo> &CSI)
const {
2834 if (
STI.hasV8_1MMainlineOps() &&
2836 CSI.emplace_back(ARM::FPCXTNS);
2837 CSI.back().setRestored(
false);
2851 [=](
const auto &CS) {
2853 return Reg == ARM::R10 || Reg == ARM::R11 ||
2854 Reg == ARM::R8 || Reg == ARM::R9 ||
2855 ARM::DPRRegClass.contains(Reg);
2865 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
2866 NumEntries = std::size(FixedSpillOffsets);
2867 return FixedSpillOffsets;
2878 unsigned Opc =
I->getOpcode();
2879 bool IsDestroy = Opc ==
TII.getCallFrameDestroyOpcode();
2880 unsigned CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
2883 "This eliminateCallFramePseudoInstr does not support Thumb1!");
2885 int PIdx =
I->findFirstPredOperandIdx();
2889 unsigned PredReg =
TII.getFramePred(*
I);
2893 if (IsDestroy && CalleePopAmount != -1U)
2899 unsigned Amount =
TII.getFrameSize(*
I);
2906 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
2910 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
2915 }
else if (CalleePopAmount != -1U) {
2929 unsigned Shifted = 0;
2934 while (!(
Value & 0xC0000000)) {
2939 bool Carry = (
Value & 0x00FFFFFF);
2940 Value = ((
Value & 0xFF000000) >> 24) + Carry;
2942 if (
Value & 0x0000100)
2986 bool Thumb = ST->isThumb();
2987 bool Thumb2 = ST->isThumb2();
2993 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3011 unsigned ScratchReg0 = ARM::R4;
3012 unsigned ScratchReg1 = ARM::R5;
3013 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3030 if (BeforePrologueRegion.
insert(PredBB).second)
3033 }
while (!WalkList.
empty());
3043 BeforePrologueRegion.
insert(
B);
3045 for (
const auto &LI : PrologueMBB.
liveins()) {
3047 PredBB->addLiveIn(LI);
3053 BeforePrologueRegion.
erase(
B);
3098 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3101 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true), -4));
3102 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3105 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true), -8));
3106 BuildMI(PrevStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3115 }
else if (CompareStackPointer) {
3123 if (!CompareStackPointer && Thumb) {
3124 if (AlignedStackSize < 256) {
3128 .
addImm(AlignedStackSize)
3131 if (Thumb2 || ST->genExecuteOnly()) {
3133 .
addImm(AlignedStackSize);
3146 }
else if (!CompareStackPointer) {
3147 if (AlignedStackSize < 256) {
3150 .
addImm(AlignedStackSize)
3166 if (Thumb && ST->isThumb1Only()) {
3167 if (ST->genExecuteOnly()) {
3178 BuildMI(GetMBB,
DL,
TII.get(ARM::tLDRpci), ScratchReg0)
3191 BuildMI(McrMBB,
DL,
TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3201 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3202 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3206 BuildMI(GetMBB,
DL,
TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3215 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3222 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3235 if (AlignedStackSize < 256) {
3236 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg0)
3238 .
addImm(AlignedStackSize)
3241 if (Thumb2 || ST->genExecuteOnly()) {
3243 .
addImm(AlignedStackSize);
3252 if (AlignedStackSize < 256) {
3254 .
addImm(AlignedStackSize)
3269 BuildMI(AllocMBB,
DL,
TII.get(ARM::tMOVi8), ScratchReg1)
3274 if (Thumb2 || ST->genExecuteOnly()) {
3281 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3295 *AllocMBB,
MBBI,
DL, ScratchReg1, 0,
3317 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3320 nullptr,
MRI->getDwarfRegNum(ARM::LR,
true), -12));
3321 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3337 if (ST->isThumb1Only()) {
3381 BuildMI(AllocMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3407 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3413 nullptr,
MRI->getDwarfRegNum(ScratchReg0,
true)));
3414 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3417 nullptr,
MRI->getDwarfRegNum(ScratchReg1,
true)));
3418 BuildMI(PostStackMBB,
DL,
TII.get(TargetOpcode::CFI_INSTRUCTION))
3434#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)
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())
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.
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.
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 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...
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...
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.
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.
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
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.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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
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.
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 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 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.
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 drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
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 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.
@ 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 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.