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) {
287 unsigned Opc =
MI.getOpcode();
289 case Hexagon::PS_alloca:
290 case Hexagon::PS_aligna:
315 if (MO.isRegMask()) {
320 const uint32_t *BM = MO.getRegMask();
324 if (!(BM[R/32] & (1u << (R%32))))
339 unsigned RetOpc =
I->getOpcode();
340 return RetOpc == Hexagon::PS_tailcall_i || RetOpc == Hexagon::PS_tailcall_r;
362 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
363 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
364 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT:
365 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC:
366 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT:
367 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC:
368 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:
369 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:
382 return F.hasOptSize() && !
F.hasMinSize();
395 static unsigned ShrinkCounter = 0;
420 RPO[
I->getNumber()] = RPON++;
426 unsigned BN =
RPO[
I.getNumber()];
429 if (
RPO[Succ->getNumber()] <= BN)
437 for (
const MCPhysReg *
P = HRI.getCalleeSavedRegs(&MF); *
P; ++
P)
443 SFBlocks.push_back(&
I);
446 dbgs() <<
"Blocks needing SF: {";
447 for (
auto &
B : SFBlocks)
452 if (SFBlocks.empty())
457 for (
unsigned i = 1,
n = SFBlocks.size();
i <
n; ++
i) {
463 for (
unsigned i = 1,
n = SFBlocks.size();
i <
n; ++
i) {
469 dbgs() <<
"Computed dom block: ";
474 dbgs() <<
", computed pdom block: ";
490 LLVM_DEBUG(
dbgs() <<
"PDom block does not post-dominate dom block\n");
513 findShrunkPrologEpilog(MF, PrologB, EpilogB);
515 bool PrologueStubs =
false;
516 insertCSRSpillsInBlock(*PrologB, CSI, HRI, PrologueStubs);
517 insertPrologueInBlock(*PrologB, PrologueStubs);
518 updateEntryPaths(MF, *PrologB);
521 insertCSRRestoresInBlock(*EpilogB, CSI, HRI);
522 insertEpilogueInBlock(*EpilogB);
525 if (
B.isReturnBlock())
526 insertCSRRestoresInBlock(
B, CSI, HRI);
529 if (
B.isReturnBlock())
530 insertEpilogueInBlock(
B);
548 BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);
549 updateExitPaths(*EpilogB, *EpilogB, DoneT, DoneF, Path);
558 assert(
F.hasFnAttribute(Attribute::NoReturn) &&
559 F.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
560 !
F.getFunction().hasFnAttribute(Attribute::UWTable));
576 assert(!MFI.hasVarSizedObjects() &&
577 !HST.getRegisterInfo()->hasStackRealignment(MF));
578 return F.hasFnAttribute(Attribute::NoReturn) &&
579 F.hasFnAttribute(Attribute::NoUnwind) &&
580 !
F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() &&
581 MFI.getStackSize() == 0;
585 bool PrologueStubs)
const {
590 auto &HRI = *HST.getRegisterInfo();
601 FrameSize = MaxCFA +
alignTo(FrameSize, MaxAlign);
608 unsigned SP = HRI.getStackRegister();
615 if (
MI.getOpcode() == Hexagon::PS_alloca)
616 AdjustRegs.push_back(&
MI);
618 for (
auto MI : AdjustRegs) {
619 assert((
MI->getOpcode() == Hexagon::PS_alloca) &&
"Expected alloca");
620 expandAlloca(
MI, HII, SP, MaxCF);
621 MI->eraseFromParent();
626 if (MF.getFunction().isVarArg() &&
630 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)
632 : NumVarArgRegs * 4 + 4;
633 if (RegisterSavedAreaSizePlusPadding > 0) {
636 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
638 .
addImm(-RegisterSavedAreaSizePlusPadding)
644 for (
int i = HMFI.getFirstNamedArgFrameIndex(),
645 e = HMFI.getLastNamedArgFrameIndex();
i >=
e; --
i) {
650 unsigned LDOpc, STOpc;
654 if (ObjAlign > ObjSize) {
657 else if (ObjSize <= 2)
659 else if (ObjSize <= 4)
661 else if (ObjSize > 4)
665 switch (OpcodeChecker) {
667 LDOpc = Hexagon::L2_loadrb_io;
668 STOpc = Hexagon::S2_storerb_io;
671 LDOpc = Hexagon::L2_loadrh_io;
672 STOpc = Hexagon::S2_storerh_io;
675 LDOpc = Hexagon::L2_loadri_io;
676 STOpc = Hexagon::S2_storeri_io;
680 LDOpc = Hexagon::L2_loadrd_io;
681 STOpc = Hexagon::S2_storerd_io;
685 unsigned RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3
687 int LoadStoreCount = ObjSize / OpcodeChecker;
689 if (ObjSize % OpcodeChecker)
697 NumBytes =
alignTo(NumBytes, ObjAlign);
700 while (Count < LoadStoreCount) {
702 BuildMI(
MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)
704 .
addImm(RegisterSavedAreaSizePlusPadding +
705 ObjAlign.
value() * Count + NumBytes)
721 NumBytes =
alignTo(NumBytes, 8);
726 NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;
729 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))
739 insertAllocframe(
MBB, InsertPt, NumBytes);
741 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
749 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
751 }
else if (NumBytes > 0) {
753 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
763 auto &HRI = *HST.getRegisterInfo();
764 unsigned SP = HRI.getStackRegister();
776 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
777 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
778 NumBytes += RegisterSavedAreaSizePlusPadding;
781 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
789 unsigned RetOpc = RetI ? RetI->
getOpcode() : 0;
792 if (RetOpc == Hexagon::EH_RETURN_JMPR) {
793 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
796 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)
804 if (RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4 ||
805 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC ||
806 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT ||
807 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC) {
823 bool NeedsDeallocframe =
true;
826 unsigned COpc = PrevIt->getOpcode();
827 if (COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||
828 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC ||
829 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||
830 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||
831 COpc == Hexagon::PS_call_nr || COpc == Hexagon::PS_callr_nr)
832 NeedsDeallocframe =
false;
837 if (!NeedsDeallocframe)
843 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
848 unsigned NewOpc = Hexagon::L4_return;
859 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
860 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
866 (
I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT &&
867 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC &&
868 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 &&
869 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC))
870 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
873 if (RegisterSavedAreaSizePlusPadding != 0)
874 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
876 .
addImm(RegisterSavedAreaSizePlusPadding);
885 auto &HRI = *HST.getRegisterInfo();
889 const unsigned int ALLOCFRAME_MAX = 16384;
897 unsigned SP = HRI.getStackRegister();
899 if (NumBytes >= ALLOCFRAME_MAX) {
901 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
908 unsigned SP = HRI.getStackRegister();
909 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
913 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
931 for (
unsigned i = 0;
i < Worklist.
size(); ++
i) {
932 unsigned BN = Worklist[
i];
939 Worklist.
insert(SB->getNumber());
948 if (Path[BN] || DoneF[BN])
956 bool ReachedExit =
false;
958 ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);
974 if (ReachedExit && &
MBB != &RestoreB) {
994 auto End =
B.instr_end();
999 if (
I.getOpcode() == Hexagon::S2_allocframe)
1000 return std::next(It);
1004 bool HasCall =
false, HasAllocFrame =
false;
1006 while (++
T != End &&
T->isBundled()) {
1007 if (
T->getOpcode() == Hexagon::S2_allocframe)
1008 HasAllocFrame =
true;
1009 else if (
T->isCall())
1013 return HasCall ? It : std::next(It);
1019 for (
auto &
B : MF) {
1022 insertCFIInstructionsAt(
B, At.getValue());
1033 auto &HRI = *HST.getRegisterInfo();
1039 const MCInstrDesc &CFID = HII.get(TargetOpcode::CFI_INSTRUCTION);
1042 bool HasFP =
hasFP(MF);
1045 unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(),
true);
1046 unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(),
true);
1072 static unsigned int RegsToMove[] = {
1073 Hexagon::R1, Hexagon::R0, Hexagon::R3,
Hexagon::R2,
1074 Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,
1075 Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,
1076 Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,
1077 Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9,
1078 Hexagon::D10, Hexagon::D11, Hexagon::D12, Hexagon::D13,
1084 for (
unsigned i = 0; RegsToMove[
i] != Hexagon::NoRegister; ++
i) {
1085 unsigned Reg = RegsToMove[
i];
1087 return C.getReg() ==
Reg;
1111 if (Reg < Hexagon::D0 || Reg > Hexagon::D15) {
1112 unsigned DwarfReg = HRI.getDwarfRegNum(
Reg,
true);
1124 Register HiReg = HRI.getSubReg(
Reg, Hexagon::isub_hi);
1125 Register LoReg = HRI.getSubReg(
Reg, Hexagon::isub_lo);
1126 unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg,
true);
1127 unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg,
true);
1146 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1162 if (HasAlloca || HasExtraAlign)
1188 bool Stkchk =
false) {
1189 const char * V4SpillToMemoryFunctions[] = {
1190 "__save_r16_through_r17",
1191 "__save_r16_through_r19",
1192 "__save_r16_through_r21",
1193 "__save_r16_through_r23",
1194 "__save_r16_through_r25",
1195 "__save_r16_through_r27" };
1197 const char * V4SpillToMemoryStkchkFunctions[] = {
1198 "__save_r16_through_r17_stkchk",
1199 "__save_r16_through_r19_stkchk",
1200 "__save_r16_through_r21_stkchk",
1201 "__save_r16_through_r23_stkchk",
1202 "__save_r16_through_r25_stkchk",
1203 "__save_r16_through_r27_stkchk" };
1205 const char * V4SpillFromMemoryFunctions[] = {
1206 "__restore_r16_through_r17_and_deallocframe",
1207 "__restore_r16_through_r19_and_deallocframe",
1208 "__restore_r16_through_r21_and_deallocframe",
1209 "__restore_r16_through_r23_and_deallocframe",
1210 "__restore_r16_through_r25_and_deallocframe",
1211 "__restore_r16_through_r27_and_deallocframe" };
1213 const char * V4SpillFromMemoryTailcallFunctions[] = {
1214 "__restore_r16_through_r17_and_deallocframe_before_tailcall",
1215 "__restore_r16_through_r19_and_deallocframe_before_tailcall",
1216 "__restore_r16_through_r21_and_deallocframe_before_tailcall",
1217 "__restore_r16_through_r23_and_deallocframe_before_tailcall",
1218 "__restore_r16_through_r25_and_deallocframe_before_tailcall",
1219 "__restore_r16_through_r27_and_deallocframe_before_tailcall"
1222 const char **SpillFunc =
nullptr;
1226 SpillFunc = Stkchk ? V4SpillToMemoryStkchkFunctions
1227 : V4SpillToMemoryFunctions;
1230 SpillFunc = V4SpillFromMemoryFunctions;
1233 SpillFunc = V4SpillFromMemoryTailcallFunctions;
1236 assert(SpillFunc &&
"Unknown spill kind");
1241 return SpillFunc[0];
1243 return SpillFunc[1];
1245 return SpillFunc[2];
1247 return SpillFunc[3];
1249 return SpillFunc[4];
1251 return SpillFunc[5];
1266 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1271 Register SP = HRI.getStackRegister();
1273 Register AP = HMFI.getStackAlignBasePhysReg();
1291 bool UseFP =
false, UseAP =
false;
1296 if (NoOpt && !HasExtraAlign)
1301 UseFP |= (HasAlloca || HasExtraAlign);
1312 bool HasFP =
hasFP(MF);
1313 assert((HasFP || !UseFP) &&
"This function must have frame pointer");
1339 if (Offset > 0 && !HasFP)
1353 int RealOffset = Offset;
1354 if (!UseFP && !UseAP)
1355 RealOffset = FrameSize+Offset;
1361 bool &PrologueStubs)
const {
1366 PrologueStubs =
false;
1371 if (useSpillFunction(MF, CSI)) {
1372 PrologueStubs =
true;
1384 if (StkOvrFlowEnabled) {
1386 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC
1387 : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;
1389 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
1390 : Hexagon::SAVE_REGISTERS_CALL_V4STK;
1393 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC
1394 : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
1396 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
1397 : Hexagon::SAVE_REGISTERS_CALL_V4;
1405 addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI,
false,
true);
1418 int FI =
I.getFrameIdx();
1420 HII.storeRegToStackSlot(
MBB,
MI,
Reg, IsKill, FI, RC, &HRI);
1437 if (useRestoreFunction(MF, CSI)) {
1454 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC
1455 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;
1457 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
1458 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
1467 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC
1468 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;
1470 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
1471 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
1477 addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI,
true,
false);
1484 int FI =
I.getFrameIdx();
1485 HII.loadRegFromStackSlot(
MBB,
MI,
Reg, FI, RC, &HRI);
1495 unsigned Opc =
MI.getOpcode();
1497 assert((Opc == Hexagon::ADJCALLSTACKDOWN || Opc == Hexagon::ADJCALLSTACKUP) &&
1498 "Cannot handle this call frame pseudo instruction");
1512 if (!HasAlloca || !NeedsAlign)
1532 assert(A <= 8 &&
"Unexpected local frame alignment");
1539 if (!DealignSlots.
empty()) {
1542 bool KeepOld =
true;
1546 auto *PV = MMO->getPseudoValue();
1547 if (
auto *
FS = dyn_cast_or_null<FixedStackPseudoSourceValue>(PV)) {
1548 int FI =
FS->getFrameIndex();
1549 if (DealignSlots.
count(FI)) {
1550 auto *NewMMO = MF.getMachineMemOperand(
1551 MMO->getPointerInfo(), MMO->getFlags(), MMO->getSize(),
1553 MMO->getSyncScopeID(), MMO->getSuccessOrdering(),
1554 MMO->getFailureOrdering());
1555 new_memops.push_back(NewMMO);
1560 new_memops.push_back(MMO);
1563 MI.setMemRefs(MF, new_memops);
1571 AP = AI->getOperand(0).getReg();
1581 auto IsUsed = [&HRI,&
MRI] (
unsigned Reg) ->
bool {
1613 BitVector SRegs(Hexagon::NUM_TARGET_REGS);
1635 for (
int x = Reserved.find_first();
x >= 0;
x = Reserved.find_next(
x)) {
1649 BitVector TmpSup(Hexagon::NUM_TARGET_REGS);
1655 for (
int x = TmpSup.find_first();
x >= 0;
x = TmpSup.find_next(
x)) {
1695 for (
const SpillSlot *
S = FixedSlots;
S != FixedSlots+NumFixed; ++
S) {
1700 MinOffset =
std::min(MinOffset,
S->Offset);
1702 SRegs[
S->Reg] =
false;
1712 int Off = MinOffset - Size;
1714 Off &= -Alignment.value();
1716 MinOffset =
std::min(MinOffset, Off);
1722 dbgs() <<
"CS information: {";
1724 int FI =
I.getFrameIdx();
1736 bool MissedReg =
false;
1756 if (!Hexagon::ModRegsRegClass.
contains(DstR) ||
1757 !Hexagon::ModRegsRegClass.
contains(SrcR))
1761 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), TmpR).
add(
MI->getOperand(1));
1762 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), DstR)
1765 NewRegs.push_back(TmpR);
1774 if (!
MI->getOperand(0).isFI())
1778 unsigned Opc =
MI->getOpcode();
1780 bool IsKill =
MI->getOperand(2).isKill();
1781 int FI =
MI->getOperand(0).getIndex();
1786 unsigned TfrOpc = (Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr
1787 : Hexagon::A2_tfrcrr;
1792 BuildMI(
B, It,
DL, HII.get(Hexagon::S2_storeri_io))
1798 NewRegs.push_back(TmpR);
1807 if (!
MI->getOperand(1).isFI())
1811 unsigned Opc =
MI->getOpcode();
1813 int FI =
MI->getOperand(1).getIndex();
1817 BuildMI(
B, It,
DL, HII.get(Hexagon::L2_loadri_io), TmpR)
1824 unsigned TfrOpc = (Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp
1825 : Hexagon::A2_tfrrcr;
1829 NewRegs.push_back(TmpR);
1838 if (!
MI->getOperand(0).isFI())
1843 bool IsKill =
MI->getOperand(2).isKill();
1844 int FI =
MI->getOperand(0).getIndex();
1845 auto *RC = &Hexagon::HvxVRRegClass;
1854 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1857 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandqrt), TmpR1)
1863 expandStoreVec(
B, std::prev(It),
MRI, HII, NewRegs);
1865 NewRegs.push_back(TmpR0);
1866 NewRegs.push_back(TmpR1);
1875 if (!
MI->getOperand(1).isFI())
1880 int FI =
MI->getOperand(1).getIndex();
1881 auto *RC = &Hexagon::HvxVRRegClass;
1889 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
1894 expandLoadVec(
B, std::prev(It),
MRI, HII, NewRegs);
1896 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandvrt), DstR)
1900 NewRegs.push_back(TmpR0);
1901 NewRegs.push_back(TmpR1);
1913 if (!
MI->getOperand(0).isFI())
1923 for (
auto R =
B.begin(); R != It; ++R) {
1925 LPR.stepForward(*R, Clobbers);
1930 Register SrcLo = HRI.getSubReg(SrcR, Hexagon::vsub_lo);
1931 Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);
1932 bool IsKill =
MI->getOperand(2).isKill();
1933 int FI =
MI->getOperand(0).getIndex();
1936 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1937 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1941 auto UseAligned = [&](
Align NeedAlign,
Align HasAlign) {
1942 return !NeedsAligna && (NeedAlign <= HasAlign);
1946 if (LPR.contains(SrcLo)) {
1947 StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
1948 : Hexagon::V6_vS32Ub_ai;
1957 if (LPR.contains(SrcHi)) {
1958 StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
1959 : Hexagon::V6_vS32Ub_ai;
1978 if (!
MI->getOperand(1).isFI())
1983 Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);
1984 Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);
1985 int FI =
MI->getOperand(1).getIndex();
1988 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
1989 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
1993 auto UseAligned = [&](
Align NeedAlign,
Align HasAlign) {
1994 return !NeedsAligna && (NeedAlign <= HasAlign);
1998 LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
1999 : Hexagon::V6_vL32Ub_ai;
2006 LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
2007 : Hexagon::V6_vL32Ub_ai;
2023 if (!
MI->getOperand(0).isFI())
2030 bool IsKill =
MI->getOperand(2).isKill();
2031 int FI =
MI->getOperand(0).getIndex();
2033 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2035 bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
2036 unsigned StoreOpc = UseAligned ? Hexagon::V6_vS32b_ai
2037 : Hexagon::V6_vS32Ub_ai;
2054 if (!
MI->getOperand(1).isFI())
2061 int FI =
MI->getOperand(1).getIndex();
2063 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2065 bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
2066 unsigned LoadOpc = UseAligned ? Hexagon::V6_vL32b_ai
2067 : Hexagon::V6_vL32Ub_ai;
2081 bool Changed =
false;
2083 for (
auto &
B : MF) {
2086 for (
auto I =
B.begin(),
E =
B.end();
I !=
E;
I = NextI) {
2088 NextI = std::next(
I);
2089 unsigned Opc =
MI->getOpcode();
2092 case TargetOpcode::COPY:
2093 Changed |= expandCopy(
B,
I,
MRI, HII, NewRegs);
2095 case Hexagon::STriw_pred:
2096 case Hexagon::STriw_ctr:
2097 Changed |= expandStoreInt(
B,
I,
MRI, HII, NewRegs);
2099 case Hexagon::LDriw_pred:
2100 case Hexagon::LDriw_ctr:
2101 Changed |= expandLoadInt(
B,
I,
MRI, HII, NewRegs);
2103 case Hexagon::PS_vstorerq_ai:
2104 Changed |= expandStoreVecPred(
B,
I,
MRI, HII, NewRegs);
2106 case Hexagon::PS_vloadrq_ai:
2107 Changed |= expandLoadVecPred(
B,
I,
MRI, HII, NewRegs);
2109 case Hexagon::PS_vloadrw_ai:
2110 Changed |= expandLoadVec2(
B,
I,
MRI, HII, NewRegs);
2112 case Hexagon::PS_vstorerw_ai:
2113 Changed |= expandStoreVec2(
B,
I,
MRI, HII, NewRegs);
2127 SavedRegs.
resize(HRI.getNumRegs());
2137 expandSpillMacros(MF, NewRegs);
2139 optimizeSpillSlots(MF, NewRegs);
2143 if (!NewRegs.empty() || mayOverflowFrameOffset(MF)) {
2149 SpillRCs.
insert(&Hexagon::IntRegsRegClass);
2151 for (
unsigned VR : NewRegs)
2154 for (
auto *RC : SpillRCs) {
2158 switch (RC->
getID()) {
2159 case Hexagon::IntRegsRegClassID:
2162 case Hexagon::HvxQRRegClassID:
2166 unsigned S = HRI.getSpillSize(*RC);
2167 Align A = HRI.getSpillAlign(*RC);
2168 for (
unsigned i = 0;
i < Num;
i++) {
2186 auto isDead = [&FIR,&DeadMap] (
unsigned Reg) ->
bool {
2187 auto F = DeadMap.find({
Reg,0});
2188 if (
F == DeadMap.end())
2190 for (
auto &DR :
F->second)
2191 if (DR.contains(FIR))
2213 auto &HII = *HST.getInstrInfo();
2214 auto &HRI = *HST.getRegisterInfo();
2218 using BlockIndexMap =
2219 std::map<MachineBasicBlock *, HexagonBlockRanges::InstrIndexMap>;
2220 using BlockRangeMap =
2221 std::map<MachineBasicBlock *, HexagonBlockRanges::RangeList>;
2229 SlotInfo() =
default;
2232 BlockIndexMap BlockIndexes;
2234 std::map<int,SlotInfo> FIRangeMap;
2243 if (HaveRC ==
nullptr || HaveRC == NewRC)
2248 if (NewRC->hasSubClassEq(HaveRC))
2255 for (
auto &
B : MF) {
2256 std::map<int,IndexType> LastStore, LastLoad;
2259 auto P = BlockIndexes.insert(
2261 auto &IndexMap =
P.first->second;
2263 << IndexMap <<
'\n');
2265 for (
auto &
In :
B) {
2267 bool Load = HII.isLoadFromStackSlot(
In, LFI) && !HII.isPredicated(
In);
2268 bool Store = HII.isStoreToStackSlot(
In, SFI) && !HII.isPredicated(
In);
2282 int TFI =
Load ? LFI : SFI;
2283 unsigned AM = HII.getAddrMode(
In);
2284 SlotInfo &
SI = FIRangeMap[TFI];
2288 unsigned OpNum =
Load ? 0 : 2;
2289 auto *RC = HII.getRegClass(
In.getDesc(), OpNum, &HRI, MF);
2290 RC = getCommonRC(
SI.RC, RC);
2298 unsigned S = HII.getMemAccessSize(
In);
2299 if (
SI.Size != 0 &&
SI.Size !=
S)
2305 for (
auto *Mo :
In.memoperands()) {
2306 if (!Mo->isVolatile() && !Mo->isAtomic())
2317 for (
unsigned i = 0,
n =
In.getNumOperands();
i <
n; ++
i) {
2321 int FI =
Op.getIndex();
2324 if (
i+1 >=
n || !
In.getOperand(
i+1).isImm() ||
2325 In.getOperand(
i+1).getImm() != 0)
2327 if (BadFIs.
count(FI))
2333 LastStore[FI] = IndexType::Entry;
2334 LastLoad[FI] =
Index;
2338 RL.
add(LastStore[FI], LastLoad[FI],
false,
false);
2340 RL.
add(IndexType::Entry, LastLoad[FI],
false,
false);
2342 LastStore[FI] =
Index;
2349 for (
auto &
I : LastLoad) {
2350 IndexType LL =
I.second;
2353 auto &RL = FIRangeMap[
I.first].Map[&
B];
2354 IndexType &
LS = LastStore[
I.first];
2356 RL.
add(
LS, LL,
false,
false);
2358 RL.
add(IndexType::Entry, LL,
false,
false);
2361 for (
auto &
I : LastStore) {
2362 IndexType
LS =
I.second;
2365 auto &RL = FIRangeMap[
I.first].Map[&
B];
2371 for (
auto &
P : FIRangeMap) {
2372 dbgs() <<
"fi#" <<
P.first;
2373 if (BadFIs.
count(
P.first))
2376 if (
P.second.RC !=
nullptr)
2377 dbgs() << HRI.getRegClassName(
P.second.RC) <<
'\n';
2379 dbgs() <<
"<null>\n";
2380 for (
auto &R :
P.second.Map)
2391 std::map<MachineBasicBlock*,std::vector<int>> BlockFIMap;
2393 for (
auto &
P : FIRangeMap) {
2395 if (BadFIs.
count(
P.first))
2397 for (
auto &
B : MF) {
2398 auto F =
P.second.Map.find(&
B);
2400 if (
F ==
P.second.Map.end() ||
F->second.empty())
2403 if (
IR.start() == IndexType::Entry)
2404 LoxFIs.insert(
P.first);
2405 BlockFIMap[&
B].push_back(
P.first);
2410 dbgs() <<
"Block-to-FI map (* -- live-on-exit):\n";
2411 for (
auto &
P : BlockFIMap) {
2412 auto &FIs =
P.second;
2416 for (
auto I : FIs) {
2417 dbgs() <<
" fi#" <<
I;
2418 if (LoxFIs.count(
I))
2430 for (
auto &
B : MF) {
2431 auto F = BlockIndexes.find(&
B);
2432 assert(
F != BlockIndexes.end());
2439 for (
auto FI : BlockFIMap[&
B]) {
2440 if (BadFIs.
count(FI))
2444 for (
auto &Range : RL) {
2446 if (!IndexType::isInstr(Range.start()) ||
2447 !IndexType::isInstr(Range.end()))
2451 assert(
SI.mayStore() &&
"Unexpected start instruction");
2456 SrcOp.getSubReg() };
2457 auto *RC = HII.getRegClass(
SI.getDesc(), 2, &HRI, MF);
2459 unsigned FoundR = this->findPhysReg(MF, Range, IM,
DM, RC);
2475 if (SrcRR.
Reg != FoundR || SrcRR.
Sub != 0) {
2477 CopyIn =
BuildMI(
B, StartIt,
DL, HII.get(TargetOpcode::COPY), FoundR)
2483 if (LoxFIs.count(FI) && (&Range == &RL.back())) {
2485 if (
unsigned SR =
SrcOp.getSubReg())
2486 SrcOp.setReg(HRI.getSubReg(FoundR, SR));
2488 SrcOp.setReg(FoundR);
2491 SrcOp.setIsKill(
false);
2498 for (
auto It = StartIt; It != EndIt; It = NextIt) {
2500 NextIt = std::next(It);
2502 if (!HII.isLoadFromStackSlot(
MI, TFI) || TFI != FI)
2505 assert(
MI.getOperand(0).getSubReg() == 0);
2507 if (DstR != FoundR) {
2509 unsigned MemSize = HII.getMemAccessSize(
MI);
2511 unsigned CopyOpc = TargetOpcode::COPY;
2512 if (HII.isSignExtendingLoad(
MI))
2513 CopyOpc = (MemSize == 1) ? Hexagon::A2_sxtb : Hexagon::A2_sxth;
2514 else if (HII.isZeroExtendingLoad(
MI))
2515 CopyOpc = (MemSize == 1) ? Hexagon::A2_zxtb : Hexagon::A2_zxth;
2516 CopyOut =
BuildMI(
B, It,
DL, HII.get(CopyOpc), DstR)
2526 DM[RR].subtract(Range);
2532 void HexagonFrameLowering::expandAlloca(
MachineInstr *AI,
2558 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), Rd)
2563 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), SP)
2569 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), Rd)
2573 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), SP)
2579 BuildMI(MB, AI,
DL, HII.get(TargetOpcode::COPY), SP)
2584 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_addi), Rd)
2604 if (
I.getOpcode() == Hexagon::PS_aligna)
2611 void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(
MachineInstr *
MI,
2612 const CSIVect &CSI,
bool IsDef,
bool IsKill)
const {
2623 const CSIVect &CSI)
const {
2636 BitVector Regs(Hexagon::NUM_TARGET_REGS);
2639 if (!Hexagon::DoubleRegsRegClass.
contains(R))
2643 int F = Regs.find_first();
2644 if (
F != Hexagon::D8)
2647 int N = Regs.find_next(
F);
2648 if (
N >= 0 &&
N !=
F+1)
2656 bool HexagonFrameLowering::useSpillFunction(
const MachineFunction &MF,
2657 const CSIVect &CSI)
const {
2658 if (shouldInlineCSR(MF, CSI))
2660 unsigned NumCSI = CSI.size();
2666 return Threshold < NumCSI;
2669 bool HexagonFrameLowering::useRestoreFunction(
const MachineFunction &MF,
2670 const CSIVect &CSI)
const {
2671 if (shouldInlineCSR(MF, CSI))
2681 unsigned NumCSI = CSI.size();
2687 return Threshold < NumCSI;
2690 bool HexagonFrameLowering::mayOverflowFrameOffset(
MachineFunction &MF)
const {
2695 if (HST.useHVXOps() && StackSize > 256)
2702 bool HasImmStack =
false;
2703 unsigned MinLS = ~0u;
2708 switch (
MI.getOpcode()) {
2709 case Hexagon::S4_storeirit_io:
2710 case Hexagon::S4_storeirif_io:
2711 case Hexagon::S4_storeiri_io:
2714 case Hexagon::S4_storeirht_io:
2715 case Hexagon::S4_storeirhf_io:
2716 case Hexagon::S4_storeirh_io:
2719 case Hexagon::S4_storeirbt_io:
2720 case Hexagon::S4_storeirbf_io:
2721 case Hexagon::S4_storeirb_io:
2722 if (
MI.getOperand(0).isFI())
2731 return !isUInt<6>(StackSize >> MinLS);