33 #define DEBUG_TYPE "arm-frame-lowering"
39 cl::desc(
"Align ARM NEON spills in prolog and epilog"));
43 unsigned NumAlignedDPRCS2Regs);
86 if (CFSize >= ((1 << 12) - 1) / 2)
112 if ((MI.
getOpcode() == ARM::LDR_POST_IMM ||
129 Pred, PredReg, TII, MIFlags);
132 Pred, PredReg, TII, MIFlags);
140 unsigned PredReg = 0) {
142 MIFlags, Pred, PredReg);
148 case ARM::VSTMDDB_UPD:
152 case ARM::t2STMDB_UPD:
156 case ARM::STR_PRE_IMM:
171 size_t StackSizeInBytes) {
179 return StackSizeInBytes >= StackProbeSize;
183 struct StackAdjustingInsts {
193 bool BeforeFPSet =
false) {
194 InstInfo Info = {
I, SPAdjust, BeforeFPSet};
195 Insts.push_back(Info);
199 auto Info =
find_if(Insts, [&](InstInfo &Info) {
return Info.I ==
I; });
200 assert(Info != Insts.end() &&
"invalid sp adjusting instruction");
201 Info->SPAdjust += ExtraBytes;
207 unsigned CFAOffset = 0;
208 for (
auto &Info : Insts) {
209 if (HasFP && !Info.BeforeFPSet)
212 CFAOffset -= Info.SPAdjust;
215 BuildMI(MBB, std::next(Info.I), dl,
216 TII.get(TargetOpcode::CFI_INSTRUCTION))
217 .addCFIIndex(CFIIndex)
236 const unsigned Alignment,
237 const bool MustBeSingleInstruction) {
241 const unsigned AlignMask = Alignment - 1;
258 }
else if (AlignMask <= 255) {
264 assert(!MustBeSingleInstruction &&
265 "Shouldn't call emitAligningInstructions demanding a single "
266 "instruction to be emitted for large stack alignment for a target "
299 "This emitPrologue does not support Thumb1!");
314 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
315 int FramePtrSpillFI = 0;
323 StackAdjustingInsts DefCFAOffsetCandidates;
324 bool HasFP =
hasFP(MF);
327 if (ArgRegsSaveSize) {
328 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize,
330 DefCFAOffsetCandidates.addInst(std::prev(MBBI), ArgRegsSaveSize,
true);
335 if (NumBytes - ArgRegsSaveSize != 0) {
336 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -(NumBytes - ArgRegsSaveSize),
338 DefCFAOffsetCandidates.addInst(std::prev(MBBI),
339 NumBytes - ArgRegsSaveSize,
true);
341 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, dl, TII, HasFP);
346 for (
unsigned i = 0, e = CSI.size();
i != e; ++
i) {
347 unsigned Reg = CSI[
i].getReg();
348 int FI = CSI[
i].getFrameIdx();
370 FramePtrSpillFI = FI;
384 if (GPRCS1Size > 0) {
385 GPRCS1Push = LastPush = MBBI++;
386 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size,
true);
390 unsigned GPRCS1Offset = NumBytes - ArgRegsSaveSize - GPRCS1Size;
391 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
392 unsigned DPRAlign = DPRCSSize ?
std::min(8U, Align) : 4U;
393 unsigned DPRGapSize = (GPRCS1Size + GPRCS2Size + ArgRegsSaveSize) % DPRAlign;
394 unsigned DPRCSOffset = GPRCS2Offset - DPRGapSize - DPRCSSize;
395 int FramePtrOffsetInPush = 0;
397 FramePtrOffsetInPush =
407 if (GPRCS2Size > 0) {
408 GPRCS2Push = LastPush = MBBI++;
409 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
415 assert(DPRGapSize == 4 &&
"unexpected alignment requirements for DPRs");
416 if (LastPush != MBB.
end() &&
418 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
422 DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize);
430 while (MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
445 NumBytes = DPRCSOffset;
450 if (NumWords < 65536)
464 BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL))
472 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12)
473 .addExternalSymbol(
"__chkstk")
476 BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr))
496 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
500 DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes);
526 PushSize + FramePtrOffsetInPush,
528 if (FramePtrOffsetInPush + PushSize != 0) {
531 -(ArgRegsSaveSize - FramePtrOffsetInPush)));
532 BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
533 .addCFIIndex(CFIIndex)
539 BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
540 .addCFIIndex(CFIIndex)
548 if (GPRCS1Size > 0) {
551 for (
const auto &Entry : CSI) {
552 unsigned Reg = Entry.getReg();
553 int FI = Entry.getFrameIdx();
574 BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
575 .addCFIIndex(CFIIndex)
582 if (GPRCS2Size > 0) {
584 for (
const auto &Entry : CSI) {
585 unsigned Reg = Entry.getReg();
586 int FI = Entry.getFrameIdx();
598 BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
599 .addCFIIndex(CFIIndex)
611 for (
const auto &Entry : CSI) {
612 unsigned Reg = Entry.getReg();
613 int FI = Entry.getFrameIdx();
614 if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
620 BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
621 .addCFIIndex(CFIIndex)
631 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, dl, TII, HasFP);
703 "This emitEpilogue does not support Thumb1!");
708 unsigned FramePtr = RegInfo->getFrameRegister(MF);
720 if (NumBytes - ArgRegsSaveSize != 0)
721 emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes - ArgRegsSaveSize);
724 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
725 if (MBBI != MBB.
begin()) {
734 NumBytes -= (ArgRegsSaveSize +
757 "No scratch register to restore SP from FP!");
767 BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
774 }
else if (NumBytes &&
783 while (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::VLDMDIA_UPD)
788 "unexpected DPR alignment gap");
797 emitSPUpdate(isARM, MBB, MBBI, dl, TII, ArgRegsSaveSize);
806 unsigned &FrameReg)
const {
812 int FI,
unsigned &FrameReg,
831 if (RegInfo->needsStackRealignment(MF)) {
832 assert (
hasFP(MF) &&
"dynamic stack realignment without a FP!");
836 }
else if (hasMovingSP) {
838 "VLAs and dynamic stack alignment, but missing base pointer!");
851 }
else if (hasMovingSP) {
857 if (FPOffset >= -255 && FPOffset < 0) {
866 if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020)
870 if (FPOffset >= -255 && FPOffset < 0) {
874 }
else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
888 const std::vector<CalleeSavedInfo> &CSI,
889 unsigned StmOpc,
unsigned StrOpc,
891 bool(*
Func)(
unsigned,
bool),
892 unsigned NumAlignedDPRCS2Regs,
893 unsigned MIFlags)
const {
900 typedef std::pair<unsigned, bool> RegAndKill;
902 unsigned i = CSI.size();
904 unsigned LastReg = 0;
905 for (; i != 0; --
i) {
906 unsigned Reg = CSI[i-1].getReg();
910 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
919 if (NoGap && LastReg && LastReg != Reg-1)
927 Regs.
push_back(std::make_pair(Reg, !isLiveIn));
933 std::sort(Regs.
begin(), Regs.
end(), [&](
const RegAndKill &LHS,
934 const RegAndKill &RHS) {
938 if (Regs.
size() > 1 || StrOpc== 0) {
942 for (
unsigned i = 0, e = Regs.
size(); i < e; ++
i)
944 }
else if (Regs.
size() == 1) {
957 if (MI != MBB.
begin())
964 const std::vector<CalleeSavedInfo> &CSI,
965 unsigned LdmOpc,
unsigned LdrOpc,
966 bool isVarArg,
bool NoGap,
967 bool(*
Func)(
unsigned,
bool),
968 unsigned NumAlignedDPRCS2Regs)
const {
974 bool isTailCall =
false;
975 bool isInterrupt =
false;
977 if (MBB.
end() !=
MI) {
978 DL = MI->getDebugLoc();
979 unsigned RetOpcode = MI->getOpcode();
980 isTailCall = (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri);
982 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
984 RetOpcode ==
ARM::TRAP || RetOpcode == ARM::TRAPNaCl ||
985 RetOpcode == ARM::tTRAP;
989 unsigned i = CSI.size();
991 unsigned LastReg = 0;
992 bool DeleteRet =
false;
993 for (; i != 0; --
i) {
994 unsigned Reg = CSI[i-1].getReg();
998 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
1001 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1015 if (NoGap && LastReg && LastReg != Reg-1)
1025 std::sort(Regs.
begin(), Regs.
end(), [&](
unsigned LHS,
unsigned RHS) {
1029 if (Regs.
size() > 1 || LdrOpc == 0) {
1033 for (
unsigned i = 0, e = Regs.
size(); i < e; ++
i)
1035 if (DeleteRet && MI != MBB.
end()) {
1037 MI->eraseFromParent();
1040 }
else if (Regs.
size() == 1) {
1046 BuildMI(MBB, MI, DL, TII.
get(LdrOpc), Regs[0])
1051 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1062 if (MI != MBB.
end())
1072 unsigned NumAlignedDPRCS2Regs,
1073 const std::vector<CalleeSavedInfo> &CSI,
1084 for (
unsigned i = 0, e = CSI.size(); i != e; ++
i) {
1085 unsigned DNum = CSI[
i].getReg() - ARM::D8;
1086 if (DNum > NumAlignedDPRCS2Regs - 1)
1088 int FI = CSI[
i].getFrameIdx();
1116 unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;
1119 .
addImm(8 * NumAlignedDPRCS2Regs)));
1133 Opc = isThumb ? ARM::tMOVr : ARM::MOVr;
1142 unsigned NextReg = ARM::D8;
1146 if (NumAlignedDPRCS2Regs >= 6) {
1148 &ARM::QQPRRegClass);
1156 NumAlignedDPRCS2Regs -= 4;
1161 unsigned R4BaseReg = NextReg;
1164 if (NumAlignedDPRCS2Regs >= 4) {
1166 &ARM::QQPRRegClass);
1172 NumAlignedDPRCS2Regs -= 4;
1176 if (NumAlignedDPRCS2Regs >= 2) {
1183 NumAlignedDPRCS2Regs -= 2;
1187 if (NumAlignedDPRCS2Regs) {
1203 unsigned NumAlignedDPRCS2Regs) {
1208 assert(MI->mayStore() &&
"Expecting spill instruction");
1211 switch(NumAlignedDPRCS2Regs) {
1214 assert(MI->mayStore() &&
"Expecting spill instruction");
1217 assert(MI->mayStore() &&
"Expecting spill instruction");
1232 unsigned NumAlignedDPRCS2Regs,
1233 const std::vector<CalleeSavedInfo> &CSI,
1242 for (
unsigned i = 0, e = CSI.size(); i != e; ++
i)
1243 if (CSI[i].
getReg() == ARM::D8) {
1244 D8SpillFI = CSI[
i].getFrameIdx();
1256 unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;
1258 .addFrameIndex(D8SpillFI).
addImm(0)));
1261 unsigned NextReg = ARM::D8;
1264 if (NumAlignedDPRCS2Regs >= 6) {
1266 &ARM::QQPRRegClass);
1272 NumAlignedDPRCS2Regs -= 4;
1277 unsigned R4BaseReg = NextReg;
1280 if (NumAlignedDPRCS2Regs >= 4) {
1282 &ARM::QQPRRegClass);
1287 NumAlignedDPRCS2Regs -= 4;
1291 if (NumAlignedDPRCS2Regs >= 2) {
1297 NumAlignedDPRCS2Regs -= 2;
1301 if (NumAlignedDPRCS2Regs)
1311 const std::vector<CalleeSavedInfo> &CSI,
1319 unsigned PushOpc = AFI->
isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
1321 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
1322 unsigned FltOpc = ARM::VSTMDDB_UPD;
1334 if (NumAlignedDPRCS2Regs)
1342 const std::vector<CalleeSavedInfo> &CSI,
1354 if (NumAlignedDPRCS2Regs)
1357 unsigned PopOpc = AFI->
isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
1358 unsigned LdrOpc = AFI->
isThumbFunction() ? ARM::t2LDR_POST :ARM::LDR_POST_IMM;
1359 unsigned FltOpc = ARM::VLDMDIA_UPD;
1361 NumAlignedDPRCS2Regs);
1362 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
1364 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg,
false,
1373 unsigned FnSize = 0;
1374 for (
auto &MBB : MF) {
1375 for (
auto &MI : MBB)
1388 unsigned Limit = (1 << 12) - 1;
1389 for (
auto &MBB : MF) {
1390 for (
auto &MI : MBB) {
1391 for (
unsigned i = 0, e = MI.getNumOperands(); i != e; ++
i) {
1392 if (!MI.getOperand(i).isFI())
1397 if (MI.getOpcode() == ARM::ADDri) {
1398 Limit =
std::min(Limit, (1U << 8) - 1);
1406 Limit =
std::min(Limit, (1U << 8) - 1);
1410 Limit =
std::min(Limit, ((1U << 8) - 1) * 4);
1416 Limit =
std::min(Limit, (1U << 8) - 1);
1449 if (!static_cast<const ARMSubtarget &>(MF.
getSubtarget()).hasNEON())
1457 if (!static_cast<const ARMBaseRegisterInfo *>(
1466 unsigned NumSpills = 0;
1467 for (; NumSpills < 8; ++NumSpills)
1468 if (!SavedRegs.
test(ARM::D8 + NumSpills))
1490 bool CanEliminateFrame =
true;
1491 bool CS1Spilled =
false;
1492 bool LRSpilled =
false;
1493 unsigned NumGPRSpills = 0;
1494 unsigned NumFPRSpills = 0;
1514 (MFI.hasVarSizedObjects() || RegInfo->needsStackRealignment(MF)))
1520 SavedRegs.
set(ARM::LR);
1528 unsigned StackSize = MFI.estimateStackSize(MF);
1529 if (MFI.hasVarSizedObjects() || StackSize > 508)
1543 for (
unsigned i = 0; CSRegs[
i]; ++
i) {
1544 unsigned Reg = CSRegs[
i];
1545 bool Spilled =
false;
1546 if (SavedRegs.
test(Reg)) {
1548 CanEliminateFrame =
false;
1551 if (!ARM::GPRRegClass.
contains(Reg)) {
1553 if (ARM::SPRRegClass.
contains(Reg))
1555 else if (ARM::DPRRegClass.
contains(Reg))
1557 else if (ARM::QPRRegClass.
contains(Reg))
1578 case ARM::R0:
case ARM::R1:
1594 case ARM::R0:
case ARM::R1:
1608 bool ForceLRSpill =
false;
1614 if (FnSize >= (1 << 11)) {
1615 CanEliminateFrame =
false;
1616 ForceLRSpill =
true;
1634 unsigned EstimatedStackSize =
1635 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
1638 EstimatedStackSize += 4;
1644 EstimatedStackSize += 16;
1647 MFI.hasVarSizedObjects() ||
1649 bool ExtraCSSpill =
false;
1654 SavedRegs.
set(FramePtr);
1658 SavedRegs.
set(ARM::LR);
1661 auto LRPos =
find(UnspilledCS1GPRs, ARM::LR);
1662 if (LRPos != UnspilledCS1GPRs.
end())
1663 UnspilledCS1GPRs.
erase(LRPos);
1665 auto FPPos =
find(UnspilledCS1GPRs, FramePtr);
1666 if (
FPPos != UnspilledCS1GPRs.
end())
1669 if (FramePtr == ARM::R7)
1688 int EntryRegDeficit = 0;
1689 for (
unsigned Reg : {ARM::R0, ARM::R1,
ARM::R2, ARM::R3}) {
1693 <<
" is unused argument register, EntryRegDeficit = "
1694 << EntryRegDeficit <<
"\n");
1701 <<
" return regs used, ExitRegDeficit = " << ExitRegDeficit
1704 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
1705 DEBUG(
dbgs() <<
"RegDeficit = " << RegDeficit <<
"\n");
1710 if (SavedRegs.
test(Reg)) {
1713 <<
" is saved low register, RegDeficit = " << RegDeficit
1719 <<
" is non-saved low register, adding to AvailableRegs\n");
1725 if (SavedRegs.
test(ARM::R7)) {
1727 DEBUG(
dbgs() <<
"%R7 is saved low register, RegDeficit = "
1728 << RegDeficit <<
"\n");
1732 <<
"%R7 is non-saved low register, adding to AvailableRegs\n");
1737 for (
unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
1738 if (SavedRegs.
test(Reg)) {
1741 <<
" is saved high register, RegDeficit = " << RegDeficit
1749 if ((EntryRegDeficit > ExitRegDeficit) &&
1752 if (SavedRegs.
test(ARM::LR)) {
1754 DEBUG(
dbgs() <<
"%LR is saved register, RegDeficit = " << RegDeficit
1758 DEBUG(
dbgs() <<
"%LR is not saved, adding to AvailableRegs\n");
1767 DEBUG(
dbgs() <<
"Final RegDeficit = " << RegDeficit <<
"\n");
1768 for (; RegDeficit > 0 && !AvailableRegs.
empty(); --RegDeficit) {
1771 <<
" to make up reg deficit\n");
1775 ExtraCSSpill =
true;
1776 UnspilledCS1GPRs.
erase(
find(UnspilledCS1GPRs, Reg));
1780 DEBUG(
dbgs() <<
"After adding spills, RegDeficit = " << RegDeficit <<
"\n");
1785 if (!LRSpilled && CS1Spilled) {
1786 SavedRegs.
set(ARM::LR);
1789 LRPos =
find(UnspilledCS1GPRs, (
unsigned)ARM::LR);
1790 if (LRPos != UnspilledCS1GPRs.
end())
1791 UnspilledCS1GPRs.
erase(LRPos);
1793 ForceLRSpill =
false;
1794 ExtraCSSpill =
true;
1800 DEBUG(
dbgs() <<
"NumGPRSpills = " << NumGPRSpills <<
"\n");
1802 if (TargetAlign >= 8 && (NumGPRSpills & 1)) {
1803 if (CS1Spilled && !UnspilledCS1GPRs.
empty()) {
1804 for (
unsigned i = 0, e = UnspilledCS1GPRs.
size(); i != e; ++
i) {
1805 unsigned Reg = UnspilledCS1GPRs[
i];
1813 <<
" to make up alignment\n");
1815 ExtraCSSpill =
true;
1820 unsigned Reg = UnspilledCS2GPRs.
front();
1823 <<
" to make up alignment\n");
1825 ExtraCSSpill =
true;
1834 if (BigStack && !ExtraCSSpill) {
1837 unsigned NumExtras = TargetAlign / 4;
1839 while (NumExtras && !UnspilledCS1GPRs.
empty()) {
1840 unsigned Reg = UnspilledCS1GPRs.
back();
1851 while (NumExtras && !UnspilledCS2GPRs.
empty()) {
1852 unsigned Reg = UnspilledCS2GPRs.
back();
1860 if (Extras.
size() && NumExtras == 0) {
1861 for (
unsigned i = 0, e = Extras.
size(); i != e; ++
i) {
1862 SavedRegs.
set(Extras[i]);
1867 assert(RS &&
"Register scavenging not provided");
1877 SavedRegs.
set(ARM::LR);
1902 "This eliminateCallFramePseudoInstr does not support Thumb1!");
1911 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
1919 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
1925 return MBB.
erase(I);
1933 unsigned Shifted = 0;
1938 while (!(Value & 0xC0000000)) {
1943 bool Carry = (Value & 0x00FFFFFF);
1944 Value = ((Value & 0xFF000000) >> 24) + Carry;
1946 if (Value & 0x0000100)
1947 Value = Value & 0x000001FC;
1950 Value = Value >> (Shifted - 24);
1952 Value = Value << (24 - Shifted);
2016 unsigned ScratchReg0 =
ARM::R4;
2017 unsigned ScratchReg1 = ARM::R5;
2018 uint64_t AlignedStackSize;
2034 if (BeforePrologueRegion.
insert(PredBB).second)
2037 }
while (!WalkList.
empty());
2047 BeforePrologueRegion.
insert(
B);
2049 for (
const auto &LI : PrologueMBB.
liveins()) {
2051 PredBB->addLiveIn(LI);
2057 BeforePrologueRegion.
erase(
B);
2089 .addReg(ScratchReg0).
addReg(ScratchReg1);
2096 BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2097 .addCFIIndex(CFIIndex);
2100 BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2101 .addCFIIndex(CFIIndex);
2104 BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2105 .addCFIIndex(CFIIndex);
2111 }
else if (CompareStackPointer) {
2113 .addReg(ARM::SP)).addReg(0);
2117 if (!CompareStackPointer && Thumb) {
2121 }
else if (!CompareStackPointer) {
2123 .addReg(ARM::SP).
addImm(AlignedStackSize)).addReg(0);
2135 .addConstantPoolIndex(CPI));
2139 .addReg(ScratchReg0).
addImm(0));
2157 .addReg(ScratchReg0).
addImm(4 * TlsOffset));
2162 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
2164 .addReg(ScratchReg0)
2168 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
2169 BuildMI(GetMBB, DL, TII.get(Opcode)).addMBB(PostStackMBB)
2182 ScratchReg0)).
addImm(AlignedStackSize));
2185 .addImm(AlignedStackSize)).addReg(0);
2214 BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2215 .addCFIIndex(CFIIndex);
2218 BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2219 .addCFIIndex(CFIIndex);
2226 BuildMI(AllocMBB, DL, TII.get(ARM::BL))
2227 .addExternalSymbol(
"__morestack");
2236 .addReg(ScratchReg0));
2263 .addReg(ScratchReg0)
2269 BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2270 .addCFIIndex(CFIIndex);
2273 Opcode = Thumb ? ARM::tBX_RET : ARM::BX_RET;
2286 .addReg(ScratchReg0)
2292 BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2293 .addCFIIndex(CFIIndex);
2299 BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2300 .addCFIIndex(CFIIndex);
2303 BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
2304 .addCFIIndex(CFIIndex);
2318 #ifdef EXPENSIVE_CHECKS
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
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...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
iterator_range< livein_iterator > liveins() const
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
static unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register...
ARMConstantPoolValue - ARM specific constantpool value.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getBaseRegister() const
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &MBB) const override
Adjust the prologue to have the function use segmented stacks.
int ResolveFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg, int SPAdj) const
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isThumbFunction() const
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
void setGPRCalleeSavedArea2Offset(unsigned o)
static uint32_t alignToARMConstant(uint32_t Value)
Get the minimum constant for ARM that is greater than or equal to the argument.
bool isThumb1Only() const
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
unsigned createPICLabelUId()
static bool isThumb(const MCSubtargetInfo &STI)
return AArch64::GPR64RegClass contains(Reg)
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
unsigned getDPRCalleeSavedAreaSize() const
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
const ARMBaseInstrInfo * getInstrInfo() const override
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
static const uint64_t kSplitStackAvailable
unsigned getSize() const
Return the size of the register in bytes, which is also the size of a stack slot allocated to hold a ...
void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New)
Given a machine basic block that branched to 'Old', change the code and CFG so that it branches to 'N...
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
unsigned getNumAlignedDPRCS2Regs() const
static const MachineInstrBuilder & AddDefaultPred(const MachineInstrBuilder &MIB)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const HexagonInstrInfo * TII
virtual bool hasFP(const MachineFunction &MF) const =0
hasFP - Return true if the specified function should have a dedicated frame pointer register...
unsigned getFrameRegister(const MachineFunction &MF) const override
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
unsigned getArgRegsSaveSize() const
Reg
All possible values of the reg field in the ModR/M byte.
static int sizeOfSPAdjustment(const MachineInstr &MI)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setDPRCalleeSavedAreaOffset(unsigned o)
LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
LLVM_NODISCARD bool empty() const
unsigned getNumOperands() const
Access to explicit operands of the instruction.
void setFramePtrSpillOffset(unsigned o)
Context object for machine code objects.
static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
unsigned getArgumentStackSize() const
bool isLiveIn(unsigned Reg) const
void setDPRCalleeSavedGapSize(unsigned s)
int getOffsetAdjustment() const
Return the correction for frame offsets.
void setShouldRestoreSPFromFP(bool s)
unsigned getReturnRegsCount() const
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const TargetRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg...
void setLRIsSpilledForFarJump(bool s)
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(std::begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
static bool isARMArea1Register(unsigned Reg, bool isIOS)
isARMArea1Register - Returns true if the register is a low register (r0-r7) or a stack/pc register th...
bool isThumb1OnlyFunction() const
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubRegIdx=0)
Prints virtual and physical registers with or without a TRI instance.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
unsigned getKillRegState(bool B)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
TargetInstrInfo - Interface to description of machine instruction set.
unsigned getDefRegState(bool B)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)
Skip past the code inserted by emitAlignedDPRCS2Spills, and return an iterator to the following instr...
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register)
.cfi_same_value Current value of Register is the same as in the previous frame.
static bool isCalleeSavedRegister(unsigned Reg, const MCPhysReg *CSRegs)
initializer< Ty > init(const Ty &Val)
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
This file declares the machine register scavenger class.
static unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
bool hasStackFrame() const
unsigned const MachineRegisterInfo * MRI
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, int Offset)
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it...
CodeModel::Model getCodeModel() const
Returns the code model.
unsigned getAlignment() const
Return the minimum required alignment for a register of this class.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
bool isReserved(unsigned PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const MachineOperand & getOperand(unsigned i) const
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Returns the size of the specified MachineInstr.
bool splitFramePushPop(const MachineFunction &MF) const
Returns true if the frame setup is split into two separate pushes (first r0-r7,lr then r8-r11)...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
unsigned getFramePtrSpillOffset() const
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment. ...
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setGPRCalleeSavedArea2Size(unsigned s)
TRAP - Trapping instruction.
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI)
Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers starting from d8...
self_iterator getIterator()
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
iterator_range< pred_iterator > predecessors()
const ARMFrameLowering * getFrameLowering() const override
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
iterator erase(const_iterator CI)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
virtual const TargetFrameLowering * getFrameLowering() const
static const MachineInstrBuilder & AddDefaultCC(const MachineInstrBuilder &MIB)
virtual bool noFramePointerElim(const MachineFunction &MF) const
Return true if the target needs to disable frame pointer elimination.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI)
Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers starting from d8...
void setGPRCalleeSavedArea1Size(unsigned s)
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false...
const MCContext & getContext() const
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool test(unsigned Idx) const
static bool isARMArea2Register(unsigned Reg, bool isIOS)
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call...
Information about stack frame layout on the target.
static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const unsigned Reg, const unsigned Alignment, const bool MustBeSingleInstruction)
Emit an instruction sequence that will align the address in register Reg by zero-ing out the lower bi...
LLVM_NODISCARD T pop_back_val()
bool isTargetAndroid() const
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool hasBasePointer(const MachineFunction &MF) const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
ARMFrameLowering(const ARMSubtarget &sti)
int findFirstPredOperandIdx() const
Find the index of the first operand in the operand list that is used to represent the predicate...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
int getStackProtectorIndex() const
Return the index for the stack protector object.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
static unsigned estimateRSStackSizeLimit(MachineFunction &MF, const TargetFrameLowering *TFI)
estimateRSStackSizeLimit - Look at each instruction that references stack frames and return the stack...
const MCRegisterInfo * getRegisterInfo() const
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
static bool isPopOpcode(int Opc)
bool noFramePointerElim(const MachineFunction &MF) const override
Return true if the target needs to disable frame pointer elimination.
static bool isARMLowRegister(unsigned Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
Representation of each machine instruction.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void setHasStackFrame(bool s)
void setGPRCalleeSavedArea1Offset(unsigned o)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isTargetLinux() const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned char TargetFlags=0) const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
unsigned getDPRCalleeSavedGapSize() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
void setDPRCalleeSavedAreaSize(unsigned s)
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
static bool isARMArea3Register(unsigned Reg, bool isIOS)
unsigned getReg() const
getReg - Returns the register number.
StringRef getValueAsString() const
Return the attribute's value as a string.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
static bool WindowsRequiresStackProbe(const MachineFunction &MF, size_t StackSizeInBytes)
bool cannotEliminateFrame(const MachineFunction &MF) const
virtual const TargetInstrInfo * getInstrInfo() const
uint16_t getEncodingValue(unsigned RegNo) const
Returns the encoding for RegNo.
LLVM Value Representation.
static unsigned GetFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
unsigned getGPRCalleeSavedArea1Size() const
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
static const unsigned FramePtr
Primary interface to the complete machine description for the target machine.
bool addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
static bool isCSRestore(MachineInstr &MI, const ARMBaseInstrInfo &TII, const MCPhysReg *CSRegs)
MachineModuleInfo & getMMI() const
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
unsigned getGPRCalleeSavedArea2Size() const
bool isThumb2Function() const
auto find_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
static void checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
void setObjectAlignment(int ObjectIdx, unsigned Align)
setObjectAlignment - Change the alignment of the specified stack object.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool isTargetWindows() const
unsigned getConstantPoolIndex(const Constant *C, unsigned Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one...
static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
This class contains meta information specific to a module.
bool shouldRestoreSPFromFP() const