67#define DEBUG_TYPE "hexagon-pei"
162 if (!HST.getFrameLowering()->hasFP(MF))
173 Register SCSPReg = HST.getSCSPReg();
174 const auto &HRI = *HST.getRegisterInfo();
175 if (!HST.isRegisterReservedByUser(SCSPReg))
180 " to use shadow call stack on Hexagon");
182 const auto &HII = *HST.getInstrInfo();
196 MBB.addLiveIn(SCSPReg);
203 unsigned DwarfSCSReg = HRI.getDwarfRegNum(SCSPReg,
true);
206 assert(DwarfSCSReg < 32 &&
"SCS register should be < 32");
207 const char CFIInst[] = {
208 (
char)dwarf::DW_CFA_val_expression,
211 (
char)(
unsigned)(dwarf::DW_OP_breg0 + DwarfSCSReg),
231 Register SCSPReg = HST.getSCSPReg();
232 const auto &HII = *HST.getInstrInfo();
235 BuildMI(
MBB,
MI,
DL, HII.get(Hexagon::L2_loadri_io), Hexagon::R31)
254 cl::desc(
"Set the number of scavenger slots"),
259 cl::desc(
"Specify O2(not Os) spill func threshold"),
264 cl::desc(
"Specify Os spill func threshold"),
273 cl::desc(
"Enable stack frame shrink wrapping"));
278 cl::desc(
"Max count of stack frame shrink-wraps"));
282 cl::desc(
"Enable long calls for save-restore stubs."),
293 cl::init(std::numeric_limits<unsigned>::max()));
312 char HexagonCallFrameInformation::ID = 0;
316bool HexagonCallFrameInformation::runOnMachineFunction(
MachineFunction &MF) {
317 auto &HFI = *MF.
getSubtarget<HexagonSubtarget>().getFrameLowering();
322 HFI.insertCFIInstructions(MF);
327 "Hexagon call frame information",
false,
false)
330 return new HexagonCallFrameInformation();
347 if (!RegNo || SubReg < RegNo)
357 static_assert(Hexagon::R1 > 0,
358 "Assume physical registers are encoded as positive integers");
363 for (
unsigned I = 1,
E = CSI.
size();
I <
E; ++
I) {
384 unsigned Opc =
MI.getOpcode();
386 case Hexagon::PS_alloca:
409 for (
MCPhysReg S : HRI.subregs_inclusive(R))
414 if (MO.isRegMask()) {
419 const uint32_t *BM = MO.getRegMask();
423 if (!(BM[R / 32] & (1u << (R % 32))))
438 unsigned RetOpc =
I->getOpcode();
439 return RetOpc == Hexagon::PS_tailcall_i || RetOpc == Hexagon::PS_tailcall_r;
461 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
462 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
463 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT:
464 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC:
465 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT:
466 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC:
467 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:
468 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:
481 return F.hasOptSize() && !
F.hasMinSize();
493 MachineBasicBlock *&PrologB, MachineBasicBlock *&EpilogB)
const {
494 static unsigned ShrinkCounter = 0;
496 if (MF.
getSubtarget<HexagonSubtarget>().isEnvironmentMusl() &&
505 auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
507 MachineDominatorTree MDT;
509 MachinePostDominatorTree MPT;
512 using UnsignedMap = DenseMap<unsigned, unsigned>;
513 using RPOTType = ReversePostOrderTraversal<const MachineFunction *>;
519 RPO[
I->getNumber()] = RPON++;
525 unsigned BN = RPO[
I.getNumber()];
526 for (MachineBasicBlock *Succ :
I.successors())
528 if (RPO[Succ->getNumber()] <= BN)
535 BitVector CSR(Hexagon::NUM_TARGET_REGS);
536 for (
const MCPhysReg *
P = HRI.getCalleeSavedRegs(&MF); *
P; ++
P)
545 dbgs() <<
"Blocks needing SF: {";
546 for (
auto &
B : SFBlocks)
551 if (SFBlocks.
empty())
555 MachineBasicBlock *DomB = SFBlocks[0];
556 for (
unsigned i = 1, n = SFBlocks.
size(); i < n; ++i) {
561 MachineBasicBlock *PDomB = SFBlocks[0];
562 for (
unsigned i = 1, n = SFBlocks.
size(); i < n; ++i) {
568 dbgs() <<
"Computed dom block: ";
573 dbgs() <<
", computed pdom block: ";
589 LLVM_DEBUG(
dbgs() <<
"PDom block does not post-dominate dom block\n");
612 findShrunkPrologEpilog(MF, PrologB, EpilogB);
614 bool PrologueStubs =
false;
616 insertCSRSpillsInBlock(*PrologB, CSI, HRI, PrologueStubs);
622 insertAlignaInBlock(*PrologB, AfterCSR);
623 insertPrologueInBlock(*PrologB, PrologueStubs);
631 while (AfterProlog != PrologB->
end() &&
637 updateEntryPaths(MF, *PrologB);
640 insertCSRRestoresInBlock(*EpilogB, CSI, HRI);
641 insertEpilogueInBlock(*EpilogB);
644 if (
B.isReturnBlock())
645 insertCSRRestoresInBlock(
B, CSI, HRI);
648 if (
B.isReturnBlock())
649 insertEpilogueInBlock(
B);
667 BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);
668 updateExitPaths(*EpilogB, *EpilogB, DoneT, DoneF, Path);
677 assert(
F.hasFnAttribute(Attribute::NoReturn) &&
678 F.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
679 !
F.getFunction().hasFnAttribute(Attribute::UWTable));
695 assert(!MFI.hasVarSizedObjects() &&
696 !HST.getRegisterInfo()->hasStackRealignment(MF));
697 return F.hasFnAttribute(Attribute::NoReturn) &&
698 F.hasFnAttribute(Attribute::NoUnwind) &&
699 !
F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() &&
700 MFI.getStackSize() == 0;
703void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &
MBB,
704 bool PrologueStubs)
const {
720 FrameSize = MaxCFA +
alignTo(FrameSize, MaxAlign);
731 SmallVector<MachineInstr *, 4> AdjustRegs;
734 if (
MI.getOpcode() == Hexagon::PS_alloca)
737 for (
auto *
MI : AdjustRegs) {
738 assert((
MI->getOpcode() == Hexagon::PS_alloca) &&
"Expected alloca");
739 expandAlloca(
MI, MF, HII, SP, MaxCF);
740 MI->eraseFromParent();
745 if (MF.getFunction().isVarArg() &&
746 MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl()) {
748 int NumVarArgRegs = 6 - FirstVarArgSavedReg;
749 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)
751 : NumVarArgRegs * 4 + 4;
752 if (RegisterSavedAreaSizePlusPadding > 0) {
755 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
757 .
addImm(-RegisterSavedAreaSizePlusPadding)
762 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
763 for (
int i = HMFI.getFirstNamedArgFrameIndex(),
764 e = HMFI.getLastNamedArgFrameIndex(); i >= e; --i) {
769 unsigned LDOpc, STOpc;
773 if (ObjAlign > ObjSize) {
776 else if (ObjSize <= 2)
778 else if (ObjSize <= 4)
780 else if (ObjSize > 4)
784 switch (OpcodeChecker) {
786 LDOpc = Hexagon::L2_loadrb_io;
787 STOpc = Hexagon::S2_storerb_io;
790 LDOpc = Hexagon::L2_loadrh_io;
791 STOpc = Hexagon::S2_storerh_io;
794 LDOpc = Hexagon::L2_loadri_io;
795 STOpc = Hexagon::S2_storeri_io;
799 LDOpc = Hexagon::L2_loadrd_io;
800 STOpc = Hexagon::S2_storerd_io;
804 Register RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3
806 int LoadStoreCount = ObjSize / OpcodeChecker;
808 if (ObjSize % OpcodeChecker)
816 NumBytes =
alignTo(NumBytes, ObjAlign);
819 while (
Count < LoadStoreCount) {
821 BuildMI(
MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)
823 .
addImm(RegisterSavedAreaSizePlusPadding +
840 NumBytes =
alignTo(NumBytes, 8);
845 NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;
847 for (
int j = FirstVarArgSavedReg, i = 0;
j < 6; ++
j, ++i) {
848 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))
858 insertAllocframe(
MBB, InsertPt, NumBytes);
860 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
868 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
870 }
else if (NumBytes > 0) {
872 auto *TLI = HST.getTargetLowering();
873 bool NeedsProbing = TLI->hasInlineStackProbe(MF);
874 unsigned ProbeSize = 0;
877 ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
879 if (NeedsProbing && NumBytes > ProbeSize) {
881 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), Hexagon::R28)
886 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_probed_stackalloc))
890 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
898void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &
MBB)
const {
912 MF.
getSubtarget<HexagonSubtarget>().isEnvironmentMusl()) {
914 int NumVarArgRegs = 6 - FirstVarArgSavedReg;
915 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
916 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
917 NumBytes += RegisterSavedAreaSizePlusPadding;
920 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
928 unsigned RetOpc = RetI ? RetI->
getOpcode() : 0;
931 if (RetOpc == Hexagon::EH_RETURN_JMPR) {
934 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
937 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)
948 if (RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4 ||
949 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC ||
950 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT ||
951 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC) {
968 bool NeedsDeallocframe =
true;
969 unsigned PrevOpc = 0;
972 PrevOpc = PrevIt->getOpcode();
973 if (PrevOpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||
974 PrevOpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC ||
975 PrevOpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||
976 PrevOpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||
977 PrevOpc == Hexagon::PS_call_nr || PrevOpc == Hexagon::PS_callr_nr)
978 NeedsDeallocframe =
false;
981 if (!MF.
getSubtarget<HexagonSubtarget>().isEnvironmentMusl() ||
983 if (!NeedsDeallocframe) {
988 if (NeedsSCS && PrevOpc != Hexagon::PS_call_nr &&
989 PrevOpc != Hexagon::PS_callr_nr)
991 "useRestoreFunction() should have prevented this");
998 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
1007 unsigned NewOpc = Hexagon::L4_return;
1008 MachineInstrBuilder NewI =
BuildMI(
MBB, RetI, dl, HII.get(NewOpc))
1018 int NumVarArgRegs = 6 - FirstVarArgSavedReg;
1019 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
1020 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
1025 bool HasRestoreStub =
1027 (
I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||
1029 Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||
1030 I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||
1031 I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC);
1032 if (!HasRestoreStub)
1033 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
1036 if (RegisterSavedAreaSizePlusPadding != 0)
1037 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
1039 .
addImm(RegisterSavedAreaSizePlusPadding);
1043 if (NeedsSCS && !HasRestoreStub)
1048void HexagonFrameLowering::insertAllocframe(MachineBasicBlock &
MBB,
1057 const unsigned int ALLOCFRAME_MAX = 16384;
1067 auto *TLI = HST.getTargetLowering();
1068 bool NeedsProbing = TLI->hasInlineStackProbe(MF) && NumBytes > 0;
1069 unsigned ProbeSize = 0;
1072 ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
1075 if (NeedsProbing && NumBytes > ProbeSize) {
1077 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
1085 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), Hexagon::R28)
1091 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::PS_probed_stackalloc))
1094 }
else if (NumBytes >= ALLOCFRAME_MAX) {
1096 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
1105 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
1110 BuildMI(
MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
1125 if (
MI.getOpcode() == Hexagon::PS_probed_stackalloc)
1130 auto *TLI = HST.getTargetLowering();
1132 unsigned ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
1138 Register TargetReg =
MI->getOperand(0).getReg();
1145 MF.
insert(InsertPt, LoopMBB);
1148 MF.
insert(InsertPt, ExitMBB);
1169 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::A2_addi),
1175 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::S4_storeiri_io))
1181 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::C2_cmpgtu),
1187 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::J2_jumpt))
1193 BuildMI(*ExitMBB, ExitMBB->
begin(),
DL, HII.get(Hexagon::A2_tfr),
1199 MBB->addSuccessor(LoopMBB);
1204 MI->eraseFromParent();
1211void HexagonFrameLowering::insertAlignaInBlock(
1219 assert(needsAligna(MF) &&
"Unexpected stack align base register");
1224 BuildMI(
MBB, InsertPt,
DL, HII.get(Hexagon::PS_aligna), AP)
1238 for (
unsigned i = 0; i < Worklist.
size(); ++i) {
1239 unsigned BN = Worklist[i];
1242 if (!
MBB.isLiveIn(R.getReg()))
1243 MBB.addLiveIn(R.getReg());
1245 for (
auto &SB :
MBB.successors())
1246 Worklist.
insert(SB->getNumber());
1250bool HexagonFrameLowering::updateExitPaths(MachineBasicBlock &
MBB,
1251 MachineBasicBlock &RestoreB, BitVector &DoneT, BitVector &DoneF,
1252 BitVector &Path)
const {
1255 if (Path[BN] || DoneF[BN])
1263 bool ReachedExit =
false;
1265 ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);
1271 MachineInstr &RetI =
MBB.
back();
1281 if (ReachedExit && &
MBB != &RestoreB) {
1294static std::optional<MachineBasicBlock::iterator>
1301 auto End =
B.instr_end();
1305 if (!
I.isBundle()) {
1306 if (
I.getOpcode() == Hexagon::S2_allocframe)
1307 return std::next(It);
1311 bool HasCall =
false, HasAllocFrame =
false;
1313 while (++
T != End &&
T->isBundled()) {
1314 if (
T->getOpcode() == Hexagon::S2_allocframe)
1315 HasAllocFrame =
true;
1316 else if (
T->isCall())
1320 return HasCall ? It : std::next(It);
1322 return std::nullopt;
1328 insertCFIInstructionsAt(
B, *At);
1343 const MCInstrDesc &CFID = HII.get(TargetOpcode::CFI_INSTRUCTION);
1346 bool HasFP = hasFP(MF);
1349 unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(),
true);
1350 unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(),
true);
1377 Hexagon::R1, Hexagon::R0, Hexagon::R3, Hexagon::R2,
1378 Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,
1379 Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,
1380 Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,
1381 Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9,
1382 Hexagon::D10, Hexagon::D11, Hexagon::D12, Hexagon::D13
1388 auto IfR = [
Reg] (
const CalleeSavedInfo &
C) ->
bool {
1389 return C.getReg() ==
Reg;
1408 getFrameIndexReference(MF,
F->getFrameIdx(), FrameReg).getFixed();
1414 unsigned DwarfReg = HRI.getDwarfRegNum(
Reg,
true);
1426 Register HiReg = HRI.getSubReg(
Reg, Hexagon::isub_hi);
1427 Register LoReg = HRI.getSubReg(
Reg, Hexagon::isub_lo);
1428 unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg,
true);
1429 unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg,
true);
1445 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1461 if (HasAlloca || HasExtraAlign)
1490 bool Stkchk =
false) {
1491 const char * V4SpillToMemoryFunctions[] = {
1492 "__save_r16_through_r17",
1493 "__save_r16_through_r19",
1494 "__save_r16_through_r21",
1495 "__save_r16_through_r23",
1496 "__save_r16_through_r25",
1497 "__save_r16_through_r27" };
1499 const char * V4SpillToMemoryStkchkFunctions[] = {
1500 "__save_r16_through_r17_stkchk",
1501 "__save_r16_through_r19_stkchk",
1502 "__save_r16_through_r21_stkchk",
1503 "__save_r16_through_r23_stkchk",
1504 "__save_r16_through_r25_stkchk",
1505 "__save_r16_through_r27_stkchk" };
1507 const char * V4SpillFromMemoryFunctions[] = {
1508 "__restore_r16_through_r17_and_deallocframe",
1509 "__restore_r16_through_r19_and_deallocframe",
1510 "__restore_r16_through_r21_and_deallocframe",
1511 "__restore_r16_through_r23_and_deallocframe",
1512 "__restore_r16_through_r25_and_deallocframe",
1513 "__restore_r16_through_r27_and_deallocframe" };
1515 const char * V4SpillFromMemoryTailcallFunctions[] = {
1516 "__restore_r16_through_r17_and_deallocframe_before_tailcall",
1517 "__restore_r16_through_r19_and_deallocframe_before_tailcall",
1518 "__restore_r16_through_r21_and_deallocframe_before_tailcall",
1519 "__restore_r16_through_r23_and_deallocframe_before_tailcall",
1520 "__restore_r16_through_r25_and_deallocframe_before_tailcall",
1521 "__restore_r16_through_r27_and_deallocframe_before_tailcall"
1524 const char **SpillFunc =
nullptr;
1528 SpillFunc = Stkchk ? V4SpillToMemoryStkchkFunctions
1529 : V4SpillToMemoryFunctions;
1532 SpillFunc = V4SpillFromMemoryFunctions;
1535 SpillFunc = V4SpillFromMemoryTailcallFunctions;
1538 assert(SpillFunc &&
"Unknown spill kind");
1543 return SpillFunc[0];
1545 return SpillFunc[1];
1547 return SpillFunc[2];
1549 return SpillFunc[3];
1551 return SpillFunc[4];
1553 return SpillFunc[5];
1568 bool HasExtraAlign = HRI.hasStackRealignment(MF);
1573 Register SP = HRI.getStackRegister();
1575 Register AP = HMFI.getStackAlignBaseReg();
1590 bool UseFP =
false, UseAP =
false;
1595 if (NoOpt && !HasExtraAlign)
1600 UseFP |= (HasAlloca || HasExtraAlign);
1611 bool HasFP =
hasFP(MF);
1612 assert((HasFP || !UseFP) &&
"This function must have frame pointer");
1638 if (
Offset > 0 && !HasFP)
1653 if (!UseFP && !UseAP)
1654 RealOffset = FrameSize+
Offset;
1660 bool &PrologueStubs)
const {
1665 PrologueStubs =
false;
1670 if (useSpillFunction(MF, CSI)) {
1671 PrologueStubs =
true;
1683 if (StkOvrFlowEnabled) {
1685 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC
1686 : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;
1688 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
1689 : Hexagon::SAVE_REGISTERS_CALL_V4STK;
1692 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC
1693 : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
1695 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
1696 : Hexagon::SAVE_REGISTERS_CALL_V4;
1699 MachineInstr *SaveRegsCall =
1704 addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI,
false,
true);
1706 for (
const CalleeSavedInfo &
I : CSI)
1709 for (
const CalleeSavedInfo &
I : CSI) {
1710 MCRegister
Reg =
I.getReg();
1715 int FI =
I.getFrameIdx();
1726bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &
MBB,
1727 const CSIVect &CSI,
const HexagonRegisterInfo &HRI)
const {
1736 if (useRestoreFunction(MF, CSI)) {
1741 auto &HTM =
static_cast<const HexagonTargetMachine&
>(MF.
getTarget());
1742 bool IsPIC = HTM.isPositionIndependent();
1748 MachineInstr *DeallocCall =
nullptr;
1753 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC
1754 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;
1756 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
1757 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
1766 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC
1767 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;
1769 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
1770 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
1776 addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI,
true,
false);
1780 for (
const CalleeSavedInfo &
I : CSI) {
1781 MCRegister
Reg =
I.getReg();
1783 int FI =
I.getFrameIdx();
1794 unsigned Opc =
MI.getOpcode();
1796 assert((
Opc == Hexagon::ADJCALLSTACKDOWN ||
Opc == Hexagon::ADJCALLSTACKUP) &&
1797 "Cannot handle this call frame pseudo instruction");
1798 return MBB.erase(
I);
1806 auto IsUsed = [&HRI,&MRI] (
Register Reg) ->
bool {
1838 BitVector SRegs(Hexagon::NUM_TARGET_REGS);
1865 "AP must be assigned before register allocation");
1870 bool HasResSub =
false;
1896 BitVector TmpSup(Hexagon::NUM_TARGET_REGS);
1902 for (
int x = TmpSup.find_first(); x >= 0; x = TmpSup.find_next(x)) {
1940 int64_t MinOffset = 0;
1942 for (
const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) {
1947 MinOffset = std::min(MinOffset, S->Offset);
1949 SRegs[S->Reg] =
false;
1958 unsigned Size =
TRI->getSpillSize(*RC);
1959 int64_t Off = MinOffset -
Size;
1961 Off &= -Alignment.value();
1963 MinOffset = std::min(MinOffset, Off);
1969 dbgs() <<
"CS information: {";
1971 int FI =
I.getFrameIdx();
1983 bool MissedReg =
false;
2003 if (!Hexagon::ModRegsRegClass.
contains(DstR) ||
2004 !Hexagon::ModRegsRegClass.
contains(SrcR))
2008 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), TmpR).
add(
MI->getOperand(1));
2009 BuildMI(
B, It,
DL, HII.get(TargetOpcode::COPY), DstR)
2021 if (!
MI->getOperand(0).isFI())
2025 unsigned Opc =
MI->getOpcode();
2027 bool IsKill =
MI->getOperand(2).isKill();
2028 int FI =
MI->getOperand(0).getIndex();
2033 unsigned TfrOpc = (
Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr
2039 BuildMI(
B, It,
DL, HII.get(Hexagon::S2_storeri_io))
2050bool HexagonFrameLowering::expandLoadInt(MachineBasicBlock &
B,
2052 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2053 MachineInstr *
MI = &*It;
2054 if (!
MI->getOperand(1).isFI())
2058 unsigned Opc =
MI->getOpcode();
2060 int FI =
MI->getOperand(1).getIndex();
2064 BuildMI(
B, It,
DL, HII.get(Hexagon::L2_loadri_io), TmpR)
2071 unsigned TfrOpc = (
Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp
2072 : Hexagon::A2_tfrrcr;
2074 .
addReg(TmpR, RegState::Kill);
2081bool HexagonFrameLowering::expandStoreVecPred(MachineBasicBlock &
B,
2083 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2084 MachineInstr *
MI = &*It;
2085 if (!
MI->getOperand(0).isFI())
2090 bool IsKill =
MI->getOperand(2).isKill();
2091 int FI =
MI->getOperand(0).getIndex();
2092 auto *RC = &Hexagon::HvxVRRegClass;
2101 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
2104 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandqrt), TmpR1)
2106 .
addReg(TmpR0, RegState::Kill);
2109 expandStoreVec(
B, std::prev(It), MRI, HII, NewRegs);
2117bool HexagonFrameLowering::expandLoadVecPred(MachineBasicBlock &
B,
2119 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2120 MachineInstr *
MI = &*It;
2121 if (!
MI->getOperand(1).isFI())
2126 int FI =
MI->getOperand(1).getIndex();
2127 auto *RC = &Hexagon::HvxVRRegClass;
2135 BuildMI(
B, It,
DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
2138 expandLoadVec(
B, std::prev(It), MRI, HII, NewRegs);
2140 BuildMI(
B, It,
DL, HII.get(Hexagon::V6_vandvrt), DstR)
2141 .
addReg(TmpR1, RegState::Kill)
2142 .
addReg(TmpR0, RegState::Kill);
2150bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &
B,
2152 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2155 auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
2156 MachineInstr *
MI = &*It;
2157 if (!
MI->getOperand(0).isFI())
2164 LivePhysRegs LPR(HRI);
2167 for (
auto R =
B.begin(); R != It; ++R) {
2169 LPR.stepForward(*R, Clobbers);
2174 Register SrcLo = HRI.getSubReg(SrcR, Hexagon::vsub_lo);
2175 Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);
2176 bool IsKill =
MI->getOperand(2).isKill();
2177 int FI =
MI->getOperand(0).getIndex();
2179 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
2180 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2185 if (LPR.contains(SrcLo)) {
2186 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
2187 : Hexagon::V6_vS32Ub_ai;
2196 if (LPR.contains(SrcHi)) {
2197 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
2198 : Hexagon::V6_vS32Ub_ai;
2210bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &
B,
2212 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2215 auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
2216 MachineInstr *
MI = &*It;
2217 if (!
MI->getOperand(1).isFI())
2222 Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);
2223 Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);
2224 int FI =
MI->getOperand(1).getIndex();
2226 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
2227 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2232 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
2233 : Hexagon::V6_vL32Ub_ai;
2240 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
2241 : Hexagon::V6_vL32Ub_ai;
2251bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &
B,
2253 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2256 MachineInstr *
MI = &*It;
2257 if (!
MI->getOperand(0).isFI())
2260 auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
2263 bool IsKill =
MI->getOperand(2).isKill();
2264 int FI =
MI->getOperand(0).getIndex();
2266 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2268 unsigned StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
2269 : Hexagon::V6_vS32Ub_ai;
2280bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &
B,
2282 const HexagonInstrInfo &HII, SmallVectorImpl<Register> &NewRegs)
const {
2285 MachineInstr *
MI = &*It;
2286 if (!
MI->getOperand(1).isFI())
2289 auto &HRI = *MF.
getSubtarget<HexagonSubtarget>().getRegisterInfo();
2292 int FI =
MI->getOperand(1).getIndex();
2294 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
2296 unsigned LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
2297 : Hexagon::V6_vL32Ub_ai;
2308 SmallVectorImpl<Register> &NewRegs)
const {
2309 auto &HII = *MF.
getSubtarget<HexagonSubtarget>().getInstrInfo();
2313 for (
auto &
B : MF) {
2316 for (
auto I =
B.begin(),
E =
B.end();
I !=
E;
I = NextI) {
2317 MachineInstr *
MI = &*
I;
2318 NextI = std::next(
I);
2319 unsigned Opc =
MI->getOpcode();
2322 case TargetOpcode::COPY:
2323 Changed |= expandCopy(
B,
I, MRI, HII, NewRegs);
2325 case Hexagon::STriw_pred:
2326 case Hexagon::STriw_ctr:
2327 Changed |= expandStoreInt(
B,
I, MRI, HII, NewRegs);
2329 case Hexagon::LDriw_pred:
2330 case Hexagon::LDriw_ctr:
2331 Changed |= expandLoadInt(
B,
I, MRI, HII, NewRegs);
2333 case Hexagon::PS_vstorerq_ai:
2334 Changed |= expandStoreVecPred(
B,
I, MRI, HII, NewRegs);
2336 case Hexagon::PS_vloadrq_ai:
2337 Changed |= expandLoadVecPred(
B,
I, MRI, HII, NewRegs);
2339 case Hexagon::PS_vloadrw_ai:
2340 Changed |= expandLoadVec2(
B,
I, MRI, HII, NewRegs);
2342 case Hexagon::PS_vstorerw_ai:
2343 Changed |= expandStoreVec2(
B,
I, MRI, HII, NewRegs);
2357 SavedRegs.
resize(HRI.getNumRegs());
2371 assert(AP.
isValid() &&
"AP must be assigned before register allocation");
2377 expandSpillMacros(MF, NewRegs);
2379 optimizeSpillSlots(MF, NewRegs);
2383 if (!NewRegs.
empty() || mayOverflowFrameOffset(MF)) {
2389 SpillRCs.
insert(&Hexagon::IntRegsRegClass);
2394 for (
const auto *RC : SpillRCs) {
2398 switch (RC->
getID()) {
2399 case Hexagon::IntRegsRegClassID:
2402 case Hexagon::HvxQRRegClassID:
2406 unsigned S = HRI.getSpillSize(*RC);
2407 Align A = HRI.getSpillAlign(*RC);
2408 for (
unsigned i = 0; i < Num; i++) {
2410 RS->addScavengingFrameIndex(NewFI);
2427 auto F = DeadMap.find({Reg,0});
2428 if (
F == DeadMap.end())
2430 for (
auto &DR :
F->second)
2431 if (DR.contains(FIR))
2436 for (
Register Reg : HRI.getRawAllocationOrder(*RC, MF)) {
2451 SmallVectorImpl<Register> &VRegs)
const {
2453 auto &HII = *HST.getInstrInfo();
2454 auto &HRI = *HST.getRegisterInfo();
2456 HexagonBlockRanges HBR(MF);
2458 using BlockIndexMap =
2459 std::map<MachineBasicBlock *, HexagonBlockRanges::InstrIndexMap>;
2460 using BlockRangeMap =
2461 std::map<MachineBasicBlock *, HexagonBlockRanges::RangeList>;
2462 using IndexType = HexagonBlockRanges::IndexType;
2469 SlotInfo() =
default;
2472 BlockIndexMap BlockIndexes;
2473 SmallSet<int,4> BadFIs;
2474 std::map<int,SlotInfo> FIRangeMap;
2483 if (HaveRC ==
nullptr || HaveRC == NewRC)
2488 if (NewRC->hasSubClassEq(HaveRC))
2495 for (
auto &
B : MF) {
2496 std::map<int,IndexType> LastStore, LastLoad;
2497 auto P = BlockIndexes.emplace(&
B, HexagonBlockRanges::InstrIndexMap(
B));
2498 auto &IndexMap =
P.first->second;
2500 << IndexMap <<
'\n');
2502 for (
auto &In :
B) {
2506 if (
In.isDebugInstr())
2509 bool Load = HII.isLoadFromStackSlot(In, LFI) && !HII.isPredicated(In);
2510 bool Store = HII.isStoreToStackSlot(In, SFI) && !HII.isPredicated(In);
2524 int TFI =
Load ? LFI : SFI;
2525 unsigned AM = HII.getAddrMode(In);
2526 SlotInfo &
SI = FIRangeMap[TFI];
2530 unsigned OpNum =
Load ? 0 : 2;
2531 auto *RC = HII.getRegClass(
In.getDesc(), OpNum);
2532 RC = getCommonRC(
SI.RC, RC);
2540 unsigned S = HII.getMemAccessSize(In);
2541 if (
SI.Size != 0 &&
SI.Size != S)
2547 for (
auto *Mo :
In.memoperands()) {
2548 if (!Mo->isVolatile() && !Mo->isAtomic())
2559 for (
unsigned i = 0, n =
In.getNumOperands(); i < n; ++i) {
2560 const MachineOperand &
Op =
In.getOperand(i);
2563 int FI =
Op.getIndex();
2566 if (i+1 >= n || !
In.getOperand(i+1).isImm() ||
2567 In.getOperand(i+1).getImm() != 0)
2569 if (BadFIs.
count(FI))
2573 auto &
LS = LastStore[FI];
2574 auto &LL = LastLoad[FI];
2576 if (LS == IndexType::None)
2577 LS = IndexType::Entry;
2580 HexagonBlockRanges::RangeList &RL = FIRangeMap[FI].Map[&
B];
2581 if (LS != IndexType::None)
2582 RL.
add(LS, LL,
false,
false);
2583 else if (LL != IndexType::None)
2584 RL.
add(IndexType::Entry, LL,
false,
false);
2585 LL = IndexType::None;
2593 for (
auto &
I : LastLoad) {
2594 IndexType LL =
I.second;
2595 if (LL == IndexType::None)
2597 auto &RL = FIRangeMap[
I.first].Map[&
B];
2598 IndexType &
LS = LastStore[
I.first];
2599 if (LS != IndexType::None)
2600 RL.
add(LS, LL,
false,
false);
2602 RL.
add(IndexType::Entry, LL,
false,
false);
2603 LS = IndexType::None;
2605 for (
auto &
I : LastStore) {
2606 IndexType
LS =
I.second;
2607 if (LS == IndexType::None)
2609 auto &RL = FIRangeMap[
I.first].Map[&
B];
2610 RL.
add(LS, IndexType::None,
false,
false);
2615 for (
auto &
P : FIRangeMap) {
2616 dbgs() <<
"fi#" <<
P.first;
2617 if (BadFIs.
count(
P.first))
2620 if (
P.second.RC !=
nullptr)
2621 dbgs() << HRI.getRegClassName(
P.second.RC) <<
'\n';
2623 dbgs() <<
"<null>\n";
2624 for (
auto &R :
P.second.Map)
2633 SmallSet<int,4> LoxFIs;
2635 std::map<MachineBasicBlock*,std::vector<int>> BlockFIMap;
2637 for (
auto &
P : FIRangeMap) {
2639 if (BadFIs.
count(
P.first))
2641 for (
auto &
B : MF) {
2642 auto F =
P.second.Map.find(&
B);
2644 if (
F ==
P.second.Map.end() ||
F->second.empty())
2646 HexagonBlockRanges::IndexRange &
IR =
F->second.front();
2647 if (
IR.start() == IndexType::Entry)
2648 LoxFIs.insert(
P.first);
2649 BlockFIMap[&
B].push_back(
P.first);
2654 dbgs() <<
"Block-to-FI map (* -- live-on-exit):\n";
2655 for (
auto &
P : BlockFIMap) {
2656 auto &FIs =
P.second;
2660 for (
auto I : FIs) {
2661 dbgs() <<
" fi#" <<
I;
2662 if (LoxFIs.count(
I))
2674 for (
auto &
B : MF) {
2675 auto F = BlockIndexes.find(&
B);
2676 assert(
F != BlockIndexes.end());
2677 HexagonBlockRanges::InstrIndexMap &IM =
F->second;
2681 << HexagonBlockRanges::PrintRangeMap(
DM, HRI));
2683 for (
auto FI : BlockFIMap[&
B]) {
2684 if (BadFIs.
count(FI))
2687 HexagonBlockRanges::RangeList &RL = FIRangeMap[FI].Map[&
B];
2688 for (
auto &
Range : RL) {
2690 if (!IndexType::isInstr(
Range.start()) ||
2691 !IndexType::isInstr(
Range.end()))
2695 assert(
SI.mayStore() &&
"Unexpected start instruction");
2697 MachineOperand &SrcOp =
SI.getOperand(2);
2699 HexagonBlockRanges::RegisterRef SrcRR = { SrcOp.
getReg(),
2701 auto *RC = HII.getRegClass(
SI.getDesc(), 2);
2718 MachineInstr *CopyIn =
nullptr;
2719 if (SrcRR.
Reg != FoundR || SrcRR.
Sub != 0) {
2721 CopyIn =
BuildMI(
B, StartIt,
DL, HII.get(TargetOpcode::COPY), FoundR)
2727 if (LoxFIs.count(FI) && (&
Range == &RL.back())) {
2730 SrcOp.
setReg(HRI.getSubReg(FoundR, SR));
2742 for (
auto It = StartIt; It != EndIt; It = NextIt) {
2743 MachineInstr &
MI = *It;
2744 NextIt = std::next(It);
2746 if (!HII.isLoadFromStackSlot(
MI, TFI) || TFI != FI)
2749 assert(
MI.getOperand(0).getSubReg() == 0);
2750 MachineInstr *CopyOut =
nullptr;
2751 if (DstR != FoundR) {
2753 unsigned MemSize = HII.getMemAccessSize(
MI);
2755 unsigned CopyOpc = TargetOpcode::COPY;
2756 if (HII.isSignExtendingLoad(
MI))
2757 CopyOpc = (MemSize == 1) ? Hexagon::A2_sxtb : Hexagon::A2_sxth;
2758 else if (HII.isZeroExtendingLoad(
MI))
2759 CopyOpc = (MemSize == 1) ? Hexagon::A2_zxtb : Hexagon::A2_zxth;
2760 CopyOut =
BuildMI(
B, It,
DL, HII.get(CopyOpc), DstR)
2768 HexagonBlockRanges::RegisterRef FoundRR = { FoundR, 0 };
2776void HexagonFrameLowering::expandAlloca(MachineInstr *AI,
MachineFunction &MF,
2777 const HexagonInstrInfo &HII,
2779 MachineBasicBlock &MB = *AI->
getParent();
2789 bool NeedsProbing = TLI->hasInlineStackProbe(MF);
2791 if (!NeedsProbing) {
2815 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), Rd)
2819 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), SP)
2857 unsigned ProbeSize = TLI->getStackProbeSize(MF, StackAlign);
2862 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_sub), Rd)
2868 BuildMI(MB, AI,
DL, HII.get(Hexagon::A2_andir), Rd)
2877 MF.
insert(InsertPt, LoopMBB);
2879 MF.
insert(InsertPt, ExitMBB);
2890 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::A2_addi), Hexagon::R29)
2895 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::S4_storeiri_io))
2901 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::C2_cmpgtu),
2907 BuildMI(*LoopMBB, LoopMBB->
end(),
DL, HII.get(Hexagon::J2_jumpt))
2916 BuildMI(*ExitMBB, ExitIt,
DL, HII.get(Hexagon::A2_tfr), Hexagon::R29)
2920 BuildMI(*ExitMBB, ExitIt,
DL, HII.get(Hexagon::A2_addi), Rd)
2948void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(
MachineInstr *
MI,
2949 const CSIVect &CSI,
bool IsDef,
bool IsKill)
const {
2960 const CSIVect &CSI)
const {
2973 BitVector Regs(Hexagon::NUM_TARGET_REGS);
2976 if (!Hexagon::DoubleRegsRegClass.
contains(R))
2980 int F = Regs.find_first();
2981 if (
F != Hexagon::D8)
2984 int N = Regs.find_next(
F);
2985 if (
N >= 0 &&
N !=
F+1)
2994 const CSIVect &CSI)
const {
2995 if (shouldInlineCSR(MF, CSI))
2997 unsigned NumCSI = CSI.size();
3016 if (HST.getSCSPReg().id() <= MaxReg.id())
3022 return Threshold < NumCSI;
3025bool HexagonFrameLowering::useRestoreFunction(
const MachineFunction &MF,
3026 const CSIVect &CSI)
const {
3027 if (shouldInlineCSR(MF, CSI))
3040 unsigned NumCSI = CSI.size();
3046 return Threshold < NumCSI;
3049bool HexagonFrameLowering::mayOverflowFrameOffset(
MachineFunction &MF)
const {
3054 if (HST.useHVXOps() && StackSize > 256)
3061 bool HasImmStack =
false;
3062 unsigned MinLS = ~0
u;
3064 for (
const MachineBasicBlock &
B : MF) {
3065 for (
const MachineInstr &
MI :
B) {
3067 switch (
MI.getOpcode()) {
3068 case Hexagon::S4_storeirit_io:
3069 case Hexagon::S4_storeirif_io:
3070 case Hexagon::S4_storeiri_io:
3073 case Hexagon::S4_storeirht_io:
3074 case Hexagon::S4_storeirhf_io:
3075 case Hexagon::S4_storeirh_io:
3078 case Hexagon::S4_storeirbt_io:
3079 case Hexagon::S4_storeirbf_io:
3080 case Hexagon::S4_storeirb_io:
3081 if (
MI.getOperand(0).isFI())
3083 MinLS = std::min(MinLS, LS);
3097struct HexagonFrameSortingObject {
3098 bool IsValid =
false;
3104struct HexagonFrameSortingComparator {
3105 inline bool operator()(
const HexagonFrameSortingObject &
A,
3106 const HexagonFrameSortingObject &
B)
const {
3107 return std::make_tuple(!
A.IsValid,
A.ObjectAlignment,
A.Size) <
3108 std::make_tuple(!
B.IsValid,
B.ObjectAlignment,
B.Size);
3118 if (ObjectsToAllocate.
empty())
3122 int NObjects = ObjectsToAllocate.
size();
3130 if (i != ObjectsToAllocate[j])
3141 SortingObjects[i].IsValid =
true;
3142 SortingObjects[i].Index = i;
3152 for (
auto &Obj : SortingObjects) {
3155 ObjectsToAllocate[--i] = Obj.Index;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
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 void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static bool isRestoreCall(unsigned Opc)
static cl::opt< bool > OptimizeSpillSlots("hexagon-opt-spill", cl::Hidden, cl::init(true), cl::desc("Optimize spill slots"))
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
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.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#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.
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
BitVector & set()
Set all bits in the bitvector.
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
Helper class for creating CFI instructions and inserting them into MIR.
void buildEscape(StringRef Bytes, StringRef Comment="") const
void buildRestore(MCRegister Reg) const
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
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)
void insertCFIInstructions(MachineFunction &MF) const
bool hasFPImpl(const MachineFunction &MF) const override
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...
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 orderFrameObjects(const MachineFunction &MF, SmallVectorImpl< int > &ObjectsToAllocate) const override
Order the symbols in the local stack frame.
void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override
Replace a StackProbe stub (if any) with the actual probe code inline.
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
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Store the specified register of the given register class to the specified stack frame index.
const HexagonRegisterInfo & getRegisterInfo() const
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Load the specified register of the given register class from the specified stack frame index.
Hexagon target-specific information for each MachineFunction.
Register getStackAlignBaseReg() const
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
const HexagonFrameLowering * getFrameLowering() const override
bool isEnvironmentMusl() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
LLVM_ABI 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.
unsigned getID() const
getID() - Return the register class ID number.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Wrapper class representing physical registers. Should be passed by value.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MachineInstrBundleIterator< const MachineInstr > const_iterator
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
bool dominates(const MachineInstr *A, const MachineInstr *B) const
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setMaxCallFrameSize(uint64_t S)
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 alignment of this function's frame.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Properties which a MachineFunction may have at a given point in time.
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.
MCContext & getContext() const
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.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
BasicBlockListType::iterator iterator
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
mop_range implicit_operands()
LLVM_ABI 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.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setIsKill(bool Val=true)
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)
LLVM_ABI MachineBasicBlock * findNearestCommonDominator(ArrayRef< MachineBasicBlock * > Blocks) const
Returns the nearest common dominator of the given blocks.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
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.
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.
int64_t getFixed() const
Returns the fixed component of the stack.
Represent a constant reference to a string, i.e.
LLVM_ABI std::string lower() const
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
const TargetRegisterInfo & getRegisterInfo() const
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
bool isPositionIndependent() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCallFrameInformation()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
MaybeAlign getStackAlign(const Function &F, unsigned Index)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
LLVM_ABI 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.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static RegisterSet expandToSubRegs(RegisterRef R, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
std::map< RegisterRef, RangeList > RegToRangeMap
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.