66 #define DEBUG_TYPE "hexagon-pei"
150 using namespace llvm;
173 cl::desc(
"Enable stack frame shrink wrapping"));
177 cl::desc(
"Max count of stack frame shrink-wraps"));
225 bool HexagonCallFrameInformation::runOnMachineFunction(
MachineFunction &MF) {
231 HFI.insertCFIInstructions(MF);
236 "Hexagon call frame information",
false,
false)
239 return new HexagonCallFrameInformation();
247 if (Reg < Hexagon::D0 || Reg > Hexagon::D15)
253 if (*SubRegs > RegNo)
256 if (!RegNo || *SubRegs < RegNo)
266 static_assert(Hexagon::R1 > 0,
267 "Assume physical registers are encoded as positive integers");
272 for (
unsigned I = 1,
E = CSI.
size();
I <
E; ++
I) {
284 for (
auto &
I :
MBB) {
288 unsigned Opc =
MI->getOpcode();
290 case Hexagon::PS_alloca:
291 case Hexagon::PS_aligna:
316 if (MO.isRegMask()) {
321 const uint32_t *BM = MO.getRegMask();
325 if (!(BM[R/32] & (1u << (R%32))))
340 unsigned RetOpc =
I->getOpcode();
341 return RetOpc == Hexagon::PS_tailcall_i || RetOpc == Hexagon::PS_tailcall_r;
363 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
364 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
365 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT:
366 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC:
367 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT:
368 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC:
369 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:
370 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:
383 return F.hasOptSize() && !
F.hasMinSize();
396 static unsigned ShrinkCounter = 0;
420 for (RPOTType::rpo_iterator
I = RPOT.begin(),
E = RPOT.end();
I !=
E; ++
I)
421 RPO[(*I)->getNumber()] = RPON++;
427 unsigned BN =
RPO[
I.getNumber()];
428 for (
auto SI =
I.succ_begin(), SE =
I.succ_end();
SI != SE; ++
SI) {
430 if (
RPO[(*SI)->getNumber()] <= BN)
439 for (
const MCPhysReg *
P = HRI.getCalleeSavedRegs(&MF); *
P; ++
P)
445 SFBlocks.push_back(&
I);
448 dbgs() <<
"Blocks needing SF: {";
449 for (
auto &
B : SFBlocks)
454 if (SFBlocks.empty())
459 for (
unsigned i = 1,
n = SFBlocks.size();
i <
n; ++
i) {
465 for (
unsigned i = 1,
n = SFBlocks.size();
i <
n; ++
i) {
471 dbgs() <<
"Computed dom block: ";
476 dbgs() <<
", computed pdom block: ";
492 LLVM_DEBUG(
dbgs() <<
"PDom block does not post-dominate dom block\n");
515 findShrunkPrologEpilog(MF, PrologB, EpilogB);
517 bool PrologueStubs =
false;
518 insertCSRSpillsInBlock(*PrologB, CSI, HRI, PrologueStubs);
519 insertPrologueInBlock(*PrologB, PrologueStubs);
520 updateEntryPaths(MF, *PrologB);
523 insertCSRRestoresInBlock(*EpilogB, CSI, HRI);
524 insertEpilogueInBlock(*EpilogB);
527 if (
B.isReturnBlock())
528 insertCSRRestoresInBlock(
B, CSI, HRI);
531 if (
B.isReturnBlock())
532 insertEpilogueInBlock(
B);
550 BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);
551 updateExitPaths(*EpilogB, *EpilogB, DoneT, DoneF, Path);
560 assert(
F.hasFnAttribute(Attribute::NoReturn) &&
561 F.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
562 !
F.getFunction().hasFnAttribute(Attribute::UWTable));
578 assert(!MFI.hasVarSizedObjects() &&
579 !HST.getRegisterInfo()->hasStackRealignment(MF));
580 return F.hasFnAttribute(Attribute::NoReturn) &&
581 F.hasFnAttribute(Attribute::NoUnwind) &&
582 !
F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() &&
583 MFI.getStackSize() == 0;
587 bool PrologueStubs)
const {
592 auto &HRI = *HST.getRegisterInfo();
603 FrameSize = MaxCFA +
alignTo(FrameSize, MaxAlign);
610 unsigned SP = HRI.getStackRegister();
617 if (
MI.getOpcode() == Hexagon::PS_alloca)
618 AdjustRegs.push_back(&
MI);
620 for (
auto MI : AdjustRegs) {
621 assert((
MI->getOpcode() == Hexagon::PS_alloca) &&
"Expected alloca");
622 expandAlloca(
MI, HII, SP, MaxCF);
623 MI->eraseFromParent();
628 if (MF.getFunction().isVarArg() &&
632 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)
634 : NumVarArgRegs * 4 + 4;
635 if (RegisterSavedAreaSizePlusPadding > 0) {
638 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
640 .
addImm(-RegisterSavedAreaSizePlusPadding)
646 for (
int i = HMFI.getFirstNamedArgFrameIndex(),
647 e = HMFI.getLastNamedArgFrameIndex();
i >=
e; --
i) {
652 unsigned LDOpc, STOpc;
653 uint64_t OpcodeChecker = ObjAlign.
value();
656 if (ObjAlign > ObjSize) {
659 else if (ObjSize <= 2)
661 else if (ObjSize <= 4)
663 else if (ObjSize > 4)
667 switch (OpcodeChecker) {
669 LDOpc = Hexagon::L2_loadrb_io;
670 STOpc = Hexagon::S2_storerb_io;
673 LDOpc = Hexagon::L2_loadrh_io;
674 STOpc = Hexagon::S2_storerh_io;
677 LDOpc = Hexagon::L2_loadri_io;
678 STOpc = Hexagon::S2_storeri_io;
682 LDOpc = Hexagon::L2_loadrd_io;
683 STOpc = Hexagon::S2_storerd_io;
687 unsigned RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3
689 int LoadStoreCount = ObjSize / OpcodeChecker;
691 if (ObjSize % OpcodeChecker)
699 NumBytes =
alignTo(NumBytes, ObjAlign);
702 while (Count < LoadStoreCount) {
704 BuildMI(
MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)
706 .
addImm(RegisterSavedAreaSizePlusPadding +
707 ObjAlign.
value() * Count + NumBytes)
723 NumBytes =
alignTo(NumBytes, 8);
728 NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;
731 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))
741 insertAllocframe(
MBB, InsertPt, NumBytes);
743 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
751 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
753 }
else if (NumBytes > 0) {
755 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
765 auto &HRI = *HST.getRegisterInfo();
766 unsigned SP = HRI.getStackRegister();
778 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
779 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
780 NumBytes += RegisterSavedAreaSizePlusPadding;
783 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
791 unsigned RetOpc = RetI ? RetI->
getOpcode() : 0;
794 if (RetOpc == Hexagon::EH_RETURN_JMPR) {
795 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
798 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)
806 if (RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4 ||
807 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC ||
808 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT ||
809 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC) {
825 bool NeedsDeallocframe =
true;
828 unsigned COpc = PrevIt->getOpcode();
829 if (COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||
830 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC ||
831 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||
832 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||
833 COpc == Hexagon::PS_call_nr || COpc == Hexagon::PS_callr_nr)
834 NeedsDeallocframe =
false;
839 if (!NeedsDeallocframe)
845 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
850 unsigned NewOpc = Hexagon::L4_return;
861 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
862 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
868 (
I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT &&
869 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC &&
870 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 &&
871 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC))
872 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
875 if (RegisterSavedAreaSizePlusPadding != 0)
876 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
878 .
addImm(RegisterSavedAreaSizePlusPadding);
887 auto &HRI = *HST.getRegisterInfo();
891 const unsigned int ALLOCFRAME_MAX = 16384;
899 unsigned SP = HRI.getStackRegister();
901 if (NumBytes >= ALLOCFRAME_MAX) {
903 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
910 unsigned SP = HRI.getStackRegister();
911 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
915 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
933 for (
unsigned i = 0;
i < Worklist.
size(); ++
i) {
934 unsigned BN = Worklist[
i];
941 Worklist.
insert(SB->getNumber());
950 if (Path[BN] || DoneF[BN])
958 bool ReachedExit =
false;
960 ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);
976 if (ReachedExit && &
MBB != &RestoreB) {
996 auto End =
B.instr_end();
1000 if (!
I.isBundle()) {
1001 if (
I.getOpcode() == Hexagon::S2_allocframe)
1002 return std::next(It);
1006 bool HasCall =
false, HasAllocFrame =
false;
1008 while (++
T != End &&
T->isBundled()) {
1009 if (
T->getOpcode() == Hexagon::S2_allocframe)
1010 HasAllocFrame =
true;
1011 else if (
T->isCall())
1015 return HasCall ? It : std::next(It);
1021 for (
auto &
B : MF) {
1024 insertCFIInstructionsAt(
B, At.getValue());
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);
1074 static unsigned int RegsToMove[] = {
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) {
1087 unsigned Reg = RegsToMove[
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();
1274 Register FP = HRI.getFrameRegister();
1275 Register AP = HMFI.getStackAlignBasePhysReg();
1293 bool UseFP =
false, UseAP =
false;
1298 if (NoOpt && !HasExtraAlign)
1303 UseFP |= (HasAlloca || HasExtraAlign);
1314 bool HasFP =
hasFP(MF);
1315 assert((HasFP || !UseFP) &&
"This function must have frame pointer");
1341 if (
Offset > 0 && !HasFP)
1356 if (!UseFP && !UseAP)
1357 RealOffset = FrameSize+
Offset;
1363 bool &PrologueStubs)
const {
1368 PrologueStubs =
false;
1373 if (useSpillFunction(MF, CSI)) {
1374 PrologueStubs =
true;
1386 if (StkOvrFlowEnabled) {
1388 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC
1389 : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;
1391 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
1392 : Hexagon::SAVE_REGISTERS_CALL_V4STK;
1395 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC
1396 : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
1398 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
1399 : Hexagon::SAVE_REGISTERS_CALL_V4;
1407 addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI,
false,
true);
1409 for (
unsigned I = 0;
I < CSI.size(); ++
I)
1414 for (
unsigned i = 0,
n = CSI.size();
i <
n; ++
i) {
1415 unsigned Reg = CSI[
i].getReg();
1420 int FI = CSI[
i].getFrameIdx();
1422 HII.storeRegToStackSlot(
MBB,
MI,
Reg, IsKill, FI, RC, &HRI);
1439 if (useRestoreFunction(MF, CSI)) {
1456 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC
1457 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;
1459 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
1460 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
1469 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC
1470 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;
1472 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
1473 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
1479 addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI,
true,
false);
1483 for (
unsigned i = 0;
i < CSI.size(); ++
i) {
1484 unsigned Reg = CSI[
i].getReg();
1486 int FI = CSI[
i].getFrameIdx();
1487 HII.loadRegFromStackSlot(
MBB,
MI,
Reg, FI, RC, &HRI);
1497 unsigned Opc =
MI.getOpcode();
1499 assert((Opc == Hexagon::ADJCALLSTACKDOWN || Opc == Hexagon::ADJCALLSTACKUP) &&
1500 "Cannot handle this call frame pseudo instruction");
1514 if (!HasAlloca || !NeedsAlign)
1534 assert(A <= 8 &&
"Unexpected local frame alignment");
1541 if (!DealignSlots.
empty()) {
1544 bool KeepOld =
true;
1548 auto *PV = MMO->getPseudoValue();
1549 if (
auto *
FS = dyn_cast_or_null<FixedStackPseudoSourceValue>(PV)) {
1550 int FI =
FS->getFrameIndex();
1551 if (DealignSlots.
count(FI)) {
1552 auto *NewMMO = MF.getMachineMemOperand(
1553 MMO->getPointerInfo(), MMO->getFlags(), MMO->getSize(),
1555 MMO->getSyncScopeID(), MMO->getOrdering(),
1556 MMO->getFailureOrdering());
1557 new_memops.push_back(NewMMO);
1562 new_memops.push_back(MMO);
1565 MI.setMemRefs(MF, new_memops);
1573 AP = AI->getOperand(0).getReg();
1583 auto IsUsed = [&HRI,&
MRI] (
unsigned Reg) ->
bool {
1615 BitVector SRegs(Hexagon::NUM_TARGET_REGS);
1624 for (
unsigned i = 0,
n = CSI.size();
i <
n; ++
i) {
1625 unsigned R = CSI[
i].getReg();
1651 BitVector TmpSup(Hexagon::NUM_TARGET_REGS);
1657 for (
int x = TmpSup.find_first();
x >= 0;
x = TmpSup.find_next(
x)) {
1697 for (
const SpillSlot *
S = FixedSlots;
S != FixedSlots+NumFixed; ++
S) {
1702 MinOffset =
std::min(MinOffset,
S->Offset);
1704 SRegs[
S->Reg] =
false;
1714 int Off = MinOffset -
Size;
1716 Off &= -Alignment.
value();
1718 MinOffset =
std::min(MinOffset, Off);
1724 dbgs() <<
"CS information: {";
1725 for (
unsigned i = 0,
n = CSI.size();
i <
n; ++
i) {
1726 int FI = CSI[
i].getFrameIdx();
1738 bool MissedReg =
false;
1758 if (!Hexagon::ModRegsRegClass.
contains(DstR) ||
1759 !Hexagon::ModRegsRegClass.
contains(SrcR))
1763 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), TmpR).
add(
MI->getOperand(1));
1764 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), DstR)
1767 NewRegs.push_back(TmpR);
1776 if (!
MI->getOperand(0).isFI())
1780 unsigned Opc =
MI->getOpcode();
1782 bool IsKill =
MI->getOperand(2).isKill();
1783 int FI =
MI->getOperand(0).getIndex();
1788 unsigned TfrOpc = (Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr
1789 : Hexagon::A2_tfrcrr;
1794 BuildMI(
B, It,
DL, HII.get(Hexagon::S2_storeri_io))
1800 NewRegs.push_back(TmpR);
1809 if (!
MI->getOperand(1).isFI())
1813 unsigned Opc =
MI->getOpcode();
1815 int FI =
MI->getOperand(1).getIndex();
1819 BuildMI(
B, It,
DL, HII.get(Hexagon::L2_loadri_io), TmpR)
1826 unsigned TfrOpc = (Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp
1827 : Hexagon::A2_tfrrcr;
1831 NewRegs.push_back(TmpR);
1840 if (!
MI->getOperand(0).isFI())
1845 bool IsKill =
MI->getOperand(2).isKill();
1846 int FI =
MI->getOperand(0).getIndex();
1847 auto *RC = &Hexagon::HvxVRRegClass;
1856 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1859 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandqrt), TmpR1)
1865 expandStoreVec(
B, std::prev(It),
MRI, HII, NewRegs);
1867 NewRegs.push_back(TmpR0);
1868 NewRegs.push_back(TmpR1);
1877 if (!
MI->getOperand(1).isFI())
1882 int FI =
MI->getOperand(1).getIndex();
1883 auto *RC = &Hexagon::HvxVRRegClass;
1891 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1896 expandLoadVec(
B, std::prev(It),
MRI, HII, NewRegs);
1898 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandvrt), DstR)
1902 NewRegs.push_back(TmpR0);
1903 NewRegs.push_back(TmpR1);
1915 if (!
MI->getOperand(0).isFI())
1925 for (
auto R =
B.begin(); R != It; ++R) {
1927 LPR.stepForward(*R, Clobbers);
1932 Register SrcLo = HRI.getSubReg(SrcR, Hexagon::vsub_lo);
1933 Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);
1934 bool IsKill =
MI->getOperand(2).isKill();
1935 int FI =
MI->getOperand(0).getIndex();
1938 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1939 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1943 auto UseAligned = [&](
Align NeedAlign,
Align HasAlign) {
1944 return !NeedsAligna && (NeedAlign <= HasAlign);
1948 if (LPR.contains(SrcLo)) {
1949 StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
1950 : Hexagon::V6_vS32Ub_ai;
1959 if (LPR.contains(SrcHi)) {
1960 StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
1961 : Hexagon::V6_vS32Ub_ai;
1980 if (!
MI->getOperand(1).isFI())
1985 Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);
1986 Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);
1987 int FI =
MI->getOperand(1).getIndex();
1990 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1991 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1995 auto UseAligned = [&](
Align NeedAlign,
Align HasAlign) {
1996 return !NeedsAligna && (NeedAlign <= HasAlign);
2000 LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
2001 : Hexagon::V6_vL32Ub_ai;
2008 LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
2009 : Hexagon::V6_vL32Ub_ai;
2025 if (!
MI->getOperand(0).isFI())
2032 bool IsKill =
MI->getOperand(2).isKill();
2033 int FI =
MI->getOperand(0).getIndex();
2035 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2037 bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
2038 unsigned StoreOpc = UseAligned ? Hexagon::V6_vS32b_ai
2039 : Hexagon::V6_vS32Ub_ai;
2056 if (!
MI->getOperand(1).isFI())
2063 int FI =
MI->getOperand(1).getIndex();
2065 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2067 bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
2068 unsigned LoadOpc = UseAligned ? Hexagon::V6_vL32b_ai
2069 : Hexagon::V6_vL32Ub_ai;
2083 bool Changed =
false;
2085 for (
auto &
B : MF) {
2088 for (
auto I =
B.begin(),
E =
B.end();
I !=
E;
I = NextI) {
2090 NextI = std::next(
I);
2091 unsigned Opc =
MI->getOpcode();
2094 case TargetOpcode::COPY:
2095 Changed |= expandCopy(
B,
I,
MRI, HII, NewRegs);
2097 case Hexagon::STriw_pred:
2098 case Hexagon::STriw_ctr:
2099 Changed |= expandStoreInt(
B,
I,
MRI, HII, NewRegs);
2101 case Hexagon::LDriw_pred:
2102 case Hexagon::LDriw_ctr:
2103 Changed |= expandLoadInt(
B,
I,
MRI, HII, NewRegs);
2105 case Hexagon::PS_vstorerq_ai:
2106 Changed |= expandStoreVecPred(
B,
I,
MRI, HII, NewRegs);
2108 case Hexagon::PS_vloadrq_ai:
2109 Changed |= expandLoadVecPred(
B,
I,
MRI, HII, NewRegs);
2111 case Hexagon::PS_vloadrw_ai:
2112 Changed |= expandLoadVec2(
B,
I,
MRI, HII, NewRegs);
2114 case Hexagon::PS_vstorerw_ai:
2115 Changed |= expandStoreVec2(
B,
I,
MRI, HII, NewRegs);
2129 SavedRegs.
resize(HRI.getNumRegs());
2139 expandSpillMacros(MF, NewRegs);
2141 optimizeSpillSlots(MF, NewRegs);
2145 if (!NewRegs.empty() || mayOverflowFrameOffset(MF)) {
2151 SpillRCs.
insert(&Hexagon::IntRegsRegClass);
2153 for (
unsigned VR : NewRegs)
2156 for (
auto *RC : SpillRCs) {
2160 switch (RC->
getID()) {
2161 case Hexagon::IntRegsRegClassID:
2164 case Hexagon::HvxQRRegClassID:
2168 unsigned S = HRI.getSpillSize(*RC);
2169 Align A = HRI.getSpillAlign(*RC);
2170 for (
unsigned i = 0;
i < Num;
i++) {
2188 auto isDead = [&FIR,&DeadMap] (
unsigned Reg) ->
bool {
2189 auto F = DeadMap.find({
Reg,0});
2190 if (
F == DeadMap.end())
2192 for (
auto &DR :
F->second)
2193 if (DR.contains(FIR))
2215 auto &HII = *HST.getInstrInfo();
2216 auto &HRI = *HST.getRegisterInfo();
2220 using BlockIndexMap =
2221 std::map<MachineBasicBlock *, HexagonBlockRanges::InstrIndexMap>;
2222 using BlockRangeMap =
2223 std::map<MachineBasicBlock *, HexagonBlockRanges::RangeList>;
2231 SlotInfo() =
default;
2234 BlockIndexMap BlockIndexes;
2236 std::map<int,SlotInfo> FIRangeMap;
2245 if (HaveRC ==
nullptr || HaveRC == NewRC)
2250 if (NewRC->hasSubClassEq(HaveRC))
2257 for (
auto &
B : MF) {
2258 std::map<int,IndexType> LastStore, LastLoad;
2261 auto P = BlockIndexes.insert(
2263 auto &IndexMap =
P.first->second;
2265 << IndexMap <<
'\n');
2267 for (
auto &
In :
B) {
2269 bool Load = HII.isLoadFromStackSlot(
In, LFI) && !HII.isPredicated(
In);
2270 bool Store = HII.isStoreToStackSlot(
In, SFI) && !HII.isPredicated(
In);
2284 int TFI =
Load ? LFI : SFI;
2285 unsigned AM = HII.getAddrMode(
In);
2286 SlotInfo &
SI = FIRangeMap[TFI];
2290 unsigned OpNum =
Load ? 0 : 2;
2291 auto *RC = HII.getRegClass(
In.getDesc(), OpNum, &HRI, MF);
2292 RC = getCommonRC(
SI.RC, RC);
2300 unsigned S = HII.getMemAccessSize(
In);
2301 if (
SI.Size != 0 &&
SI.Size !=
S)
2307 for (
auto *Mo :
In.memoperands()) {
2308 if (!Mo->isVolatile() && !Mo->isAtomic())
2319 for (
unsigned i = 0,
n =
In.getNumOperands();
i <
n; ++
i) {
2323 int FI =
Op.getIndex();
2326 if (
i+1 >=
n || !
In.getOperand(
i+1).isImm() ||
2327 In.getOperand(
i+1).getImm() != 0)
2329 if (BadFIs.
count(FI))
2335 LastStore[FI] = IndexType::Entry;
2336 LastLoad[FI] =
Index;
2340 RL.
add(LastStore[FI], LastLoad[FI],
false,
false);
2342 RL.
add(IndexType::Entry, LastLoad[FI],
false,
false);
2344 LastStore[FI] =
Index;
2351 for (
auto &
I : LastLoad) {
2352 IndexType LL =
I.second;
2355 auto &RL = FIRangeMap[
I.first].Map[&
B];
2356 IndexType &
LS = LastStore[
I.first];
2358 RL.
add(
LS, LL,
false,
false);
2360 RL.
add(IndexType::Entry, LL,
false,
false);
2363 for (
auto &
I : LastStore) {
2364 IndexType
LS =
I.second;
2367 auto &RL = FIRangeMap[
I.first].Map[&
B];
2373 for (
auto &
P : FIRangeMap) {
2374 dbgs() <<
"fi#" <<
P.first;
2375 if (BadFIs.
count(
P.first))
2378 if (
P.second.RC !=
nullptr)
2379 dbgs() << HRI.getRegClassName(
P.second.RC) <<
'\n';
2381 dbgs() <<
"<null>\n";
2382 for (
auto &R :
P.second.Map)
2393 std::map<MachineBasicBlock*,std::vector<int>> BlockFIMap;
2395 for (
auto &
P : FIRangeMap) {
2397 if (BadFIs.
count(
P.first))
2399 for (
auto &
B : MF) {
2400 auto F =
P.second.Map.find(&
B);
2402 if (
F ==
P.second.Map.end() ||
F->second.empty())
2405 if (
IR.start() == IndexType::Entry)
2406 LoxFIs.insert(
P.first);
2407 BlockFIMap[&
B].push_back(
P.first);
2412 dbgs() <<
"Block-to-FI map (* -- live-on-exit):\n";
2413 for (
auto &
P : BlockFIMap) {
2414 auto &FIs =
P.second;
2418 for (
auto I : FIs) {
2419 dbgs() <<
" fi#" <<
I;
2420 if (LoxFIs.count(
I))
2432 for (
auto &
B : MF) {
2433 auto F = BlockIndexes.find(&
B);
2434 assert(
F != BlockIndexes.end());
2441 for (
auto FI : BlockFIMap[&
B]) {
2442 if (BadFIs.
count(FI))
2446 for (
auto &Range : RL) {
2448 if (!IndexType::isInstr(Range.start()) ||
2449 !IndexType::isInstr(Range.end()))
2453 assert(
SI.mayStore() &&
"Unexpected start instruction");
2458 SrcOp.getSubReg() };
2459 auto *RC = HII.getRegClass(
SI.getDesc(), 2, &HRI, MF);
2461 unsigned FoundR = this->findPhysReg(MF, Range, IM,
DM, RC);
2477 if (SrcRR.
Reg != FoundR || SrcRR.
Sub != 0) {
2479 CopyIn =
BuildMI(
B, StartIt,
DL, HII.get(TargetOpcode::COPY), FoundR)
2485 if (LoxFIs.count(FI) && (&Range == &RL.back())) {
2487 if (
unsigned SR =
SrcOp.getSubReg())
2488 SrcOp.setReg(HRI.getSubReg(FoundR, SR));
2490 SrcOp.setReg(FoundR);
2493 SrcOp.setIsKill(
false);
2500 for (
auto It = StartIt; It != EndIt; It = NextIt) {
2502 NextIt = std::next(It);
2504 if (!HII.isLoadFromStackSlot(
MI, TFI) || TFI != FI)
2507 assert(
MI.getOperand(0).getSubReg() == 0);
2509 if (DstR != FoundR) {
2511 unsigned MemSize = HII.getMemAccessSize(
MI);
2513 unsigned CopyOpc = TargetOpcode::COPY;
2514 if (HII.isSignExtendingLoad(
MI))
2515 CopyOpc = (MemSize == 1) ? Hexagon::A2_sxtb : Hexagon::A2_sxth;
2516 else if (HII.isZeroExtendingLoad(
MI))
2517 CopyOpc = (MemSize == 1) ? Hexagon::A2_zxtb : Hexagon::A2_zxth;
2518 CopyOut =
BuildMI(
B, It,
DL, HII.get(CopyOpc), DstR)
2528 DM[RR].subtract(Range);
2534 void HexagonFrameLowering::expandAlloca(
MachineInstr *AI,
2560 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), Rd)
2565 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), SP)
2571 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), Rd)
2575 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), SP)
2581 BuildMI(MB, AI,
DL, HII.get(TargetOpcode::COPY), SP)
2586 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_addi), Rd)
2606 if (
I.getOpcode() == Hexagon::PS_aligna)
2613 void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(
MachineInstr *
MI,
2614 const CSIVect &CSI,
bool IsDef,
bool IsKill)
const {
2625 const CSIVect &CSI)
const {
2638 BitVector Regs(Hexagon::NUM_TARGET_REGS);
2639 for (
unsigned i = 0,
n = CSI.size();
i <
n; ++
i) {
2640 unsigned R = CSI[
i].getReg();
2641 if (!Hexagon::DoubleRegsRegClass.
contains(R))
2645 int F = Regs.find_first();
2646 if (
F != Hexagon::D8)
2649 int N = Regs.find_next(
F);
2650 if (
N >= 0 &&
N !=
F+1)
2658 bool HexagonFrameLowering::useSpillFunction(
const MachineFunction &MF,
2659 const CSIVect &CSI)
const {
2660 if (shouldInlineCSR(MF, CSI))
2662 unsigned NumCSI = CSI.size();
2671 bool HexagonFrameLowering::useRestoreFunction(
const MachineFunction &MF,
2672 const CSIVect &CSI)
const {
2673 if (shouldInlineCSR(MF, CSI))
2683 unsigned NumCSI = CSI.size();
2692 bool HexagonFrameLowering::mayOverflowFrameOffset(
MachineFunction &MF)
const {
2697 if (HST.useHVXOps() && StackSize > 256)
2704 bool HasImmStack =
false;
2705 unsigned MinLS = ~0u;
2710 switch (
MI.getOpcode()) {
2711 case Hexagon::S4_storeirit_io:
2712 case Hexagon::S4_storeirif_io:
2713 case Hexagon::S4_storeiri_io:
2716 case Hexagon::S4_storeirht_io:
2717 case Hexagon::S4_storeirhf_io:
2718 case Hexagon::S4_storeirh_io:
2721 case Hexagon::S4_storeirbt_io:
2722 case Hexagon::S4_storeirbf_io:
2723 case Hexagon::S4_storeirb_io:
2724 if (
MI.getOperand(0).isFI())
2733 return !isUInt<6>(StackSize >> MinLS);