33#define DEBUG_TYPE "riscv-frame"
67 RISCV::X18, RISCV::X19, RISCV::X20,
68 RISCV::X21, RISCV::X22, RISCV::X23,
69 RISCV::X24, RISCV::X25, RISCV::X26,
118 STI.hasStdExtZimop();
119 bool HasSWShadowStack =
121 if (!HasHWShadowStack && !HasSWShadowStack)
134 if (HasHWShadowStack) {
143 bool IsRV64 = STI.is64Bit();
144 int64_t SlotSize = STI.getXLen() / 8;
164 char DwarfSCSReg =
TRI->getDwarfRegNum(SCSPReg,
true);
165 assert(DwarfSCSReg < 32 &&
"SCS Register should be < 32 (X3).");
167 char Offset =
static_cast<char>(-SlotSize) & 0x7f;
168 const char CFIInst[] = {
169 dwarf::DW_CFA_val_expression,
172 static_cast<char>(
unsigned(dwarf::DW_OP_breg0 + DwarfSCSReg)),
185 STI.hasStdExtZimop();
186 bool HasSWShadowStack =
188 if (!HasHWShadowStack && !HasSWShadowStack)
198 if (
MI !=
MBB.end() &&
199 (
MI->getOpcode() == RISCV::CM_POP ||
MI->getOpcode() == RISCV::QC_CM_POP))
202 if (HasHWShadowStack) {
211 bool IsRV64 = STI.is64Bit();
212 int64_t SlotSize = STI.getXLen() / 8;
238 if (!RVFI->isSiFiveStackSwapInterrupt(MF))
244 assert(STI.hasVendorXSfmclic() &&
"Stack Swapping Requires XSfmclic");
248 .
addImm(RISCVSysReg::sf_mscratchcsw)
269 for (
int I = 0;
I < 2; ++
I) {
282 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
297 TII->storeRegToStackSlot(
MBB,
MBBI, RISCV::X8,
true,
298 RVFI->getInterruptCSRFrameIndex(0),
301 TII->storeRegToStackSlot(
MBB,
MBBI, RISCV::X9,
true,
302 RVFI->getInterruptCSRFrameIndex(1),
311 .
addImm(RISCVSysReg::mcause)
316 .
addImm(RISCVSysReg::mepc)
323 .
addImm(RISCVSysReg::mstatus)
334 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
345 .
addImm(RISCVSysReg::mstatus)
354 .
addImm(RISCVSysReg::mepc)
359 .
addImm(RISCVSysReg::mcause)
365 TII->loadRegFromStackSlot(
MBB,
MBBI, RISCV::X9,
366 RVFI->getInterruptCSRFrameIndex(1),
369 TII->loadRegFromStackSlot(
MBB,
MBBI, RISCV::X8,
370 RVFI->getInterruptCSRFrameIndex(0),
380 const std::vector<CalleeSavedInfo> &CSI) {
383 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
390 if (
CS.getFrameIdx() < 0)
391 MaxReg = std::max(MaxReg.
id(),
CS.getReg().id());
396 switch (MaxReg.
id()) {
400 case RISCV::X27:
return 12;
401 case RISCV::X26:
return 11;
402 case RISCV::X25:
return 10;
403 case RISCV::X24:
return 9;
404 case RISCV::X23:
return 8;
405 case RISCV::X22:
return 7;
406 case RISCV::X21:
return 6;
407 case RISCV::X20:
return 5;
408 case RISCV::X19:
return 4;
409 case RISCV::X18:
return 3;
410 case RISCV::X9:
return 2;
411 case FPReg:
return 1;
412 case RAReg:
return 0;
421 const std::vector<CalleeSavedInfo> &CSI) {
422 static const char *
const SpillLibCalls[] = {
441 return SpillLibCalls[LibCallID];
448 const std::vector<CalleeSavedInfo> &CSI) {
449 static const char *
const RestoreLibCalls[] = {
460 "__riscv_restore_10",
461 "__riscv_restore_11",
468 return RestoreLibCalls[LibCallID];
473 unsigned NumPushPopRegs = 0;
474 for (
auto &
CS : CSI) {
478 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
479 NumPushPopRegs = std::max(NumPushPopRegs, RegNum + 1);
482 assert(NumPushPopRegs != 12 &&
"x26 requires x27 to also be pushed");
483 return NumPushPopRegs;
527 TRI->hasStackRealignment(MF);
531void RISCVFrameLowering::determineFrameLayout(
MachineFunction &MF)
const {
539 if (RVFI->useQCIInterrupt(MF))
546 FrameSize =
alignTo(FrameSize, StackAlign);
556 if (RVFI->getRVVStackSize() && (!
hasFP(MF) ||
TRI->hasStackRealignment(MF))) {
557 int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() -
558 RVFI->getVarArgsSaveSize();
559 if (
auto RVVPadding =
561 RVFI->setRVVPadding(RVVPadding);
576 const std::vector<CalleeSavedInfo> &CSI,
577 bool ReverseOrder =
false) {
581 for (
auto &
CS : CSI) {
582 int FI =
CS.getFrameIdx();
590 std::reverse(NonLibcallCSI.
begin(), NonLibcallCSI.
end());
592 return NonLibcallCSI;
597 const std::vector<CalleeSavedInfo> &CSI) {
601 for (
auto &
CS : CSI) {
602 int FI =
CS.getFrameIdx();
612 const std::vector<CalleeSavedInfo> &CSI) {
616 if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
617 return PushOrLibCallsCSI;
619 for (
const auto &
CS : CSI) {
620 if (RVFI->useQCIInterrupt(MF)) {
631 PushOrLibCallsCSI.push_back(
CS);
634 return PushOrLibCallsCSI;
639 const std::vector<CalleeSavedInfo> &CSI) {
643 if (!RVFI->useQCIInterrupt(MF))
644 return QCIInterruptCSI;
646 for (
const auto &
CS : CSI) {
649 QCIInterruptCSI.push_back(
CS);
652 return QCIInterruptCSI;
655void RISCVFrameLowering::allocateAndProbeStackForRVV(
659 assert(Amount != 0 &&
"Did not need to adjust stack pointer for RVV.");
664 const RISCVInstrInfo *
TII =
STI.getInstrInfo();
669 TII->mulImm(MF,
MBB,
MBBI,
DL, TargetReg, NumOfVReg, Flag);
674 CFIBuilder.buildDefCFA(TargetReg, -Amount);
683 CFIBuilder.buildDefCFARegister(
SPReg);
706 int64_t FixedOffset =
Offset.getFixed();
707 int64_t ScalableOffset =
Offset.getScalable();
708 unsigned DwarfVLenB =
TRI.getDwarfRegNum(RISCV::VLENB,
true);
713 Comment << (FixedOffset < 0 ?
" - " :
" + ") << std::abs(FixedOffset);
726 Comment << (ScalableOffset < 0 ?
" - " :
" + ") << std::abs(ScalableOffset)
733 assert(
Offset.getScalable() != 0 &&
"Did not need to adjust CFA for RVV");
735 std::string CommentBuffer;
738 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
749 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
759 assert(
Offset.getScalable() != 0 &&
"Did not need to adjust CFA for RVV");
761 std::string CommentBuffer;
769 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
770 DefCfaExpr.
push_back(dwarf::DW_CFA_expression);
783 uint64_t RealStackSize,
bool EmitCFI,
790 bool IsRV64 =
STI.is64Bit();
794 if (!NeedProbe ||
Offset <= ProbeSize) {
801 if (NeedProbe && DynAllocation) {
814 if (
Offset < ProbeSize * 5) {
818 while (CurrentOffset + ProbeSize <=
Offset) {
828 CurrentOffset += ProbeSize;
895 case RISCV::QC_CM_PUSH:
896 case RISCV::QC_CM_PUSHFP:
908 case RISCV::QC_CM_POP:
919 return RISCV::CM_PUSH;
921 return UpdateFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
932 return RISCV::CM_POP;
934 return RISCV::QC_CM_POP;
946 bool PreferAscendingLS =
STI.preferAscendingLoadStore();
968 auto PossiblePush =
MBBI;
975 determineFrameLayout(MF);
1010 unsigned LibCallFrameSize =
1012 RVFI->setLibCallStackSize(LibCallFrameSize);
1014 if (NeedsDwarfCFI) {
1025 uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
1026 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1029 if (RealStackSize == 0 && !MFI.
adjustsStack() && RVVStackSize == 0)
1034 if (
STI.isRegisterReservedByUser(
SPReg))
1036 MF.
getFunction(),
"Stack pointer required, but has been reserved."});
1040 if (FirstSPAdjustAmount) {
1041 StackSize = FirstSPAdjustAmount;
1042 RealStackSize = FirstSPAdjustAmount;
1045 if (RVFI->useQCIInterrupt(MF)) {
1050 if (NeedsDwarfCFI) {
1063 if (RVFI->isPushable(MF) && PossiblePush !=
MBB.end() &&
1064 isPush(PossiblePush->getOpcode())) {
1071 PossiblePush->getOperand(1).setImm(StackAdj);
1072 StackSize -= StackAdj;
1074 if (NeedsDwarfCFI) {
1087 bool DynAllocation =
1091 NeedProbe, ProbeSize, DynAllocation,
1108 if (NeedsDwarfCFI) {
1115 if (RISCV::GPRPairRegClass.
contains(Reg)) {
1116 MCRegister EvenReg = RI->getSubReg(Reg, RISCV::sub_gpr_even);
1117 MCRegister OddReg = RI->getSubReg(Reg, RISCV::sub_gpr_odd);
1128 if (
STI.isRegisterReservedByUser(
FPReg))
1130 MF.
getFunction(),
"Frame pointer required, but has been reserved."});
1136 if (!RVFI->hasImplicitFPUpdates(MF)) {
1149 if (FirstSPAdjustAmount) {
1151 assert(SecondSPAdjustAmount > 0 &&
1152 "SecondSPAdjustAmount should be greater than zero");
1156 NeedProbe, ProbeSize, DynAllocation,
1162 allocateAndProbeStackForRVV(MF,
MBB,
MBBI,
DL, RVVStackSize,
1164 NeedsDwarfCFI && !
hasFP(MF), DynAllocation);
1173 if (NeedsDwarfCFI && !
hasFP(MF)) {
1188 if (RI->hasStackRealignment(MF)) {
1192 if (
isInt<12>(-(
int)MaxAlignment.value())) {
1195 .
addImm(-(
int)MaxAlignment.value())
1198 unsigned ShiftAmount =
Log2(MaxAlignment);
1210 if (NeedProbe && RVVStackSize == 0) {
1213 if (SecondSPAdjustAmount < ProbeSize &&
1214 SecondSPAdjustAmount + MaxAlignment.value() >= ProbeSize) {
1215 bool IsRV64 =
STI.is64Bit();
1242 int64_t CFAOffset)
const {
1259 bool PreferAscendingLS =
STI.preferAscendingLoadStore();
1271 MBBI =
MBB.getLastNonDebugInstr();
1273 DL =
MBBI->getDebugLoc();
1275 MBBI =
MBB.getFirstTerminator();
1288 auto FirstScalarCSRRestoreInsn =
1295 uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1297 uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1299 RVFI->getReservedSpillsSize();
1300 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
1301 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1303 bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
1308 if (!RestoreSPFromFP)
1313 if (NeedsDwarfCFI) {
1316 emitCalleeSavedRVVEpilogCFI(
MBB, FirstScalarCSRRestoreInsn);
1320 if (FirstSPAdjustAmount) {
1323 assert(SecondSPAdjustAmount > 0 &&
1324 "SecondSPAdjustAmount should be greater than zero");
1328 if (!RestoreSPFromFP)
1333 if (NeedsDwarfCFI && !
hasFP(MF))
1347 if (RestoreSPFromFP) {
1348 assert(
hasFP(MF) &&
"frame pointer should not have been eliminated");
1354 if (NeedsDwarfCFI &&
hasFP(MF))
1360 MBBI = std::next(FirstScalarCSRRestoreInsn,
1369 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1370 RVFI->getLibCallStackSize());
1378 if (NeedsDwarfCFI) {
1383 if (RISCV::GPRPairRegClass.
contains(Reg)) {
1384 MCRegister EvenReg = RI->getSubReg(Reg, RISCV::sub_gpr_even);
1385 MCRegister OddReg = RI->getSubReg(Reg, RISCV::sub_gpr_odd);
1394 if (RVFI->isPushable(MF) &&
MBBI !=
MBB.end() &&
isPop(
MBBI->getOpcode())) {
1401 MBBI->getOperand(1).setImm(StackAdj);
1402 StackSize -= StackAdj;
1405 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1406 RealStackSize - StackSize);
1409 if (NextI ==
MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
1411 if (NeedsDwarfCFI) {
1431 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1432 RVFI->getQCIInterruptStackSize());
1446 std::array<TargetRegisterClass const *, 2> RegisterClasses = {
1447 &RISCV::GPRF16RegClass, &RISCV::GPRF32RegClass};
1448 std::array<unsigned, 2> SubIdx = {RISCV::sub_16, RISCV::sub_32};
1450 for (
auto [RegClass, SubReg] :
zip(RegisterClasses, SubIdx)) {
1451 if (RegClass->contains(
Reg)) {
1453 TRI.getMatchingSuperReg(
Reg, SubReg, &RISCV::GPRRegClass))
1459 "getPhysicalGPR called with unsupported register");
1465 if (!STI.hasStdExtF())
1469 assert(LargestFPRegClass);
1474 std::array<TargetRegisterClass const *, 3> RegisterClasses = {
1475 &RISCV::FPR16RegClass, &RISCV::FPR32RegClass, &RISCV::FPR64RegClass};
1476 std::array<unsigned, 3> SubIdx = {RISCV::sub_16, RISCV::sub_32,
1479 for (
auto [RegClass, SubReg] :
zip(RegisterClasses, SubIdx)) {
1480 if (RegClass->contains(
Reg)) {
1482 TRI.getMatchingSuperReg(
Reg, SubReg, LargestFPRegClass))
1492void RISCVFrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
1501 DL =
MBBI->getDebugLoc();
1504 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
1505 const RISCVInstrInfo &
TII = *
STI.getInstrInfo();
1507 BitVector FinalRegsToZero(
TRI.getNumRegs());
1509 bool HasVRegister =
false;
1512 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
1514 }
else if (RISCV::GPRPairRegClass.
contains(
Reg)) {
1515 FinalRegsToZero.set(
1517 FinalRegsToZero.set(
1519 }
else if (
TRI.isFPRegister(
Reg)) {
1521 FinalRegsToZero.set(MaybeReg.id());
1523 TRI.getMinimalPhysRegClass(
Reg))) {
1524 if (!
STI.hasVInstructions())
1526 HasVRegister =
true;
1528 for (MCRegister SubReg :
TRI.subregs_inclusive(
Reg)) {
1529 if (
TRI.subregs(SubReg).empty())
1530 FinalRegsToZero.set(SubReg.id());
1538 VLMUL, 32,
true,
true);
1540 MCRegister TemporaryReg = RISCV::NoRegister;
1541 for (MCRegister
Reg : FinalRegsToZero.set_bits()) {
1542 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
1548 if (TemporaryReg == RISCV::NoRegister) {
1549 RS->enterBasicBlockEnd(
MBB);
1550 TemporaryReg =
RS->scavengeRegisterBackwards(RISCV::GPRRegClass,
MBBI,
1559 FinalRegsToZero.set(TemporaryReg.
id());
1568 for (MCRegister
Reg : FinalRegsToZero.set_bits())
1583 STI.preferAscendingLoadStore());
1591 "Unexpected stack ID for the frame object.");
1603 MinCSFI = std::min(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
1604 MaxCSFI = std::max(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
1607 if (FI >= MinCSFI && FI <= MaxCSFI) {
1610 if (FirstSPAdjustAmount)
1674 int64_t CLWSPMaxOffset = 252;
1675 int64_t CLDSPMaxOffset = 504;
1676 int64_t SPThreshold =
STI.is64Bit() ? CLDSPMaxOffset : CLWSPMaxOffset;
1677 if (SPOff >= 0 && SPOff <= SPThreshold)
1683 "Expected fixed object with stack realignment");
1684 assert(
hasFP(MF) &&
"Re-aligned stack must have frame pointer");
1688 if (FrameReg ==
FPReg) {
1707 "Can't index across variable sized realign");
1712 "Inconsistent stack layout");
1755 "Can't index across variable sized realign");
1757 RVFI->getRVVStackSize());
1764 int64_t ScalarLocalVarSize =
1766 RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding();
1777 if (!BaseReg.isValid())
1797 for (
unsigned i = 0; CSRegs[i]; ++i) {
1798 unsigned CSReg = CSRegs[i];
1803 SavedRegs.
reset(CSReg);
1805 auto SubRegs =
TRI.subregs(CSReg);
1808 SavedRegs.
set(CSReg);
1809 for (
unsigned Reg : SubRegs)
1827 if (RVFI->isPushable(MF) && SavedRegs.
test(RISCV::X26))
1828 SavedRegs.
set(RISCV::X27);
1835 bool UseZilsd = !
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
1837 !RVFI->isPushable(MF) && !RVFI->useSaveRestoreLibCalls(MF);
1841 for (
unsigned i = 0; CSRegs[i]; ++i) {
1843 CSRSet.
insert(CSRegs[i]);
1848 for (
MCPhysReg Pair : RISCV::GPRPairRegClass) {
1852 MCRegister EvenReg =
TRI.getSubReg(Pair, RISCV::sub_gpr_even);
1853 MCRegister OddReg =
TRI.getSubReg(Pair, RISCV::sub_gpr_odd);
1867 for (
unsigned i = 0; CSRegs[i]; ++i) {
1869 bool CombineToSuperReg;
1870 if (RISCV::GPRPairRegClass.
contains(CSReg)) {
1871 MCRegister EvenReg =
TRI.getSubReg(CSReg, RISCV::sub_gpr_even);
1872 MCRegister OddReg =
TRI.getSubReg(CSReg, RISCV::sub_gpr_odd);
1874 SavedRegs.
test(EvenReg.
id()) && SavedRegs.
test(OddReg.
id());
1877 if (
hasFP(MF) && CSReg == RISCV::X8_X9)
1878 CombineToSuperReg =
false;
1880 auto SubRegs =
TRI.subregs(CSReg);
1882 !SubRegs.empty() &&
llvm::all_of(SubRegs, [&](
unsigned Reg) {
1883 return SavedRegs.
test(Reg);
1887 if (CombineToSuperReg)
1888 SavedRegs.
set(CSReg);
1895std::pair<int64_t, Align>
1896RISCVFrameLowering::assignRVVStackObjectOffsets(
MachineFunction &MF)
const {
1900 auto pushRVVObjects = [&](
int FIBegin,
int FIEnd) {
1901 for (
int I = FIBegin, E = FIEnd;
I != E; ++
I) {
1914 if (!RVVCSI.empty())
1915 pushRVVObjects(RVVCSI[0].getFrameIdx(),
1916 RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1);
1920 Align RVVStackAlign(16);
1923 if (!
ST.hasVInstructions()) {
1925 "Can't allocate scalable-vector objects without V instructions");
1926 return std::make_pair(0, RVVStackAlign);
1931 for (
int FI : ObjectsToAllocate) {
1943 RVVStackAlign = std::max(RVVStackAlign, ObjectAlign);
1946 uint64_t StackSize =
Offset;
1956 if (
auto RVVStackAlignVScale = RVVStackAlign.value() / VScale) {
1957 if (
auto AlignmentPadding =
1959 StackSize += AlignmentPadding;
1960 for (
int FI : ObjectsToAllocate)
1965 return std::make_pair(StackSize, RVVStackAlign);
1971 static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2;
1975 static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1;
1979 static constexpr unsigned ScavSlotsADDIScalableObject = 1;
1981 static constexpr unsigned MaxScavSlotsNumKnown =
1982 std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject,
1983 ScavSlotsNumRVVSpillNonScalableObject});
1985 unsigned MaxScavSlotsNum = 0;
1991 for (
auto &MO :
MI.operands()) {
1997 MaxScavSlotsNum = std::max(
1998 MaxScavSlotsNum, IsScalableVectorID
1999 ? ScavSlotsNumRVVSpillScalableObject
2000 : ScavSlotsNumRVVSpillNonScalableObject);
2001 }
else if (
MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) {
2003 std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject);
2006 if (MaxScavSlotsNum == MaxScavSlotsNumKnown)
2007 return MaxScavSlotsNumKnown;
2009 return MaxScavSlotsNum;
2033 unsigned FnSize = 0;
2034 for (
auto &
MBB : MF) {
2035 for (
auto &
MI :
MBB) {
2053 if (
MI.isConditionalBranch())
2054 FnSize +=
TII.getInstSizeInBytes(
MI);
2055 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
2057 FnSize += 2 + 8 + 2 + 2;
2059 FnSize += 4 + 8 + 4 + 4;
2063 FnSize +=
TII.getInstSizeInBytes(
MI);
2078 int64_t RVVStackSize;
2079 Align RVVStackAlign;
2080 std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MF);
2082 RVFI->setRVVStackSize(RVVStackSize);
2083 RVFI->setRVVStackAlign(RVVStackAlign);
2092 unsigned ScavSlotsNum = 0;
2102 if (IsLargeFunction)
2103 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
2110 for (
unsigned I = 0;
I < ScavSlotsNum;
I++) {
2112 RegInfo->getSpillAlign(*RC));
2113 RS->addScavengingFrameIndex(FI);
2115 if (IsLargeFunction && RVFI->getBranchRelaxationScratchFrameIndex() == -1)
2116 RVFI->setBranchRelaxationScratchFrameIndex(FI);
2119 unsigned Size = RVFI->getReservedSpillsSize();
2121 int FrameIdx = Info.getFrameIdx();
2127 RVFI->setCalleeSavedStackSize(
Size);
2151 int64_t Amount =
MI->getOperand(0).getImm();
2157 if (
MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
2167 bool DynAllocation =
2171 true, ProbeSize, DynAllocation,
2173 inlineStackProbe(MF,
MBB);
2182 return MBB.erase(
MI);
2200 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
2206 if (RVFI->getReservedSpillsSize())
2211 if (!
isInt<12>(StackSize) && (CSI.size() > 0)) {
2224 if (
STI.hasStdExtZca()) {
2241 auto CanCompress = [&](
uint64_t CompressLen) ->
bool {
2242 if (StackSize <= 2047 + CompressLen ||
2243 (StackSize > 2048 * 2 - StackAlign &&
2244 StackSize <= 2047 * 2 + CompressLen) ||
2245 StackSize > 2048 * 3 - StackAlign)
2253 const uint64_t ADDI16SPCompressLen = 496;
2254 if (
STI.is64Bit() && CanCompress(ADDI16SPCompressLen))
2255 return ADDI16SPCompressLen;
2256 if (CanCompress(RVCompressLen))
2257 return RVCompressLen;
2259 return 2048 - StackAlign;
2266 std::vector<CalleeSavedInfo> &CSI)
const {
2273 if (RVFI->isSiFivePreemptibleInterrupt(MF)) {
2274 for (
int I = 0;
I < 2; ++
I) {
2275 int FI = RVFI->getInterruptCSRFrameIndex(
I);
2276 MFI.setIsCalleeSavedObjectIndex(FI,
true);
2284 if (RVFI->useQCIInterrupt(MF)) {
2288 if (RVFI->isPushable(MF)) {
2295 unsigned OnlyPushIfMoreThan = RVFI->useQCIInterrupt(MF) ? 2 : 0;
2296 if (PushedRegNum > OnlyPushIfMoreThan) {
2297 RVFI->setRVPushRegs(PushedRegNum);
2298 RVFI->setRVPushStackSize(
alignTo((
STI.getXLen() / 8) * PushedRegNum, 16));
2302 for (
auto &
CS : CSI) {
2305 unsigned Size = RegInfo->getSpillSize(*RC);
2307 if (RVFI->useQCIInterrupt(MF)) {
2309 return P.first ==
CS.getReg();
2312 int64_t
Offset = FFI->second * (int64_t)
Size;
2314 int FrameIdx = MFI.CreateFixedSpillStackObject(
Size,
Offset);
2316 CS.setFrameIdx(FrameIdx);
2321 if (RVFI->useSaveRestoreLibCalls(MF) || RVFI->isPushable(MF)) {
2324 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
2328 if (RVFI->getPushPopKind(MF) ==
2330 Offset = -int64_t(RVFI->getRVPushRegs() - RegNum) *
Size;
2334 if (RVFI->useQCIInterrupt(MF))
2337 int FrameIdx = MFI.CreateFixedSpillStackObject(
Size,
Offset);
2339 CS.setFrameIdx(FrameIdx);
2345 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
2346 RISCV::GPRPairRegClass.contains(Reg)) {
2347 Align PairAlign =
STI.getZilsdAlign();
2348 int FrameIdx = MFI.CreateStackObject(8, PairAlign,
true);
2349 MFI.setIsCalleeSavedObjectIndex(FrameIdx,
true);
2350 CS.setFrameIdx(FrameIdx);
2355 Align Alignment = RegInfo->getSpillAlign(*RC);
2360 int FrameIdx = MFI.CreateStackObject(
Size, Alignment,
true);
2361 MFI.setIsCalleeSavedObjectIndex(FrameIdx,
true);
2362 CS.setFrameIdx(FrameIdx);
2367 if (RVFI->useQCIInterrupt(MF)) {
2370 MFI.CreateFixedSpillStackObject(
2374 if (RVFI->isPushable(MF)) {
2377 if (int64_t PushSize = RVFI->getRVPushStackSize())
2378 MFI.CreateFixedSpillStackObject(PushSize, -PushSize - QCIOffset);
2379 }
else if (
int LibCallRegs =
getLibCallID(MF, CSI) + 1) {
2380 int64_t LibCallFrameSize =
2382 MFI.CreateFixedSpillStackObject(LibCallFrameSize, -LibCallFrameSize);
2397 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
2398 DL =
MI->getDebugLoc();
2407 ? RISCV::QC_C_MIENTER_NEST
2408 : RISCV::QC_C_MIENTER))
2418 if (PushedRegNum > 0) {
2426 PushBuilder.
addImm(RegEnc);
2429 for (
unsigned i = 0; i < PushedRegNum; i++)
2442 for (
auto &
CS : CSI)
2447 const auto &UnmanagedCSI =
2451 auto storeRegsToStackSlots = [&](
decltype(UnmanagedCSI) CSInfo) {
2452 for (
auto &
CS : CSInfo) {
2456 TII.storeRegToStackSlot(
MBB,
MI, Reg, !
MBB.isLiveIn(Reg),
2461 storeRegsToStackSlots(UnmanagedCSI);
2462 storeRegsToStackSlots(RVVCSI);
2468 return RISCV::VRRegClass.contains(BaseReg) ? 1
2469 : RISCV::VRM2RegClass.contains(BaseReg) ? 2
2470 : RISCV::VRM4RegClass.contains(BaseReg) ? 4
2474void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
2478 RISCVMachineFunctionInfo *RVFI = MF->
getInfo<RISCVMachineFunctionInfo>();
2479 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
2487 uint64_t ScalarLocalVarSize =
2490 FixedSize -= ScalarLocalVarSize;
2494 for (
auto &
CS : RVVCSI) {
2496 int FI =
CS.getFrameIdx();
2499 for (
unsigned i = 0; i < NumRegs; ++i) {
2507void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
2511 const RISCVRegisterInfo &
TRI = *
STI.getRegisterInfo();
2515 for (
auto &
CS : RVVCSI) {
2518 for (
unsigned i = 0; i < NumRegs; ++i)
2519 CFIHelper.buildRestore(BaseReg + i);
2532 if (
MI !=
MBB.end() && !
MI->isDebugInstr())
2533 DL =
MI->getDebugLoc();
2541 const auto &UnmanagedCSI =
2545 auto loadRegFromStackSlot = [&](
decltype(UnmanagedCSI) CSInfo) {
2546 for (
auto &
CS : CSInfo) {
2550 RISCV::NoSubRegister,
2553 "loadRegFromStackSlot didn't insert any code!");
2556 loadRegFromStackSlot(RVVCSI);
2557 loadRegFromStackSlot(UnmanagedCSI);
2563 assert(
MI->getOpcode() == RISCV::QC_C_MILEAVERET &&
2564 "Unexpected QCI Interrupt Return Instruction");
2569 if (PushedRegNum > 0) {
2576 PopBuilder.
addImm(RegEnc);
2591 for (
auto &
CS : CSI)
2596 if (
MI !=
MBB.end() &&
MI->getOpcode() == RISCV::PseudoRET) {
2598 MI->eraseFromParent();
2624 if (
STI.preferVsetvliOverReadVLENB() &&
2625 (
MBB.isLiveIn(RISCV::VTYPE) ||
MBB.isLiveIn(RISCV::VL)))
2636 RS.enterBasicBlock(*TmpMBB);
2637 return !RS.isRegUsed(RISCV::X5);
2648 return MBB.succ_empty();
2657 if (
MBB.succ_size() > 1)
2695 assert(TargetReg != RISCV::X2 &&
"New top of stack cannot already be in SP");
2702 bool IsRV64 = Subtarget.is64Bit();
2703 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
2710 MF.
insert(MBBInsertPoint, LoopTestMBB);
2712 MF.
insert(MBBInsertPoint, ExitMBB);
2717 TII->movImm(
MBB,
MBBI,
DL, ScratchReg, ProbeSize, Flags);
2728 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
2763 MBB.addSuccessor(LoopTestMBB);
2773 SmallVector<MachineInstr *, 4> ToReplace;
2774 for (MachineInstr &
MI :
MBB) {
2775 unsigned Opc =
MI.getOpcode();
2776 if (
Opc == RISCV::PROBED_STACKALLOC ||
2777 Opc == RISCV::PROBED_STACKALLOC_RVV) {
2782 for (MachineInstr *
MI : ToReplace) {
2783 if (
MI->getOpcode() == RISCV::PROBED_STACKALLOC ||
2784 MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) {
2787 Register TargetReg =
MI->getOperand(0).getReg();
2789 (
MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV));
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 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 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 void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
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 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 void emitSiFiveCLICStackSwap(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
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.
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 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 the alignment in bytes that this function must be aligned to, which is greater than the defaul...
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
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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 & 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
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 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
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.
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.
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
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.
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 find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
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