40#define DEBUG_TYPE "x86-fl"
42STATISTIC(NumFrameLoopProbe,
"Number of loop stack probes used in prologue");
44 "Number of extra stack probes generated in prologue");
45STATISTIC(NumFunctionUsingPush2Pop2,
"Number of funtions using push2/pop2");
53 STI(STI),
TII(*STI.getInstrInfo()),
TRI(STI.getRegisterInfo()) {
77 (
hasFP(MF) && !
TRI->hasStackRealignment(MF)) ||
110 return IsLP64 ? X86::SUB64ri32 : X86::SUB32ri;
114 return IsLP64 ? X86::ADD64ri32 : X86::ADD32ri;
118 return IsLP64 ? X86::SUB64rr : X86::SUB32rr;
122 return IsLP64 ? X86::ADD64rr : X86::ADD32rr;
126 return IsLP64 ? X86::AND64ri32 : X86::AND32ri;
130 return IsLP64 ? X86::LEA64r : X86::LEA32r;
136 return X86::MOV32ri64;
138 return X86::MOV64ri32;
162 return ST.is64Bit() ? (ST.hasPPX() ? X86::PUSHP64r : X86::PUSH64r)
166 return ST.is64Bit() ? (ST.hasPPX() ? X86::POPP64r : X86::POP64r)
170 return ST.hasPPX() ? X86::PUSH2P : X86::PUSH2;
173 return ST.hasPPX() ? X86::POP2P : X86::POP2;
178 unsigned Reg = RegMask.PhysReg;
180 if (Reg == X86::RAX || Reg == X86::EAX || Reg == X86::AX ||
181 Reg == X86::AH || Reg == X86::AL)
195 bool BreakNext =
false;
200 if (Reg != X86::EFLAGS)
221 if (Succ->isLiveIn(X86::EFLAGS))
232 bool InEpilogue)
const {
233 bool isSub = NumBytes < 0;
247 if (EmitInlineStackProbe && !InEpilogue) {
253 }
else if (
Offset > Chunk) {
264 unsigned AddSubRROpc =
273 MI->getOperand(3).setIsDead();
275 }
else if (
Offset > 8 * Chunk) {
299 MI->getOperand(3).setIsDead();
319 unsigned Opc = isSub ? (
Is64Bit ? X86::PUSH64r : X86::PUSH32r)
320 : (
Is64Bit ? X86::POP64r : X86::POP32r);
329 BuildStackAdjustment(
MBB,
MBBI,
DL, isSub ? -ThisVal : ThisVal, InEpilogue)
339 assert(
Offset != 0 &&
"zero offset stack adjustment requested");
357 if (UseLEA && !
STI.useLeaForSP())
362 "We shouldn't have allowed this insertion point");
379 MI->getOperand(3).setIsDead();
386 bool doMergeWithPrevious)
const {
405 if (doMergeWithPrevious && PI !=
MBB.
begin() && PI->isCFIInstruction())
408 unsigned Opc = PI->getOpcode();
411 if ((Opc == X86::ADD64ri32 || Opc == X86::ADD32ri) &&
412 PI->getOperand(0).getReg() ==
StackPtr) {
414 Offset = PI->getOperand(2).getImm();
415 }
else if ((Opc == X86::LEA32r || Opc == X86::LEA64_32r) &&
416 PI->getOperand(0).getReg() ==
StackPtr &&
417 PI->getOperand(1).getReg() ==
StackPtr &&
418 PI->getOperand(2).getImm() == 1 &&
419 PI->getOperand(3).getReg() == X86::NoRegister &&
420 PI->getOperand(5).getReg() == X86::NoRegister) {
422 Offset = PI->getOperand(4).getImm();
423 }
else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB32ri) &&
424 PI->getOperand(0).getReg() ==
StackPtr) {
426 Offset = -PI->getOperand(2).getImm();
431 if (PI !=
MBB.
end() && PI->isCFIInstruction()) {
438 if (!doMergeWithPrevious)
475 unsigned DwarfReg =
MRI->getDwarfRegNum(MachineFramePtr,
true);
499 unsigned DwarfReg =
MRI->getDwarfRegNum(Reg,
true);
510 CfaExpr.
push_back(dwarf::DW_CFA_expression);
519 unsigned DwarfFramePtr =
MRI->getDwarfRegNum(MachineFramePtr,
true);
520 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfFramePtr));
535 int FI =
MI->getOperand(1).getIndex();
543 unsigned DwarfFramePtr =
MRI->getDwarfRegNum(MachineFramePtr,
true);
544 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfFramePtr));
550 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
560void X86FrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
576 if (!X86::RFP80RegClass.
contains(Reg))
579 unsigned NumFPRegs = ST.is64Bit() ? 8 : 7;
580 for (
unsigned i = 0; i != NumFPRegs; ++i)
583 for (
unsigned i = 0; i != NumFPRegs; ++i)
591 if (
TRI->isGeneralPurposeRegister(MF, Reg)) {
593 RegsToZero.
reset(Reg);
608 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
615 emitStackProbeInline(MF,
MBB,
MBBI,
DL,
false);
618 emitStackProbeCall(MF,
MBB,
MBBI,
DL, InProlog, InstrNum);
629 return MI.getOpcode() == X86::STACKALLOC_W_PROBING;
631 if (Where != PrologMBB.
end()) {
633 emitStackProbeInline(MF, PrologMBB, Where,
DL,
true);
634 Where->eraseFromParent();
642 bool InProlog)
const {
645 emitStackProbeInlineWindowsCoreCLR64(MF,
MBB,
MBBI,
DL, InProlog);
647 emitStackProbeInlineGeneric(MF,
MBB,
MBBI,
DL, InProlog);
650void X86FrameLowering::emitStackProbeInlineGeneric(
659 "different expansion expected for CoreCLR 64 bit");
661 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
662 uint64_t ProbeChunk = StackProbeSize * 8;
665 TRI->hasStackRealignment(MF) ? calculateMaxStackAlign(MF) : 0;
670 if (
Offset > ProbeChunk) {
672 MaxAlign % StackProbeSize);
675 MaxAlign % StackProbeSize);
679void X86FrameLowering::emitStackProbeInlineGenericBlock(
684 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
688 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
689 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
693 assert(AlignOffset < StackProbeSize);
696 if (StackProbeSize <
Offset + AlignOffset) {
699 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackAdjustment,
false)
701 if (!HasFP && NeedsDwarfCFI) {
712 NumFrameExtraProbe++;
713 CurrentOffset = StackProbeSize - AlignOffset;
719 while (CurrentOffset + StackProbeSize <
Offset) {
720 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackProbeSize,
false)
723 if (!HasFP && NeedsDwarfCFI) {
733 NumFrameExtraProbe++;
734 CurrentOffset += StackProbeSize;
743 unsigned Opc =
Is64Bit ? X86::PUSH64r : X86::PUSH32r;
748 BuildStackAdjustment(
MBB,
MBBI,
DL, -ChunkSize,
false)
755void X86FrameLowering::emitStackProbeInlineGenericLoop(
763 "Inline stack probe loop will clobber live EFLAGS.");
765 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
769 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
770 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
773 if (AlignOffset < StackProbeSize) {
775 BuildStackAdjustment(
MBB,
MBBI,
DL, -AlignOffset,
false)
783 NumFrameExtraProbe++;
796 MF.
insert(MBBIter, testMBB);
797 MF.
insert(MBBIter, tailMBB);
818 if (!HasFP && NeedsDwarfCFI) {
821 const Register DwarfFinalStackProbed =
828 nullptr,
TRI->getDwarfRegNum(DwarfFinalStackProbed,
true)));
835 BuildStackAdjustment(*testMBB, testMBB->
end(),
DL, -StackProbeSize,
869 BuildStackAdjustment(*tailMBB, TailMBBIter,
DL, -TailOffset,
875 if (!HasFP && NeedsDwarfCFI) {
885 nullptr,
TRI->getDwarfRegNum(DwarfStackPtr,
true)));
892void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
896 assert(
STI.is64Bit() &&
"different expansion needed for 32 bit");
903 "Inline stack probe loop will clobber live EFLAGS.");
938 MF.
insert(MBBIter, RoundMBB);
939 MF.
insert(MBBIter, LoopMBB);
940 MF.
insert(MBBIter, ContinueMBB);
948 const int64_t ThreadEnvironmentStackLimit = 0x10;
950 const int64_t PageMask = ~(
PageSize - 1);
957 SizeReg = InProlog ? X86::RAX :
MRI.createVirtualRegister(RegClass),
958 ZeroReg = InProlog ? X86::RCX :
MRI.createVirtualRegister(RegClass),
959 CopyReg = InProlog ? X86::RDX :
MRI.createVirtualRegister(RegClass),
960 TestReg = InProlog ? X86::RDX :
MRI.createVirtualRegister(RegClass),
961 FinalReg = InProlog ? X86::RDX :
MRI.createVirtualRegister(RegClass),
962 RoundedReg = InProlog ? X86::RDX :
MRI.createVirtualRegister(RegClass),
963 LimitReg = InProlog ? X86::RCX :
MRI.createVirtualRegister(RegClass),
964 JoinReg = InProlog ? X86::RCX :
MRI.createVirtualRegister(RegClass),
965 ProbeReg = InProlog ? X86::RCX :
MRI.createVirtualRegister(RegClass);
968 int64_t RCXShadowSlot = 0;
969 int64_t RDXShadowSlot = 0;
985 int64_t InitSlot = 8 + CalleeSaveSize + (
HasFP ? 8 : 0);
989 RCXShadowSlot = InitSlot;
991 RDXShadowSlot = InitSlot;
992 if (IsRDXLiveIn && IsRCXLiveIn)
1033 .
addImm(ThreadEnvironmentStackLimit)
1043 BuildMI(RoundMBB,
DL,
TII.get(X86::AND64ri32), RoundedReg)
1086 TII.get(X86::MOV64rm), X86::RCX),
1087 X86::RSP,
false, RCXShadowSlot);
1090 TII.get(X86::MOV64rm), X86::RDX),
1091 X86::RSP,
false, RDXShadowSlot);
1097 BuildMI(*ContinueMBB, ContinueMBBI,
DL,
TII.get(X86::SUB64rr), X86::RSP)
1110 for (++BeforeMBBI; BeforeMBBI !=
MBB.
end(); ++BeforeMBBI) {
1126void X86FrameLowering::emitStackProbeCall(
1129 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
1135 "code model and indirect thunks not yet implemented.");
1139 "Stack probe calls will clobber live EFLAGS.");
1143 CallOp = IsLargeCodeModel ? X86::CALL64r : X86::CALL64pcrel32;
1145 CallOp = X86::CALLpcrel32;
1206 for (++ExpansionMBBI; ExpansionMBBI !=
MBBI; ++ExpansionMBBI)
1214 const uint64_t Win64MaxSEHOffset = 128;
1215 uint64_t SEHFrameOffset = std::min(SPAdjust, Win64MaxSEHOffset);
1217 return SEHFrameOffset & -16;
1225X86FrameLowering::calculateMaxStackAlign(
const MachineFunction &MF)
const {
1232 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
1239 MaxAlign = (MaxAlign > 16) ? MaxAlign :
Align(16);
1241 MaxAlign =
Align(16);
1243 return MaxAlign.
value();
1256 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
1257 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
1262 if (Reg ==
StackPtr && EmitInlineStackProbe && MaxAlign >= StackProbeSize) {
1264 NumFrameLoopProbe++;
1275 MF.
insert(MBBIter, entryMBB);
1276 MF.
insert(MBBIter, headMBB);
1277 MF.
insert(MBBIter, bodyMBB);
1278 MF.
insert(MBBIter, footMBB);
1279 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
1288 BuildMI(entryMBB,
DL,
TII.get(TargetOpcode::COPY), FinalStackProbed)
1292 BuildMI(entryMBB,
DL,
TII.get(AndOp), FinalStackProbed)
1293 .
addReg(FinalStackProbed)
1298 MI->getOperand(3).setIsDead();
1302 .
addReg(FinalStackProbed)
1325 .
addReg(FinalStackProbed)
1355 .
addReg(FinalStackProbed)
1371 .
addReg(FinalStackProbed)
1390 MI->getOperand(3).setIsDead();
1398 "MF used frame lowering for wrong subtarget");
1407bool X86FrameLowering::isWin64Prologue(
const MachineFunction &MF)
const {
1411bool X86FrameLowering::needsDwarfCFI(
const MachineFunction &MF)
const {
1418 case X86::REPNE_PREFIX:
1419 case X86::REP_MOVSB_32:
1420 case X86::REP_MOVSB_64:
1421 case X86::REP_MOVSD_32:
1422 case X86::REP_MOVSD_64:
1423 case X86::REP_MOVSQ_32:
1424 case X86::REP_MOVSQ_64:
1425 case X86::REP_MOVSW_32:
1426 case X86::REP_MOVSW_64:
1427 case X86::REP_PREFIX:
1428 case X86::REP_STOSB_32:
1429 case X86::REP_STOSB_64:
1430 case X86::REP_STOSD_32:
1431 case X86::REP_STOSD_64:
1432 case X86::REP_STOSQ_32:
1433 case X86::REP_STOSQ_64:
1434 case X86::REP_STOSW_32:
1435 case X86::REP_STOSW_64:
1531 "MF used frame lowering for wrong subtarget");
1537 uint64_t MaxAlign = calculateMaxStackAlign(MF);
1543 bool FnHasClrFunclet =
1545 bool IsClrFunclet = IsFunclet && FnHasClrFunclet;
1546 bool HasFP =
hasFP(MF);
1547 bool IsWin64Prologue = isWin64Prologue(MF);
1552 bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;
1553 bool NeedsDwarfCFI = needsDwarfCFI(MF);
1559 bool HasWinCFI =
false;
1570 ArgBaseReg =
MI->getOperand(0).getReg();
1583 if (NeedsDwarfCFI) {
1585 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(ArgBaseReg,
true);
1604 if (TailCallArgReserveSize && IsWin64Prologue)
1607 const bool EmitStackProbeCall =
1624 .
addUse(X86::NoRegister);
1632 "win64 prologue does not set the bit 60 in the saved frame pointer");
1674 !EmitStackProbeCall &&
1682 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
1689 if (TailCallArgReserveSize != 0) {
1690 BuildStackAdjustment(
MBB,
MBBI,
DL, -(
int)TailCallArgReserveSize,
1713 Register Establisher = X86::NoRegister;
1719 if (IsWin64Prologue && IsFunclet && !IsClrFunclet) {
1739 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
1740 NumBytes =
alignTo(NumBytes, MaxAlign);
1748 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1754 nullptr, -2 * stackGrowth + (
int)TailCallArgReserveSize),
1758 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1762 (
int)TailCallArgReserveSize),
1775 assert(!IsWin64Prologue &&
1776 "win64 prologue does not store async context right below rbp");
1782 if (Attrs.hasAttrSomewhere(Attribute::SwiftAsync)) {
1817 if (!IsWin64Prologue && !IsFunclet) {
1826 if (NeedsDwarfCFI) {
1829 CfaExpr.
push_back(dwarf::DW_CFA_expression);
1831 unsigned DwarfReg =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1834 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfReg));
1843 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1862 assert(!IsFunclet &&
"funclets without FPs not yet implemented");
1870 if (HasFP &&
TRI->hasStackRealignment(MF))
1878 unsigned ParentFrameNumBytes = NumBytes;
1880 NumBytes = getWinEHFuncletFrameSize(MF);
1883 bool PushedRegs =
false;
1889 unsigned Opc =
MBBI->getOpcode();
1890 return Opc == X86::PUSH32r || Opc == X86::PUSH64r || Opc == X86::PUSHP64r ||
1891 Opc == X86::PUSH2 || Opc == X86::PUSH2P;
1894 while (IsCSPush(
MBBI)) {
1899 unsigned Opc = LastCSPush->getOpcode();
1901 if (!HasFP && NeedsDwarfCFI) {
1907 if (Opc == X86::PUSH2 || Opc == X86::PUSH2P)
1920 if (Opc == X86::PUSH2 || Opc == X86::PUSH2P)
1922 .
addImm(LastCSPush->getOperand(1).getReg())
1930 if (!IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF) &&
1932 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
1958 uint64_t AlignedNumBytes = NumBytes;
1959 if (IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF))
1960 AlignedNumBytes =
alignTo(AlignedNumBytes, MaxAlign);
1961 if (AlignedNumBytes >= StackProbeSize && EmitStackProbeCall) {
1963 "The Red Zone is not accounted for in stack probes");
1985 int64_t
Alloc = isEAXAlive ? NumBytes - 8 : NumBytes;
1993 .
addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
2012 }
else if (NumBytes) {
2016 if (NeedsWinCFI && NumBytes) {
2023 int SEHFrameOffset = 0;
2024 unsigned SPOrEstablisher;
2031 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2035 Establisher,
false, PSPSlotOffset)
2042 false, PSPSlotOffset)
2049 SPOrEstablisher = Establisher;
2054 if (IsWin64Prologue && HasFP) {
2061 SPOrEstablisher,
false, SEHFrameOffset);
2064 .
addReg(SPOrEstablisher);
2067 if (NeedsWinCFI && !IsFunclet) {
2068 assert(!NeedsWinFPO &&
"this setframe incompatible with FPO data");
2077 }
else if (IsFunclet &&
STI.is32Bit()) {
2101 if (X86::FR64RegClass.
contains(Reg)) {
2104 if (IsWin64Prologue && IsFunclet)
2112 assert(!NeedsWinFPO &&
"SEH_SaveXMM incompatible with FPO data");
2122 if (NeedsWinCFI && HasWinCFI)
2126 if (FnHasClrFunclet && !IsFunclet) {
2130 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2144 if (IsWin64Prologue &&
TRI->hasStackRealignment(MF)) {
2145 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2146 BuildStackAlignAND(
MBB,
MBBI,
DL, SPOrEstablisher, MaxAlign);
2150 if (IsFunclet &&
STI.is32Bit())
2183 assert(UsedReg == BasePtr);
2192 int FI =
MI->getOperand(1).getIndex();
2193 unsigned MOVmr =
Is64Bit ? X86::MOV64mr : X86::MOV32mr;
2200 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
2202 if (!HasFP && NumBytes) {
2228 bool NeedsCLD =
false;
2242 if (
MI.isInlineAsm()) {
2274 switch (
MI.getOpcode()) {
2276 case X86::CLEANUPRET:
2298X86FrameLowering::getPSPSlotOffsetFromSP(
const MachineFunction &MF)
const {
2305 return static_cast<unsigned>(
Offset);
2309X86FrameLowering::getWinEHFuncletFrameSize(
const MachineFunction &MF)
const {
2316 WinEHXMMSlotInfo.
size() *
TRI->getSpillSize(X86::VR128RegClass);
2325 UsedSize = getPSPSlotOffsetFromSP(MF) +
SlotSize;
2336 return FrameSizeMinusRBP + XMMSize - CSSize;
2340 return Opc == X86::TCRETURNri || Opc == X86::TCRETURNdi ||
2341 Opc == X86::TCRETURNmi || Opc == X86::TCRETURNri64 ||
2342 Opc == X86::TCRETURNdi64 || Opc == X86::TCRETURNmi64;
2353 DL =
MBBI->getDebugLoc();
2361 bool NeedsWin64CFI =
2367 uint64_t MaxAlign = calculateMaxStackAlign(MF);
2370 bool HasFP =
hasFP(MF);
2379 unsigned Opc = X86::LEA32r;
2381 ArgBaseReg =
MI->getOperand(0).getReg();
2382 if (
STI.is64Bit()) {
2384 StackReg = X86::RSP;
2395 if (NeedsDwarfCFI) {
2396 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(StackReg,
true);
2406 assert(HasFP &&
"EH funclets without FP not yet implemented");
2407 NumBytes = getWinEHFuncletFrameSize(MF);
2411 NumBytes = FrameSize - CSSize - TailCallArgReserveSize;
2415 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
2416 NumBytes =
alignTo(FrameSize, MaxAlign);
2418 NumBytes = StackSize - CSSize - TailCallArgReserveSize;
2420 uint64_t SEHStackAllocAmt = NumBytes;
2445 if (NeedsDwarfCFI) {
2447 unsigned DwarfStackPtr =
2448 TRI->getDwarfRegNum(
Is64Bit ? X86::RSP : X86::ESP,
true);
2454 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2469 unsigned Opc = PI->getOpcode();
2471 if (Opc != X86::DBG_VALUE && !PI->isTerminator()) {
2473 (Opc != X86::POP32r && Opc != X86::POP64r && Opc != X86::BTR64ri8 &&
2474 Opc != X86::ADD64ri32 && Opc != X86::POPP64r && Opc != X86::POP2 &&
2475 Opc != X86::POP2P && Opc != X86::LEA64r))
2485 int FI =
MI->getOperand(1).getIndex();
2486 unsigned MOVrm =
Is64Bit ? X86::MOV64rm : X86::MOV32rm;
2493 if (IsFunclet && Terminator->getOpcode() == X86::CATCHRET)
2494 emitCatchRetReturnValue(
MBB, FirstCSPop, &*Terminator);
2497 DL =
MBBI->getDebugLoc();
2509 if (
TRI->hasStackRealignment(MF))
2513 IsWin64Prologue ? SEHStackAllocAmt - SEHFrameOffset : -CSSize;
2525 if (LEAAmount != 0) {
2535 }
else if (NumBytes) {
2538 if (!HasFP && NeedsDwarfCFI) {
2542 nullptr, CSSize + TailCallArgReserveSize +
SlotSize),
2557 if (!HasFP && NeedsDwarfCFI) {
2564 unsigned Opc = PI->getOpcode();
2566 if (Opc == X86::POP32r || Opc == X86::POP64r || Opc == X86::POPP64r ||
2567 Opc == X86::POP2 || Opc == X86::POP2P) {
2571 if (Opc == X86::POP2 || Opc == X86::POP2P)
2589 assert(
Offset >= 0 &&
"TCDelta should never be positive");
2613 else if (
TRI->hasStackRealignment(MF))
2627 int64_t FPDelta = 0;
2638 if (IsWin64Prologue) {
2647 uint64_t NumBytes = FrameSize - CSSize;
2657 FPDelta = FrameSize - SEHFrameOffset;
2659 "FPDelta isn't aligned per the Win64 ABI!");
2671 if (TailCallReturnAddrDelta < 0)
2672 Offset -= TailCallReturnAddrDelta;
2690 const auto it = WinEHXMMSlotInfo.find(FI);
2692 if (it == WinEHXMMSlotInfo.end())
2703 int Adjustment)
const {
2713 bool IgnoreSPUpdates)
const {
2763 "we don't handle this case!");
2795 std::vector<CalleeSavedInfo> &CSI)
const {
2799 unsigned CalleeSavedFrameSize = 0;
2800 unsigned XMMCalleeSavedFrameSize = 0;
2806 if (TailCallReturnAddrDelta < 0) {
2817 TailCallReturnAddrDelta -
SlotSize,
true);
2821 if (this->TRI->hasBasePointer(MF)) {
2847 for (
unsigned i = 0; i < CSI.size(); ++i) {
2848 if (
TRI->regsOverlap(CSI[i].getReg(), FPReg)) {
2849 CSI.erase(CSI.begin() + i);
2864 unsigned NumRegsForPush2 = 0;
2865 if (
STI.hasPush2Pop2()) {
2867 return X86::GR64RegClass.contains(
I.getReg());
2869 bool NeedPadding = (SpillSlotOffset % 16 != 0) && (NumCSGPR % 2 == 0);
2870 bool UsePush2Pop2 = NeedPadding ? NumCSGPR > 2 : NumCSGPR > 1;
2872 NumRegsForPush2 = UsePush2Pop2 ?
alignDown(NumCSGPR, 2) : 0;
2889 (SpillSlotOffset % 16 == 0 ||
2911 "Expect even candidates for push2/pop2");
2913 ++NumFunctionUsingPush2Pop2;
2924 MVT VT = MVT::Other;
2925 if (X86::VK16RegClass.
contains(Reg))
2926 VT =
STI.hasBWI() ? MVT::v64i1 : MVT::v16i1;
2929 unsigned Size =
TRI->getSpillSize(*RC);
2930 Align Alignment =
TRI->getSpillAlign(*RC);
2932 assert(SpillSlotOffset < 0 &&
"SpillSlotOffset should always < 0 on X86");
2933 SpillSlotOffset = -
alignTo(-SpillSlotOffset, Alignment);
2936 SpillSlotOffset -=
Size;
2942 if (X86::VR128RegClass.
contains(Reg)) {
2943 WinEHXMMSlotInfo[
SlotIndex] = XMMCalleeSavedFrameSize;
2944 XMMCalleeSavedFrameSize +=
Size;
2969 auto UpdateLiveInCheckCanKill = [&](
Register Reg) {
2976 if (
MRI.isLiveIn(Reg))
2981 if (
MRI.isLiveIn(*AReg))
2985 auto UpdateLiveInGetKillRegState = [&](
Register Reg) {
2989 for (
auto RI = CSI.
rbegin(), RE = CSI.
rend(); RI != RE; ++RI) {
2997 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
2998 .
addReg(Reg2, UpdateLiveInGetKillRegState(Reg2))
3002 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3008 unsigned Opc =
STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r;
3009 Register BaseReg = this->TRI->getBaseRegister();
3023 MVT VT = MVT::Other;
3024 if (X86::VK16RegClass.
contains(Reg))
3025 VT =
STI.hasBWI() ? MVT::v64i1 : MVT::v16i1;
3047 "SEH should not use CATCHRET");
3052 if (
STI.is64Bit()) {
3084 if (
MI->getOpcode() == X86::CATCHRET) {
3102 MVT VT = MVT::Other;
3103 if (X86::VK16RegClass.
contains(Reg))
3104 VT =
STI.hasBWI() ? MVT::v64i1 : MVT::v16i1;
3115 unsigned Opc =
STI.is64Bit() ? X86::POP64r : X86::POP32r;
3116 Register BaseReg = this->TRI->getBaseRegister();
3122 for (
auto I = CSI.
begin(), E = CSI.
end();
I != E; ++
I) {
3151 SavedRegs.
set(BasePtr);
3159 if (
I->hasNestAttr() && !
I->use_empty())
3176 return Primary ? X86::R14 : X86::R13;
3178 return Primary ? X86::EBX : X86::EDI;
3183 return Primary ? X86::R11 : X86::R12;
3185 return Primary ? X86::R11D : X86::R12D;
3195 "nested function.");
3196 return Primary ? X86::EAX : X86::ECX;
3199 return Primary ? X86::EDX : X86::EAX;
3200 return Primary ? X86::ECX : X86::EAX;
3211 unsigned TlsReg, TlsOffset;
3216 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3220 "Scratch register is live-in");
3240 bool IsNested =
false;
3249 for (
const auto &LI : PrologueMBB.
liveins()) {
3268 TlsOffset =
IsLP64 ? 0x70 : 0x40;
3271 TlsOffset = 0x60 + 90 * 8;
3285 if (CompareStackPointer)
3286 ScratchReg =
IsLP64 ? X86::RSP : X86::ESP;
3309 TlsOffset = 0x48 + 90 * 4;
3322 if (CompareStackPointer)
3323 ScratchReg = X86::ESP;
3325 BuildMI(checkMBB,
DL,
TII.get(X86::LEA32r), ScratchReg)
3344 unsigned ScratchReg2;
3346 if (CompareStackPointer) {
3349 SaveScratch2 =
false;
3361 "Scratch register is live-in and not saved");
3367 BuildMI(checkMBB,
DL,
TII.get(X86::MOV32ri), ScratchReg2)
3378 BuildMI(checkMBB,
DL,
TII.get(X86::POP32r), ScratchReg2);
3394 const unsigned RegAX =
IsLP64 ? X86::RAX : X86::EAX;
3395 const unsigned Reg10 =
IsLP64 ? X86::R10 : X86::R10D;
3396 const unsigned Reg11 =
IsLP64 ? X86::R11 : X86::R11D;
3397 const unsigned MOVrr =
IsLP64 ? X86::MOV64rr : X86::MOV32rr;
3433 "code model and thunks not yet implemented.");
3450 BuildMI(allocMBB,
DL,
TII.get(X86::MORESTACK_RET_RESTORE_R10));
3459#ifdef EXPENSIVE_CHECKS
3470 for (
int i = 0, e = HiPELiteralsMD->
getNumOperands(); i != e; ++i) {
3472 if (
Node->getNumOperands() != 2)
3474 MDString *NodeName = dyn_cast<MDString>(
Node->getOperand(0));
3476 if (!NodeName || !NodeVal)
3479 if (ValConst && NodeName->
getString() == LiteralName) {
3485 " required but not provided");
3496 return MI.isMetaInstruction();
3522 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3527 if (!HiPELiteralsMD)
3529 "Can't generate HiPE prologue without runtime parameters");
3531 HiPELiteralsMD,
Is64Bit ?
"AMD64_LEAF_WORDS" :
"X86_LEAF_WORDS");
3532 const unsigned CCRegisteredArgs =
Is64Bit ? 6 : 5;
3533 const unsigned Guaranteed = HipeLeafWords *
SlotSize;
3540 "HiPE prologue is only supported on Linux operating systems.");
3550 unsigned MoreStackForCalls = 0;
3552 for (
auto &
MBB : MF) {
3553 for (
auto &
MI :
MBB) {
3573 if (
F->getName().contains(
"erlang.") ||
F->getName().contains(
"bif_") ||
3577 unsigned CalleeStkArity =
F->arg_size() > CCRegisteredArgs
3578 ?
F->arg_size() - CCRegisteredArgs
3580 if (HipeLeafWords - 1 > CalleeStkArity)
3582 std::max(MoreStackForCalls,
3583 (HipeLeafWords - 1 - CalleeStkArity) *
SlotSize);
3586 MaxStack += MoreStackForCalls;
3591 if (MaxStack > Guaranteed) {
3595 for (
const auto &LI : PrologueMBB.
liveins()) {
3603 unsigned ScratchReg, SPReg, PReg, SPLimitOffset;
3604 unsigned LEAop, CMPop, CALLop;
3609 LEAop = X86::LEA64r;
3610 CMPop = X86::CMP64rm;
3611 CALLop = X86::CALL64pcrel32;
3615 LEAop = X86::LEA32r;
3616 CMPop = X86::CMP32rm;
3617 CALLop = X86::CALLpcrel32;
3622 "HiPE prologue scratch register is live-in");
3629 PReg,
false, SPLimitOffset);
3639 PReg,
false, SPLimitOffset);
3649#ifdef EXPENSIVE_CHECKS
3666 if (NumPops != 1 && NumPops != 2)
3674 if (!Prev->isCall() || !Prev->getOperand(1).isRegMask())
3678 unsigned FoundRegs = 0;
3684 Is64Bit ? X86::GR64_NOREX_NOSPRegClass : X86::GR32_NOREX_NOSPRegClass;
3686 for (
auto Candidate : RegClass) {
3694 if (
MRI.isReserved(Candidate))
3699 if (MO.isReg() && MO.isDef() &&
3700 TRI->isSuperOrSubRegisterEq(MO.getReg(), Candidate)) {
3709 Regs[FoundRegs++] = Candidate;
3710 if (FoundRegs == (
unsigned)NumPops)
3718 while (FoundRegs < (
unsigned)NumPops)
3719 Regs[FoundRegs++] = Regs[0];
3721 for (
int i = 0; i < NumPops; ++i)
3732 unsigned Opcode =
I->getOpcode();
3733 bool isDestroy = Opcode ==
TII.getCallFrameDestroyOpcode();
3746 if (!reserveCallFrame) {
3767 bool HasDwarfEHHandlers = !WindowsCFI && !MF.
getLandingPads().empty();
3769 if (HasDwarfEHHandlers && !isDestroy &&
3779 Amount -= InternalAmt;
3789 int64_t StackAdjustment = isDestroy ? Amount : -Amount;
3791 if (StackAdjustment) {
3798 if (StackAdjustment) {
3799 if (!(
F.hasMinSize() &&
3800 adjustStackWithPops(
MBB, InsertPos,
DL, StackAdjustment)))
3801 BuildStackAdjustment(
MBB, InsertPos,
DL, StackAdjustment,
3814 int64_t CfaAdjustment = -StackAdjustment;
3817 if (CfaAdjustment) {
3830 while (CI !=
B && !std::prev(CI)->isCall())
3832 BuildStackAdjustment(
MBB, CI,
DL, -InternalAmt,
false);
3848 if (TLI.hasInlineStackProbe(MF) || TLI.hasStackProbeSymbol(MF))
3884 bool CompactUnwind =
3904 "restoring EBP/ESI on non-32-bit target");
3916 int EHRegSize = MFI.getObjectSize(FI);
3921 X86::EBP,
true, -EHRegSize)
3927 int EndOffset = -EHRegOffset - EHRegSize;
3940 "end of registration object above normal EBP position!");
3941 }
else if (UsedReg == BasePtr) {
3951 assert(UsedReg == BasePtr);
3977 FrameBase.
Kind = DwarfFrameBase::CFA;
3983 return DwarfFrameBase{DwarfFrameBase::Register, {FrameRegister}};
3988struct X86FrameSortingObject {
3989 bool IsValid =
false;
3990 unsigned ObjectIndex = 0;
3991 unsigned ObjectSize = 0;
3993 unsigned ObjectNumUses = 0;
4009struct X86FrameSortingComparator {
4010 inline bool operator()(
const X86FrameSortingObject &
A,
4011 const X86FrameSortingObject &
B)
const {
4012 uint64_t DensityAScaled, DensityBScaled;
4032 DensityAScaled =
static_cast<uint64_t>(
A.ObjectNumUses) *
4034 DensityBScaled =
static_cast<uint64_t>(
B.ObjectNumUses) *
4045 if (DensityAScaled == DensityBScaled)
4046 return A.ObjectAlignment <
B.ObjectAlignment;
4048 return DensityAScaled < DensityBScaled;
4062 if (ObjectsToAllocate.
empty())
4074 for (
auto &Obj : ObjectsToAllocate) {
4075 SortingObjects[Obj].IsValid =
true;
4076 SortingObjects[Obj].ObjectIndex = Obj;
4080 if (ObjectSize == 0)
4082 SortingObjects[Obj].ObjectSize = 4;
4084 SortingObjects[Obj].ObjectSize = ObjectSize;
4088 for (
auto &
MBB : MF) {
4089 for (
auto &
MI :
MBB) {
4090 if (
MI.isDebugInstr())
4096 int Index = MO.getIndex();
4100 SortingObjects[
Index].IsValid)
4101 SortingObjects[
Index].ObjectNumUses++;
4116 for (
auto &Obj : SortingObjects) {
4120 ObjectsToAllocate[i++] = Obj.ObjectIndex;
4124 if (!
TRI->hasStackRealignment(MF) &&
hasFP(MF))
4125 std::reverse(ObjectsToAllocate.
begin(), ObjectsToAllocate.
end());
4137 Offset += getWinEHFuncletFrameSize(MF);
4157 adjustFrameForMsvcCxxEh(MF);
4161void X86FrameLowering::adjustFrameForMsvcCxxEh(
MachineFunction &MF)
const {
4169 int64_t MinFixedObjOffset = -
SlotSize;
4175 int FrameIndex =
H.CatchObj.FrameIndex;
4176 if (FrameIndex != INT_MAX) {
4179 MinFixedObjOffset -= std::abs(MinFixedObjOffset) %
Align;
4187 MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8;
4188 int64_t UnwindHelpOffset = MinFixedObjOffset -
SlotSize;
4215 MI->eraseFromParent();
unsigned const MachineRegisterInfo * MRI
static bool isFuncletReturnInstr(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const uint64_t kSplitStackAvailable
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Given that RA is a live value
const HexagonInstrInfo * TII
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static bool isTailCallOpcode(unsigned Opc)
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static bool is64Bit(const char *name)
static unsigned calculateSetFPREG(uint64_t SPAdjust)
static unsigned GetScratchRegister(bool Is64Bit, bool IsLP64, const MachineFunction &MF, bool Primary)
GetScratchRegister - Get a temp register for performing work in the segmented stack and the Erlang/Hi...
static unsigned getADDriOpcode(bool IsLP64)
static unsigned getPUSH2Opcode(const X86Subtarget &ST)
static unsigned getMOVriOpcode(bool Use64BitReg, int64_t Imm)
static unsigned getLEArOpcode(bool IsLP64)
static unsigned getSUBriOpcode(bool IsLP64)
static bool flagsNeedToBePreservedBeforeTheTerminators(const MachineBasicBlock &MBB)
Check if the flags need to be preserved before the terminators.
static bool isOpcodeRep(unsigned Opcode)
Return true if an opcode is part of the REP group of instructions.
static unsigned getANDriOpcode(bool IsLP64, int64_t Imm)
static bool isEAXLiveIn(MachineBasicBlock &MBB)
static unsigned getADDrrOpcode(bool IsLP64)
static bool HasNestArgument(const MachineFunction *MF)
static unsigned getPOPOpcode(const X86Subtarget &ST)
static unsigned getPOP2Opcode(const X86Subtarget &ST)
static unsigned getHiPELiteral(NamedMDNode *HiPELiteralsMD, const StringRef LiteralName)
Lookup an ERTS parameter in the !hipe.literals named metadata node.
static bool blockEndIsUnreachable(const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI)
static unsigned getSUBrrOpcode(bool IsLP64)
static unsigned getPUSHOpcode(const X86Subtarget &ST)
static const unsigned FramePtr
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
reverse_iterator rend() const
bool empty() const
empty - Check if the array is empty.
reverse_iterator rbegin() const
LLVM Basic Block Representation.
iterator_range< const_set_bits_iterator > set_bits() const
static BranchProbability getOne()
static BranchProbability getZero()
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
AttributeList getAttributes() const
Return the attribute list for this Function.
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
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 createOffset(MCSymbol *L, unsigned Register, int Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_restore says that the rule for Register is now the same as it was at the beginning of the functi...
OpType getOperation() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment, SMLoc Loc={})
.cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but Offset is a relative value that is added/subt...
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
const MCObjectFileInfo * getObjectFileInfo() const
const MCRegisterInfo * getRegisterInfo() const
MCSection * getCompactUnwindSection() const
MCRegAliasIterator enumerates all registers aliasing Reg.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
StringRef getString() const
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator_range< livein_iterator > liveins() const
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
bool isEHFuncletEntry() const
Returns true if this is the entry block of an EH funclet.
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
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_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
@ LQR_Live
Register is known to be (at least partially) live.
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
bool isCleanupFuncletEntry() const
Returns true if this is the entry block of a cleanup funclet.
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.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
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 adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
void ensureMaxAlignment(Align Alignment)
Make sure the function is at least Align bytes aligned.
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...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool hasOpaqueSPAdjustment() const
Returns true if the function contains opaque dynamic stack adjustments.
void setCVBytesOfCalleeSavedRegisters(unsigned S)
int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
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.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
bool hasCopyImplyingStackAdjustment() const
Returns true if the function contains operations which will lower down to instructions which manipula...
bool hasStackObjects() const
Return true if there are any stack objects in this function.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getObjectIndexBegin() const
Return the minimum frame object index.
const WinEHFuncInfo * getWinEHFuncInfo() const
getWinEHFuncInfo - Return information about how the current function uses Windows exception handling.
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.
const std::vector< MCCFIInstruction > & getFrameInstructions() const
Returns a reference to a list of cfi instructions in the function's prologue.
void makeDebugValueSubstitution(DebugInstrOperandPair, DebugInstrOperandPair, unsigned SubReg=0)
Create a substitution between one <instr,operand> value to a different, new value.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
bool callsUnwindInit() const
void push_front(MachineBasicBlock *MBB)
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
bool callsEHReturn() 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
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
MachineModuleInfo & getMMI() const
bool shouldSplitStack() const
Should we be emitting segmented stack stuff for the function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
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.
bool hasEHFunclets() const
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 & 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 & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getDebugInstrNum()
Fetch the instruction number of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
const MCContext & getContext() const
const Module * getModule() const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
bool isLiveIn(Register Reg) const
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
unsigned getCodeViewFlag() const
Returns the CodeView Version by checking module flags.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
MDNode * getOperand(unsigned i) const
unsigned getNumOperands() const
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SlotIndex - An opaque wrapper around machine indexes.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
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...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
const Triple & getTargetTriple() const
CodeModel::Model getCodeModel() const
Returns the code model.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
SwiftAsyncFramePointerMode SwiftAsyncFramePointer
Control when and how the Swift async frame pointer bit should be set.
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool isOSWindows() const
Tests whether the OS is Windows.
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, XROS, or DriverKit).
bool has128ByteRedZone(const MachineFunction &MF) const
Return true if the function has a redzone (accessible bytes past the frame of the top of stack functi...
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
bool needsFrameIndexResolution(const MachineFunction &MF) const override
X86FrameLowering(const X86Subtarget &STI, MaybeAlign StackAlignOverride)
const X86RegisterInfo * TRI
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
MachineBasicBlock::iterator restoreWin32EHStackPointers(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool RestoreSP=false) const
Sets up EBP and optionally ESI based on the incoming EBP value.
int getInitialCFAOffset(const MachineFunction &MF) const override
Return initial CFA offset value i.e.
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog, std::optional< MachineFunction::DebugInstrOperandPair > InstrNum=std::nullopt) const
Emit target stack probe code.
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool IsPrologue) const
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
StackOffset getFrameIndexReferenceSP(const MachineFunction &MF, int FI, Register &SPReg, int Adjustment) const
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override
Replace a StackProbe inline-stub with the actual probe code inline.
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...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const
Emit a series of instructions to increment / decrement the stack pointer by a constant value.
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
bool Is64Bit
Is64Bit implies that x86_64 instructions are available.
Register getInitialCFARegister(const MachineFunction &MF) const override
Return initial CFA register value i.e.
bool Uses64BitFramePtr
True if the 64-bit frame or stack pointer should be used.
unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override
Adjust the prologue to have the function use segmented stacks.
DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override
Return the frame base information to be encoded in the DWARF subprogram debug info.
void emitCalleeSavedFrameMovesFullCFA(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override
Emits Dwarf Info specifying offsets of callee saved registers and frame pointer.
int getWin64EHFrameIndexRef(const MachineFunction &MF, int FI, Register &SPReg) const
bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const
Check that LEA can be used on SP in an epilogue sequence for MF.
bool stackProbeFunctionModifiesSP() const override
Does the stack probe function call return with a modified stack pointer?
void orderFrameObjects(const MachineFunction &MF, SmallVectorImpl< int > &ObjectsToAllocate) const override
Order the symbols in the local stack.
void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCCFIInstruction &CFIInst, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
Wraps up getting a CFI index and building a MachineInstr for it.
int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, bool doMergeWithPrevious) const
Check the instruction before/after the passed instruction.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
void processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameIndicesReplaced - This method is called immediately before MO_FrameIndex op...
StackOffset getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, Register &FrameReg, bool IgnoreSPUpdates) const override
Same as getFrameIndexReference, except that the stack pointer (as opposed to the frame pointer) will ...
void restoreWinEHStackPointersInParent(MachineFunction &MF) const
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...
void adjustForHiPEPrologue(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override
Erlang programs may need a special prologue to handle the stack size they might need at runtime.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void buildClearRegister(Register Reg, MachineBasicBlock &MBB, MachineBasicBlock::iterator Iter, DebugLoc &DL, bool AllowSideEffects=true) const override
int64_t getFrameAdjustment(const MachineInstr &I) const
Returns the stack pointer adjustment that happens inside the frame setup..destroy sequence (e....
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
bool getForceFramePointer() const
void setPadForPush2Pop2(bool V)
bool isCandidateForPush2Pop2(Register Reg) const
unsigned getArgumentStackSize() const
int getRestoreBasePointerOffset() const
int getSEHFramePtrSaveIndex() const
bool hasCFIAdjustCfa() const
int getTCReturnAddrDelta() const
void setRestoreBasePointer(const MachineFunction *MF)
bool getHasSEHFramePtrSave() const
DenseMap< int, unsigned > & getWinEHXMMSlotInfo()
void setUsesRedZone(bool V)
bool hasPreallocatedCall() const
bool hasSwiftAsyncContext() const
void setHasSEHFramePtrSave(bool V)
bool getRestoreBasePointer() const
MachineInstr * getStackPtrSaveMI() const
size_t getNumCandidatesForPush2Pop2() const
AMXProgModelEnum getAMXProgModel() const
void addCandidateForPush2Pop2(Register Reg)
unsigned getCalleeSavedFrameSize() const
bool getHasPushSequences() const
bool padForPush2Pop2() const
void setStackPtrSaveMI(MachineInstr *MI)
bool getUsesRedZone() const
void setCalleeSavedFrameSize(unsigned bytes)
void setSEHFramePtrSaveIndex(int Index)
bool hasBasePointer(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI) const
findDeadCallerSavedReg - Return a caller-saved register that isn't live when it reaches the "return" ...
Register getStackRegister() const
unsigned getSlotSize() const
Register getFramePtr() const
Returns physical register used as frame pointer.
Register getBaseRegister() const
const X86TargetLowering * getTargetLowering() const override
bool isTargetDragonFly() const
bool isTargetWindowsMSVC() const
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
bool isTargetDarwin() const
bool isTargetWin64() const
bool isTarget64BitLP64() const
Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
bool swiftAsyncContextIsDynamicallySet() const
Return whether FrameLowering should always set the "extended frame present" bit in FP,...
bool isTargetWindowsCoreCLR() const
const X86InstrInfo * getInstrInfo() const override
bool isCallingConvWin64(CallingConv::ID CC) const
bool isTargetFreeBSD() const
bool isTargetNaCl64() const
bool isTargetWin32() const
bool useIndirectThunkCalls() const
bool isTargetLinux() const
bool hasInlineStackProbe(const MachineFunction &MF) const override
Returns true if stack probing through inline assembly is requested.
StringRef getStackProbeSymbolName(const MachineFunction &MF) const override
Returns the name of the symbol used to emit stack probes or the empty string if not applicable.
bool hasStackProbeSymbol(const MachineFunction &MF) const override
Returns true if stack probing through a function call is requested.
unsigned getStackProbeSize(const MachineFunction &MF) const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint16_t StackAdjustment(const RuntimeFunction &RF)
StackAdjustment - calculated stack adjustment in words.
@ HiPE
Used by the High-Performance Erlang Compiler (HiPE).
@ X86_INTR
x86 hardware interrupt context.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ X86_FastCall
'fast' analog of X86_StdCall.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
Reg
All possible values of the reg field in the ModR/M byte.
@ MO_GOTPCREL
MO_GOTPCREL - On a symbol operand this indicates that the immediate is offset to the GOT entry for th...
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
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.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
@ DwarfCFI
DWARF-like instruction based exceptions.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0, bool mem=true)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
auto reverse(ContainerTy &&C)
static const MachineInstrBuilder & addRegOffset(const MachineInstrBuilder &MIB, unsigned Reg, bool isKill, int Offset)
addRegOffset - This function is used to add a memory reference of the form [Reg + Offset],...
@ Always
Always set the bit.
@ Never
Never set the bit.
@ DeploymentBased
Determine whether to set the bit statically or dynamically based on the deployment target.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
IterT skipDebugInstructionsBackward(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It until it points to a non-debug instruction or to Begin and return the resulting iterator...
unsigned getUndefRegState(bool B)
unsigned getDefRegState(bool B)
unsigned getKillRegState(bool B)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the largest uint64_t less than or equal to Value and is Skew mod Align.
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
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.
Pair of physical register and lane mask.
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
enum llvm::TargetFrameLowering::DwarfFrameBase::FrameBaseKind Kind
union llvm::TargetFrameLowering::DwarfFrameBase::@240 Location
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
SmallVector< WinEHHandlerType, 1 > HandlerArray