65#define DEBUG_TYPE "hexagon-pei"
156 cl::desc(
"Set the number of scavenger slots"),
161 cl::desc(
"Specify O2(not Os) spill func threshold"),
166 cl::desc(
"Specify Os spill func threshold"),
175 cl::desc(
"Enable stack frame shrink wrapping"));
180 cl::desc(
"Max count of stack frame shrink-wraps"));
184 cl::desc(
"Enable long calls for save-restore stubs."),
195 cl::init(std::numeric_limits<unsigned>::max()));
221 MachineFunctionProperties::Property::NoVRegs);
225 char HexagonCallFrameInformation::ID = 0;
229bool HexagonCallFrameInformation::runOnMachineFunction(
MachineFunction &MF) {
235 HFI.insertCFIInstructions(MF);
240 "Hexagon call frame information",
false,
false)
243 return new HexagonCallFrameInformation();
251 if (Reg < Hexagon::D0 || Reg > Hexagon::D15)
260 if (!RegNo ||
SubReg < RegNo)
270 static_assert(Hexagon::R1 > 0,
271 "Assume physical registers are encoded as positive integers");
276 for (
unsigned I = 1,
E = CSI.
size();
I <
E; ++
I) {
291 unsigned Opc =
MI.getOpcode();
293 case Hexagon::PS_alloca:
294 case Hexagon::PS_aligna:
314 for (
MCPhysReg S : HRI.subregs_inclusive(R))
319 if (MO.isRegMask()) {
324 const uint32_t *BM = MO.getRegMask();
328 if (!(BM[R/32] & (1u << (R%32))))
343 unsigned RetOpc =
I->getOpcode();
344 return RetOpc == Hexagon::PS_tailcall_i || RetOpc == Hexagon::PS_tailcall_r;
366 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
367 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
368 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT:
369 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC:
370 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT:
371 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC:
372 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:
373 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:
386 return F.hasOptSize() && !
F.hasMinSize();
399 static unsigned ShrinkCounter = 0;
424 RPO[
I->getNumber()] = RPON++;
430 unsigned BN = RPO[
I.getNumber()];
433 if (RPO[Succ->getNumber()] <= BN)
441 for (
const MCPhysReg *
P = HRI.getCalleeSavedRegs(&MF); *
P; ++
P)
450 dbgs() <<
"Blocks needing SF: {";
451 for (
auto &
B : SFBlocks)
456 if (SFBlocks.
empty())
461 for (
unsigned i = 1, n = SFBlocks.
size(); i < n; ++i) {
467 for (
unsigned i = 1, n = SFBlocks.
size(); i < n; ++i) {
473 dbgs() <<
"Computed dom block: ";
478 dbgs() <<
", computed pdom block: ";
494 LLVM_DEBUG(
dbgs() <<
"PDom block does not post-dominate dom block\n");
517 findShrunkPrologEpilog(MF, PrologB, EpilogB);
519 bool PrologueStubs =
false;
520 insertCSRSpillsInBlock(*PrologB, CSI, HRI, PrologueStubs);
521 insertPrologueInBlock(*PrologB, PrologueStubs);
522 updateEntryPaths(MF, *PrologB);
525 insertCSRRestoresInBlock(*EpilogB, CSI, HRI);
526 insertEpilogueInBlock(*EpilogB);
529 if (
B.isReturnBlock())
530 insertCSRRestoresInBlock(
B, CSI, HRI);
533 if (
B.isReturnBlock())
534 insertEpilogueInBlock(
B);
552 BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);
553 updateExitPaths(*EpilogB, *EpilogB, DoneT, DoneF, Path);
562 assert(
F.hasFnAttribute(Attribute::NoReturn) &&
563 F.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
564 !
F.getFunction().hasFnAttribute(Attribute::UWTable));
580 assert(!MFI.hasVarSizedObjects() &&
581 !HST.getRegisterInfo()->hasStackRealignment(MF));
582 return F.hasFnAttribute(Attribute::NoReturn) &&
583 F.hasFnAttribute(Attribute::NoUnwind) &&
584 !
F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() &&
585 MFI.getStackSize() == 0;
589 bool PrologueStubs)
const {
594 auto &HRI = *HST.getRegisterInfo();
605 FrameSize = MaxCFA +
alignTo(FrameSize, MaxAlign);
612 Register SP = HRI.getStackRegister();
619 if (
MI.getOpcode() == Hexagon::PS_alloca)
622 for (
auto *
MI : AdjustRegs) {
623 assert((
MI->getOpcode() == Hexagon::PS_alloca) &&
"Expected alloca");
624 expandAlloca(
MI, HII, SP, MaxCF);
625 MI->eraseFromParent();
630 if (MF.getFunction().isVarArg() &&
634 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)
636 : NumVarArgRegs * 4 + 4;
637 if (RegisterSavedAreaSizePlusPadding > 0) {
640 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
642 .
addImm(-RegisterSavedAreaSizePlusPadding)
648 for (
int i = HMFI.getFirstNamedArgFrameIndex(),
649 e = HMFI.getLastNamedArgFrameIndex(); i >=
e; --i) {
654 unsigned LDOpc, STOpc;
658 if (ObjAlign > ObjSize) {
661 else if (ObjSize <= 2)
663 else if (ObjSize <= 4)
665 else if (ObjSize > 4)
669 switch (OpcodeChecker) {
671 LDOpc = Hexagon::L2_loadrb_io;
672 STOpc = Hexagon::S2_storerb_io;
675 LDOpc = Hexagon::L2_loadrh_io;
676 STOpc = Hexagon::S2_storerh_io;
679 LDOpc = Hexagon::L2_loadri_io;
680 STOpc = Hexagon::S2_storeri_io;
684 LDOpc = Hexagon::L2_loadrd_io;
685 STOpc = Hexagon::S2_storerd_io;
689 Register RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3
691 int LoadStoreCount = ObjSize / OpcodeChecker;
693 if (ObjSize % OpcodeChecker)
701 NumBytes =
alignTo(NumBytes, ObjAlign);
704 while (Count < LoadStoreCount) {
706 BuildMI(
MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)
708 .
addImm(RegisterSavedAreaSizePlusPadding +
709 ObjAlign.
value() * Count + NumBytes)
725 NumBytes =
alignTo(NumBytes, 8);
730 NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;
733 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))
743 insertAllocframe(
MBB, InsertPt, NumBytes);
745 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
753 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
755 }
else if (NumBytes > 0) {
757 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
767 auto &HRI = *HST.getRegisterInfo();
768 Register SP = HRI.getStackRegister();
780 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
781 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
782 NumBytes += RegisterSavedAreaSizePlusPadding;
785 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
793 unsigned RetOpc = RetI ? RetI->
getOpcode() : 0;
796 if (RetOpc == Hexagon::EH_RETURN_JMPR) {
797 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
800 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)
808 if (RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4 ||
809 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC ||
810 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT ||
811 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC) {
827 bool NeedsDeallocframe =
true;
830 unsigned COpc = PrevIt->getOpcode();
831 if (COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||
832 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC ||
833 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||
834 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||
835 COpc == Hexagon::PS_call_nr || COpc == Hexagon::PS_callr_nr)
836 NeedsDeallocframe =
false;
841 if (!NeedsDeallocframe)
847 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
852 unsigned NewOpc = Hexagon::L4_return;
863 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
864 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
870 (
I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT &&
871 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC &&
872 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 &&
873 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC))
874 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
877 if (RegisterSavedAreaSizePlusPadding != 0)
878 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
880 .
addImm(RegisterSavedAreaSizePlusPadding);
889 auto &HRI = *HST.getRegisterInfo();
893 const unsigned int ALLOCFRAME_MAX = 16384;
901 Register SP = HRI.getStackRegister();
903 if (NumBytes >= ALLOCFRAME_MAX) {
905 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
912 Register SP = HRI.getStackRegister();
913 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
917 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
935 for (
unsigned i = 0; i < Worklist.
size(); ++i) {
936 unsigned BN = Worklist[i];
943 Worklist.
insert(SB->getNumber());
952 if (Path[BN] || DoneF[BN])
960 bool ReachedExit =
false;
962 ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);
978 if (ReachedExit && &
MBB != &RestoreB) {
991static std::optional<MachineBasicBlock::iterator>
998 auto End =
B.instr_end();
1002 if (!
I.isBundle()) {
1003 if (
I.getOpcode() == Hexagon::S2_allocframe)
1004 return std::next(It);
1008 bool HasCall =
false, HasAllocFrame =
false;
1010 while (++
T !=
End &&
T->isBundled()) {
1011 if (
T->getOpcode() == Hexagon::S2_allocframe)
1012 HasAllocFrame =
true;
1013 else if (
T->isCall())
1017 return HasCall ? It : std::next(It);
1019 return std::nullopt;
1025 insertCFIInstructionsAt(
B, *At);
1035 auto &HRI = *HST.getRegisterInfo();
1041 const MCInstrDesc &CFID = HII.get(TargetOpcode::CFI_INSTRUCTION);
1044 bool HasFP =
hasFP(MF);
1047 unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(),
true);
1048 unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(),
true);
1075 Hexagon::R1, Hexagon::R0, Hexagon::R3, Hexagon::R2,
1076 Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,
1077 Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,
1078 Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,
1079 Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9,
1080 Hexagon::D10, Hexagon::D11, Hexagon::D12, Hexagon::D13,
1086 for (
unsigned i = 0; RegsToMove[i] != Hexagon::NoRegister; ++i) {
1089 return C.getReg() ==
Reg;
1113 if (Reg < Hexagon::D0 || Reg > Hexagon::D15) {
1114 unsigned DwarfReg = HRI.getDwarfRegNum(Reg,
true);
1126 Register HiReg = HRI.getSubReg(Reg, Hexagon::isub_hi);
1127 Register LoReg = HRI.getSubReg(Reg, Hexagon::isub_lo);
1128 unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg,
true);
1129 unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg,
true);
1148 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1164 if (HasAlloca || HasExtraAlign)
1190 bool Stkchk =
false) {
1191 const char * V4SpillToMemoryFunctions[] = {
1192 "__save_r16_through_r17",
1193 "__save_r16_through_r19",
1194 "__save_r16_through_r21",
1195 "__save_r16_through_r23",
1196 "__save_r16_through_r25",
1197 "__save_r16_through_r27" };
1199 const char * V4SpillToMemoryStkchkFunctions[] = {
1200 "__save_r16_through_r17_stkchk",
1201 "__save_r16_through_r19_stkchk",
1202 "__save_r16_through_r21_stkchk",
1203 "__save_r16_through_r23_stkchk",
1204 "__save_r16_through_r25_stkchk",
1205 "__save_r16_through_r27_stkchk" };
1207 const char * V4SpillFromMemoryFunctions[] = {
1208 "__restore_r16_through_r17_and_deallocframe",
1209 "__restore_r16_through_r19_and_deallocframe",
1210 "__restore_r16_through_r21_and_deallocframe",
1211 "__restore_r16_through_r23_and_deallocframe",
1212 "__restore_r16_through_r25_and_deallocframe",
1213 "__restore_r16_through_r27_and_deallocframe" };
1215 const char * V4SpillFromMemoryTailcallFunctions[] = {
1216 "__restore_r16_through_r17_and_deallocframe_before_tailcall",
1217 "__restore_r16_through_r19_and_deallocframe_before_tailcall",
1218 "__restore_r16_through_r21_and_deallocframe_before_tailcall",
1219 "__restore_r16_through_r23_and_deallocframe_before_tailcall",
1220 "__restore_r16_through_r25_and_deallocframe_before_tailcall",
1221 "__restore_r16_through_r27_and_deallocframe_before_tailcall"
1224 const char **SpillFunc =
nullptr;
1228 SpillFunc = Stkchk ? V4SpillToMemoryStkchkFunctions
1229 : V4SpillToMemoryFunctions;
1232 SpillFunc = V4SpillFromMemoryFunctions;
1235 SpillFunc = V4SpillFromMemoryTailcallFunctions;
1238 assert(SpillFunc &&
"Unknown spill kind");
1243 return SpillFunc[0];
1245 return SpillFunc[1];
1247 return SpillFunc[2];
1249 return SpillFunc[3];
1251 return SpillFunc[4];
1253 return SpillFunc[5];
1268 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1273 Register SP = HRI.getStackRegister();
1275 Register AP = HMFI.getStackAlignBaseReg();
1290 bool UseFP =
false, UseAP =
false;
1295 if (NoOpt && !HasExtraAlign)
1300 UseFP |= (HasAlloca || HasExtraAlign);
1311 bool HasFP =
hasFP(MF);
1312 assert((HasFP || !UseFP) &&
"This function must have frame pointer");
1338 if (
Offset > 0 && !HasFP)
1353 if (!UseFP && !UseAP)
1354 RealOffset = FrameSize+
Offset;
1360 bool &PrologueStubs)
const {
1365 PrologueStubs =
false;
1370 if (useSpillFunction(MF, CSI)) {
1371 PrologueStubs =
true;
1383 if (StkOvrFlowEnabled) {
1385 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC
1386 : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;
1388 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
1389 : Hexagon::SAVE_REGISTERS_CALL_V4STK;
1392 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC
1393 : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
1395 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
1396 : Hexagon::SAVE_REGISTERS_CALL_V4;
1404 addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI,
false,
true);
1417 int FI =
I.getFrameIdx();
1419 HII.storeRegToStackSlot(
MBB,
MI, Reg, IsKill, FI, RC, &HRI,
Register());
1436 if (useRestoreFunction(MF, CSI)) {
1442 bool IsPIC = HTM.isPositionIndependent();
1453 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC
1454 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;
1456 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
1457 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
1466 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC
1467 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;
1469 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
1470 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
1476 addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI,
true,
false);
1483 int FI =
I.getFrameIdx();
1484 HII.loadRegFromStackSlot(
MBB,
MI, Reg, FI, RC, &HRI,
Register());
1494 unsigned Opc =
MI.getOpcode();
1496 assert((Opc == Hexagon::ADJCALLSTACKDOWN || Opc == Hexagon::ADJCALLSTACKUP) &&
1497 "Cannot handle this call frame pseudo instruction");
1511 if (!HasAlloca || !NeedsAlign)
1517 AP = AI->getOperand(0).getReg();
1520 HMFI.setStackAlignBaseReg(AP);
1528 auto IsUsed = [&HRI,&
MRI] (
Register Reg) ->
bool {
1530 if (
MRI.isPhysRegUsed(*AI))
1560 BitVector SRegs(Hexagon::NUM_TARGET_REGS);
1590 bool HasResSub =
false;
1616 BitVector TmpSup(Hexagon::NUM_TARGET_REGS);
1622 for (
int x = TmpSup.find_first(); x >= 0; x = TmpSup.find_next(x)) {
1662 for (
const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) {
1667 MinOffset = std::min(MinOffset, S->Offset);
1669 SRegs[S->Reg] =
false;
1678 unsigned Size =
TRI->getSpillSize(*RC);
1679 int Off = MinOffset -
Size;
1681 Off &= -Alignment.
value();
1683 MinOffset = std::min(MinOffset, Off);
1689 dbgs() <<
"CS information: {";
1691 int FI =
I.getFrameIdx();
1703 bool MissedReg =
false;
1723 if (!Hexagon::ModRegsRegClass.
contains(DstR) ||
1724 !Hexagon::ModRegsRegClass.
contains(SrcR))
1727 Register TmpR =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
1728 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), TmpR).
add(
MI->getOperand(1));
1729 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), DstR)
1741 if (!
MI->getOperand(0).isFI())
1745 unsigned Opc =
MI->getOpcode();
1747 bool IsKill =
MI->getOperand(2).isKill();
1748 int FI =
MI->getOperand(0).getIndex();
1752 Register TmpR =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
1753 unsigned TfrOpc = (Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr
1754 : Hexagon::A2_tfrcrr;
1759 BuildMI(
B, It,
DL, HII.get(Hexagon::S2_storeri_io))
1774 if (!
MI->getOperand(1).isFI())
1778 unsigned Opc =
MI->getOpcode();
1780 int FI =
MI->getOperand(1).getIndex();
1783 Register TmpR =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
1784 BuildMI(
B, It,
DL, HII.get(Hexagon::L2_loadri_io), TmpR)
1791 unsigned TfrOpc = (Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp
1792 : Hexagon::A2_tfrrcr;
1805 if (!
MI->getOperand(0).isFI())
1810 bool IsKill =
MI->getOperand(2).isKill();
1811 int FI =
MI->getOperand(0).getIndex();
1812 auto *RC = &Hexagon::HvxVRRegClass;
1818 Register TmpR0 =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
1821 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1824 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandqrt), TmpR1)
1830 expandStoreVec(
B, std::prev(It),
MRI, HII, NewRegs);
1842 if (!
MI->getOperand(1).isFI())
1847 int FI =
MI->getOperand(1).getIndex();
1848 auto *RC = &Hexagon::HvxVRRegClass;
1853 Register TmpR0 =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
1856 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1861 expandLoadVec(
B, std::prev(It),
MRI, HII, NewRegs);
1863 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandvrt), DstR)
1880 if (!
MI->getOperand(0).isFI())
1890 for (
auto R =
B.begin(); R != It; ++R) {
1892 LPR.stepForward(*R, Clobbers);
1897 Register SrcLo = HRI.getSubReg(SrcR, Hexagon::vsub_lo);
1898 Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);
1899 bool IsKill =
MI->getOperand(2).isKill();
1900 int FI =
MI->getOperand(0).getIndex();
1902 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1903 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1908 if (LPR.contains(SrcLo)) {
1909 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
1910 : Hexagon::V6_vS32Ub_ai;
1919 if (LPR.contains(SrcHi)) {
1920 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
1921 : Hexagon::V6_vS32Ub_ai;
1940 if (!
MI->getOperand(1).isFI())
1945 Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);
1946 Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);
1947 int FI =
MI->getOperand(1).getIndex();
1949 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1950 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1955 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
1956 : Hexagon::V6_vL32Ub_ai;
1963 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
1964 : Hexagon::V6_vL32Ub_ai;
1980 if (!
MI->getOperand(0).isFI())
1986 bool IsKill =
MI->getOperand(2).isKill();
1987 int FI =
MI->getOperand(0).getIndex();
1989 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1991 unsigned StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
1992 : Hexagon::V6_vS32Ub_ai;
2009 if (!
MI->getOperand(1).isFI())
2015 int FI =
MI->getOperand(1).getIndex();
2017 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2019 unsigned LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
2020 : Hexagon::V6_vL32Ub_ai;
2034 bool Changed =
false;
2036 for (
auto &
B : MF) {
2039 for (
auto I =
B.begin(),
E =
B.end();
I !=
E;
I = NextI) {
2041 NextI = std::next(
I);
2042 unsigned Opc =
MI->getOpcode();
2045 case TargetOpcode::COPY:
2046 Changed |= expandCopy(
B,
I,
MRI, HII, NewRegs);
2048 case Hexagon::STriw_pred:
2049 case Hexagon::STriw_ctr:
2050 Changed |= expandStoreInt(
B,
I,
MRI, HII, NewRegs);
2052 case Hexagon::LDriw_pred:
2053 case Hexagon::LDriw_ctr:
2054 Changed |= expandLoadInt(
B,
I,
MRI, HII, NewRegs);
2056 case Hexagon::PS_vstorerq_ai:
2057 Changed |= expandStoreVecPred(
B,
I,
MRI, HII, NewRegs);
2059 case Hexagon::PS_vloadrq_ai:
2060 Changed |= expandLoadVecPred(
B,
I,
MRI, HII, NewRegs);
2062 case Hexagon::PS_vloadrw_ai:
2063 Changed |= expandLoadVec2(
B,
I,
MRI, HII, NewRegs);
2065 case Hexagon::PS_vstorerw_ai:
2066 Changed |= expandStoreVec2(
B,
I,
MRI, HII, NewRegs);
2080 SavedRegs.
resize(HRI.getNumRegs());
2090 expandSpillMacros(MF, NewRegs);
2092 optimizeSpillSlots(MF, NewRegs);
2096 if (!NewRegs.
empty() || mayOverflowFrameOffset(MF)) {
2102 SpillRCs.
insert(&Hexagon::IntRegsRegClass);
2107 for (
const auto *RC : SpillRCs) {
2111 switch (RC->
getID()) {
2112 case Hexagon::IntRegsRegClassID:
2115 case Hexagon::HvxQRRegClassID:
2119 unsigned S = HRI.getSpillSize(*RC);
2120 Align A = HRI.getSpillAlign(*RC);
2121 for (
unsigned i = 0; i < Num; i++) {
2139 auto isDead = [&FIR,&DeadMap] (
Register Reg) ->
bool {
2140 auto F = DeadMap.find({Reg,0});
2141 if (
F == DeadMap.end())
2143 for (
auto &DR :
F->second)
2144 if (DR.contains(FIR))
2166 auto &HII = *HST.getInstrInfo();
2167 auto &HRI = *HST.getRegisterInfo();
2171 using BlockIndexMap =
2172 std::map<MachineBasicBlock *, HexagonBlockRanges::InstrIndexMap>;
2173 using BlockRangeMap =
2174 std::map<MachineBasicBlock *, HexagonBlockRanges::RangeList>;
2182 SlotInfo() =
default;
2185 BlockIndexMap BlockIndexes;
2187 std::map<int,SlotInfo> FIRangeMap;
2196 if (HaveRC ==
nullptr || HaveRC == NewRC)
2201 if (NewRC->hasSubClassEq(HaveRC))
2208 for (
auto &
B : MF) {
2209 std::map<int,IndexType> LastStore, LastLoad;
2212 auto P = BlockIndexes.insert(
2214 auto &IndexMap =
P.first->second;
2216 << IndexMap <<
'\n');
2218 for (
auto &In :
B) {
2220 bool Load = HII.isLoadFromStackSlot(In, LFI) && !HII.isPredicated(In);
2221 bool Store = HII.isStoreToStackSlot(In, SFI) && !HII.isPredicated(In);
2222 if (Load && Store) {
2234 if (Load || Store) {
2235 int TFI =
Load ? LFI : SFI;
2236 unsigned AM = HII.getAddrMode(In);
2237 SlotInfo &
SI = FIRangeMap[TFI];
2241 unsigned OpNum =
Load ? 0 : 2;
2242 auto *RC = HII.getRegClass(
In.getDesc(), OpNum, &HRI, MF);
2243 RC = getCommonRC(
SI.RC, RC);
2251 unsigned S = HII.getMemAccessSize(In);
2252 if (
SI.Size != 0 &&
SI.Size != S)
2258 for (
auto *Mo :
In.memoperands()) {
2259 if (!Mo->isVolatile() && !Mo->isAtomic())
2270 for (
unsigned i = 0, n =
In.getNumOperands(); i < n; ++i) {
2274 int FI =
Op.getIndex();
2277 if (i+1 >= n || !
In.getOperand(i+1).isImm() ||
2278 In.getOperand(i+1).getImm() != 0)
2280 if (BadFIs.
count(FI))
2285 if (LastStore[FI] == IndexType::None)
2286 LastStore[FI] = IndexType::Entry;
2287 LastLoad[FI] =
Index;
2290 if (LastStore[FI] != IndexType::None)
2291 RL.
add(LastStore[FI], LastLoad[FI],
false,
false);
2292 else if (LastLoad[FI] != IndexType::None)
2293 RL.
add(IndexType::Entry, LastLoad[FI],
false,
false);
2294 LastLoad[FI] = IndexType::None;
2295 LastStore[FI] =
Index;
2302 for (
auto &
I : LastLoad) {
2303 IndexType LL =
I.second;
2304 if (LL == IndexType::None)
2306 auto &RL = FIRangeMap[
I.first].Map[&
B];
2307 IndexType &
LS = LastStore[
I.first];
2308 if (LS != IndexType::None)
2309 RL.
add(LS, LL,
false,
false);
2311 RL.
add(IndexType::Entry, LL,
false,
false);
2312 LS = IndexType::None;
2314 for (
auto &
I : LastStore) {
2315 IndexType
LS =
I.second;
2316 if (LS == IndexType::None)
2318 auto &RL = FIRangeMap[
I.first].Map[&
B];
2319 RL.
add(LS, IndexType::None,
false,
false);
2324 for (
auto &
P : FIRangeMap) {
2325 dbgs() <<
"fi#" <<
P.first;
2326 if (BadFIs.
count(
P.first))
2329 if (
P.second.RC !=
nullptr)
2330 dbgs() << HRI.getRegClassName(
P.second.RC) <<
'\n';
2332 dbgs() <<
"<null>\n";
2333 for (
auto &R :
P.second.Map)
2344 std::map<MachineBasicBlock*,std::vector<int>> BlockFIMap;
2346 for (
auto &
P : FIRangeMap) {
2348 if (BadFIs.
count(
P.first))
2350 for (
auto &
B : MF) {
2351 auto F =
P.second.Map.find(&
B);
2353 if (
F ==
P.second.Map.end() ||
F->second.empty())
2356 if (
IR.start() == IndexType::Entry)
2357 LoxFIs.insert(
P.first);
2358 BlockFIMap[&
B].push_back(
P.first);
2363 dbgs() <<
"Block-to-FI map (* -- live-on-exit):\n";
2364 for (
auto &
P : BlockFIMap) {
2365 auto &FIs =
P.second;
2369 for (
auto I : FIs) {
2370 dbgs() <<
" fi#" <<
I;
2371 if (LoxFIs.count(
I))
2383 for (
auto &
B : MF) {
2384 auto F = BlockIndexes.find(&
B);
2385 assert(
F != BlockIndexes.end());
2392 for (
auto FI : BlockFIMap[&
B]) {
2393 if (BadFIs.
count(FI))
2397 for (
auto &Range : RL) {
2399 if (!IndexType::isInstr(
Range.start()) ||
2400 !IndexType::isInstr(
Range.end()))
2404 assert(
SI.mayStore() &&
"Unexpected start instruction");
2409 SrcOp.getSubReg() };
2410 auto *RC = HII.getRegClass(
SI.getDesc(), 2, &HRI, MF);
2412 Register FoundR = this->findPhysReg(MF, Range, IM,
DM, RC);
2428 if (SrcRR.
Reg != FoundR || SrcRR.
Sub != 0) {
2430 CopyIn =
BuildMI(
B, StartIt,
DL, HII.get(TargetOpcode::COPY), FoundR)
2436 if (LoxFIs.count(FI) && (&Range == &RL.back())) {
2438 if (
unsigned SR =
SrcOp.getSubReg())
2439 SrcOp.setReg(HRI.getSubReg(FoundR, SR));
2441 SrcOp.setReg(FoundR);
2444 SrcOp.setIsKill(
false);
2451 for (
auto It = StartIt; It != EndIt; It = NextIt) {
2453 NextIt = std::next(It);
2455 if (!HII.isLoadFromStackSlot(
MI, TFI) || TFI != FI)
2458 assert(
MI.getOperand(0).getSubReg() == 0);
2460 if (DstR != FoundR) {
2462 unsigned MemSize = HII.getMemAccessSize(
MI);
2464 unsigned CopyOpc = TargetOpcode::COPY;
2465 if (HII.isSignExtendingLoad(
MI))
2466 CopyOpc = (MemSize == 1) ? Hexagon::A2_sxtb : Hexagon::A2_sxth;
2467 else if (HII.isZeroExtendingLoad(
MI))
2468 CopyOpc = (MemSize == 1) ? Hexagon::A2_zxtb : Hexagon::A2_zxth;
2469 CopyOut =
BuildMI(
B, It,
DL, HII.get(CopyOpc), DstR)
2479 DM[RR].subtract(Range);
2485void HexagonFrameLowering::expandAlloca(
MachineInstr *AI,
2511 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), Rd)
2516 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), SP)
2522 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), Rd)
2526 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), SP)
2532 BuildMI(MB, AI,
DL, HII.get(TargetOpcode::COPY), SP)
2537 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_addi), Rd)
2557 if (
I.getOpcode() == Hexagon::PS_aligna)
2564void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(
MachineInstr *
MI,
2565 const CSIVect &CSI,
bool IsDef,
bool IsKill)
const {
2576 const CSIVect &CSI)
const {
2589 BitVector Regs(Hexagon::NUM_TARGET_REGS);
2592 if (!Hexagon::DoubleRegsRegClass.
contains(R))
2596 int F = Regs.find_first();
2597 if (
F != Hexagon::D8)
2600 int N = Regs.find_next(
F);
2601 if (
N >= 0 &&
N !=
F+1)
2610 const CSIVect &CSI)
const {
2611 if (shouldInlineCSR(MF, CSI))
2613 unsigned NumCSI = CSI.size();
2619 return Threshold < NumCSI;
2622bool HexagonFrameLowering::useRestoreFunction(
const MachineFunction &MF,
2623 const CSIVect &CSI)
const {
2624 if (shouldInlineCSR(MF, CSI))
2634 unsigned NumCSI = CSI.size();
2640 return Threshold < NumCSI;
2643bool HexagonFrameLowering::mayOverflowFrameOffset(
MachineFunction &MF)
const {
2648 if (HST.useHVXOps() && StackSize > 256)
2655 bool HasImmStack =
false;
2656 unsigned MinLS = ~0
u;
2661 switch (
MI.getOpcode()) {
2662 case Hexagon::S4_storeirit_io:
2663 case Hexagon::S4_storeirif_io:
2664 case Hexagon::S4_storeiri_io:
2667 case Hexagon::S4_storeirht_io:
2668 case Hexagon::S4_storeirhf_io:
2669 case Hexagon::S4_storeirh_io:
2672 case Hexagon::S4_storeirbt_io:
2673 case Hexagon::S4_storeirbf_io:
2674 case Hexagon::S4_storeirb_io:
2675 if (
MI.getOperand(0).isFI())
2677 MinLS = std::min(MinLS, LS);
2684 return !isUInt<6>(StackSize >> MinLS);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
This file defines the DenseMap class.
static MachineInstr * getReturn(MachineBasicBlock &MBB)
Returns the "return" instruction from this block, or nullptr if there isn't any.
static cl::opt< unsigned > ShrinkLimit("shrink-frame-limit", cl::init(std::numeric_limits< unsigned >::max()), cl::Hidden, cl::desc("Max count of stack frame shrink-wraps"))
static bool isOptNone(const MachineFunction &MF)
static cl::opt< int > SpillFuncThreshold("spill-func-threshold", cl::Hidden, cl::desc("Specify O2(not Os) spill func threshold"), cl::init(6))
static std::optional< MachineBasicBlock::iterator > findCFILocation(MachineBasicBlock &B)
static cl::opt< bool > EliminateFramePointer("hexagon-fp-elim", cl::init(true), cl::Hidden, cl::desc("Refrain from using FP whenever possible"))
static bool enableAllocFrameElim(const MachineFunction &MF)
static const char * getSpillFunctionFor(Register MaxReg, SpillKind SpillType, bool Stkchk=false)
static bool hasReturn(const MachineBasicBlock &MBB)
Returns true if MBB contains an instruction that returns.
static cl::opt< bool > EnableSaveRestoreLong("enable-save-restore-long", cl::Hidden, cl::desc("Enable long calls for save-restore stubs."), cl::init(false))
static bool needToReserveScavengingSpillSlots(MachineFunction &MF, const HexagonRegisterInfo &HRI, const TargetRegisterClass *RC)
Returns true if there are no caller-saved registers available in class RC.
static bool isOptSize(const MachineFunction &MF)
static Register getMax32BitSubRegister(Register Reg, const TargetRegisterInfo &TRI, bool hireg=true)
Map a register pair Reg to the subregister that has the greater "number", i.e.
static cl::opt< int > SpillFuncThresholdOs("spill-func-threshold-Os", cl::Hidden, cl::desc("Specify Os spill func threshold"), cl::init(1))
static bool needsStackFrame(const MachineBasicBlock &MBB, const BitVector &CSR, const HexagonRegisterInfo &HRI)
Checks if the basic block contains any instruction that needs a stack frame to be already in place.
static cl::opt< bool > DisableDeallocRet("disable-hexagon-dealloc-ret", cl::Hidden, cl::desc("Disable Dealloc Return for Hexagon target"))
static cl::opt< bool > EnableShrinkWrapping("hexagon-shrink-frame", cl::init(true), cl::Hidden, cl::desc("Enable stack frame shrink wrapping"))
static bool hasTailCall(const MachineBasicBlock &MBB)
Returns true if MBB has a machine instructions that indicates a tail call in the block.
static cl::opt< unsigned > NumberScavengerSlots("number-scavenger-slots", cl::Hidden, cl::desc("Set the number of scavenger slots"), cl::init(2))
static Register getMaxCalleeSavedReg(ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo &TRI)
Returns the callee saved register with the largest id in the vector.
static bool isMinSize(const MachineFunction &MF)
static cl::opt< unsigned > SpillOptMax("spill-opt-max", cl::Hidden, cl::init(std::numeric_limits< unsigned >::max()))
static unsigned SpillOptCount
static void dump_registers(BitVector &Regs, const TargetRegisterInfo &TRI)
static bool isRestoreCall(unsigned Opc)
static cl::opt< bool > OptimizeSpillSlots("hexagon-opt-spill", cl::Hidden, cl::init(true), cl::desc("Optimize spill slots"))
static cl::opt< bool > EnableStackOVFSanitizer("enable-stackovf-sanitizer", cl::Hidden, cl::desc("Enable runtime checks for stack overflow."), cl::init(false))
Legalize the Machine IR a function s Machine IR
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
FunctionPass class - This class is used to implement most global optimizations.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
bool hasOptNone() const
Do not optimize this function (-O0).
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.
void replaceInstr(MachineInstr *OldMI, MachineInstr *NewMI)
IndexType getIndex(MachineInstr *MI) const
MachineInstr * getInstr(IndexType Idx) const
void add(IndexType Start, IndexType End, bool Fixed, bool TiedEnd)
const MachineInstr * getAlignaInstr(const MachineFunction &MF) const
void insertCFIInstructions(MachineFunction &MF) const
bool enableCalleeSaveSkip(const MachineFunction &MF) const override
Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functi...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Perform most of the PEI work here:
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override
getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs, that contains an entry...
bool needsAligna(const MachineFunction &MF) const
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Load the specified register of the given register class from the specified stack frame index.
Hexagon target-specific information for each MachineFunction.
bool isEHReturnCalleeSaveReg(Register Reg) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
const MCPhysReg * getCallerSavedRegs(const MachineFunction *MF, const TargetRegisterClass *RC) const
const HexagonInstrInfo * getInstrInfo() const override
bool isEnvironmentMusl() const
A set of physical registers with utility functions to track liveness when walking backward/forward th...
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset)
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Describe properties that are true of each instruction in the target description file.
MCRegAliasIterator enumerates all registers aliasing Reg.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< iterator > terminators()
iterator_range< succ_iterator > successors()
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineBasicBlock * findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B)
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
bool runOnMachineFunction(MachineFunction &F) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool hasCalls() const
Return true if the current function has any function calls.
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
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.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
void setMaxCallFrameSize(unsigned S)
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.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, 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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
MachineModuleInfo & getMMI() const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
instr_iterator getInstrIterator() const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isReturn(QueryType Type=AnyInBundle) const
const MachineBasicBlock * getParent() const
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
const MCContext & getContext() const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachinePostDominatorTree - an analysis pass wrapper for DominatorTree used to compute the post-domina...
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
MachineBasicBlock * findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B) const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
static StackOffset getFixed(int64_t Fixed)
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
Primary interface to the complete machine description for the target machine.
bool isPositionIndependent() const
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
unsigned getID() const
Return the register class ID number.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
ArrayRef< MCPhysReg > getRawAllocationOrder(const MachineFunction &MF) const
Returns the preferred order for allocating registers from this register class in MF.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCallFrameInformation()
void initializeHexagonCallFrameInformationPass(PassRegistry &)
unsigned getKillRegState(bool B)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
static RegisterSet expandToSubRegs(RegisterRef R, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
std::map< RegisterRef, RangeList > RegToRangeMap
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.