31#define DEBUG_TYPE "riscv-frame"
65 RISCV::X18, RISCV::X19, RISCV::X20,
66 RISCV::X21, RISCV::X22, RISCV::X23,
67 RISCV::X24, RISCV::X25, RISCV::X26,
110 STI.hasStdExtZicfiss();
111 bool HasSWShadowStack =
113 if (!HasHWShadowStack && !HasSWShadowStack)
126 if (HasHWShadowStack) {
133 bool IsRV64 = STI.is64Bit();
134 int64_t SlotSize = STI.getXLen() / 8;
154 char DwarfSCSReg =
TRI->getDwarfRegNum(SCSPReg,
true);
155 assert(DwarfSCSReg < 32 &&
"SCS Register should be < 32 (X3).");
157 char Offset =
static_cast<char>(-SlotSize) & 0x7f;
158 const char CFIInst[] = {
159 dwarf::DW_CFA_val_expression,
162 static_cast<char>(
unsigned(dwarf::DW_OP_breg0 + DwarfSCSReg)),
175 STI.hasStdExtZicfiss();
176 bool HasSWShadowStack =
178 if (!HasHWShadowStack && !HasSWShadowStack)
188 if (HasHWShadowStack) {
195 bool IsRV64 = STI.is64Bit();
196 int64_t SlotSize = STI.getXLen() / 8;
222 if (!RVFI->isSiFiveStackSwapInterrupt(MF))
228 assert(STI.hasVendorXSfmclic() &&
"Stack Swapping Requires XSfmclic");
232 .
addImm(RISCVSysReg::sf_mscratchcsw)
253 for (
int I = 0;
I < 2; ++
I) {
266 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
282 RVFI->getInterruptCSRFrameIndex(0),
283 &RISCV::GPRRegClass, STI.getRegisterInfo(),
286 RVFI->getInterruptCSRFrameIndex(1),
287 &RISCV::GPRRegClass, STI.getRegisterInfo(),
295 .
addImm(RISCVSysReg::mcause)
300 .
addImm(RISCVSysReg::mepc)
307 .
addImm(RISCVSysReg::mstatus)
318 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
329 .
addImm(RISCVSysReg::mstatus)
338 .
addImm(RISCVSysReg::mepc)
343 .
addImm(RISCVSysReg::mcause)
350 RVFI->getInterruptCSRFrameIndex(1),
351 &RISCV::GPRRegClass, STI.getRegisterInfo(),
354 RVFI->getInterruptCSRFrameIndex(0),
355 &RISCV::GPRRegClass, STI.getRegisterInfo(),
364 const std::vector<CalleeSavedInfo> &CSI) {
367 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
374 if (CS.getFrameIdx() < 0)
375 MaxReg = std::max(MaxReg.
id(), CS.getReg().id());
380 switch (MaxReg.
id()) {
384 case RISCV::X27:
return 12;
385 case RISCV::X26:
return 11;
386 case RISCV::X25:
return 10;
387 case RISCV::X24:
return 9;
388 case RISCV::X23:
return 8;
389 case RISCV::X22:
return 7;
390 case RISCV::X21:
return 6;
391 case RISCV::X20:
return 5;
392 case RISCV::X19:
return 4;
393 case RISCV::X18:
return 3;
394 case RISCV::X9:
return 2;
395 case FPReg:
return 1;
396 case RAReg:
return 0;
405 const std::vector<CalleeSavedInfo> &CSI) {
406 static const char *
const SpillLibCalls[] = {
425 return SpillLibCalls[LibCallID];
432 const std::vector<CalleeSavedInfo> &CSI) {
433 static const char *
const RestoreLibCalls[] = {
444 "__riscv_restore_10",
445 "__riscv_restore_11",
452 return RestoreLibCalls[LibCallID];
457 unsigned NumPushPopRegs = 0;
458 for (
auto &CS : CSI) {
462 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
463 NumPushPopRegs = std::max(NumPushPopRegs, RegNum + 1);
466 assert(NumPushPopRegs != 12 &&
"x26 requires x27 to also be pushed");
467 return NumPushPopRegs;
494 TRI->hasStackRealignment(MF);
498void RISCVFrameLowering::determineFrameLayout(
MachineFunction &MF)
const {
506 if (RVFI->useQCIInterrupt(MF))
513 FrameSize =
alignTo(FrameSize, StackAlign);
523 if (RVFI->getRVVStackSize() && (!
hasFP(MF) ||
TRI->hasStackRealignment(MF))) {
524 int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() -
525 RVFI->getVarArgsSaveSize();
526 if (
auto RVVPadding =
528 RVFI->setRVVPadding(RVVPadding);
543 const std::vector<CalleeSavedInfo> &CSI) {
547 for (
auto &CS : CSI) {
548 int FI = CS.getFrameIdx();
553 return NonLibcallCSI;
558 const std::vector<CalleeSavedInfo> &CSI) {
562 for (
auto &CS : CSI) {
563 int FI = CS.getFrameIdx();
573 const std::vector<CalleeSavedInfo> &CSI) {
577 if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
578 return PushOrLibCallsCSI;
580 for (
const auto &CS : CSI) {
581 if (RVFI->useQCIInterrupt(MF)) {
595 return PushOrLibCallsCSI;
600 const std::vector<CalleeSavedInfo> &CSI) {
604 if (!RVFI->useQCIInterrupt(MF))
605 return QCIInterruptCSI;
607 for (
const auto &CS : CSI) {
613 return QCIInterruptCSI;
616void RISCVFrameLowering::allocateAndProbeStackForRVV(
620 assert(Amount != 0 &&
"Did not need to adjust stack pointer for RVV.");
630 TII->mulImm(MF,
MBB,
MBBI,
DL, TargetReg, NumOfVReg, Flag);
635 CFIBuilder.buildDefCFA(TargetReg, -Amount);
644 CFIBuilder.buildDefCFARegister(
SPReg);
665 int FixedOffset,
int ScalableOffset,
667 unsigned DwarfVLenB =
TRI.getDwarfRegNum(RISCV::VLENB,
true);
673 Comment << (FixedOffset < 0 ?
" - " :
" + ") << std::abs(FixedOffset);
686 Comment << (ScalableOffset < 0 ?
" - " :
" + ") << std::abs(ScalableOffset)
694 assert(ScalableOffset != 0 &&
"Did not need to adjust CFA for RVV");
696 std::string CommentBuffer;
699 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
712 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
723 assert(ScalableOffset != 0 &&
"Did not need to adjust CFA for RVV");
725 std::string CommentBuffer;
735 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
736 DefCfaExpr.
push_back(dwarf::DW_CFA_expression);
749 uint64_t RealStackSize,
bool EmitCFI,
760 if (!NeedProbe ||
Offset <= ProbeSize) {
767 if (NeedProbe && DynAllocation) {
780 if (
Offset < ProbeSize * 5) {
782 while (CurrentOffset + ProbeSize <=
Offset) {
792 CurrentOffset += ProbeSize;
859 case RISCV::QC_CM_PUSH:
860 case RISCV::QC_CM_PUSHFP:
872 case RISCV::QC_CM_POP:
883 return RISCV::CM_PUSH;
885 return UpdateFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
896 return RISCV::CM_POP;
898 return RISCV::QC_CM_POP;
931 auto PossiblePush =
MBBI;
938 determineFrameLayout(MF);
972 unsigned LibCallFrameSize =
974 RVFI->setLibCallStackSize(LibCallFrameSize);
987 uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
988 uint64_t RVVStackSize = RVFI->getRVVStackSize();
991 if (RealStackSize == 0 && !MFI.
adjustsStack() && RVVStackSize == 0)
998 MF.
getFunction(),
"Stack pointer required, but has been reserved."});
1002 if (FirstSPAdjustAmount) {
1003 StackSize = FirstSPAdjustAmount;
1004 RealStackSize = FirstSPAdjustAmount;
1007 if (RVFI->useQCIInterrupt(MF)) {
1012 if (NeedsDwarfCFI) {
1025 if (RVFI->isPushable(MF) && PossiblePush !=
MBB.
end() &&
1026 isPush(PossiblePush->getOpcode())) {
1033 PossiblePush->getOperand(1).setImm(StackAdj);
1034 StackSize -= StackAdj;
1036 if (NeedsDwarfCFI) {
1049 bool DynAllocation =
1053 NeedProbe, ProbeSize, DynAllocation,
1079 MF.
getFunction(),
"Frame pointer required, but has been reserved."});
1085 if (!RVFI->hasImplicitFPUpdates(MF)) {
1098 if (FirstSPAdjustAmount) {
1100 assert(SecondSPAdjustAmount > 0 &&
1101 "SecondSPAdjustAmount should be greater than zero");
1105 NeedProbe, ProbeSize, DynAllocation,
1111 allocateAndProbeStackForRVV(MF,
MBB,
MBBI,
DL, RVVStackSize,
1113 NeedsDwarfCFI && !
hasFP(MF), DynAllocation);
1122 if (NeedsDwarfCFI && !
hasFP(MF)) {
1136 if (RI->hasStackRealignment(MF)) {
1140 if (isInt<12>(-(
int)MaxAlignment.
value())) {
1146 unsigned ShiftAmount =
Log2(MaxAlignment);
1158 if (NeedProbe && RVVStackSize == 0) {
1161 if (SecondSPAdjustAmount < ProbeSize &&
1162 SecondSPAdjustAmount + MaxAlignment.
value() >= ProbeSize) {
1190 int64_t CFAOffset)
const {
1220 DL =
MBBI->getDebugLoc();
1235 auto FirstScalarCSRRestoreInsn =
1242 uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1244 uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1246 RVFI->getReservedSpillsSize();
1247 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
1248 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1250 bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
1255 if (!RestoreSPFromFP)
1260 if (NeedsDwarfCFI) {
1263 emitCalleeSavedRVVEpilogCFI(
MBB, FirstScalarCSRRestoreInsn);
1267 if (FirstSPAdjustAmount) {
1270 assert(SecondSPAdjustAmount > 0 &&
1271 "SecondSPAdjustAmount should be greater than zero");
1275 if (!RestoreSPFromFP)
1280 if (NeedsDwarfCFI && !
hasFP(MF))
1294 if (RestoreSPFromFP) {
1295 assert(
hasFP(MF) &&
"frame pointer should not have been eliminated");
1301 if (NeedsDwarfCFI &&
hasFP(MF))
1315 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1316 RVFI->getLibCallStackSize());
1335 MBBI->getOperand(1).setImm(StackAdj);
1336 StackSize -= StackAdj;
1339 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1340 RealStackSize - StackSize);
1343 if (NextI ==
MBB.
end() || NextI->getOpcode() != RISCV::PseudoRET) {
1345 if (NeedsDwarfCFI) {
1365 deallocateStack(MF,
MBB,
MBBI,
DL, StackSize,
1366 RVFI->getQCIInterruptStackSize());
1393 "Unexpected stack ID for the frame object.");
1405 MinCSFI = CSI[0].getFrameIdx();
1406 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
1409 if (FI >= MinCSFI && FI <= MaxCSFI) {
1412 if (FirstSPAdjustAmount)
1463 if (FrameReg ==
FPReg) {
1482 "Can't index across variable sized realign");
1487 "Inconsistent stack layout");
1530 "Can't index across variable sized realign");
1532 RVFI->getRVVStackSize());
1540 RVFI->getCalleeSavedStackSize() -
1541 RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding();
1552 if (BaseReg == RISCV::NoRegister)
1572 for (
unsigned i = 0; CSRegs[i]; ++i) {
1573 unsigned CSReg = CSRegs[i];
1578 SavedRegs.
reset(CSReg);
1580 auto SubRegs =
TRI.subregs(CSReg);
1582 if (!
MRI.def_empty(CSReg) ||
MRI.getUsedPhysRegsMask().test(CSReg)) {
1583 SavedRegs.
set(CSReg);
1584 for (
unsigned Reg : SubRegs)
1589 if (!SubRegs.empty() &&
llvm::all_of(SubRegs, [&](
unsigned Reg) {
1590 return SavedRegs.test(Reg);
1592 SavedRegs.
set(CSReg);
1607 if (RVFI->isPushable(MF) && SavedRegs.
test(RISCV::X26))
1608 SavedRegs.
set(RISCV::X27);
1614std::pair<int64_t, Align>
1615RISCVFrameLowering::assignRVVStackObjectOffsets(
MachineFunction &MF)
const {
1619 auto pushRVVObjects = [&](
int FIBegin,
int FIEnd) {
1620 for (
int I = FIBegin, E = FIEnd;
I != E; ++
I) {
1633 if (!RVVCSI.empty())
1634 pushRVVObjects(RVVCSI[0].getFrameIdx(),
1635 RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1);
1639 Align RVVStackAlign(16);
1642 if (!
ST.hasVInstructions()) {
1644 "Can't allocate scalable-vector objects without V instructions");
1645 return std::make_pair(0, RVVStackAlign);
1650 for (
int FI : ObjectsToAllocate) {
1662 RVVStackAlign = std::max(RVVStackAlign, ObjectAlign);
1675 if (
auto RVVStackAlignVScale = RVVStackAlign.value() / VScale) {
1676 if (
auto AlignmentPadding =
1678 StackSize += AlignmentPadding;
1679 for (
int FI : ObjectsToAllocate)
1684 return std::make_pair(StackSize, RVVStackAlign);
1690 static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2;
1694 static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1;
1698 static constexpr unsigned ScavSlotsADDIScalableObject = 1;
1700 static constexpr unsigned MaxScavSlotsNumKnown =
1701 std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject,
1702 ScavSlotsNumRVVSpillNonScalableObject});
1704 unsigned MaxScavSlotsNum = 0;
1710 for (
auto &MO :
MI.operands()) {
1716 MaxScavSlotsNum = std::max(
1717 MaxScavSlotsNum, IsScalableVectorID
1718 ? ScavSlotsNumRVVSpillScalableObject
1719 : ScavSlotsNumRVVSpillNonScalableObject);
1720 }
else if (
MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) {
1722 std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject);
1725 if (MaxScavSlotsNum == MaxScavSlotsNumKnown)
1726 return MaxScavSlotsNumKnown;
1728 return MaxScavSlotsNum;
1752 unsigned FnSize = 0;
1753 for (
auto &
MBB : MF) {
1754 for (
auto &
MI :
MBB) {
1772 if (
MI.isConditionalBranch())
1773 FnSize +=
TII.getInstSizeInBytes(
MI);
1774 if (
MI.isConditionalBranch() ||
MI.isUnconditionalBranch()) {
1776 FnSize += 2 + 8 + 2 + 2;
1778 FnSize += 4 + 8 + 4 + 4;
1782 FnSize +=
TII.getInstSizeInBytes(
MI);
1797 int64_t RVVStackSize;
1798 Align RVVStackAlign;
1799 std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MF);
1801 RVFI->setRVVStackSize(RVVStackSize);
1802 RVFI->setRVVStackAlign(RVVStackAlign);
1811 unsigned ScavSlotsNum = 0;
1821 if (IsLargeFunction)
1822 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
1829 for (
unsigned I = 0;
I < ScavSlotsNum;
I++) {
1831 RegInfo->getSpillAlign(*RC));
1834 if (IsLargeFunction && RVFI->getBranchRelaxationScratchFrameIndex() == -1)
1835 RVFI->setBranchRelaxationScratchFrameIndex(FI);
1838 unsigned Size = RVFI->getReservedSpillsSize();
1840 int FrameIdx =
Info.getFrameIdx();
1846 RVFI->setCalleeSavedStackSize(
Size);
1870 int64_t Amount =
MI->getOperand(0).getImm();
1876 if (
MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
1886 bool DynAllocation =
1890 true, ProbeSize, DynAllocation,
1924 if (RVFI->getReservedSpillsSize())
1929 if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
1942 if (
STI.hasStdExtZca()) {
1959 auto CanCompress = [&](
uint64_t CompressLen) ->
bool {
1960 if (StackSize <= 2047 + CompressLen ||
1961 (StackSize > 2048 * 2 - StackAlign &&
1962 StackSize <= 2047 * 2 + CompressLen) ||
1963 StackSize > 2048 * 3 - StackAlign)
1971 const uint64_t ADDI16SPCompressLen = 496;
1972 if (
STI.
is64Bit() && CanCompress(ADDI16SPCompressLen))
1973 return ADDI16SPCompressLen;
1974 if (CanCompress(RVCompressLen))
1975 return RVCompressLen;
1977 return 2048 - StackAlign;
1984 std::vector<CalleeSavedInfo> &CSI,
unsigned &MinCSFrameIndex,
1985 unsigned &MaxCSFrameIndex)
const {
1990 if (RVFI->isSiFivePreemptibleInterrupt(MF)) {
1991 for (
int I = 0;
I < 2; ++
I) {
1993 MinCSFrameIndex = std::min<unsigned>(MinCSFrameIndex, FI);
1994 MaxCSFrameIndex = std::max<unsigned>(MaxCSFrameIndex, FI);
2002 if (RVFI->useQCIInterrupt(MF)) {
2006 if (RVFI->isPushable(MF)) {
2013 unsigned OnlyPushIfMoreThan = RVFI->useQCIInterrupt(MF) ? 2 : 0;
2014 if (PushedRegNum > OnlyPushIfMoreThan) {
2015 RVFI->setRVPushRegs(PushedRegNum);
2023 for (
auto &CS : CSI) {
2028 if (RVFI->useQCIInterrupt(MF)) {
2030 return P.first == CS.getReg();
2033 int64_t
Offset = FFI->second * (int64_t)
Size;
2037 CS.setFrameIdx(FrameIdx);
2042 if (RVFI->useSaveRestoreLibCalls(MF) || RVFI->isPushable(MF)) {
2045 unsigned RegNum = std::distance(std::begin(
FixedCSRFIMap), FII);
2049 if (RVFI->getPushPopKind(MF) ==
2051 Offset = -int64_t(RVFI->getRVPushRegs() - RegNum) *
Size;
2055 if (RVFI->useQCIInterrupt(MF))
2060 CS.setFrameIdx(FrameIdx);
2072 if ((
unsigned)FrameIdx < MinCSFrameIndex)
2073 MinCSFrameIndex = FrameIdx;
2074 if ((
unsigned)FrameIdx > MaxCSFrameIndex)
2075 MaxCSFrameIndex = FrameIdx;
2076 CS.setFrameIdx(FrameIdx);
2081 if (RVFI->useQCIInterrupt(MF)) {
2088 if (RVFI->isPushable(MF)) {
2091 if (int64_t PushSize = RVFI->getRVPushStackSize())
2093 }
else if (
int LibCallRegs =
getLibCallID(MF, CSI) + 1) {
2094 int64_t LibCallFrameSize =
2112 DL =
MI->getDebugLoc();
2121 ? RISCV::QC_C_MIENTER_NEST
2122 : RISCV::QC_C_MIENTER))
2132 if (PushedRegNum > 0) {
2140 PushBuilder.
addImm(RegEnc);
2143 for (
unsigned i = 0; i < PushedRegNum; i++)
2153 for (
auto &CS : CSI)
2161 auto storeRegsToStackSlots = [&](
decltype(UnmanagedCSI) CSInfo) {
2162 for (
auto &CS : CSInfo) {
2171 storeRegsToStackSlots(UnmanagedCSI);
2172 storeRegsToStackSlots(RVVCSI);
2178 return RISCV::VRRegClass.contains(BaseReg) ? 1
2179 : RISCV::VRM2RegClass.contains(BaseReg) ? 2
2180 : RISCV::VRM4RegClass.contains(BaseReg) ? 4
2184void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
2200 FixedSize -= ScalarLocalVarSize;
2204 for (
auto &CS : RVVCSI) {
2206 int FI = CS.getFrameIdx();
2209 for (
unsigned i = 0; i < NumRegs; ++i) {
2216void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
2224 for (
auto &CS : RVVCSI) {
2227 for (
unsigned i = 0; i < NumRegs; ++i)
2228 CFIHelper.buildRestore(BaseReg + i);
2242 DL =
MI->getDebugLoc();
2253 auto loadRegFromStackSlot = [&](
decltype(UnmanagedCSI) CSInfo) {
2254 for (
auto &CS : CSInfo) {
2260 "loadRegFromStackSlot didn't insert any code!");
2263 loadRegFromStackSlot(RVVCSI);
2264 loadRegFromStackSlot(UnmanagedCSI);
2270 assert(
MI->getOpcode() == RISCV::QC_C_MILEAVERET &&
2271 "Unexpected QCI Interrupt Return Instruction");
2276 if (PushedRegNum > 0) {
2283 PopBuilder.
addImm(RegEnc);
2291 if (RestoreLibCall) {
2300 if (
MI !=
MBB.
end() &&
MI->getOpcode() == RISCV::PseudoRET) {
2301 NewMI->copyImplicitOps(*MF, *
MI);
2302 MI->eraseFromParent();
2329 if (
STI.preferVsetvliOverReadVLENB() &&
2399 assert(TargetReg != RISCV::X2 &&
"New top of stack cannot already be in SP");
2406 bool IsRV64 = Subtarget.is64Bit();
2407 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
2414 MF.
insert(MBBInsertPoint, LoopTestMBB);
2416 MF.
insert(MBBInsertPoint, ExitMBB);
2421 TII->movImm(
MBB,
MBBI,
DL, ScratchReg, ProbeSize, Flags);
2432 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
2479 unsigned Opc =
MI.getOpcode();
2480 if (
Opc == RISCV::PROBED_STACKALLOC ||
2481 Opc == RISCV::PROBED_STACKALLOC_RVV) {
2487 if (
MI->getOpcode() == RISCV::PROBED_STACKALLOC ||
2488 MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) {
2491 Register TargetReg =
MI->getOperand(0).getReg();
2493 (
MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV));
unsigned const MachineRegisterInfo * MRI
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
Analysis containing CSE Info
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII, const MachineFunction &MF)
Register const TargetRegisterInfo * TRI
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 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 void appendScalableVectorExpression(const TargetRegisterInfo &TRI, SmallVectorImpl< char > &Expr, int FixedOffset, int ScalableOffset, llvm::raw_string_ostream &Comment)
static bool isPop(unsigned Opcode)
static unsigned getCalleeSavedRVVNumRegs(const Register &BaseReg)
static void emitStackProbeInline(MachineBasicBlock::iterator MBBI, DebugLoc DL, Register TargetReg, bool IsRVV)
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 void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static const MCPhysReg FixedCSRFIMap[]
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static SmallVector< CalleeSavedInfo, 8 > getUnmanagedCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static void emitSiFiveCLICStackSwap(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
static unsigned getNumPushPopRegs(const std::vector< CalleeSavedInfo > &CSI)
static unsigned getScavSlotsNumForRVV(MachineFunction &MF)
static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI, Register Reg, uint64_t FixedOffset, uint64_t ScalableOffset)
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
bool test(unsigned Idx) 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.
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.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Load the specified register of the given register class from the specified stack frame index.
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.
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...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
succ_iterator succ_begin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
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 iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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 '...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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 int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
void setStackID(int ObjectIdx, uint8_t ID)
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
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
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.
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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 & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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.
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 assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI, unsigned &MinCSFrameIndex, unsigned &MaxCSFrameIndex) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
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,...
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.
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
int getInterruptCSRFrameIndex(size_t Idx) const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
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
bool isRegUsed(Register Reg, bool includeReserved=true) const
Return if a specific register is currently used.
void enterBasicBlock(MachineBasicBlock &MBB)
Start tracking liveness from the begin of basic block MBB.
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
Represents a location in source code.
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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)
StringRef - Represent a constant reference to a string, i.e.
Information about stack frame layout on the target.
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...
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...
const TargetRegisterClass * getMinimalPhysRegClass(MCRegister Reg, MVT VT=MVT::Other) const
Returns the Register Class of a physical register of the given type, picking the most sub register cl...
Align getSpillAlign(const TargetRegisterClass &RC) const
Return the minimum required alignment in bytes for a spill slot for a register of this class.
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
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.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
static unsigned encodeRegListNumRegs(unsigned NumRegs)
static constexpr unsigned RVVBitsPerBlock
bool isRVVSpill(const MachineInstr &MI)
static constexpr unsigned RVVBytesPerBlock
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
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.
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 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.
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.
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...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
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.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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