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 functions using push2/pop2");
53 return STI.hasBWI() ? &X86::VK64RegClass : &X86::VK16RegClass;
54 return TRI.getMinimalPhysRegClass(
Reg);
86 (
hasFP(MF) && !
TRI->hasStackRealignment(MF)) ||
87 TRI->hasBasePointer(MF);
119 return IsLP64 ? X86::SUB64ri32 : X86::SUB32ri;
123 return IsLP64 ? X86::ADD64ri32 : X86::ADD32ri;
127 return IsLP64 ? X86::SUB64rr : X86::SUB32rr;
131 return IsLP64 ? X86::ADD64rr : X86::ADD32rr;
135 return IsLP64 ? X86::AND64ri32 : X86::AND32ri;
139 return IsLP64 ? X86::LEA64r : X86::LEA32r;
160 return ST.is64Bit() ? (ST.hasPPX() ? X86::PUSHP64r : X86::PUSH64r)
164 return ST.is64Bit() ? (ST.hasPPX() ? X86::POPP64r : X86::POP64r)
168 return ST.hasPPX() ? X86::PUSH2P : X86::PUSH2;
171 return ST.hasPPX() ? X86::POP2P : X86::POP2;
178 if (
Reg == X86::RAX ||
Reg == X86::EAX ||
Reg == X86::AX ||
179 Reg == X86::AH ||
Reg == X86::AL)
193 bool BreakNext =
false;
198 if (
Reg != X86::EFLAGS)
219 if (Succ->isLiveIn(X86::EFLAGS))
232 bool InEpilogue)
const {
233 bool isSub = NumBytes < 0;
249 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
253 if (EmitInlineStackProbe && !InEpilogue) {
281 MI->getOperand(3).setIsDead();
308 MI->getOperand(3).setIsDead();
327 unsigned Opc = isSub ? (
Is64Bit ? X86::PUSH64r : X86::PUSH32r)
328 : (
Is64Bit ? X86::POP64r : X86::POP32r);
338 BuildStackAdjustment(
MBB,
MBBI,
DL, isSub ? -ThisVal : ThisVal, InEpilogue)
348 assert(
Offset != 0 &&
"zero offset stack adjustment requested");
358 UseLEA =
STI.useLeaForSP() ||
MBB.isLiveIn(X86::EFLAGS);
366 if (UseLEA && !
STI.useLeaForSP())
371 "We shouldn't have allowed this insertion point");
374 MachineInstrBuilder
MI;
388 const unsigned Opc = IsSub ? X86::SUB64ri32_NF : X86::ADD64ri32_NF;
404 MI->getOperand(3).setIsDead();
409template <
typename FoundT,
typename CalcT>
412 FoundT FoundStackAdjust,
414 bool doMergeWithPrevious)
const {
417 return CalcNewOffset(0);
433 if (doMergeWithPrevious && PI !=
MBB.
begin() && PI->isCFIInstruction())
438 unsigned Opc = PI->getOpcode();
440 if ((
Opc == X86::ADD64ri32 ||
Opc == X86::ADD32ri ||
441 Opc == X86::ADD64ri32_NF) &&
442 PI->getOperand(0).getReg() ==
StackPtr) {
444 Offset = PI->getOperand(2).getImm();
445 }
else if ((
Opc == X86::LEA32r ||
Opc == X86::LEA64_32r) &&
446 PI->getOperand(0).getReg() ==
StackPtr &&
447 PI->getOperand(1).getReg() ==
StackPtr &&
448 PI->getOperand(2).getImm() == 1 &&
449 PI->getOperand(3).getReg() == X86::NoRegister &&
450 PI->getOperand(5).getReg() == X86::NoRegister) {
452 Offset = PI->getOperand(4).getImm();
453 }
else if ((
Opc == X86::SUB64ri32 ||
Opc == X86::SUB32ri ||
454 Opc == X86::SUB64ri32_NF) &&
455 PI->getOperand(0).getReg() ==
StackPtr) {
457 Offset = -PI->getOperand(2).getImm();
459 return CalcNewOffset(0);
461 FoundStackAdjust(PI,
Offset);
465 if (doMergeWithPrevious ? (PI ==
MBB.
begin()) : (PI ==
MBB.
end()))
466 return CalcNewOffset(0);
468 PI = doMergeWithPrevious ? std::prev(PI) : std::next(PI);
472 if (PI !=
MBB.
end() && PI->isCFIInstruction()) {
474 MCCFIInstruction CI = CIs[PI->getOperand(0).getCFIIndex()];
479 if (!doMergeWithPrevious)
482 return CalcNewOffset(
Offset);
488 bool doMergeWithPrevious)
const {
489 return mergeSPUpdates(
491 doMergeWithPrevious);
558 CfaExpr.
push_back(dwarf::DW_CFA_expression);
564 STI.isTarget64BitILP32()
567 unsigned DwarfFramePtr = MRI->
getDwarfRegNum(MachineFramePtr,
true);
583 int FI =
MI->getOperand(1).getIndex();
588 STI.isTarget64BitILP32()
591 unsigned DwarfFramePtr = MRI->
getDwarfRegNum(MachineFramePtr,
true);
598 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
608void X86FrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
624 if (!X86::RFP80RegClass.
contains(Reg))
627 unsigned NumFPRegs = ST.is64Bit() ? 8 : 7;
628 for (
unsigned i = 0; i != NumFPRegs; ++i)
631 for (
unsigned i = 0; i != NumFPRegs; ++i)
639 if (
TRI->isGeneralPurposeRegister(MF,
Reg)) {
645 for (MCRegister
Reg : GPRsToZero.set_bits())
656 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
658 if (
STI.isTargetWindowsCoreCLR()) {
663 emitStackProbeInline(MF,
MBB,
MBBI,
DL,
false);
666 emitStackProbeCall(MF,
MBB,
MBBI,
DL, InProlog, InstrNum);
671 return STI.isOSWindows() && !
STI.isTargetWin64();
677 return MI.getOpcode() == X86::STACKALLOC_W_PROBING;
679 if (Where != PrologMBB.
end()) {
681 emitStackProbeInline(MF, PrologMBB, Where,
DL,
true);
682 Where->eraseFromParent();
690 bool InProlog)
const {
693 emitStackProbeInlineWindowsCoreCLR64(MF,
MBB,
MBBI,
DL, InProlog);
695 emitStackProbeInlineGeneric(MF,
MBB,
MBBI,
DL, InProlog);
698void X86FrameLowering::emitStackProbeInlineGeneric(
707 "different expansion expected for CoreCLR 64 bit");
709 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
710 uint64_t ProbeChunk = StackProbeSize * 8;
713 TRI->hasStackRealignment(MF) ? calculateMaxStackAlign(MF) : 0;
718 if (
Offset > ProbeChunk) {
720 MaxAlign % StackProbeSize);
723 MaxAlign % StackProbeSize);
727void X86FrameLowering::emitStackProbeInlineGenericBlock(
730 uint64_t AlignOffset)
const {
732 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
735 const X86TargetLowering &TLI = *
STI.getTargetLowering();
736 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
737 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
739 uint64_t CurrentOffset = 0;
741 assert(AlignOffset < StackProbeSize);
744 if (StackProbeSize <
Offset + AlignOffset) {
747 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackAdjustment,
false)
749 if (!HasFP && NeedsDwarfCFI) {
760 NumFrameExtraProbe++;
761 CurrentOffset = StackProbeSize - AlignOffset;
767 while (CurrentOffset + StackProbeSize <
Offset) {
768 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackProbeSize,
false)
771 if (!HasFP && NeedsDwarfCFI) {
781 NumFrameExtraProbe++;
782 CurrentOffset += StackProbeSize;
786 uint64_t ChunkSize =
Offset - CurrentOffset;
791 unsigned Opc =
Is64Bit ? X86::PUSH64r : X86::PUSH32r;
796 BuildStackAdjustment(
MBB,
MBBI,
DL, -ChunkSize,
false)
803void X86FrameLowering::emitStackProbeInlineGenericLoop(
806 uint64_t AlignOffset)
const {
811 "Inline stack probe loop will clobber live EFLAGS.");
813 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
816 const X86TargetLowering &TLI = *
STI.getTargetLowering();
817 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
818 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
821 if (AlignOffset < StackProbeSize) {
823 BuildStackAdjustment(
MBB,
MBBI,
DL, -AlignOffset,
false)
831 NumFrameExtraProbe++;
844 MF.
insert(MBBIter, testMBB);
845 MF.
insert(MBBIter, tailMBB);
885 if (!HasFP && NeedsDwarfCFI) {
888 const Register DwarfFinalStackProbed =
889 STI.isTarget64BitILP32()
895 nullptr,
TRI->getDwarfRegNum(DwarfFinalStackProbed,
true)));
902 BuildStackAdjustment(*testMBB, testMBB->
end(),
DL, -StackProbeSize,
933 const uint64_t TailOffset =
Offset % StackProbeSize;
936 BuildStackAdjustment(*tailMBB, TailMBBIter,
DL, -TailOffset,
942 if (!HasFP && NeedsDwarfCFI) {
946 STI.isTarget64BitILP32()
952 nullptr,
TRI->getDwarfRegNum(DwarfStackPtr,
true)));
959void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
963 assert(
STI.is64Bit() &&
"different expansion needed for 32 bit");
964 assert(
STI.isTargetWindowsCoreCLR() &&
"custom expansion expects CoreCLR");
965 const TargetInstrInfo &
TII = *
STI.getInstrInfo();
970 "Inline stack probe loop will clobber live EFLAGS.");
1005 MF.
insert(MBBIter, RoundMBB);
1006 MF.
insert(MBBIter, LoopMBB);
1007 MF.
insert(MBBIter, ContinueMBB);
1015 const int64_t ThreadEnvironmentStackLimit = 0x10;
1017 const int64_t PageMask = ~(
PageSize - 1);
1022 const TargetRegisterClass *RegClass = &X86::GR64RegClass;
1035 int64_t RCXShadowSlot = 0;
1036 int64_t RDXShadowSlot = 0;
1043 X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
1052 int64_t InitSlot = 8 + CalleeSaveSize + (
HasFP ? 8 : 0);
1056 RCXShadowSlot = InitSlot;
1058 RDXShadowSlot = InitSlot;
1059 if (IsRDXLiveIn && IsRCXLiveIn)
1100 .
addImm(ThreadEnvironmentStackLimit)
1111 BuildMI(RoundMBB,
DL,
TII.get(X86::AND64ri32), RoundedReg)
1156 TII.get(X86::MOV64rm), X86::RCX),
1157 X86::RSP,
false, RCXShadowSlot);
1160 TII.get(X86::MOV64rm), X86::RDX),
1161 X86::RSP,
false, RDXShadowSlot);
1166 BuildMI(*ContinueMBB, ContinueMBBI,
DL,
TII.get(X86::SUB64rr), X86::RSP)
1178 LivePhysRegs LiveRegs;
1184 for (++BeforeMBBI; BeforeMBBI !=
MBB.
end(); ++BeforeMBBI) {
1187 for (MachineInstr &
MI : *RoundMBB) {
1190 for (MachineInstr &
MI : *LoopMBB) {
1193 for (MachineInstr &
MI :
1200void X86FrameLowering::emitStackProbeCall(
1203 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
1207 if (
Is64Bit && IsLargeCodeModel &&
STI.useIndirectThunkCalls())
1209 "code model and indirect thunks not yet implemented.");
1213 "Stack probe calls will clobber live EFLAGS.");
1217 CallOp = IsLargeCodeModel ? X86::CALL64r : X86::CALL64pcrel32;
1219 CallOp = X86::CALLpcrel32;
1221 StringRef
Symbol =
STI.getTargetLowering()->getStackProbeSymbolName(MF);
1223 MachineInstrBuilder CI;
1247 MachineInstr *ModInst = CI;
1248 if (
STI.isTargetWin64() || !
STI.isOSWindows()) {
1265 if (
STI.isTargetWin64() || !
STI.isOSWindows()) {
1280 for (++ExpansionMBBI; ExpansionMBBI !=
MBBI; ++ExpansionMBBI)
1288 const uint64_t Win64MaxSEHOffset = 128;
1289 uint64_t SEHFrameOffset = std::min(SPAdjust, Win64MaxSEHOffset);
1291 return SEHFrameOffset & -16;
1299X86FrameLowering::calculateMaxStackAlign(
const MachineFunction &MF)
const {
1306 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
1313 MaxAlign = (MaxAlign > 16) ? MaxAlign :
Align(16);
1315 MaxAlign =
Align(16);
1317 return MaxAlign.
value();
1323 uint64_t MaxAlign)
const {
1324 uint64_t Val = -MaxAlign;
1329 const X86TargetLowering &TLI = *
STI.getTargetLowering();
1330 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
1331 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
1336 if (
Reg ==
StackPtr && EmitInlineStackProbe && MaxAlign >= StackProbeSize) {
1338 NumFrameLoopProbe++;
1339 MachineBasicBlock *entryMBB =
1341 MachineBasicBlock *headMBB =
1343 MachineBasicBlock *bodyMBB =
1345 MachineBasicBlock *footMBB =
1349 MF.
insert(MBBIter, entryMBB);
1350 MF.
insert(MBBIter, headMBB);
1351 MF.
insert(MBBIter, bodyMBB);
1352 MF.
insert(MBBIter, footMBB);
1353 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
1362 BuildMI(entryMBB,
DL,
TII.get(TargetOpcode::COPY), FinalStackProbed)
1366 BuildMI(entryMBB,
DL,
TII.get(AndOp), FinalStackProbed)
1367 .
addReg(FinalStackProbed)
1372 MI->getOperand(3).setIsDead();
1376 .
addReg(FinalStackProbed)
1399 .
addReg(FinalStackProbed)
1429 .
addReg(FinalStackProbed)
1445 .
addReg(FinalStackProbed)
1464 MI->getOperand(3).setIsDead();
1472 "MF used frame lowering for wrong subtarget");
1481bool X86FrameLowering::isWin64Prologue(
const MachineFunction &MF)
const {
1485bool X86FrameLowering::needsDwarfCFI(
const MachineFunction &MF)
const {
1492 case X86::REPNE_PREFIX:
1493 case X86::REP_MOVSB_32:
1494 case X86::REP_MOVSB_64:
1495 case X86::REP_MOVSD_32:
1496 case X86::REP_MOVSD_64:
1497 case X86::REP_MOVSQ_32:
1498 case X86::REP_MOVSQ_64:
1499 case X86::REP_MOVSW_32:
1500 case X86::REP_MOVSW_64:
1501 case X86::REP_PREFIX:
1502 case X86::REP_STOSB_32:
1503 case X86::REP_STOSB_64:
1504 case X86::REP_STOSD_32:
1505 case X86::REP_STOSD_64:
1506 case X86::REP_STOSQ_32:
1507 case X86::REP_STOSQ_64:
1508 case X86::REP_STOSW_32:
1509 case X86::REP_STOSW_64:
1605 "MF used frame lowering for wrong subtarget");
1610 uint64_t MaxAlign = calculateMaxStackAlign(MF);
1612 bool IsFunclet =
MBB.isEHFuncletEntry();
1616 bool FnHasClrFunclet =
1618 bool IsClrFunclet = IsFunclet && FnHasClrFunclet;
1619 bool HasFP =
hasFP(MF);
1620 bool IsWin64Prologue = isWin64Prologue(MF);
1623 bool NeedsWinFPO = !IsFunclet &&
STI.isTargetWin32() &&
1625 bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;
1626 bool NeedsDwarfCFI = needsDwarfCFI(MF);
1627 bool IsWin64UnwindV3 =
1635 bool HasWinCFI =
false;
1644 auto EmitSEHBefore = [&](
auto EmitFn) {
1645 if (NeedsWinCFI && IsWin64UnwindV3) {
1650 auto EmitSEHAfter = [&](
auto EmitFn) {
1651 if (NeedsWinCFI && !IsWin64UnwindV3) {
1666 ArgBaseReg =
MI->getOperand(0).getReg();
1679 if (NeedsDwarfCFI) {
1681 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(ArgBaseReg,
true);
1700 if (TailCallArgReserveSize && IsWin64Prologue)
1703 const bool EmitStackProbeCall =
1704 STI.getTargetLowering()->hasStackProbeSymbol(MF);
1705 unsigned StackProbeSize =
STI.getTargetLowering()->getStackProbeSize(MF);
1710 if (
STI.swiftAsyncContextIsDynamicallySet()) {
1720 .
addUse(X86::NoRegister);
1728 "win64 prologue does not set the bit 60 in the saved frame pointer");
1770 !EmitStackProbeCall &&
1778 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
1785 if (TailCallArgReserveSize != 0) {
1786 BuildStackAdjustment(
MBB,
MBBI,
DL, -(
int)TailCallArgReserveSize,
1815 if (IsWin64Prologue && IsFunclet && !IsClrFunclet) {
1823 MBB.addLiveIn(Establisher);
1835 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
1836 NumBytes =
alignTo(NumBytes, MaxAlign);
1839 auto EmitSEHPushFramePtr = [&]() {
1844 EmitSEHBefore(EmitSEHPushFramePtr);
1849 EmitSEHAfter(EmitSEHPushFramePtr);
1851 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1857 nullptr, -2 * stackGrowth + (
int)TailCallArgReserveSize),
1861 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1865 (
int)TailCallArgReserveSize),
1871 assert(!IsWin64Prologue &&
1872 "win64 prologue does not store async context right below rbp");
1878 auto EmitSEHPushR14 = [&]() {
1883 EmitSEHBefore(EmitSEHPushR14);
1884 if (Attrs.hasAttrSomewhere(Attribute::SwiftAsync)) {
1887 MBB.addLiveIn(X86::R14);
1898 EmitSEHAfter(EmitSEHPushR14);
1913 if (!IsWin64Prologue && !IsFunclet) {
1922 if (NeedsDwarfCFI) {
1925 CfaExpr.
push_back(dwarf::DW_CFA_expression);
1927 unsigned DwarfReg =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1939 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1951 assert(!IsWin64UnwindV3);
1961 assert(!IsFunclet &&
"funclets without FPs not yet implemented");
1969 if (HasFP &&
TRI->hasStackRealignment(MF))
1977 unsigned ParentFrameNumBytes = NumBytes;
1979 NumBytes = getWinEHFuncletFrameSize(MF);
1982 bool PushedRegs =
false;
1988 unsigned Opc =
MBBI->getOpcode();
1989 return Opc == X86::PUSH32r ||
Opc == X86::PUSH64r ||
Opc == X86::PUSHP64r ||
1990 Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
1993 while (IsCSPush(
MBBI)) {
1997 unsigned Opc = LastCSPush->getOpcode();
1998 bool IsPush2 =
Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
2001 EmitSEHBefore([&]() {
2005 .
addImm(LastCSPush->getOperand(1).getReg())
2015 if (!HasFP && NeedsDwarfCFI) {
2030 EmitSEHAfter([&]() {
2036 .
addImm(LastCSPush->getOperand(1).getReg())
2044 if (!IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF) &&
2046 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2047 auto EmitSEHStackAlign = [&]() {
2052 EmitSEHBefore(EmitSEHStackAlign);
2054 EmitSEHAfter(EmitSEHStackAlign);
2060 NumBytes = mergeSPUpdates(
2074 uint64_t AlignedNumBytes = NumBytes;
2075 if (IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF))
2076 AlignedNumBytes =
alignTo(AlignedNumBytes, MaxAlign);
2078 auto EmitSEHStackAlloc = [&]() {
2084 EmitSEHBefore(EmitSEHStackAlloc);
2086 if (AlignedNumBytes >= StackProbeSize && EmitStackProbeCall) {
2088 "The Red Zone is not accounted for in stack probes");
2110 int64_t
Alloc = isEAXAlive ? NumBytes - 8 : NumBytes;
2119 .
addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
2138 }
else if (NumBytes) {
2143 EmitSEHAfter(EmitSEHStackAlloc);
2145 int SEHFrameOffset = 0;
2153 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2155 MBB.addLiveIn(Establisher);
2157 Establisher,
false, PSPSlotOffset)
2164 false, PSPSlotOffset)
2171 SPOrEstablisher = Establisher;
2176 if (IsWin64Prologue && HasFP) {
2183 if (NeedsWinCFI && !IsFunclet) {
2184 assert(!NeedsWinFPO &&
"this setframe incompatible with FPO data");
2187 if (
TRI->hasBasePointer(MF))
2195 auto EmitSEHSetFrame = [&]() {
2203 EmitSEHBefore(EmitSEHSetFrame);
2207 SPOrEstablisher,
false, SEHFrameOffset);
2210 .
addReg(SPOrEstablisher);
2213 EmitSEHAfter(EmitSEHSetFrame);
2214 }
else if (IsFunclet &&
STI.is32Bit()) {
2219 if (!
MBB.isCleanupFuncletEntry()) {
2236 if (
Register Reg =
TII.isStoreToStackSlot(FrameInstr, FI)) {
2237 if (X86::FR64RegClass.
contains(Reg)) {
2240 if (IsWin64Prologue && IsFunclet)
2247 assert(!NeedsWinFPO &&
"SEH_SaveXMM incompatible with FPO data");
2248 auto EmitSEHSaveXMM = [&]() {
2254 EmitSEHBefore(EmitSEHSaveXMM);
2256 EmitSEHAfter(EmitSEHSaveXMM);
2264 if (NeedsWinCFI && HasWinCFI) {
2269 if (FnHasClrFunclet && !IsFunclet) {
2273 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2287 if (IsWin64Prologue &&
TRI->hasStackRealignment(MF)) {
2288 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2289 BuildStackAlignAND(
MBB,
MBBI,
DL, SPOrEstablisher, MaxAlign);
2293 if (IsFunclet &&
STI.is32Bit())
2300 if (
TRI->hasBasePointer(MF)) {
2326 assert(UsedReg == BasePtr);
2335 int FI =
MI->getOperand(1).getIndex();
2336 unsigned MOVmr =
Is64Bit ? X86::MOV64mr : X86::MOV32mr;
2343 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
2345 if (!HasFP && NumBytes) {
2371 bool NeedsCLD =
false;
2385 if (
MI.isInlineAsm()) {
2417 switch (
MI.getOpcode()) {
2419 case X86::CLEANUPRET:
2441X86FrameLowering::getPSPSlotOffsetFromSP(
const MachineFunction &MF)
const {
2448 return static_cast<unsigned>(
Offset);
2452X86FrameLowering::getWinEHFuncletFrameSize(
const MachineFunction &MF)
const {
2453 const X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
2459 WinEHXMMSlotInfo.
size() *
TRI->getSpillSize(X86::VR128RegClass);
2468 UsedSize = getPSPSlotOffsetFromSP(MF) +
SlotSize;
2479 return FrameSizeMinusRBP + XMMSize - CSSize;
2483 return Opc == X86::TCRETURNri ||
Opc == X86::TCRETURN_WIN64ri ||
2484 Opc == X86::TCRETURN_HIPE32ri ||
Opc == X86::TCRETURNdi ||
2485 Opc == X86::TCRETURNmi ||
Opc == X86::TCRETURNri64 ||
2486 Opc == X86::TCRETURNri64_ImpCall ||
Opc == X86::TCRETURNdi64 ||
2487 Opc == X86::TCRETURNmi64 ||
Opc == X86::TCRETURN_WINmi64;
2498 DL =
MBBI->getDebugLoc();
2500 const bool Is64BitILP32 =
STI.isTarget64BitILP32();
2506 bool NeedsWin64CFI =
2510 bool IsWin64UnwindV3 =
2518 uint64_t MaxAlign = calculateMaxStackAlign(MF);
2521 bool HasFP =
hasFP(MF);
2524 bool NeedsDwarfCFI = (!MF.
getTarget().getTargetTriple().isOSDarwin() &&
2531 unsigned Opc = X86::LEA32r;
2533 ArgBaseReg =
MI->getOperand(0).getReg();
2534 if (
STI.is64Bit()) {
2536 StackReg = X86::RSP;
2547 if (NeedsDwarfCFI) {
2548 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(StackReg,
true);
2558 assert(HasFP &&
"EH funclets without FP not yet implemented");
2559 NumBytes = getWinEHFuncletFrameSize(MF);
2563 NumBytes = FrameSize - CSSize - TailCallArgReserveSize;
2567 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
2568 NumBytes =
alignTo(FrameSize, MaxAlign);
2570 NumBytes = StackSize - CSSize - TailCallArgReserveSize;
2572 uint64_t SEHStackAllocAmt = NumBytes;
2574 unsigned SEHFrameOffset = 0;
2575 if (IsWin64Prologue && HasFP)
2587 if (IsWin64UnwindV3)
2605 if (NeedsDwarfCFI) {
2607 unsigned DwarfStackPtr =
2608 TRI->getDwarfRegNum(
Is64Bit ? X86::RSP : X86::ESP,
true);
2613 if (!
MBB.succ_empty() && !
MBB.isReturnBlock()) {
2614 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2629 unsigned Opc = PI->getOpcode();
2631 if (
Opc != X86::DBG_VALUE && !PI->isTerminator()) {
2633 (
Opc != X86::POP32r &&
Opc != X86::POP64r &&
Opc != X86::BTR64ri8 &&
2634 Opc != X86::ADD64ri32 &&
Opc != X86::POPP64r &&
Opc != X86::POP2 &&
2635 Opc != X86::POP2P &&
Opc != X86::LEA64r &&
Opc != X86::SEH_PushReg &&
2636 Opc != X86::SEH_Push2Regs &&
Opc != X86::SEH_StackAlloc &&
2637 Opc != X86::ADD64ri32_NF))
2647 int FI =
MI->getOperand(1).getIndex();
2648 unsigned MOVrm =
Is64Bit ? X86::MOV64rm : X86::MOV32rm;
2655 if (IsFunclet && Terminator->getOpcode() == X86::CATCHRET)
2656 emitCatchRetReturnValue(
MBB, FirstCSPop, &*Terminator);
2659 DL =
MBBI->getDebugLoc();
2665 if (IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI()) {
2668 auto EpilogStart =
MBBI;
2671 while (ScanIt !=
MBB.begin()) {
2672 auto PI = std::prev(ScanIt);
2675 TII.isLoadFromStackSlot(*PI, FI)) {
2676 Register Reg = PI->getOperand(0).getReg();
2677 if (X86::FR64RegClass.
contains(Reg)) {
2690 EpilogStart = std::prev(PI);
2691 ScanIt = EpilogStart;
2709 if (
TRI->hasStackRealignment(MF))
2712 IsWin64Prologue ? SEHStackAllocAmt - SEHFrameOffset : -CSSize;
2724 if (IsWin64UnwindV3) {
2729 if (SEHStackAllocAmt)
2731 .
addImm(SEHStackAllocAmt)
2734 if (LEAAmount != 0) {
2744 }
else if (NumBytes) {
2746 if (IsWin64UnwindV3)
2751 if (!HasFP && NeedsDwarfCFI) {
2755 nullptr, CSSize + TailCallArgReserveSize +
SlotSize),
2762 if (!IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI())
2765 if (!HasFP && NeedsDwarfCFI) {
2772 unsigned Opc = PI->getOpcode();
2774 if (
Opc == X86::POP32r ||
Opc == X86::POP64r ||
Opc == X86::POPP64r ||
2775 Opc == X86::POP2 ||
Opc == X86::POP2P) {
2779 if (
Opc == X86::POP2 ||
Opc == X86::POP2P)
2791 if (NeedsDwarfCFI && !
MBB.succ_empty())
2797 assert(Delta <= 0 &&
"TCDelta should never be positive");
2822 if (
TRI->hasBasePointer(MF))
2823 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getBaseRegister();
2824 else if (
TRI->hasStackRealignment(MF))
2825 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getStackRegister();
2827 FrameReg =
TRI->getFrameRegister(MF);
2838 int64_t FPDelta = 0;
2849 if (IsWin64Prologue) {
2858 uint64_t NumBytes = FrameSize - CSSize;
2868 FPDelta = FrameSize - SEHFrameOffset;
2870 "FPDelta isn't aligned per the Win64 ABI!");
2873 if (FrameReg ==
TRI->getFramePtr()) {
2882 if (TailCallReturnAddrDelta < 0)
2883 Offset -= TailCallReturnAddrDelta;
2891 if (
TRI->hasStackRealignment(MF) ||
TRI->hasBasePointer(MF))
2901 const auto it = WinEHXMMSlotInfo.find(FI);
2903 if (it == WinEHXMMSlotInfo.end())
2906 FrameReg =
TRI->getStackRegister();
2914 int Adjustment)
const {
2916 FrameReg =
TRI->getStackRegister();
2924 bool IgnoreSPUpdates)
const {
2963 !
STI.isTargetWin64())
2974 "we don't handle this case!");
3006 std::vector<CalleeSavedInfo> &CSI)
const {
3010 unsigned CalleeSavedFrameSize = 0;
3011 unsigned XMMCalleeSavedFrameSize = 0;
3017 if (TailCallReturnAddrDelta < 0) {
3028 TailCallReturnAddrDelta -
SlotSize,
true);
3032 if (this->TRI->hasBasePointer(MF)) {
3041 bool IsFPRemovedFromCSI =
false;
3059 for (
unsigned i = 0; i < CSI.size(); ++i) {
3060 if (
TRI->regsOverlap(CSI[i].getReg(),
FPReg)) {
3061 CSI.erase(CSI.begin() + i);
3062 IsFPRemovedFromCSI =
true;
3078 unsigned NumRegsForPush2 = 0;
3081 return X86::GR64RegClass.contains(
I.getReg());
3083 bool UsePush2Pop2 = !IsFPRemovedFromCSI ? NumCSGPR > 2 : NumCSGPR > 1;
3086 ?
alignDown(IsFPRemovedFromCSI ? NumCSGPR : NumCSGPR - 1, 2)
3100 (SpillSlotOffset % 16 == 0 ||
3122 "Expect even candidates for push2/pop2");
3124 ++NumFunctionUsingPush2Pop2;
3135 unsigned Size =
TRI->getSpillSize(*RC);
3136 Align Alignment =
TRI->getSpillAlign(*RC);
3138 assert(SpillSlotOffset < 0 &&
"SpillSlotOffset should always < 0 on X86");
3139 SpillSlotOffset = -
alignTo(-SpillSlotOffset, Alignment);
3142 SpillSlotOffset -=
Size;
3148 if (X86::VR128RegClass.
contains(Reg)) {
3149 WinEHXMMSlotInfo[
SlotIndex] = XMMCalleeSavedFrameSize;
3150 XMMCalleeSavedFrameSize +=
Size;
3164 if (
MBB.isEHFuncletEntry() &&
STI.is32Bit() &&
STI.isOSWindows())
3173 auto UpdateLiveInCheckCanKill = [&](
Register Reg) {
3189 auto UpdateLiveInGetKillRegState = [&](
Register Reg) {
3193 for (
auto RI = CSI.
rbegin(), RE = CSI.
rend(); RI != RE; ++RI) {
3201 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3202 .
addReg(Reg2, UpdateLiveInGetKillRegState(Reg2))
3206 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3212 unsigned Opc =
STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r;
3213 Register BaseReg = this->TRI->getBaseRegister();
3242 MBB.getParent()->getFunction().getPersonalityFn())) &&
3243 "SEH should not use CATCHRET");
3248 if (
STI.is64Bit()) {
3280 if (
MI->getOpcode() == X86::CATCHRET) {
3293 bool NeedsWin64CFI =
3295 bool IsWin64UnwindV3 =
3312 if (IsWin64UnwindV3)
3314 .
addImm(this->TRI->getBaseRegister())
3316 unsigned Opc =
STI.is64Bit() ? X86::POP64r : X86::POP32r;
3317 Register BaseReg = this->TRI->getBaseRegister();
3323 for (
auto I = CSI.
begin(), E = CSI.
end();
I != E; ++
I) {
3330 if (IsWin64UnwindV3) {
3340 if (IsWin64UnwindV3)
3358 if (
TRI->hasBasePointer(MF)) {
3360 if (
STI.isTarget64BitILP32())
3362 SavedRegs.
set(BasePtr);
3364 if (
STI.hasUserReservedRegisters()) {
3365 for (
int Reg = SavedRegs.
find_first(); Reg != -1;
3367 if (
STI.isRegisterReservedByUser(Reg)) {
3368 SavedRegs.
reset(Reg);
3378 if (
I->hasNestAttr() && !
I->use_empty())
3395 return Primary ? X86::R14 : X86::R13;
3397 return Primary ? X86::EBX : X86::EDI;
3402 return Primary ? X86::R11 : X86::R12;
3404 return Primary ? X86::R11D : X86::R12D;
3414 "nested function.");
3415 return Primary ? X86::EAX : X86::ECX;
3418 return Primary ? X86::EDX : X86::EAX;
3419 return Primary ? X86::ECX : X86::EAX;
3430 unsigned TlsReg, TlsOffset;
3435 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3439 "Scratch register is live-in");
3443 if (!
STI.isTargetLinux() && !
STI.isTargetDarwin() && !
STI.isTargetWin32() &&
3444 !
STI.isTargetWin64() && !
STI.isTargetFreeBSD() &&
3445 !
STI.isTargetDragonFly())
3459 bool IsNested =
false;
3468 for (
const auto &LI : PrologueMBB.
liveins()) {
3485 if (
STI.isTargetLinux()) {
3487 TlsOffset =
IsLP64 ? 0x70 : 0x40;
3488 }
else if (
STI.isTargetDarwin()) {
3490 TlsOffset = 0x60 + 90 * 8;
3491 }
else if (
STI.isTargetWin64()) {
3494 }
else if (
STI.isTargetFreeBSD()) {
3497 }
else if (
STI.isTargetDragonFly()) {
3504 if (CompareStackPointer)
3505 ScratchReg =
IsLP64 ? X86::RSP : X86::ESP;
3523 if (
STI.isTargetLinux()) {
3526 }
else if (
STI.isTargetDarwin()) {
3528 TlsOffset = 0x48 + 90 * 4;
3529 }
else if (
STI.isTargetWin32()) {
3532 }
else if (
STI.isTargetDragonFly()) {
3535 }
else if (
STI.isTargetFreeBSD()) {
3541 if (CompareStackPointer)
3542 ScratchReg = X86::ESP;
3544 BuildMI(checkMBB,
DL,
TII.get(X86::LEA32r), ScratchReg)
3551 if (
STI.isTargetLinux() ||
STI.isTargetWin32() ||
STI.isTargetWin64() ||
3552 STI.isTargetDragonFly()) {
3560 }
else if (
STI.isTargetDarwin()) {
3563 unsigned ScratchReg2;
3565 if (CompareStackPointer) {
3568 SaveScratch2 =
false;
3580 "Scratch register is live-in and not saved");
3586 BuildMI(checkMBB,
DL,
TII.get(X86::MOV32ri), ScratchReg2)
3597 BuildMI(checkMBB,
DL,
TII.get(X86::POP32r), ScratchReg2);
3613 const unsigned RegAX =
IsLP64 ? X86::RAX : X86::EAX;
3614 const unsigned Reg10 =
IsLP64 ? X86::R10 : X86::R10D;
3615 const unsigned Reg11 =
IsLP64 ? X86::R11 : X86::R11D;
3616 const unsigned MOVrr =
IsLP64 ? X86::MOV64rr : X86::MOV32rr;
3651 if (
STI.useIndirectThunkCalls())
3653 "code model and thunks not yet implemented.");
3670 BuildMI(allocMBB,
DL,
TII.get(X86::MORESTACK_RET_RESTORE_R10));
3679#ifdef EXPENSIVE_CHECKS
3690 for (
int i = 0, e = HiPELiteralsMD->
getNumOperands(); i != e; ++i) {
3692 if (
Node->getNumOperands() != 2)
3696 if (!NodeName || !NodeVal)
3699 if (ValConst && NodeName->
getString() == LiteralName) {
3705 " required but not provided");
3716 return MI.isMetaInstruction();
3742 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3747 if (!HiPELiteralsMD)
3749 "Can't generate HiPE prologue without runtime parameters");
3751 HiPELiteralsMD,
Is64Bit ?
"AMD64_LEAF_WORDS" :
"X86_LEAF_WORDS");
3752 const unsigned CCRegisteredArgs =
Is64Bit ? 6 : 5;
3753 const unsigned Guaranteed = HipeLeafWords *
SlotSize;
3760 "HiPE prologue is only supported on Linux operating systems.");
3770 unsigned MoreStackForCalls = 0;
3772 for (
auto &
MBB : MF) {
3773 for (
auto &
MI :
MBB) {
3793 if (
F->getName().contains(
"erlang.") ||
F->getName().contains(
"bif_") ||
3797 unsigned CalleeStkArity =
F->arg_size() > CCRegisteredArgs
3798 ?
F->arg_size() - CCRegisteredArgs
3800 if (HipeLeafWords - 1 > CalleeStkArity)
3802 std::max(MoreStackForCalls,
3803 (HipeLeafWords - 1 - CalleeStkArity) *
SlotSize);
3806 MaxStack += MoreStackForCalls;
3811 if (MaxStack > Guaranteed) {
3815 for (
const auto &LI : PrologueMBB.
liveins()) {
3823 unsigned ScratchReg,
SPReg, PReg, SPLimitOffset;
3824 unsigned LEAop, CMPop, CALLop;
3829 LEAop = X86::LEA64r;
3830 CMPop = X86::CMP64rm;
3831 CALLop = X86::CALL64pcrel32;
3835 LEAop = X86::LEA32r;
3836 CMPop = X86::CMP32rm;
3837 CALLop = X86::CALLpcrel32;
3842 "HiPE prologue scratch register is live-in");
3849 PReg,
false, SPLimitOffset);
3859 PReg,
false, SPLimitOffset);
3869#ifdef EXPENSIVE_CHECKS
3886 if (NumPops != 1 && NumPops != 2)
3894 if (!Prev->isCall() || !Prev->getOperand(1).isRegMask())
3898 unsigned FoundRegs = 0;
3904 Is64Bit ? X86::GR64_NOREX_NOSPRegClass : X86::GR32_NOREX_NOSPRegClass;
3906 for (
auto Candidate : RegClass) {
3919 if (MO.isReg() && MO.isDef() &&
3920 TRI->isSuperOrSubRegisterEq(MO.getReg(), Candidate)) {
3929 Regs[FoundRegs++] = Candidate;
3930 if (FoundRegs == (
unsigned)NumPops)
3938 while (FoundRegs < (
unsigned)NumPops)
3939 Regs[FoundRegs++] = Regs[0];
3941 for (
int i = 0; i < NumPops; ++i)
3952 unsigned Opcode =
I->getOpcode();
3953 bool isDestroy = Opcode ==
TII.getCallFrameDestroyOpcode();
3956 uint64_t InternalAmt = (isDestroy || Amount) ?
TII.getFrameAdjustment(*
I) : 0;
3966 if (!reserveCallFrame) {
3987 bool HasDwarfEHHandlers = !WindowsCFI && !MF.
getLandingPads().empty();
3989 if (HasDwarfEHHandlers && !isDestroy &&
3999 Amount -= InternalAmt;
4009 int64_t StackAdjustment = isDestroy ? Amount : -Amount;
4010 int64_t CfaAdjustment = StackAdjustment;
4012 if (StackAdjustment) {
4021 auto CalcNewOffset = [&StackAdjustment](int64_t
Offset) {
4022 return StackAdjustment +
Offset;
4025 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
true);
4027 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
false);
4029 if (StackAdjustment) {
4030 if (!(
F.hasMinSize() &&
4031 adjustStackWithPops(
MBB, InsertPos,
DL, StackAdjustment)))
4032 BuildStackAdjustment(
MBB, InsertPos,
DL, StackAdjustment,
4058 while (CI !=
B && !std::prev(CI)->isCall())
4060 BuildStackAdjustment(
MBB, CI,
DL, -InternalAmt,
false);
4067 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4069 if (!
MBB.isLiveIn(X86::EFLAGS))
4076 if (TLI.hasInlineStackProbe(MF) || TLI.hasStackProbeSymbol(MF))
4084 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4090 if (
STI.isTargetWin64() && !
MBB.succ_empty() && !
MBB.isReturnBlock())
4112 bool CompactUnwind =
4128 assert(
STI.isTargetWindowsMSVC() &&
"funclets only supported in MSVC env");
4129 assert(
STI.isTargetWin32() &&
"EBP/ESI restoration only required on win32");
4131 "restoring EBP/ESI on non-32-bit target");
4143 int EHRegSize = MFI.getObjectSize(FI);
4148 X86::EBP,
true, -EHRegSize)
4154 int EndOffset = -EHRegOffset - EHRegSize;
4167 "end of registration object above normal EBP position!");
4168 }
else if (UsedReg == BasePtr) {
4178 assert(UsedReg == BasePtr);
4189 return TRI->getSlotSize();
4204 FrameBase.
Kind = DwarfFrameBase::CFA;
4210 return DwarfFrameBase{DwarfFrameBase::Register, {FrameRegister}};
4215struct X86FrameSortingObject {
4216 bool IsValid =
false;
4217 unsigned ObjectIndex = 0;
4218 unsigned ObjectSize = 0;
4220 unsigned ObjectNumUses = 0;
4236struct X86FrameSortingComparator {
4237 inline bool operator()(
const X86FrameSortingObject &
A,
4238 const X86FrameSortingObject &
B)
const {
4239 uint64_t DensityAScaled, DensityBScaled;
4259 DensityAScaled =
static_cast<uint64_t>(
A.ObjectNumUses) *
4261 DensityBScaled =
static_cast<uint64_t>(
B.ObjectNumUses) *
4272 if (DensityAScaled == DensityBScaled)
4273 return A.ObjectAlignment <
B.ObjectAlignment;
4275 return DensityAScaled < DensityBScaled;
4289 if (ObjectsToAllocate.
empty())
4301 for (
auto &Obj : ObjectsToAllocate) {
4302 SortingObjects[Obj].IsValid =
true;
4303 SortingObjects[Obj].ObjectIndex = Obj;
4307 if (ObjectSize == 0)
4309 SortingObjects[Obj].ObjectSize = 4;
4311 SortingObjects[Obj].ObjectSize = ObjectSize;
4315 for (
auto &
MBB : MF) {
4316 for (
auto &
MI :
MBB) {
4317 if (
MI.isDebugInstr())
4323 int Index = MO.getIndex();
4327 SortingObjects[Index].IsValid)
4328 SortingObjects[Index].ObjectNumUses++;
4343 for (
auto &Obj : SortingObjects) {
4347 ObjectsToAllocate[i++] = Obj.ObjectIndex;
4351 if (!
TRI->hasStackRealignment(MF) &&
hasFP(MF))
4352 std::reverse(ObjectsToAllocate.
begin(), ObjectsToAllocate.
end());
4364 Offset += getWinEHFuncletFrameSize(MF);
4379 RS->addScavengingFrameIndex(FI);
4392 adjustFrameForMsvcCxxEh(MF);
4396void X86FrameLowering::adjustFrameForMsvcCxxEh(
MachineFunction &MF)
const {
4404 int64_t MinFixedObjOffset = -
SlotSize;
4410 int FrameIndex =
H.CatchObj.FrameIndex;
4411 if ((FrameIndex != INT_MAX) && MFI.
getObjectOffset(FrameIndex) == 0) {
4414 MinFixedObjOffset -= std::abs(MinFixedObjOffset) %
Align;
4422 MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8;
4423 int64_t UnwindHelpOffset = MinFixedObjOffset -
SlotSize;
4430 MachineBasicBlock &
MBB = MF.
front();
4450 MI->eraseFromParent();
4463 bool NeedsRestore =
MBB.isEHPad() && !
MBB.isEHFuncletEntry();
4474 unsigned NumSpilledRegs) {
4476 unsigned AllocSize =
TRI->getSpillSize(*RC) * NumSpilledRegs;
4478 unsigned AlignedSize =
alignTo(AllocSize, StackAlign);
4479 return AlignedSize - AllocSize;
4485 int SPAdjust)
const {
4488 MachineBasicBlock *
MBB = BeforeMI->getParent();
4510 if (
FP.isValid() && needsDwarfCFI(MF)) {
4519 SmallString<64> CfaExpr;
4523 Offset +=
TRI->getSpillSize(*
TRI->getMinimalPhysRegClass(BP));
4526 if (
TII.isFrameSetup(*BeforeMI)) {
4528 BeforeMI = std::next(BeforeMI);
4531 if (
STI.isTarget64BitILP32())
4533 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(
StackPtr,
true);
4534 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfStackPtr));
4539 CfaExpr.
push_back((uint8_t)dwarf::DW_OP_plus);
4541 SmallString<64> DefCfaExpr;
4542 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
4554 int SPAdjust)
const {
4558 MachineBasicBlock *
MBB = AfterMI->getParent();
4576 if (needsDwarfCFI(MF)) {
4586void X86FrameLowering::saveAndRestoreFPBPUsingSP(
4589 assert(SpillFP || SpillBP);
4592 const TargetRegisterClass *RC;
4593 unsigned NumRegs = 0;
4596 FP =
TRI->getFrameRegister(MF);
4597 if (
STI.isTarget64BitILP32())
4599 RC =
TRI->getMinimalPhysRegClass(
FP);
4603 BP =
TRI->getBaseRegister();
4604 if (
STI.isTarget64BitILP32())
4606 RC =
TRI->getMinimalPhysRegClass(BP);
4611 spillFPBPUsingSP(MF, BeforeMI,
FP, BP, SPAdjust);
4612 restoreFPBPUsingSP(MF, AfterMI,
FP, BP, SPAdjust);
4615bool X86FrameLowering::skipSpillFPBP(
4617 if (
MI->getOpcode() == X86::LCMPXCHG16B_SAVE_RBX) {
4625 while (!(
MI->getOpcode() == TargetOpcode::COPY &&
4626 MI->getOperand(1).getReg() == X86::RBX) &&
4627 !((
Reg =
TII.isStoreToStackSlot(*
MI, FI)) &&
Reg == X86::RBX))
4637 AccessFP = AccessBP =
false;
4639 if (
MI.findRegisterUseOperandIdx(
FP,
TRI,
false) != -1 ||
4640 MI.findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4644 if (
MI.findRegisterUseOperandIdx(BP,
TRI,
false) != -1 ||
4645 MI.findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4648 return AccessFP || AccessBP;
4661 if (!
MBB->hasEHPadSuccessor())
4674void X86FrameLowering::checkInterferedAccess(
4677 bool SpillBP)
const {
4678 if (
DefMI == KillMI)
4680 if (
TRI->hasBasePointer(MF)) {
4691 [](
const MachineOperand &MO) { return MO.isFI(); }))
4693 "Interference usage of base pointer/frame "
4724 FP =
TRI->getFrameRegister(MF);
4725 if (
TRI->hasBasePointer(MF))
4726 BP =
TRI->getBaseRegister();
4741 bool InsideEHLabels =
false;
4742 auto MI =
MBB.rbegin(), ME =
MBB.rend();
4743 auto TermMI =
MBB.getFirstTerminator();
4744 if (TermMI ==
MBB.begin())
4746 MI = *(std::prev(TermMI));
4754 isInvoke(*
MI, InsideEHLabels) || skipSpillFPBP(MF,
MI)) {
4759 if (
MI->getOpcode() == TargetOpcode::EH_LABEL) {
4760 InsideEHLabels = !InsideEHLabels;
4765 bool AccessFP, AccessBP;
4774 bool FPLive =
false, BPLive =
false;
4775 bool SpillFP =
false, SpillBP =
false;
4778 SpillFP |= AccessFP;
4779 SpillBP |= AccessBP;
4782 if (FPLive &&
MI->findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4784 if (
FP &&
MI->findRegisterUseOperandIdx(
FP,
TRI,
false) != -1)
4786 if (BPLive &&
MI->findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4788 if (BP &&
MI->findRegisterUseOperandIdx(BP,
TRI,
false) != -1)
4792 }
while ((
MI != ME) &&
4793 (FPLive || BPLive ||
4797 if (FPLive && !SpillBP)
4802 if (KillMI->isCall() &&
DefMI != ME) {
4803 auto FrameSetup = std::next(
DefMI);
4807 while (FrameSetup != ME && !
TII.isFrameSetup(*FrameSetup) &&
4808 !FrameSetup->isCall())
4812 if (FrameSetup != ME &&
TII.isFrameSetup(*FrameSetup) &&
4813 (
TII.getFrameSize(*FrameSetup) ||
4814 TII.getFrameAdjustment(*FrameSetup))) {
4815 while (!
TII.isFrameInstr(*KillMI))
4823 checkInterferedAccess(MF,
DefMI, KillMI, SpillFP, SpillBP);
4826 saveAndRestoreFPBPUsingSP(MF, &(*
DefMI), &(*KillMI), SpillFP, SpillBP);
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const uint64_t kSplitStackAvailable
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
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)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg FPReg
static constexpr MCPhysReg SPReg
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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 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 isFPBPAccess(const MachineInstr &MI, Register FP, Register BP, const TargetRegisterInfo *TRI, bool &AccessFP, bool &AccessBP)
static const TargetRegisterClass * getCalleeSavedSpillRC(MCRegister Reg, const X86Subtarget &STI, const TargetRegisterInfo &TRI)
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 int computeFPBPAlignmentGap(MachineFunction &MF, const TargetRegisterClass *RC, unsigned NumSpilledRegs)
static unsigned getADDrrOpcode(bool IsLP64)
static bool HasNestArgument(const MachineFunction *MF)
static unsigned getPOPOpcode(const X86Subtarget &ST)
static bool isInvoke(const MachineInstr &MI, bool InsideEHLabels)
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)
constexpr uint64_t MaxSPChunk
static const unsigned FramePtr
Represent a constant reference to an array (0 or more elements consecutively in memory),...
reverse_iterator rend() const
bool empty() const
Check if the array is empty.
reverse_iterator rbegin() const
BitVector & reset()
Reset all bits in the bitvector.
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
BitVector & set()
Set all bits in the bitvector.
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
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.
const Argument * const_arg_iterator
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.
Module * getParent()
Get the module that this global value is contained inside of...
bool usesWindowsCFI() const
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
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...
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 createRememberState(MCSymbol *L, SMLoc Loc={})
.cfi_remember_state Save all current rules for all registers.
OpType getOperation() const
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
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 createAdjustCfaOffset(MCSymbol *L, int64_t 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 createRestoreState(MCSymbol *L, SMLoc Loc={})
.cfi_restore_state Restore the previously saved state.
const MCObjectFileInfo * getObjectFileInfo() const
const MCRegisterInfo * getRegisterInfo() const
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
MCSection * getCompactUnwindSection() const
MCRegAliasIterator enumerates all registers aliasing Reg.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI StringRef getString() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MachineInstrBundleIterator< const MachineInstr > const_iterator
iterator_range< livein_iterator > liveins() const
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI 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.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
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.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
@ 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...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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.
LLVM_ABI 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.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
LLVM_ABI 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.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
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)
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
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...
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
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.
LLVM_ABI 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.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
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.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
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.
MCContext & getContext() const
bool callsEHReturn() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
BasicBlockListType::iterator iterator
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 hasEHFunclets() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
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.
LLVM_ABI 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.
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.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI bool isLiveIn(Register Reg) const
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
WinX64EHUnwindMode getWinX64EHUnwindMode() const
Get how unwind information should be generated for x64 Windows.
unsigned getCodeViewFlag() const
Returns the CodeView Version by checking module flags.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI 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)
Represent a constant reference to a string, i.e.
static constexpr size_t npos
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
const Triple & getTargetTriple() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
SwiftAsyncFramePointerMode SwiftAsyncFramePointer
Control when and how the Swift async frame pointer bit should be set.
LLVM_ABI 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 TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
bool isUEFI() const
Tests whether the OS is UEFI.
bool isOSWindows() const
Tests whether the OS is Windows.
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...
void spillFPBP(MachineFunction &MF) const override
If a function uses base pointer and the base pointer is clobbered by inline asm, RA doesn't detect th...
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
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool hasFPImpl(const MachineFunction &MF) const override
hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.
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...
int64_t mergeSPAdd(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int64_t AddOffset, bool doMergeWithPrevious) const
Equivalent to: mergeSPUpdates(MBB, MBBI, [AddOffset](int64_t Offset) { return AddOffset + Offset; }...
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
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
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.
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.
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
bool getForceFramePointer() const
bool isCandidateForPush2Pop2(Register Reg) const
unsigned getArgumentStackSize() const
bool getFPClobberedByCall() 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()
bool getBPClobberedByCall() const
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
void setStackPtrSaveMI(MachineInstr *MI)
bool getUsesRedZone() const
void setCalleeSavedFrameSize(unsigned bytes)
void setSEHFramePtrSaveIndex(int Index)
const X86TargetLowering * getTargetLowering() const override
bool isTargetWindowsCoreCLR() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
uint16_t StackAdjustment(const RuntimeFunction &RF)
StackAdjustment - calculated stack adjustment in words.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
@ BasicBlock
Various leaf nodes.
@ MO_GOTPCREL
MO_GOTPCREL - On a symbol operand this indicates that the immediate is offset to the GOT entry for th...
unsigned getMOVriOpcode(bool Use64BitReg, int64_t Imm)
Return a MOVri opcode for materializing Imm into a 32- or 64-bit GPR.
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
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 dyn_cast_or_null(const Y &Val)
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 isFuncletReturnInstr(const MachineInstr &MI)
auto reverse(ContainerTy &&C)
@ 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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr RegState getDefRegState(bool B)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
LLVM_ABI 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...
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.
LLVM_ABI void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
static const MachineInstrBuilder & addRegOffset(const MachineInstrBuilder &MIB, Register Reg, bool isKill, int Offset)
addRegOffset - This function is used to add a memory reference of the form [Reg + Offset],...
constexpr RegState getUndefRegState(bool B)
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.
constexpr 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 LLVM_ABI 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.
union llvm::TargetFrameLowering::DwarfFrameBase::@004076321055032247336074224075335064105264310375 Location
enum llvm::TargetFrameLowering::DwarfFrameBase::FrameBaseKind Kind
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
SmallVector< WinEHHandlerType, 1 > HandlerArray