34#define DEBUG_TYPE "riscv-frame"
68 RISCV::X18, RISCV::X19, RISCV::X20,
69 RISCV::X21, RISCV::X22, RISCV::X23,
70 RISCV::X24, RISCV::X25, RISCV::X26,
119 STI.hasStdExtZimop();
120 bool HasSWShadowStack =
122 if (!HasHWShadowStack && !HasSWShadowStack)
135 if (HasHWShadowStack) {
144 bool IsRV64 = STI.is64Bit();
145 int64_t SlotSize = STI.getXLen() / 8;
165 char DwarfSCSReg =
TRI->getDwarfRegNum(SCSPReg,
true);
166 assert(DwarfSCSReg < 32 &&
"SCS Register should be < 32 (X3).");
168 char Offset =
static_cast<char>(-SlotSize) & 0x7f;
169 const char CFIInst[] = {
170 dwarf::DW_CFA_val_expression,
173 static_cast<char>(
unsigned(dwarf::DW_OP_breg0 + DwarfSCSReg)),
186 STI.hasStdExtZimop();
187 bool HasSWShadowStack =
189 if (!HasHWShadowStack && !HasSWShadowStack)
199 if (
MI !=
MBB.end() &&
200 (
MI->getOpcode() == RISCV::CM_POP ||
MI->getOpcode() == RISCV::QC_CM_POP))
203 if (HasHWShadowStack) {
212 bool IsRV64 = STI.is64Bit();
213 int64_t SlotSize = STI.getXLen() / 8;
240 if (!RVFI->isSiFiveStackSwapInterrupt(MF))
246 assert(STI.hasVendorXSfmclic() &&
"Stack Swapping Requires XSfmclic");
250 .
addImm(RISCVSysReg::sf_mscratchcsw)
269 for (
int I = 0;
I < 2; ++
I) {
282 assert(ScratchCS != CSI.end() &&
"Missing SiFive CLIC scratch spill slot");
283 return ScratchCS->getFrameIdx();
292 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
303 TII->storeRegToStackSlot(
MBB,
MBBI, RISCV::X5,
true, ScratchFI,
312 .
addImm(RISCVSysReg::mcause)
315 TII->storeRegToStackSlot(
MBB,
MBBI, RISCV::X5,
true,
316 RVFI->getInterruptCSRFrameIndex(0),
322 .
addImm(RISCVSysReg::mepc)
329 .
addImm(RISCVSysReg::mstatus)
332 TII->storeRegToStackSlot(
MBB,
MBBI, RISCV::X5,
true,
333 RVFI->getInterruptCSRFrameIndex(1),
345 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
355 TII->loadRegFromStackSlot(
MBB,
MBBI, RISCV::X5,
356 RVFI->getInterruptCSRFrameIndex(1),
363 .
addImm(RISCVSysReg::mstatus)
371 .
addImm(RISCVSysReg::mepc)
375 TII->loadRegFromStackSlot(
MBB,
MBBI, RISCV::X5,
376 RVFI->getInterruptCSRFrameIndex(0),
381 .
addImm(RISCVSysReg::mcause)
387 TII->loadRegFromStackSlot(
MBB,
MBBI, RISCV::X5,
400 const std::vector<CalleeSavedInfo> &CSI) {
403 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
410 if (CS.getFrameIdx() < 0)
411 MaxReg = std::max(MaxReg.
id(), CS.getReg().id());
416 switch (MaxReg.
id()) {
420 case RISCV::X27:
return 12;
421 case RISCV::X26:
return 11;
422 case RISCV::X25:
return 10;
423 case RISCV::X24:
return 9;
424 case RISCV::X23:
return 8;
425 case RISCV::X22:
return 7;
426 case RISCV::X21:
return 6;
427 case RISCV::X20:
return 5;
428 case RISCV::X19:
return 4;
429 case RISCV::X18:
return 3;
430 case RISCV::X9:
return 2;
431 case FPReg:
return 1;
432 case RAReg:
return 0;
441 const std::vector<CalleeSavedInfo> &CSI) {
442 static const char *
const SpillLibCalls[] = {
461 return SpillLibCalls[LibCallID];
468 const std::vector<CalleeSavedInfo> &CSI) {
469 static const char *
const RestoreLibCalls[] = {
480 "__riscv_restore_10",
481 "__riscv_restore_11",
488 return RestoreLibCalls[LibCallID];
493 unsigned NumPushPopRegs = 0;
494 for (
auto &CS : CSI) {
498 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
499 NumPushPopRegs = std::max(NumPushPopRegs, RegNum + 1);
502 assert(NumPushPopRegs != 12 &&
"x26 requires x27 to also be pushed");
503 return NumPushPopRegs;
546 TRI->hasStackRealignment(MF);
550void RISCVFrameLowering::determineFrameLayout(
MachineFunction &MF)
const {
558 if (RVFI->useQCIInterrupt(MF))
565 FrameSize =
alignTo(FrameSize, StackAlign);
575 if (RVFI->getRVVStackSize() && (!
hasFP(MF) ||
TRI->hasStackRealignment(MF))) {
576 int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() -
577 RVFI->getVarArgsSaveSize();
578 if (
auto RVVPadding =
580 RVFI->setRVVPadding(RVVPadding);
595 const std::vector<CalleeSavedInfo> &CSI,
596 bool ReverseOrder =
false) {
600 for (
auto &CS : CSI) {
601 int FI = CS.getFrameIdx();
609 std::reverse(NonLibcallCSI.
begin(), NonLibcallCSI.
end());
611 return NonLibcallCSI;
618 const std::vector<CalleeSavedInfo> &CSI,
619 bool ReverseOrder =
false) {
623 return CS.
getReg() == RISCV::X5;
630 const std::vector<CalleeSavedInfo> &CSI) {
634 for (
auto &CS : CSI) {
635 int FI = CS.getFrameIdx();
645 const std::vector<CalleeSavedInfo> &CSI) {
649 if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
650 return PushOrLibCallsCSI;
652 for (
const auto &CS : CSI) {
653 if (RVFI->useQCIInterrupt(MF)) {
664 PushOrLibCallsCSI.push_back(CS);
667 return PushOrLibCallsCSI;
672 const std::vector<CalleeSavedInfo> &CSI) {
676 if (!RVFI->useQCIInterrupt(MF))
677 return QCIInterruptCSI;
679 for (
const auto &CS : CSI) {
682 QCIInterruptCSI.push_back(CS);
685 return QCIInterruptCSI;
693 for (
unsigned i = 0; CSRegs[i]; ++i)
713 if (
LiveRegs.available(MRI, PreferredReg))
716 static const MCPhysReg CandidateRegs[] = {
717 RISCV::X5, RISCV::X6, RISCV::X7, RISCV::X28,
718 RISCV::X29, RISCV::X30, RISCV::X31,
721 for (
unsigned Reg : CandidateRegs) {
722 if (Reg != DontUseReg &&
LiveRegs.available(MRI, Reg))
729void RISCVFrameLowering::allocateAndProbeStackForRVV(
733 assert(Amount != 0 &&
"Did not need to adjust stack pointer for RVV.");
740 "No available scratch register for stack probing");
745 TII->mulImm(MF,
MBB,
MBBI,
DL, TargetReg, NumOfVReg, Flag);
750 CFIBuilder.buildDefCFA(TargetReg, -Amount);
759 CFIBuilder.buildDefCFARegister(
SPReg);
782 int64_t FixedOffset =
Offset.getFixed();
783 int64_t ScalableOffset =
Offset.getScalable();
784 unsigned DwarfVLenB =
TRI.getDwarfRegNum(RISCV::VLENB,
true);
789 Comment << (FixedOffset < 0 ?
" - " :
" + ") << std::abs(FixedOffset);
802 Comment << (ScalableOffset < 0 ?
" - " :
" + ") << std::abs(ScalableOffset)
809 assert(
Offset.getScalable() != 0 &&
"Did not need to adjust CFA for RVV");
811 std::string CommentBuffer;
814 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
825 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
835 assert(
Offset.getScalable() != 0 &&
"Did not need to adjust CFA for RVV");
837 std::string CommentBuffer;
845 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
846 DefCfaExpr.
push_back(dwarf::DW_CFA_expression);
859 uint64_t RealStackSize,
bool EmitCFI,
860 bool NeedProbe, uint64_t ProbeSize,
866 bool IsRV64 =
STI.is64Bit();
870 if (!NeedProbe ||
Offset <= ProbeSize) {
877 if (NeedProbe && DynAllocation) {
890 if (
Offset < ProbeSize * 5) {
891 uint64_t CFAAdjust = RealStackSize -
Offset;
893 uint64_t CurrentOffset = 0;
894 while (CurrentOffset + ProbeSize <=
Offset) {
904 CurrentOffset += ProbeSize;
909 uint64_t Residual =
Offset - CurrentOffset;
931 uint64_t Residual =
Offset - RoundedSize;
935 "No available scratch register for stack probing");
973 case RISCV::QC_CM_PUSH:
974 case RISCV::QC_CM_PUSHFP:
986 case RISCV::QC_CM_POP:
997 return RISCV::CM_PUSH;
999 return UpdateFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
1010 return RISCV::CM_POP;
1012 return RISCV::QC_CM_POP;
1024 bool PreferAscendingLS =
STI.preferAscendingLoadStore();
1046 auto PossiblePush =
MBBI;
1053 determineFrameLayout(MF);
1088 unsigned LibCallFrameSize =
1090 RVFI->setLibCallStackSize(LibCallFrameSize);
1092 if (NeedsDwarfCFI) {
1103 uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
1104 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1107 if (RealStackSize == 0 && !MFI.
adjustsStack() && RVVStackSize == 0)
1112 if (
STI.isRegisterReservedByUser(
SPReg))
1114 MF.
getFunction(),
"Stack pointer required, but has been reserved."});
1118 if (FirstSPAdjustAmount) {
1119 StackSize = FirstSPAdjustAmount;
1120 RealStackSize = FirstSPAdjustAmount;
1123 if (RVFI->useQCIInterrupt(MF)) {
1128 if (NeedsDwarfCFI) {
1141 if (RVFI->isPushable(MF) && PossiblePush !=
MBB.end() &&
1142 isPush(PossiblePush->getOpcode())) {
1148 std::min(
alignDown(StackSize, 16),
static_cast<uint64_t
>(48));
1149 PossiblePush->getOperand(1).setImm(StackAdj);
1150 StackSize -= StackAdj;
1152 if (NeedsDwarfCFI) {
1164 uint64_t ProbeSize = TLI->getStackProbeSize(MF,
getStackAlign());
1165 bool DynAllocation =
1169 NeedProbe, ProbeSize, DynAllocation,
1187 if (NeedsDwarfCFI) {
1194 if (RISCV::GPRPairRegClass.
contains(Reg)) {
1195 MCRegister EvenReg = RI->getSubReg(Reg, RISCV::sub_gpr_even);
1196 MCRegister OddReg = RI->getSubReg(Reg, RISCV::sub_gpr_odd);
1207 if (
STI.isRegisterReservedByUser(
FPReg))
1209 MF.
getFunction(),
"Frame pointer required, but has been reserved."});
1215 if (!RVFI->hasImplicitFPUpdates(MF)) {
1226 uint64_t SecondSPAdjustAmount = 0;
1228 if (FirstSPAdjustAmount) {
1230 assert(SecondSPAdjustAmount > 0 &&
1231 "SecondSPAdjustAmount should be greater than zero");
1235 NeedProbe, ProbeSize, DynAllocation,
1241 allocateAndProbeStackForRVV(MF,
MBB,
MBBI,
DL, RVVStackSize,
1243 NeedsDwarfCFI && !
hasFP(MF), DynAllocation);
1252 if (NeedsDwarfCFI && !
hasFP(MF)) {
1267 if (RI->hasStackRealignment(MF)) {
1271 if (
isInt<12>(-(
int)MaxAlignment.value())) {
1274 .
addImm(-(
int)MaxAlignment.value())
1277 unsigned ShiftAmount =
Log2(MaxAlignment);
1289 if (NeedProbe && RVVStackSize == 0) {
1292 if (SecondSPAdjustAmount < ProbeSize &&
1293 SecondSPAdjustAmount + MaxAlignment.value() >= ProbeSize) {
1294 bool IsRV64 =
STI.is64Bit();
1320 uint64_t &StackSize,
1321 int64_t CFAOffset)
const {
1338 bool PreferAscendingLS =
STI.preferAscendingLoadStore();
1350 MBBI =
MBB.getLastNonDebugInstr();
1352 DL =
MBBI->getDebugLoc();
1354 MBBI =
MBB.getFirstTerminator();
1367 auto FirstScalarCSRRestoreInsn =
1374 uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1376 uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1378 RVFI->getReservedSpillsSize();
1379 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
1380 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1382 bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
1387 if (!RestoreSPFromFP)
1392 if (NeedsDwarfCFI) {
1395 emitCalleeSavedRVVEpilogCFI(
MBB, FirstScalarCSRRestoreInsn);
1399 if (FirstSPAdjustAmount) {
1400 uint64_t SecondSPAdjustAmount =
1402 assert(SecondSPAdjustAmount > 0 &&
1403 "SecondSPAdjustAmount should be greater than zero");
1407 if (!RestoreSPFromFP)
1412 if (NeedsDwarfCFI && !
hasFP(MF))
1426 if (RestoreSPFromFP) {
1427 assert(
hasFP(MF) &&
"frame pointer should not have been eliminated");
1433 if (NeedsDwarfCFI &&
hasFP(MF))
1439 MBBI = std::next(FirstScalarCSRRestoreInsn,
1449 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1450 RVFI->getLibCallStackSize());
1458 if (NeedsDwarfCFI) {
1463 if (RISCV::GPRPairRegClass.
contains(Reg)) {
1464 MCRegister EvenReg = RI->getSubReg(Reg, RISCV::sub_gpr_even);
1465 MCRegister OddReg = RI->getSubReg(Reg, RISCV::sub_gpr_odd);
1474 if (RVFI->isPushable(MF) &&
MBBI !=
MBB.end() &&
isPop(
MBBI->getOpcode())) {
1480 std::min(
alignDown(StackSize, 16),
static_cast<uint64_t
>(48));
1481 MBBI->getOperand(1).setImm(StackAdj);
1482 StackSize -= StackAdj;
1485 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1486 RealStackSize - StackSize);
1489 if (NextI ==
MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
1491 if (NeedsDwarfCFI) {
1509 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1510 RVFI->getQCIInterruptStackSize());
1524 std::array<TargetRegisterClass const *, 2> RegisterClasses = {
1525 &RISCV::GPRF16RegClass, &RISCV::GPRF32RegClass};
1526 std::array<unsigned, 2> SubIdx = {RISCV::sub_16, RISCV::sub_32};
1528 for (
auto [RegClass, SubReg] :
zip(RegisterClasses, SubIdx)) {
1529 if (RegClass->contains(
Reg)) {
1531 TRI.getMatchingSuperReg(
Reg, SubReg, &RISCV::GPRRegClass))
1537 "getPhysicalGPR called with unsupported register");
1543 if (!STI.hasStdExtF())
1547 assert(LargestFPRegClass);
1552 std::array<TargetRegisterClass const *, 3> RegisterClasses = {
1553 &RISCV::FPR16RegClass, &RISCV::FPR32RegClass, &RISCV::FPR64RegClass};
1554 std::array<unsigned, 3> SubIdx = {RISCV::sub_16, RISCV::sub_32,
1557 for (
auto [RegClass, SubReg] :
zip(RegisterClasses, SubIdx)) {
1558 if (RegClass->contains(
Reg)) {
1560 TRI.getMatchingSuperReg(
Reg, SubReg, LargestFPRegClass))
1570void RISCVFrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
1579 DL =
MBBI->getDebugLoc();
1582 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
1583 const RISCVInstrInfo &
TII = *
STI.getInstrInfo();
1585 BitVector FinalRegsToZero(
TRI.getNumRegs());
1587 bool HasVRegister =
false;
1590 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
1592 }
else if (RISCV::GPRPairRegClass.
contains(
Reg)) {
1593 FinalRegsToZero.set(
1595 FinalRegsToZero.set(
1597 }
else if (
TRI.isFPRegister(
Reg)) {
1599 FinalRegsToZero.set(MaybeReg.id());
1601 TRI.getMinimalPhysRegClass(
Reg))) {
1602 if (!
STI.hasVInstructions())
1604 HasVRegister =
true;
1606 for (MCRegister SubReg :
TRI.subregs_inclusive(
Reg)) {
1607 if (
TRI.subregs(SubReg).empty())
1608 FinalRegsToZero.set(SubReg.id());
1616 VLMUL, 32,
true,
true);
1618 MCRegister TemporaryReg = RISCV::NoRegister;
1619 for (MCRegister
Reg : FinalRegsToZero.set_bits()) {
1620 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
1626 if (TemporaryReg == RISCV::NoRegister) {
1627 RS->enterBasicBlockEnd(
MBB);
1628 TemporaryReg =
RS->scavengeRegisterBackwards(RISCV::GPRRegClass,
MBBI,
1637 FinalRegsToZero.set(TemporaryReg.
id());
1646 for (MCRegister
Reg : FinalRegsToZero.set_bits())
1661 STI.preferAscendingLoadStore());
1669 "Unexpected stack ID for the frame object.");
1681 MinCSFI = std::min(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
1682 MaxCSFI = std::max(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
1685 bool IsInterruptCSR = RVFI->isSiFivePreemptibleInterrupt(MF) &&
1686 (FI == RVFI->getInterruptCSRFrameIndex(0) ||
1687 FI == RVFI->getInterruptCSRFrameIndex(1));
1688 if ((FI >= MinCSFI && FI <= MaxCSFI) || IsInterruptCSR) {
1691 if (FirstSPAdjustAmount)
1755 int64_t CLWSPMaxOffset = 252;
1756 int64_t CLDSPMaxOffset = 504;
1757 int64_t SPThreshold =
STI.is64Bit() ? CLDSPMaxOffset : CLWSPMaxOffset;
1758 if (SPOff >= 0 && SPOff <= SPThreshold)
1764 "Expected fixed object with stack realignment");
1765 assert(
hasFP(MF) &&
"Re-aligned stack must have frame pointer");
1769 if (FrameReg ==
FPReg) {
1788 "Can't index across variable sized realign");
1793 "Inconsistent stack layout");
1836 "Can't index across variable sized realign");
1838 RVFI->getRVVStackSize());
1845 int64_t ScalarLocalVarSize =
1847 RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding();
1858 if (!BaseReg.isValid())
1878 for (
unsigned i = 0; CSRegs[i]; ++i) {
1879 unsigned CSReg = CSRegs[i];
1884 SavedRegs.
reset(CSReg);
1886 auto SubRegs =
TRI.subregs(CSReg);
1889 SavedRegs.
set(CSReg);
1890 for (
unsigned Reg : SubRegs)
1908 if (RVFI->isSiFivePreemptibleInterrupt(MF))
1909 SavedRegs.
set(RISCV::X5);
1912 if (RVFI->isPushable(MF) && SavedRegs.
test(RISCV::X26))
1913 SavedRegs.
set(RISCV::X27);
1920 bool UseZilsd = !
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
1922 !RVFI->isPushable(MF) && !RVFI->useSaveRestoreLibCalls(MF);
1926 for (
unsigned i = 0; CSRegs[i]; ++i) {
1928 CSRSet.
insert(CSRegs[i]);
1933 for (
MCPhysReg Pair : RISCV::GPRPairRegClass) {
1937 MCRegister EvenReg =
TRI.getSubReg(Pair, RISCV::sub_gpr_even);
1938 MCRegister OddReg =
TRI.getSubReg(Pair, RISCV::sub_gpr_odd);
1952 for (
unsigned i = 0; CSRegs[i]; ++i) {
1954 bool CombineToSuperReg;
1955 if (RISCV::GPRPairRegClass.
contains(CSReg)) {
1956 MCRegister EvenReg =
TRI.getSubReg(CSReg, RISCV::sub_gpr_even);
1957 MCRegister OddReg =
TRI.getSubReg(CSReg, RISCV::sub_gpr_odd);
1959 SavedRegs.
test(EvenReg.
id()) && SavedRegs.
test(OddReg.
id());
1962 if (
hasFP(MF) && CSReg == RISCV::X8_X9)
1963 CombineToSuperReg =
false;
1965 auto SubRegs =
TRI.subregs(CSReg);
1967 !SubRegs.empty() &&
llvm::all_of(SubRegs, [&](
unsigned Reg) {
1968 return SavedRegs.
test(Reg);
1972 if (CombineToSuperReg)
1973 SavedRegs.
set(CSReg);
1980std::pair<int64_t, Align>
1981RISCVFrameLowering::assignRVVStackObjectOffsets(
MachineFunction &MF)
const {
1985 auto pushRVVObjects = [&](
int FIBegin,
int FIEnd) {
1986 for (
int I = FIBegin, E = FIEnd;
I != E; ++
I) {
1999 if (!RVVCSI.empty())
2000 pushRVVObjects(RVVCSI[0].getFrameIdx(),
2001 RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1);
2005 Align RVVStackAlign(16);
2008 if (!
ST.hasVInstructions()) {
2010 "Can't allocate scalable-vector objects without V instructions");
2011 return std::make_pair(0, RVVStackAlign);
2016 for (
int FI : ObjectsToAllocate) {
2028 RVVStackAlign = std::max(RVVStackAlign, ObjectAlign);
2041 if (
auto RVVStackAlignVScale = RVVStackAlign.value() / VScale) {
2042 if (
auto AlignmentPadding =
2044 StackSize += AlignmentPadding;
2045 for (
int FI : ObjectsToAllocate)
2050 return std::make_pair(StackSize, RVVStackAlign);
2056 static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2;
2060 static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1;
2064 static constexpr unsigned ScavSlotsADDIScalableObject = 1;
2066 static constexpr unsigned MaxScavSlotsNumKnown =
2067 std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject,
2068 ScavSlotsNumRVVSpillNonScalableObject});
2070 unsigned MaxScavSlotsNum = 0;
2076 for (
auto &MO :
MI.operands()) {
2082 MaxScavSlotsNum = std::max(
2083 MaxScavSlotsNum, IsScalableVectorID
2084 ? ScavSlotsNumRVVSpillScalableObject
2085 : ScavSlotsNumRVVSpillNonScalableObject);
2086 }
else if (
MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) {
2088 std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject);
2091 if (MaxScavSlotsNum == MaxScavSlotsNumKnown)
2092 return MaxScavSlotsNumKnown;
2094 return MaxScavSlotsNum;
2118 unsigned FnSize = 0;
2119 for (
auto &
MBB : MF) {
2120 for (
auto &
MI :
MBB) {
2138 if (
MI.isConditionalBranch())
2139 FnSize +=
TII.getInstSizeInBytes(
MI);
2140 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
2142 FnSize += 2 + 8 + 2 + 2;
2144 FnSize += 4 + 8 + 4 + 4;
2148 FnSize +=
TII.getInstSizeInBytes(
MI);
2163 int64_t RVVStackSize;
2164 Align RVVStackAlign;
2165 std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MF);
2167 RVFI->setRVVStackSize(RVVStackSize);
2168 RVFI->setRVVStackAlign(RVVStackAlign);
2177 unsigned ScavSlotsNum = 0;
2187 if (IsLargeFunction)
2188 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
2195 for (
unsigned I = 0;
I < ScavSlotsNum;
I++) {
2197 RegInfo->getSpillAlign(*RC));
2198 RS->addScavengingFrameIndex(FI);
2200 if (IsLargeFunction && RVFI->getBranchRelaxationScratchFrameIndex() == -1)
2201 RVFI->setBranchRelaxationScratchFrameIndex(FI);
2204 unsigned Size = RVFI->getReservedSpillsSize();
2206 int FrameIdx = Info.getFrameIdx();
2212 RVFI->setCalleeSavedStackSize(
Size);
2236 int64_t Amount =
MI->getOperand(0).getImm();
2242 if (
MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
2252 bool DynAllocation =
2256 true, ProbeSize, DynAllocation,
2258 inlineStackProbe(MF,
MBB);
2267 return MBB.erase(
MI);
2285 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2291 if (RVFI->getReservedSpillsSize())
2296 if (!
isInt<12>(StackSize) && (CSI.size() > 0)) {
2309 if (
STI.hasStdExtZca()) {
2319 const uint64_t RVCompressLen =
STI.getXLen() * 8;
2326 auto CanCompress = [&](uint64_t CompressLen) ->
bool {
2327 if (StackSize <= 2047 + CompressLen ||
2328 (StackSize > 2048 * 2 - StackAlign &&
2329 StackSize <= 2047 * 2 + CompressLen) ||
2330 StackSize > 2048 * 3 - StackAlign)
2338 const uint64_t ADDI16SPCompressLen = 496;
2339 if (
STI.is64Bit() && CanCompress(ADDI16SPCompressLen))
2340 return ADDI16SPCompressLen;
2341 if (CanCompress(RVCompressLen))
2342 return RVCompressLen;
2344 return 2048 - StackAlign;
2351 std::vector<CalleeSavedInfo> &CSI)
const {
2358 if (RVFI->isSiFivePreemptibleInterrupt(MF)) {
2359 for (
int I = 0;
I < 2; ++
I) {
2360 int FI = RVFI->getInterruptCSRFrameIndex(
I);
2361 MFI.setIsCalleeSavedObjectIndex(FI,
true);
2369 if (RVFI->useQCIInterrupt(MF)) {
2373 if (RVFI->isPushable(MF)) {
2380 unsigned OnlyPushIfMoreThan = RVFI->useQCIInterrupt(MF) ? 2 : 0;
2381 if (PushedRegNum > OnlyPushIfMoreThan) {
2382 RVFI->setRVPushRegs(PushedRegNum);
2383 RVFI->setRVPushStackSize(
alignTo((
STI.getXLen() / 8) * PushedRegNum, 16));
2387 for (
auto &CS : CSI) {
2390 unsigned Size = RegInfo->getSpillSize(*RC);
2392 if (RVFI->useQCIInterrupt(MF)) {
2394 return P.first == CS.getReg();
2397 int64_t
Offset = FFI->second * (int64_t)
Size;
2399 int FrameIdx = MFI.CreateFixedSpillStackObject(
Size,
Offset);
2401 CS.setFrameIdx(FrameIdx);
2406 if (RVFI->useSaveRestoreLibCalls(MF) || RVFI->isPushable(MF)) {
2409 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
2413 if (RVFI->getPushPopKind(MF) ==
2415 Offset = -int64_t(RVFI->getRVPushRegs() - RegNum) *
Size;
2419 if (RVFI->useQCIInterrupt(MF))
2422 int FrameIdx = MFI.CreateFixedSpillStackObject(
Size,
Offset);
2424 CS.setFrameIdx(FrameIdx);
2430 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
2431 RISCV::GPRPairRegClass.contains(Reg)) {
2432 Align PairAlign =
STI.getZilsdAlign();
2433 int FrameIdx = MFI.CreateStackObject(8, PairAlign,
true);
2434 MFI.setIsCalleeSavedObjectIndex(FrameIdx,
true);
2435 CS.setFrameIdx(FrameIdx);
2440 Align Alignment = RegInfo->getSpillAlign(*RC);
2445 int FrameIdx = MFI.CreateStackObject(
Size, Alignment,
true);
2446 MFI.setIsCalleeSavedObjectIndex(FrameIdx,
true);
2447 CS.setFrameIdx(FrameIdx);
2452 if (RVFI->useQCIInterrupt(MF)) {
2455 MFI.CreateFixedSpillStackObject(
2459 if (RVFI->isPushable(MF)) {
2462 if (int64_t PushSize = RVFI->getRVPushStackSize())
2463 MFI.CreateFixedSpillStackObject(PushSize, -PushSize - QCIOffset);
2464 }
else if (
int LibCallRegs =
getLibCallID(MF, CSI) + 1) {
2465 int64_t LibCallFrameSize =
2467 MFI.CreateFixedSpillStackObject(LibCallFrameSize, -LibCallFrameSize);
2482 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
2483 DL =
MI->getDebugLoc();
2492 ? RISCV::QC_C_MIENTER_NEST
2493 : RISCV::QC_C_MIENTER))
2503 if (PushedRegNum > 0) {
2511 PushBuilder.
addImm(RegEnc);
2514 for (
unsigned i = 0; i < PushedRegNum; i++)
2527 for (
auto &CS : CSI)
2532 const auto &UnmanagedCSI =
2537 for (
auto &CS : CSInfo) {
2541 TII.storeRegToStackSlot(
MBB,
MI, Reg, !
MBB.isLiveIn(Reg),
2546 storeRegsToStackSlots(UnmanagedCSI);
2547 storeRegsToStackSlots(RVVCSI);
2553 return RISCV::VRRegClass.contains(BaseReg) ? 1
2554 : RISCV::VRM2RegClass.contains(BaseReg) ? 2
2555 : RISCV::VRM4RegClass.contains(BaseReg) ? 4
2559void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
2563 RISCVMachineFunctionInfo *RVFI = MF->
getInfo<RISCVMachineFunctionInfo>();
2564 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
2575 FixedSize -= ScalarLocalVarSize;
2579 for (
auto &CS : RVVCSI) {
2581 int FI = CS.getFrameIdx();
2584 for (
unsigned i = 0; i < NumRegs; ++i) {
2592void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
2596 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
2600 for (
auto &CS : RVVCSI) {
2603 for (
unsigned i = 0; i < NumRegs; ++i)
2604 CFIHelper.buildRestore(BaseReg + i);
2617 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
2618 DL =
MI->getDebugLoc();
2626 const auto &UnmanagedCSI =
2631 for (
auto &CS : CSInfo) {
2635 RISCV::NoSubRegister,
2638 "loadRegFromStackSlot didn't insert any code!");
2641 loadRegFromStackSlot(RVVCSI);
2642 loadRegFromStackSlot(UnmanagedCSI);
2648 assert(
MI->getOpcode() == RISCV::QC_C_MILEAVERET &&
2649 "Unexpected QCI Interrupt Return Instruction");
2654 if (PushedRegNum > 0) {
2661 PopBuilder.
addImm(RegEnc);
2676 for (
auto &CS : CSI)
2681 if (
MI !=
MBB.end() &&
MI->getOpcode() == RISCV::PseudoRET) {
2683 MI->eraseFromParent();
2715 if (
STI.preferVsetvliOverReadVLENB() &&
2716 (
MBB.isLiveIn(RISCV::VTYPE) ||
MBB.isLiveIn(RISCV::VL)))
2727 RS.enterBasicBlock(*TmpMBB);
2728 return !RS.isRegUsed(RISCV::X5);
2743 if (
MBB.succ_size() > 1)
2760 return !MI.isDebugInstr();
2787 assert(TargetReg != RISCV::X2 &&
"New top of stack cannot already be in SP");
2788 assert(ScratchReg != RISCV::X2 &&
"Scratch register cannot be SP");
2789 assert(TargetReg != ScratchReg &&
"Target and scratch must be different");
2796 bool IsRV64 = Subtarget.is64Bit();
2797 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
2804 MF.
insert(MBBInsertPoint, LoopTestMBB);
2806 MF.
insert(MBBInsertPoint, ExitMBB);
2810 TII->movImm(
MBB,
MBBI,
DL, ScratchReg, ProbeSize, Flags);
2821 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
2856 MBB.addSuccessor(LoopTestMBB);
2866 SmallVector<MachineInstr *, 4> ToReplace;
2867 for (MachineInstr &
MI :
MBB) {
2868 unsigned Opc =
MI.getOpcode();
2869 if (
Opc == RISCV::PROBED_STACKALLOC ||
2870 Opc == RISCV::PROBED_STACKALLOC_RVV) {
2875 for (MachineInstr *
MI : ToReplace) {
2876 if (
MI->getOpcode() == RISCV::PROBED_STACKALLOC ||
2877 MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) {
2880 Register TargetReg =
MI->getOperand(0).getReg();
2886 "No available scratch register for stack probe loop");
2889 (
MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV));
static void getLiveRegsForEntryMBB(LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII, const MachineFunction &MF)
static void emitStackProbeInline(MachineBasicBlock::iterator MBBI, DebugLoc DL, Register TargetReg)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr uint64_t QCIInterruptPushAmount
static void emitSiFiveCLICStackSwap(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MachineInstr::MIFlag FrameFlag)
static unsigned getPushOpcode(RISCVMachineFunctionInfo::PushPopKind Kind, bool UpdateFP)
static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI, const Register &Reg)
static void createSiFivePreemptibleInterruptFrameEntries(MachineFunction &MF, RISCVMachineFunctionInfo &RVFI)
static constexpr MCPhysReg FPReg
static const char * getRestoreLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static bool needsDwarfCFI(const MachineFunction &MF)
Returns true if DWARF CFI instructions ("frame moves") should be emitted.
static constexpr MCPhysReg SPReg
static const char * getSpillLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static bool hasRVVFrameObject(const MachineFunction &MF)
static SmallVector< CalleeSavedInfo, 8 > getUnmanagedInterruptCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI, bool ReverseOrder=false)
static void appendScalableVectorExpression(const TargetRegisterInfo &TRI, SmallVectorImpl< char > &Expr, StackOffset Offset, llvm::raw_string_ostream &Comment)
static SmallVector< CalleeSavedInfo, 8 > getQCISavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static SmallVector< CalleeSavedInfo, 8 > getRVVCalleeSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static SmallVector< CalleeSavedInfo, 8 > getUnmanagedCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI, bool ReverseOrder=false)
static void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, CFIInstBuilder &CFIBuilder, const DebugLoc &DL)
static bool isPop(unsigned Opcode)
static unsigned getCalleeSavedRVVNumRegs(const Register &BaseReg)
static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI, Register Reg, StackOffset Offset)
static Align getABIStackAlignment(RISCVABI::ABI ABI)
static unsigned getPopOpcode(RISCVMachineFunctionInfo::PushPopKind Kind)
static SmallVector< CalleeSavedInfo, 8 > getPushOrLibCallsSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static int getLibCallID(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static const std::pair< MCPhysReg, int8_t > FixedCSRFIQCIInterruptMap[]
static bool isPush(unsigned Opcode)
static constexpr MCPhysReg RAReg
static MCRegister getLargestFPRegisterOrZero(const RISCVSubtarget &STI, const TargetRegisterInfo &TRI, MCRegister Reg)
static const MCPhysReg FixedCSRFIMap[]
static int getSiFiveCLICScratchFrameIndex(const MachineFunction &MF)
static unsigned getNumPushPopRegs(const std::vector< CalleeSavedInfo > &CSI)
static MCRegister getPhysicalGPR(const TargetRegisterInfo &TRI, MCRegister Reg)
static unsigned getScavSlotsNumForRVV(MachineFunction &MF)
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
BitVector & reset()
Reset all bits in the bitvector.
BitVector & set()
Set all bits in the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
Helper class for creating CFI instructions and inserting them into MIR.
void buildEscape(StringRef Bytes, StringRef Comment="") const
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void buildRestore(MCRegister Reg) const
void buildDefCFARegister(MCRegister Reg) const
void buildOffset(MCRegister Reg, int64_t Offset) const
void insertCFIInst(const MCCFIInstruction &CFIInst) const
void buildDefCFA(MCRegister Reg, int64_t Offset) const
void setInsertPoint(MachineBasicBlock::iterator IP)
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
MCRegister getReg() const
Diagnostic information for unsupported feature in backend.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasOptNone() const
Do not optimize this function (-O0).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
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.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
LLVM_ABI void ensureMaxAlignment(Align Alignment)
Make sure the function's frame is at least Align bytes aligned.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return alignment of this function's frame.
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
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.
bool isMaxCallFrameSizeComputed() const
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.
uint8_t getStackID(int ObjectIdx) const
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.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
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
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
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 & 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 & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
LLVM_ABI void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const BitVector & getUsedPhysRegsMask() const
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved 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...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
LLVM_ABI void setCalleeSavedRegs(ArrayRef< MCPhysReg > CSRs)
Sets the updated Callee Saved Registers list.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
uint64_t getFirstSPAdjustAmount(const MachineFunction &MF) const
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
uint64_t getStackThreshold() const override
getStackThreshold - Return the maximum stack size
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
bool hasBP(const MachineFunction &MF) const
void allocateStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineFunction &MF, uint64_t Offset, uint64_t RealStackSize, bool EmitCFI, bool NeedProbe, uint64_t ProbeSize, bool DynAllocation, MachineInstr::MIFlag Flag) const
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
bool hasFPImpl(const MachineFunction &MF) const override
Register findScratchNonCalleeSaveRegister(MachineBasicBlock *MBB, Register PreferredReg, Register DontUseReg=Register()) const
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
Register getInitialCFARegister(const MachineFunction &MF) const override
Return initial CFA register value i.e.
const RISCVSubtarget & STI
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...
bool isSupportedStackID(TargetStackID::Value ID) const override
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
TargetStackID::Value getStackIDForScalableVectors() const override
Returns the StackID that scalable vectors should be associated with.
int getInitialCFAOffset(const MachineFunction &MF) const override
Return initial CFA offset value i.e.
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
RISCVFrameLowering(const RISCVSubtarget &STI)
uint64_t getStackSizeWithRVVPadding(const MachineFunction &MF) const
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
bool isPushable(const MachineFunction &MF) const
InterruptStackKind getInterruptStackKind(const MachineFunction &MF) const
bool useSiFiveInterrupt(const MachineFunction &MF) const
bool isSiFivePreemptibleInterrupt(const MachineFunction &MF) const
void pushInterruptCSRFrameIndex(int FI)
PushPopKind getPushPopKind(const MachineFunction &MF) const
uint64_t getRVVPadding() const
unsigned getRVPushRegs() const
bool useSaveRestoreLibCalls(const MachineFunction &MF) const
unsigned getVarArgsSaveSize() const
bool useQCIInterrupt(const MachineFunction &MF) const
unsigned getCalleeSavedStackSize() const
TargetRegisterClass const * getLargestFPRegClass() const
bool hasVInstructions() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
Represents a location in source code.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
int64_t getScalable() const
Returns the scalable component of the stack.
static StackOffset get(int64_t Fixed, int64_t Scalable)
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
Represent a constant reference to a string, i.e.
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...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
self_iterator getIterator()
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
static unsigned encodeRegListNumRegs(unsigned NumRegs)
static constexpr unsigned RVVBitsPerBlock
bool isRVVSpill(const MachineInstr &MI)
static constexpr unsigned RVVBytesPerBlock
@ ScalablePredicateVector
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
unsigned Log2(Align A)
Returns the log2 of the alignment.
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.
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 bool isRVVRegClass(const TargetRegisterClass *RC)
void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, Register SrcReg, StackOffset Offset, MachineInstr::MIFlag Flag, MaybeAlign RequiredAlign) const