26#define DEBUG_TYPE "frame-info"
29 "amdgpu-spill-vgpr-to-agpr",
30 cl::desc(
"Enable spilling VGPRs to AGPRs"),
42 return ST.isWave64() && (
Reg == AMDGPU::VCC_LO ||
Reg == AMDGPU::VCC_HI);
64 OS <<
uint8_t(dwarf::DW_OP_reg0 + DwarfReg);
66 OS <<
uint8_t(dwarf::DW_OP_regx);
72 int64_t DwarfStackPtrReg) {
73 assert(ST.hasFlatScratchEnabled());
81 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
82 assert(WavefrontSizeLog2 < 32);
88 <<
uint8_t(dwarf::DW_OP_lit0 + WavefrontSizeLog2)
91 dwarf::DW_ASPACE_LLVM_AMDGPU_private_wave)
92 <<
uint8_t(dwarf::DW_OP_LLVM_user)
93 <<
uint8_t(dwarf::DW_OP_LLVM_form_aspace_address);
97 OSCFIInst <<
uint8_t(dwarf::DW_CFA_def_cfa_expression);
107 bool AspaceAlreadyDefined,
111 const SIRegisterInfo *
TRI =
ST.getRegisterInfo();
113 int64_t DwarfStackPtrReg =
TRI->getDwarfRegNum(StackPtrReg,
false);
114 MCCFIInstruction CFIInst =
115 ST.hasFlatScratchEnabled()
117 : (AspaceAlreadyDefined
118 ? MCCFIInstruction::createLLVMDefAspaceCfa(
119 nullptr, DwarfStackPtrReg, 0,
120 dwarf::DW_ASPACE_LLVM_AMDGPU_private_wave, SMLoc())
121 : MCCFIInstruction::createDefCfaRegister(nullptr,
135 for (
unsigned i = 0; CSRegs[i]; ++i)
136 LiveUnits.
addReg(CSRegs[i]);
156 bool IncludeScratchCopy =
true) {
162 unsigned Size =
TRI->getSpillSize(RC);
163 Align Alignment =
TRI->getSpillAlign(RC);
171 if (IncludeScratchCopy)
175 int FI = FrameInfo.CreateStackObject(
Size, Alignment,
true,
nullptr,
178 if (
TRI->spillSGPRToVGPR() &&
195 FI = FrameInfo.CreateSpillStackObject(
Size, Alignment);
206 LiveUnits.
addReg(ScratchSGPR);
221 int64_t DwordOff = 0) {
222 unsigned Opc = ST.hasFlatScratchEnabled() ? AMDGPU::SCRATCH_STORE_DWORD_SADDR
223 : AMDGPU::BUFFER_STORE_DWORD_OFFSET;
229 FrameInfo.getObjectAlign(FI));
230 LiveUnits.
addReg(SpillReg);
231 bool IsKill = !
MBB.isLiveIn(SpillReg);
232 TRI.buildSpillLoadStore(
MBB,
I,
DL,
Opc, FI, SpillReg, IsKill, FrameReg,
233 DwordOff, MMO,
nullptr, &LiveUnits);
245 Register FrameReg, int64_t DwordOff = 0) {
246 unsigned Opc = ST.hasFlatScratchEnabled() ? AMDGPU::SCRATCH_LOAD_DWORD_SADDR
247 : AMDGPU::BUFFER_LOAD_DWORD_OFFSET;
253 FrameInfo.getObjectAlign(FI));
254 TRI.buildSpillLoadStore(
MBB,
I,
DL,
Opc, FI, SpillReg,
false, FrameReg,
255 DwordOff, MMO,
nullptr, &LiveUnits);
265 Register TargetLo =
TRI->getSubReg(TargetReg, AMDGPU::sub0);
266 Register TargetHi =
TRI->getSubReg(TargetReg, AMDGPU::sub1);
273 const MCInstrDesc &GetPC64 =
TII->get(AMDGPU::S_GETPC_B64_pseudo);
278 MBB.addLiveIn(GitPtrLo);
287 if (LiveUnits.
empty()) {
323 unsigned EltSize = 4;
324 bool IsFramePtrPrologSpill;
325 bool NeedsFrameMoves;
328 return Reg == AMDGPU::EXEC_LO || Reg == AMDGPU::EXEC;
340 if (IsFramePtrPrologSpill)
341 return FuncInfo->getFrameOffsetReg();
344 if (isExec(SuperReg))
349 void saveToMemory(
const int FI)
const {
352 assert(!MFI.isDeadObjectIndex(FI));
357 MRI, LiveUnits, AMDGPU::VGPR_32RegClass);
362 TFI->buildCFI(MBB, MI, DL,
364 nullptr, MCRI->getDwarfRegNum(Reg,
false),
365 MFI.getObjectOffset(FI) * ST.getWavefrontSize()));
368 for (
unsigned I = 0, DwordOff = 0;
I < NumSubRegs; ++
I) {
371 :
Register(TRI.getSubReg(SuperReg, SplitParts[
I]));
372 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), TmpVGPR)
376 FI, FrameReg, DwordOff);
377 if (NeedsFrameMoves && !CFISuperReg)
381 if (NeedsFrameMoves && CFISuperReg)
382 BuildCFI(CFISuperReg);
385 void saveToVGPRLane(
const int FI)
const {
386 assert(!MFI.isDeadObjectIndex(FI));
390 FuncInfo->getSGPRSpillToPhysicalVGPRLanes(FI);
391 assert(Spill.size() == NumSubRegs);
394 for (
unsigned I = 0;
I < NumSubRegs; ++
I) {
397 :
Register(TRI.getSubReg(SuperReg, SplitParts[
I]));
398 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_S32_TO_VGPR),
403 if (NeedsFrameMoves && !CFISuperReg)
404 TFI->buildCFIForSGPRToVGPRSpill(MBB, MI, DL, SubReg, Spill[
I].VGPR,
407 if (NeedsFrameMoves && CFISuperReg)
408 TFI->buildCFIForSGPRToVGPRSpill(MBB, MI, DL, CFISuperReg, Spill);
411 void copyToScratchSGPR(
Register DstReg)
const {
412 BuildMI(MBB, MI, DL, TII->get(AMDGPU::COPY), DstReg)
415 if (NeedsFrameMoves) {
418 CFISuperReg = SuperReg;
420 assert(NumSubRegs == 1 &&
"Expected a 32-bit SGPR");
421 TFI->buildCFIForSGPRToVCCHalfCopy(MBB, MI, DL, CFISuperReg, DstReg);
423 TFI->buildCFIForSRegToSRegSpill(MBB, MI, DL, CFISuperReg, DstReg);
428 void restoreFromMemory(
const int FI) {
434 MRI, LiveUnits, AMDGPU::VGPR_32RegClass);
438 for (
unsigned I = 0, DwordOff = 0;
I < NumSubRegs; ++
I) {
441 : TRI.getSubReg(SuperReg, SplitParts[
I]);
444 TmpVGPR, FI, FrameReg, DwordOff);
447 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), SubReg)
453 void restoreFromVGPRLane(
const int FI) {
456 FuncInfo->getSGPRSpillToPhysicalVGPRLanes(FI);
457 assert(Spill.size() == NumSubRegs);
459 for (
unsigned I = 0;
I < NumSubRegs; ++
I) {
462 : TRI.getSubReg(SuperReg, SplitParts[
I]);
463 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_RESTORE_S32_FROM_VGPR), SubReg)
469 void copyFromScratchSGPR(
Register SrcReg)
const {
470 BuildMI(MBB, MI, DL, TII->get(AMDGPU::COPY), SuperReg)
483 bool IsFramePtrPrologSpill =
false)
484 : MI(MI), MBB(MBB), MF(*MBB.
getParent()),
485 ST(MF.getSubtarget<
GCNSubtarget>()), MFI(MF.getFrameInfo()),
487 MCRI(MF.
getContext().getRegisterInfo()), TFI(ST.getFrameLowering()),
488 SuperReg(Reg), SI(SI), LiveUnits(LiveUnits), DL(DL), FrameReg(FrameReg),
489 IsFramePtrPrologSpill(IsFramePtrPrologSpill),
490 NeedsFrameMoves(MF.needsFrameMoves()) {
492 SplitParts = TRI.getRegSplitParts(RC, EltSize);
493 NumSubRegs = SplitParts.empty() ? 1 : SplitParts.size();
495 assert(SuperReg != AMDGPU::M0 &&
"m0 should never spill");
499 switch (SI.getKind()) {
501 return saveToMemory(SI.getIndex());
503 return saveToVGPRLane(SI.getIndex());
505 return copyToScratchSGPR(SI.getReg());
510 switch (SI.getKind()) {
512 return restoreFromMemory(SI.getIndex());
514 return restoreFromVGPRLane(SI.getIndex());
516 return copyFromScratchSGPR(SI.getReg());
524void SIFrameLowering::emitEntryFunctionFlatScratchInit(
528 const SIInstrInfo *
TII =
ST.getInstrInfo();
530 const SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
545 if (
ST.isAmdPalOS()) {
547 LiveRegUnits LiveUnits;
553 Register FlatScrInit = AMDGPU::NoRegister;
556 AllSGPR64s = AllSGPR64s.
slice(
557 std::min(
static_cast<unsigned>(AllSGPR64s.
size()), NumPreloaded));
566 assert(FlatScrInit &&
"Failed to find free register for scratch init");
568 FlatScrInitLo =
TRI->getSubReg(FlatScrInit, AMDGPU::sub0);
569 FlatScrInitHi =
TRI->getSubReg(FlatScrInit, AMDGPU::sub1);
576 const MCInstrDesc &LoadDwordX2 =
TII->get(AMDGPU::S_LOAD_DWORDX2_IMM);
584 const GCNSubtarget &Subtarget = MF.
getSubtarget<GCNSubtarget>();
593 const MCInstrDesc &SAndB32 =
TII->get(AMDGPU::S_AND_B32);
601 assert(FlatScratchInitReg);
607 FlatScrInitLo =
TRI->getSubReg(FlatScratchInitReg, AMDGPU::sub0);
608 FlatScrInitHi =
TRI->getSubReg(FlatScratchInitReg, AMDGPU::sub1);
612 if (
ST.flatScratchIsPointer()) {
616 .
addReg(ScratchWaveOffsetReg);
623 using namespace AMDGPU::Hwreg;
626 .
addImm(int16_t(HwregEncoding::encode(ID_FLAT_SCR_LO, 0, 32)));
629 .
addImm(int16_t(HwregEncoding::encode(ID_FLAT_SCR_HI, 0, 32)));
636 .
addReg(ScratchWaveOffsetReg);
656 .
addReg(ScratchWaveOffsetReg);
679Register SIFrameLowering::getEntryFunctionReservedScratchRsrcReg(
683 const SIInstrInfo *
TII =
ST.getInstrInfo();
686 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
696 if (
ST.hasSGPRInitBug() ||
697 ScratchRsrcReg !=
TRI->reservedPrivateSegmentBufferReg(MF))
698 return ScratchRsrcReg;
711 AllSGPR128s = AllSGPR128s.
slice(std::min(
static_cast<unsigned>(AllSGPR128s.
size()), NumPreloaded));
721 (!GITPtrLoReg || !
TRI->isSubRegisterEq(
Reg, GITPtrLoReg))) {
729 return ScratchRsrcReg;
733 return ST.hasFlatScratchEnabled() ? 1 : ST.getWavefrontSize();
738 assert(&MF.
front() == &
MBB &&
"Shrink-wrapping not yet supported");
769 static const char CFAEncodedInstUserOpsArr[] = {
770 dwarf::DW_CFA_def_cfa_expression,
772 static_cast<char>(dwarf::DW_OP_lit0),
773 static_cast<char>(dwarf::DW_OP_lit0 +
774 dwarf::DW_ASPACE_LLVM_AMDGPU_private_wave),
775 static_cast<char>(dwarf::DW_OP_LLVM_user),
776 static_cast<char>(dwarf::DW_OP_LLVM_form_aspace_address)};
778 StringRef(CFAEncodedInstUserOpsArr,
sizeof(CFAEncodedInstUserOpsArr));
782 "CFA is 0 in private_wave aspace"));
786 nullptr,
TRI->getDwarfRegNum(AMDGPU::PC_REG,
false)));
799 if (!ST.hasFlatScratchEnabled())
800 ScratchRsrcReg = getEntryFunctionReservedScratchRsrcReg(MF);
803 if (ScratchRsrcReg) {
805 if (&OtherBB != &
MBB) {
806 OtherBB.addLiveIn(ScratchRsrcReg);
814 if (ST.isAmdHsaOrMesa(
F)) {
815 PreloadedScratchRsrcReg =
817 if (ScratchRsrcReg && PreloadedScratchRsrcReg) {
820 MRI.addLiveIn(PreloadedScratchRsrcReg);
821 MBB.addLiveIn(PreloadedScratchRsrcReg);
831 if (PreloadedScratchWaveOffsetReg &&
832 TRI->isSubRegisterEq(ScratchRsrcReg, PreloadedScratchWaveOffsetReg)) {
835 AllSGPRs = AllSGPRs.
slice(
836 std::min(
static_cast<unsigned>(AllSGPRs.
size()), NumPreloaded));
839 if (!
MRI.isPhysRegUsed(Reg) &&
MRI.isAllocatable(Reg) &&
840 !
TRI->isSubRegisterEq(ScratchRsrcReg, Reg) && GITPtrLoReg != Reg) {
841 ScratchWaveOffsetReg = Reg;
850 if (!ScratchWaveOffsetReg)
852 "could not find temporary scratch offset register in prolog");
854 ScratchWaveOffsetReg = PreloadedScratchWaveOffsetReg;
856 assert(ScratchWaveOffsetReg || !PreloadedScratchWaveOffsetReg);
886 FrameInfo.getMaxAlign());
898 ST.hasInv2PiInlineImm())) {
910 bool NeedsFlatScratchInit =
912 (
MRI.isPhysRegUsed(AMDGPU::FLAT_SCR) || FrameInfo.hasCalls() ||
915 if ((NeedsFlatScratchInit || ScratchRsrcReg) &&
916 PreloadedScratchWaveOffsetReg && !ST.hasArchitectedFlatScratch()) {
917 MRI.addLiveIn(PreloadedScratchWaveOffsetReg);
918 MBB.addLiveIn(PreloadedScratchWaveOffsetReg);
921 if (NeedsFlatScratchInit) {
922 emitEntryFunctionFlatScratchInit(MF,
MBB,
I,
DL, ScratchWaveOffsetReg);
925 if (ScratchRsrcReg) {
926 emitEntryFunctionScratchRsrcRegSetup(MF,
MBB,
I,
DL,
927 PreloadedScratchRsrcReg,
928 ScratchRsrcReg, ScratchWaveOffsetReg);
933void SIFrameLowering::emitEntryFunctionScratchRsrcRegSetup(
944 if (ST.isAmdPalOS()) {
947 Register Rsrc01 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub0_sub1);
948 Register Rsrc03 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub3);
955 const MCInstrDesc &LoadDwordX4 =
TII->get(AMDGPU::S_LOAD_DWORDX4_IMM);
984 }
else if (
ST.isMesaGfxShader(Fn) || !PreloadedScratchRsrcReg) {
986 const MCInstrDesc &SMovB32 =
TII->get(AMDGPU::S_MOV_B32);
988 Register Rsrc2 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub2);
989 Register Rsrc3 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub3);
995 Register Rsrc01 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub0_sub1);
998 const MCInstrDesc &Mov64 =
TII->get(AMDGPU::S_MOV_B64);
1004 const MCInstrDesc &LoadDwordX2 =
TII->get(AMDGPU::S_LOAD_DWORDX2_IMM);
1023 Register Rsrc0 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub0);
1024 Register Rsrc1 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub1);
1042 }
else if (
ST.isAmdHsaOrMesa(Fn)) {
1043 assert(PreloadedScratchRsrcReg);
1045 if (ScratchRsrcReg != PreloadedScratchRsrcReg) {
1060 Register ScratchRsrcSub0 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub0);
1061 Register ScratchRsrcSub1 =
TRI->getSubReg(ScratchRsrcReg, AMDGPU::sub1);
1067 .
addReg(ScratchWaveOffsetReg)
1069 auto Addc =
BuildMI(
MBB,
I,
DL,
TII->get(AMDGPU::S_ADDC_U32), ScratchRsrcSub1)
1102 emitDefCFA(
MBB,
MBBI,
DL, StackPtrReg,
true,
1106 TRI.getReturnAddressReg(MF));
1110 for (
unsigned I = 0; CSRegs[
I]; ++
I) {
1111 IsCalleeSaved.set(CSRegs[
I]);
1115 if (
Reg == AMDGPU::VCC ||
Reg == AMDGPU::VCC_LO ||
Reg == AMDGPU::VCC_HI)
1117 if (IsCalleeSaved.test(
Reg) || !
MRI.isPhysRegModified(
Reg))
1125 unsigned NumArchVGPRs =
ST.hasVGPRMSBs() ? 1024 : 256;
1126 for_each(AMDGPU::VGPR_32RegClass.getRegisters().take_front(NumArchVGPRs),
1130 if (
ST.hasMAIInsts()) {
1131 for_each(AMDGPU::AGPR_32RegClass.getRegisters(), ProcessReg);
1135 for_each(AMDGPU::SGPR_32RegClass.getRegisters(), ProcessReg);
1145 bool EnableInactiveLanes) {
1158 assert(IsProlog &&
"Epilog should look at return, not setup");
1160 TII->getWholeWaveFunctionSetup(MF)->getOperand(0).getReg();
1161 assert(ScratchExecCopy &&
"Couldn't find copy of EXEC");
1164 MRI, LiveUnits, *
TRI.getWaveMaskRegClass());
1167 if (!ScratchExecCopy)
1170 LiveUnits.
addReg(ScratchExecCopy);
1172 const unsigned SaveExecOpc =
1173 ST.isWave32() ? (EnableInactiveLanes ? AMDGPU::S_XOR_SAVEEXEC_B32
1174 : AMDGPU::S_OR_SAVEEXEC_B32)
1175 : (EnableInactiveLanes ? AMDGPU::S_XOR_SAVEEXEC_B64
1176 : AMDGPU::S_OR_SAVEEXEC_B64);
1181 return ScratchExecCopy;
1188 const bool NeedsFrameMoves)
const {
1204 if (!WWMScratchRegs.
empty())
1209 auto StoreWWMRegisters =
1211 for (
const auto &Reg : WWMRegs) {
1213 int FI = Reg.second;
1215 VGPR, FI, FrameReg);
1216 if (NeedsFrameMoves) {
1221 MFI.getObjectOffset(FI) * ST.getWavefrontSize()));
1227 if (!
MRI.isReserved(Reg)) {
1232 StoreWWMRegisters(WWMScratchRegs);
1234 auto EnableAllLanes = [&]() {
1238 if (!WWMCalleeSavedRegs.
empty()) {
1239 if (ScratchExecCopy) {
1248 StoreWWMRegisters(WWMCalleeSavedRegs);
1253 if (!ScratchExecCopy)
1256 else if (WWMCalleeSavedRegs.
empty())
1258 }
else if (ScratchExecCopy) {
1262 LiveUnits.
addReg(ScratchExecCopy);
1272 bool IsFramePtrPrologSpill = Spill.first == FramePtrReg;
1273 Register Reg = IsFramePtrPrologSpill ? FramePtrRegScratchCopy : Spill.first;
1278 LiveUnits, FrameReg, IsFramePtrPrologSpill);
1286 if (!ScratchSGPRs.
empty()) {
1291 MBB.sortUniqueLiveIns();
1293 if (!LiveUnits.
empty()) {
1301 if (
TRI.isCFISavedRegsSpillEnabled())
1309 Register FramePtrRegScratchCopy)
const {
1324 Spill.first == FramePtrReg ? FramePtrRegScratchCopy : Spill.first;
1329 LiveUnits, FrameReg);
1339 auto RestoreWWMRegisters =
1341 for (
const auto &Reg : WWMRegs) {
1343 int FI = Reg.second;
1345 VGPR, FI, FrameReg);
1352 RestoreWWMRegisters(WWMCalleeSavedRegs);
1356 unsigned Opcode = Return.getOpcode();
1358 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN:
1359 Opcode = AMDGPU::SI_RETURN;
1361 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
1362 Opcode = AMDGPU::SI_TCRETURN_GFX;
1367 Register OrigExec = Return.getOperand(0).getReg();
1369 if (!WWMScratchRegs.
empty()) {
1373 RestoreWWMRegisters(WWMScratchRegs);
1380 Return.removeOperand(0);
1381 Return.setDesc(
TII->get(Opcode));
1386 if (!WWMScratchRegs.
empty()) {
1391 RestoreWWMRegisters(WWMScratchRegs);
1392 if (!WWMCalleeSavedRegs.
empty()) {
1393 if (ScratchExecCopy) {
1402 RestoreWWMRegisters(WWMCalleeSavedRegs);
1403 if (ScratchExecCopy) {
1438 int64_t RoundedSize = NumBytes;
1442 bool SavesStackRegs =
1447 if (NeedsFrameMoves)
1450 if (
TRI.hasStackRealignment(MF))
1454 if (!HasFP && !
hasFP(MF)) {
1457 FramePtrRegScratchCopy, NeedsFrameMoves);
1458 }
else if (SavesStackRegs) {
1460 Register SGPRForFPSaveRestoreCopy =
1464 if (SGPRForFPSaveRestoreCopy) {
1471 DL,
TII,
TRI, LiveUnits, FramePtrReg,
1474 LiveUnits.
addReg(SGPRForFPSaveRestoreCopy);
1479 MRI, LiveUnits, AMDGPU::SReg_32_XM0_XEXECRegClass);
1480 if (!FramePtrRegScratchCopy)
1483 LiveUnits.
addReg(FramePtrRegScratchCopy);
1492 RoundedSize += Alignment;
1493 if (LiveUnits.
empty()) {
1508 And->getOperand(3).setIsDead();
1510 }
else if ((HasFP =
hasFP(MF))) {
1519 FramePtrRegScratchCopy, NeedsFrameMoves);
1520 if (FramePtrRegScratchCopy)
1521 LiveUnits.
removeReg(FramePtrRegScratchCopy);
1528 if ((HasBP =
TRI.hasBasePointer(MF))) {
1535 if (NeedsFrameMoves)
1536 emitDefCFA(
MBB,
MBBI,
DL, FramePtrReg,
false,
1540 if (HasFP && RoundedSize != 0) {
1545 Add->getOperand(3).setIsDead();
1550 assert((!HasFP || FPSaved || !SavesStackRegs) &&
1551 "Needed to save FP but didn't save it anywhere");
1556 "Saved FP but didn't need it");
1560 assert((!HasBP || BPSaved || !SavesStackRegs) &&
1561 "Needed to save BP but didn't save it anywhere");
1563 assert((HasBP || !BPSaved) &&
"Saved BP but didn't need it");
1567 TII->getWholeWaveFunctionSetup(MF)->eraseFromParent();
1591 MBBI =
MBB.getLastNonDebugInstr();
1593 DL =
MBBI->getDebugLoc();
1595 MBBI =
MBB.getFirstTerminator();
1606 if (RoundedSize != 0) {
1607 if (
TRI.hasBasePointer(MF)) {
1611 }
else if (
hasFP(MF)) {
1619 Register SGPRForFPSaveRestoreCopy =
1627 if (SGPRForFPSaveRestoreCopy) {
1628 LiveUnits.
addReg(SGPRForFPSaveRestoreCopy);
1631 MRI, LiveUnits, AMDGPU::SReg_32_XM0_XEXECRegClass);
1632 if (!FramePtrRegScratchCopy)
1635 LiveUnits.
addReg(FramePtrRegScratchCopy);
1639 FramePtrRegScratchCopy);
1643 emitDefCFA(
MBB,
MBBI,
DL, StackPtrReg,
false,
1649 Register SrcReg = SGPRForFPSaveRestoreCopy ? SGPRForFPSaveRestoreCopy
1650 : FramePtrRegScratchCopy;
1654 if (SGPRForFPSaveRestoreCopy)
1659 FramePtrRegScratchCopy);
1700 const bool SpillVGPRToAGPR = ST.hasMAIInsts() && FuncInfo->
hasSpilledVGPRs()
1703 if (SpillVGPRToAGPR) {
1708 bool SeenDbgInstr =
false;
1713 if (
MI.isDebugInstr())
1714 SeenDbgInstr =
true;
1716 if (
TII->isVGPRSpill(
MI)) {
1719 unsigned FIOp = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
1720 AMDGPU::OpName::vaddr);
1721 int FI =
MI.getOperand(FIOp).getIndex();
1723 TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)->getReg();
1725 TRI->isAGPR(
MRI, VReg))) {
1727 RS->enterBasicBlockEnd(
MBB);
1728 RS->backward(std::next(
MI.getIterator()));
1729 TRI->eliminateFrameIndex(
MI, 0, FIOp, RS);
1733 }
else if (
TII->isStoreToStackSlot(
MI, FrameIndex) ||
1734 TII->isLoadFromStackSlot(
MI, FrameIndex))
1736 NonVGPRSpillFIs.
set(FrameIndex);
1742 for (
unsigned FI : SpillFIs.
set_bits())
1743 if (!NonVGPRSpillFIs.
test(FI))
1753 MBB.sortUniqueLiveIns();
1755 if (!SpillFIs.
empty() && SeenDbgInstr)
1763 bool HaveSGPRToVMemSpill =
1766 "SGPR spill should have been removed in SILowerSGPRSpills");
1772 assert(RS &&
"RegScavenger required if spilling");
1783 }
else if (HaveSGPRToVMemSpill &&
1799 if (ST.hasMAIInsts() && !ST.hasGFX90AInsts()) {
1806 TRI->findUnusedRegister(
MRI, &AMDGPU::VGPR_32RegClass, MF);
1807 if (UnusedLowVGPR && (
TRI->getHWRegIndex(UnusedLowVGPR) <
1808 TRI->getHWRegIndex(VGPRForAGPRCopy))) {
1814 MRI.reserveReg(UnusedLowVGPR,
TRI);
1821 TRI->findUnusedRegister(
MRI, &AMDGPU::SGPR_64RegClass, MF);
1826 if (LongBranchReservedReg && UnusedLowSGPR) {
1828 MRI.reserveReg(UnusedLowSGPR,
TRI);
1836 bool NeedExecCopyReservedReg)
const {
1847 for (
unsigned I = 0; CSRegs[
I]; ++
I)
1853 if (NeedExecCopyReservedReg ||
1854 (ReservedRegForExecCopy &&
1855 MRI.isPhysRegUsed(ReservedRegForExecCopy,
true))) {
1856 MRI.reserveReg(ReservedRegForExecCopy,
TRI);
1858 if (UnusedScratchReg) {
1862 MRI.replaceRegWith(ReservedRegForExecCopy, UnusedScratchReg);
1863 LiveUnits.
addReg(UnusedScratchReg);
1867 "Re-reserving spill slot for EXEC copy register");
1871 }
else if (ReservedRegForExecCopy) {
1877 if (
TRI->isCFISavedRegsSpillEnabled()) {
1880 "Re-reserving spill slot for EXEC");
1887 if (
F.hasFnAttribute(Attribute::NoReturn) ||
1899 const bool WillHaveFP =
1900 FrameInfo.hasCalls() &&
1903 if (WillHaveFP ||
hasFP(MF)) {
1906 "Re-reserving spill slot for FP");
1910 if (
TRI->hasBasePointer(MF)) {
1913 "Re-reserving spill slot for BP");
1935 bool NeedExecCopyReservedReg =
false;
1942 if (
TII->isWWMRegSpillOpcode(
MI.getOpcode()))
1943 NeedExecCopyReservedReg =
true;
1944 else if (
MI.getOpcode() == AMDGPU::SI_RETURN ||
1945 MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG ||
1946 MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN ||
1948 TII->isChainCallOpcode(
MI.getOpcode()))) {
1951 (
count_if(
MI.operands(), [](
auto Op) { return Op.isReg(); }) ==
1964 if (
TRI->getRegSizeInBits(*RC) != 32)
1969 sort(SortedWWMVGPRs, std::greater<Register>());
1978 assert(!NeedExecCopyReservedReg &&
1979 "Whole wave functions can use the reg mapped for their i1 argument");
1981 unsigned NumArchVGPRs = ST.getAddressableNumArchVGPRs();
1983 AMDGPU::VGPR_32RegClass.getRegisters().take_front(NumArchVGPRs))
1986 MF.
begin()->addLiveIn(Reg);
1988 MF.
begin()->sortUniqueLiveIns();
1996 SavedVGPRs.
reset(
Op.getReg());
2004 TRI->getSpillAlign(*RC));
2013 if (!ST.hasGFX90AInsts())
2021 SavedVGPRs.
reset(Reg.first);
2038 const BitVector AllSavedRegs = SavedRegs;
2047 const bool WillHaveFP =
2051 if (WillHaveFP ||
hasFP(MF))
2061 Register RetAddrReg =
TRI->getReturnAddressReg(MF);
2063 (FrameInfo.hasCalls() ||
MRI.isPhysRegModified(RetAddrReg))) {
2064 SavedRegs.
set(
TRI->getSubReg(RetAddrReg, AMDGPU::sub0));
2065 SavedRegs.
set(
TRI->getSubReg(RetAddrReg, AMDGPU::sub1));
2071 std::vector<CalleeSavedInfo> &CSI) {
2079 return A.getReg() <
B.getReg();
2081 "Callee saved registers not sorted");
2084 return !CSI.isSpilledToReg() &&
2085 TRI->getPhysRegBaseClass(CSI.getReg()) == &AMDGPU::VGPR_32RegClass &&
2089 auto CSEnd = CSI.end();
2090 for (
auto CSIt = CSI.begin(); CSIt != CSEnd; ++CSIt) {
2092 if (!CanUseBlockOps(*CSIt))
2099 CSEnd = std::remove_if(
2101 if (CanUseBlockOps(CSI) && CSI.
getReg() <
Reg + 32) {
2111 TRI->getMatchingSuperReg(
Reg, AMDGPU::sub0, BlockRegClass);
2120 TRI->getMatchingSuperReg(LastBlockStart, AMDGPU::sub0, BlockRegClass);
2121 assert(RegBlock &&
TRI->isSubRegister(RegBlock,
Reg) &&
2122 "Couldn't find super register");
2123 int RegDelta =
Reg - LastBlockStart;
2125 "Bad shift amount");
2136 unsigned BlockSize =
TRI->getSpillSize(*BlockRegClass) - UnusedBits * 4;
2138 MFI.CreateStackObject(
BlockSize,
TRI->getSpillAlign(*BlockRegClass),
2140 MFI.setIsCalleeSavedObjectIndex(FrameIdx,
true);
2142 CSIt->setFrameIdx(FrameIdx);
2143 CSIt->setReg(RegBlock);
2145 CSI.erase(CSEnd, CSI.end());
2150 std::vector<CalleeSavedInfo> &CSI)
const {
2155 bool UseVGPRBlocks = ST.useVGPRBlockOpsForCSR();
2165 std::vector<CalleeSavedInfo> &CSI)
const {
2173 Register BasePtrReg = RI->getBaseRegister();
2174 Register SGPRForFPSaveRestoreCopy =
2176 Register SGPRForBPSaveRestoreCopy =
2178 if (!SGPRForFPSaveRestoreCopy && !SGPRForBPSaveRestoreCopy)
2181 unsigned NumModifiedRegs = 0;
2183 if (SGPRForFPSaveRestoreCopy)
2185 if (SGPRForBPSaveRestoreCopy)
2188 for (
auto &CS : CSI) {
2189 if (CS.getReg() == FramePtrReg.
asMCReg() && SGPRForFPSaveRestoreCopy) {
2190 CS.setDstReg(SGPRForFPSaveRestoreCopy);
2191 if (--NumModifiedRegs)
2193 }
else if (CS.getReg() == BasePtrReg.
asMCReg() &&
2194 SGPRForBPSaveRestoreCopy) {
2195 CS.setDstReg(SGPRForBPSaveRestoreCopy);
2196 if (--NumModifiedRegs)
2210 uint64_t EstStackSize = MFI.estimateStackSize(MF);
2211 uint64_t MaxOffset = EstStackSize - 1;
2220 if (ST.hasFlatScratchEnabled()) {
2225 if (
TII->isLegalMUBUFImmOffset(MaxOffset))
2239 for (
const auto &LI :
MBB.liveins()) {
2241 auto [Unit, UnitLaneMask] = *
MI;
2242 if ((LI.LaneMask & UnitLaneMask).none())
2245 LiveInRoots.
set(*RI);
2257 if (LiveInRoots.
test(*RI))
2264void SIFrameLowering::spillCalleeSavedRegisterWithoutBlockOps(
2298 std::optional<SparseBitVector<>> LiveInRoots;
2299 if (
MBB.getParent()->getRegInfo().tracksLiveness())
2302 if (!ST.useVGPRBlockOpsForCSR()) {
2304 spillCalleeSavedRegisterWithoutBlockOps(
MBB,
MI, CS,
TII,
TRI,
2307 MBB.sortUniqueLiveIns();
2317 if (!BlockRegClass->contains(Reg) ||
2319 spillCalleeSavedRegisterWithoutBlockOps(
MBB,
MI, CS,
TII,
TRI,
2331 FrameInfo.getObjectSize(FrameIndex),
2332 FrameInfo.getObjectAlign(FrameIndex));
2335 TII->get(AMDGPU::SI_BLOCK_SPILL_V1024_CFI_SAVE))
2353 MBB.sortUniqueLiveIns();
2365 if (!ST.useVGPRBlockOpsForCSR())
2374 if (!BlockRegClass->
contains(Reg) ||
2387 MFI.getObjectAlign(FrameIndex));
2390 TII->get(AMDGPU::SI_BLOCK_SPILL_V1024_RESTORE), Reg)
2396 TRI.addImplicitUsesForBlockCSRLoad(MIB, Reg);
2405 MBB.sortUniqueLiveIns();
2413 int64_t Amount =
I->getOperand(0).getImm();
2415 return MBB.erase(
I);
2420 unsigned Opc =
I->getOpcode();
2421 bool IsDestroy =
Opc ==
TII->getCallFrameDestroyOpcode();
2422 uint64_t CalleePopAmount = IsDestroy ?
I->getOperand(1).getImm() : 0;
2436 Add->getOperand(3).setIsDead();
2437 }
else if (CalleePopAmount != 0) {
2441 return MBB.erase(
I);
2495 "only expected to call this for entry points functions");
2530 ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC,
false);
2534 ST.getWavefrontSize());
2541 const int Lane)
const {
2547 assert(DwarfSGPR != -1 && DwarfVGPR != -1);
2548 assert(Lane != -1 &&
"Expected a lane to be present");
2563 if (VGPRSpills.
size() == 1u)
2565 VGPRSpills[0].Lane);
2579 assert(Spill.hasLane() &&
"Expected a lane to be present");
2610 ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC,
false);
2619 int64_t DwarfReg =
TRI.getDwarfRegNum(
Reg,
false);
2620 if (DwarfReg >= 0) {
2621 DwarfRegs.
push_back(
unsigned(DwarfReg));
2627 for (
unsigned I = 0;
I < SplitParts.
size(); ++
I) {
2629 DwarfReg =
TRI.getDwarfRegNum(SubReg,
false);
2634 DwarfRegs.
push_back(
unsigned(DwarfReg));
2649 if (DwarfRegs.
size() == DwarfCopyRegs.
size()) {
2650 for (
unsigned I = 0, E = DwarfRegs.
size();
I < E; ++
I) {
2658 if (DwarfRegs.
size() == 1 && DwarfCopyRegs.
size() == 2) {
2660 nullptr, DwarfRegs[0], DwarfCopyRegs[0],
SGPRBitSize, DwarfCopyRegs[1],
2666 for (
unsigned I = 0, E = DwarfRegs.
size();
I < E; ++
I) {
2681 assert(DwarfSGPR != -1 && DwarfVCC != -1);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains constants used for implementing Dwarf debug support.
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr MCPhysReg FPReg
static constexpr MCPhysReg SPReg
MachineRegisterInfo & MRI
This file declares the machine register scavenger class.
static void buildEpilogRestore(const GCNSubtarget &ST, const SIRegisterInfo &TRI, const SIMachineFunctionInfo &FuncInfo, LiveRegUnits &LiveUnits, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register SpillReg, int FI, Register FrameReg, int64_t DwordOff=0)
static cl::opt< bool > EnableSpillVGPRToAGPR("amdgpu-spill-vgpr-to-agpr", cl::desc("Enable spilling VGPRs to AGPRs"), cl::ReallyHidden, cl::init(true))
static void getVGPRSpillLaneOrTempRegister(MachineFunction &MF, LiveRegUnits &LiveUnits, Register SGPR, const TargetRegisterClass &RC=AMDGPU::SReg_32_XM0_XEXECRegClass, bool IncludeScratchCopy=true)
Query target location for spilling SGPRs IncludeScratchCopy : Also look for free scratch SGPRs.
static void buildGitPtr(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, const SIInstrInfo *TII, Register TargetReg)
static bool allStackObjectsAreDead(const MachineFrameInfo &MFI)
static MCCFIInstruction createScaledCFAInPrivateWave(const GCNSubtarget &ST, int64_t DwarfStackPtrReg)
static void buildPrologSpill(const GCNSubtarget &ST, const SIRegisterInfo &TRI, const SIMachineFunctionInfo &FuncInfo, LiveRegUnits &LiveUnits, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register SpillReg, int FI, Register FrameReg, int64_t DwordOff=0)
static Register buildScratchExecCopy(LiveRegUnits &LiveUnits, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool IsProlog, bool EnableInactiveLanes)
static void encodeDwarfRegisterLocation(int DwarfReg, raw_ostream &OS)
static constexpr unsigned SGPRBitSize
static bool frameTriviallyRequiresSP(const MachineFrameInfo &MFI)
Returns true if the frame will require a reference to the stack pointer.
static void decomposeDwarfRegs(const SIRegisterInfo &TRI, MCRegister Reg, SmallVectorImpl< unsigned > &DwarfRegs)
static SparseBitVector buildLiveInRoots(const MachineBasicBlock &MBB, const SIRegisterInfo &TRI)
Return the set of all root registers of regunits live-in to MBB.
static void initLiveUnits(LiveRegUnits &LiveUnits, const SIRegisterInfo &TRI, const SIMachineFunctionInfo *FuncInfo, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsProlog)
static constexpr unsigned VGPRLaneBitSize
static bool allSGPRSpillsAreDead(const MachineFunction &MF)
static bool isWave64VCCHalf(const GCNSubtarget &ST, MCRegister Reg)
static MCRegister findScratchNonCalleeSaveRegister(MachineRegisterInfo &MRI, LiveRegUnits &LiveUnits, const TargetRegisterClass &RC, bool Unused=false)
static MCRegister findUnusedRegister(MachineRegisterInfo &MRI, const LiveRegUnits &LiveUnits, const TargetRegisterClass &RC)
static constexpr unsigned SGPRByteSize
static void assignSlotsUsingVGPRBlocks(MachineFunction &MF, const GCNSubtarget &ST, std::vector< CalleeSavedInfo > &CSI)
static bool isAnyRootLiveIn(const SparseBitVector<> &LiveInRoots, const SIRegisterInfo &TRI, MCRegister Reg)
Returns true iff any root of Reg is in LiveInRoots (see buildLiveInRoots).
static unsigned getScratchScaleFactor(const GCNSubtarget &ST)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static const int BlockSize
bool isChainFunction() const
bool isEntryFunction() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
BitVector & reset()
Reset all bits in the bitvector.
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords=~0u)
Clear a bit in this vector for every '0' bit in Mask.
BitVector & set()
Set all bits in the bitvector.
bool any() const
Returns true if any bit is set.
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords=~0u)
Clear any bits in this vector that are set in Mask.
iterator_range< const_set_bits_iterator > set_bits() const
bool empty() const
Returns whether there are no bits in this bitvector.
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
bool isSpilledToReg() const
MCRegister getReg() const
MCRegister getDstReg() const
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasImplicitBufferPtr() const
bool hasFlatScratchInit() const
const HexagonRegisterInfo & getRegisterInfo() const
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
void addReg(MCRegister Reg)
Adds register units covered by physical register Reg.
LLVM_ABI void stepBackward(const MachineInstr &MI)
Updates liveness when stepping backwards over the instruction MI.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
void removeReg(MCRegister Reg)
Removes all register units covered by physical register Reg.
bool empty() const
Returns true if the set is empty.
LLVM_ABI void addLiveIns(const MachineBasicBlock &MBB)
Adds registers living into block MBB.
static MCCFIInstruction createLLVMVectorOffset(MCSymbol *L, unsigned Register, unsigned RegisterSizeInBits, unsigned MaskRegister, unsigned MaskRegisterSizeInBits, int64_t Offset, SMLoc Loc={})
.cfi_llvm_vector_offset Previous value of Register is saved at Offset from CFA.
static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_undefined From now on the previous value of Register can't be restored anymore.
static MCCFIInstruction createLLVMVectorRegisters(MCSymbol *L, unsigned Register, ArrayRef< VectorRegisterWithLane > VectorRegisters, SMLoc Loc={})
.cfi_llvm_vector_registers Previous value of Register is saved in lanes of vector registers.
static MCCFIInstruction createLLVMVectorRegisterMask(MCSymbol *L, unsigned Register, unsigned SpillRegister, unsigned SpillRegisterLaneSizeInBits, unsigned MaskRegister, unsigned MaskRegisterSizeInBits, SMLoc Loc={})
.cfi_llvm_vector_register_mask Previous value of Register is saved in SpillRegister,...
static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, unsigned Register2, SMLoc Loc={})
.cfi_register Previous value of Register1 is saved in register Register2.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction createLLVMRegisterPair(MCSymbol *L, unsigned Register, unsigned R1, unsigned R1SizeInBits, unsigned R2, unsigned R2SizeInBits, SMLoc Loc={})
.cfi_llvm_register_pair Previous value of Register is saved in R1:R2.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_same_value Current value of Register is the same as in the previous frame.
const MCRegisterInfo * getRegisterInfo() const
Describe properties that are true of each instruction in the target description file.
bool isValid() const
Returns true if this iterator is not yet at the end.
MCRegUnitMaskIterator enumerates a list of register units and their associated lane masks for Reg.
MCRegUnitRootIterator enumerates the root registers of a register unit.
bool isValid() const
Check if the iterator is at the end of the list.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
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.
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 hasCalls() const
Return true if the current function has any function calls.
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.
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool hasTailCall() const
Returns true if the function contains a tail call.
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
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...
void RemoveStackObject(int ObjectIdx)
Remove or mark dead a statically sized stack object.
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.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
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.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
void setIsDead(bool Val=true)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
bool isAllocatable(MCRegister PhysReg) const
isAllocatable - Returns true when PhysReg belongs to an allocatable register class and it hasn't been...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
void reserveReg(MCRegister PhysReg, const TargetRegisterInfo *TRI)
reserveReg – Mark a register as reserved so checks like isAllocatable will not suggest using it.
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI bool isPhysRegModified(MCRegister PhysReg, bool SkipNoReturnDef=false) const
Return true if the specified register is modified in this function.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
PrologEpilogSGPRSpillBuilder(Register Reg, const PrologEpilogSGPRSaveRestoreInfo SI, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, const SIInstrInfo *TII, const SIRegisterInfo &TRI, LiveRegUnits &LiveUnits, Register FrameReg, bool IsFramePtrPrologSpill=false)
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
void determinePrologEpilogSGPRSaves(MachineFunction &MF, BitVector &SavedRegs, bool NeedExecCopyReservedReg) const
MachineInstr * buildCFIForSGPRToVMEMSpill(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister SGPR, int64_t Offset) const
Create a CFI index describing a spill of a SGPR to VMEM and build a MachineInstr around it.
void buildCFIForSRegToSRegSpill(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister Reg, MCRegister CopyReg) const
void emitCSRSpillRestores(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, LiveRegUnits &LiveUnits, Register FrameReg, Register FramePtrRegScratchCopy) const
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool mayReserveScratchForCWSR(const MachineFunction &MF) const
bool allocateScavengingFrameIndexesNearIncomingSP(const MachineFunction &MF) const override
Control the placement of special register scavenging spill slots when allocating a stack frame.
bool requiresStackPointerReference(const MachineFunction &MF) const
void emitEntryFunctionPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const
MachineInstr * buildCFIForSGPRToVCCHalfCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister SGPR, MCRegister VCCHalf) const
Create a CFI index describing a copy of the 32-bit SGPR to VCCHalf (vcc_lo or vcc_hi) in wave64 and b...
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool hasFPImpl(const MachineFunction &MF) const override
bool assignCalleeSavedSpillSlotsImpl(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const
MachineInstr * buildCFIForVRegToVRegSpill(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCRegister Reg, const MCRegister RegCopy) const
Create a CFI index describing a spill of the VGPR/AGPR Reg to another VGPR/AGPR RegCopy and build a M...
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...
MachineInstr * buildCFIForVGPRToVMEMSpill(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister VGPR, int64_t Offset) const
Create a CFI index describing a spill of a VGPR to VMEM and build a MachineInstr around it.
MachineInstr * buildCFIForSGPRToVGPRSpill(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCRegister SGPR, const MCRegister VGPR, const int Lane) const
Create a CFI index describing a spill of an SGPR to a single lane of a VGPR and build a MachineInstr ...
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
void determineCalleeSavesSGPR(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
MachineInstr * buildCFIForSameValue(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister Reg) const
MachineInstr * buildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCCFIInstruction &CFIInst, MachineInstr::MIFlag flag=MachineInstr::FrameSetup) const
Create a CFI index for CFIInst and build a MachineInstr around it.
void emitCSRSpillStores(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, LiveRegUnits &LiveUnits, Register FrameReg, Register FramePtrRegScratchCopy, const bool NeedsFrameMoves) const
void processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameIndicesReplaced - This method is called immediately before MO_FrameIndex op...
bool isSupportedStackID(TargetStackID::Value ID) const override
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the 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 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...
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
ArrayRef< PrologEpilogSGPRSpill > getPrologEpilogSGPRSpills() const
const WWMSpillsMap & getWWMSpills() const
void getAllScratchSGPRCopyDstRegs(SmallVectorImpl< Register > &Regs) const
ArrayRef< MCPhysReg > getAGPRSpillVGPRs() const
void setSGPRForEXECCopy(Register Reg)
void removePrologEpilogSGPRSpillEntry(Register Reg)
unsigned getNumPreloadedSGPRs() const
void shiftWwmVGPRsToLowestRange(MachineFunction &MF, SmallVectorImpl< Register > &WWMVGPRs, BitVector &SavedVGPRs)
void setMaskForVGPRBlockOps(Register RegisterBlock, uint32_t Mask)
GCNUserSGPRUsageInfo & getUserSGPRInfo()
void allocateWWMSpill(MachineFunction &MF, Register VGPR, uint64_t Size=4, Align Alignment=Align(4))
Register getLongBranchReservedReg() const
unsigned getDynamicVGPRBlockSize() const
bool hasSpilledVGPRs() const
void setVGPRToAGPRSpillDead(int FrameIndex)
bool isWholeWaveFunction() const
Register getStackPtrOffsetReg() const
bool isStackRealigned() const
Register getScratchRSrcReg() const
Returns the physical register reserved for use as the resource descriptor for scratch accesses.
ArrayRef< MCPhysReg > getVGPRSpillAGPRs() const
int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI)
uint32_t getMaskForVGPRBlockOps(Register RegisterBlock) const
bool hasMaskForVGPRBlockOps(Register RegisterBlock) const
bool hasPrologEpilogSGPRSpillEntry(Register Reg) const
Register getGITPtrLoReg(const MachineFunction &MF) const
void setVGPRForAGPRCopy(Register NewVGPRForAGPRCopy)
bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR)
Reserve AGPRs or VGPRs to support spilling for FrameIndex FI.
bool hasNoWWMPoolSGPRSpillFallback() const
void splitWWMSpillRegisters(MachineFunction &MF, SmallVectorImpl< std::pair< Register, int > > &CalleeSavedRegs, SmallVectorImpl< std::pair< Register, int > > &ScratchRegs) const
Register getSGPRForEXECCopy() const
bool isWWMReservedRegister(Register Reg) const
ArrayRef< SIRegisterInfo::SpilledReg > getSGPRSpillToPhysicalVGPRLanes(int FrameIndex) const
Register getVGPRForAGPRCopy() const
bool allocateSGPRSpillToVGPRLane(MachineFunction &MF, int FI, bool SpillToPhysVGPRLane=false, bool IsPrologEpilog=false)
Register getFrameOffsetReg() const
void setLongBranchReservedReg(Register Reg)
void setHasSpilledVGPRs(bool Spill=true)
bool removeDeadFrameIndices(MachineFrameInfo &MFI, bool ResetSGPRSpillStackIDs)
If ResetSGPRSpillStackIDs is true, reset the stack ID from sgpr-spill to the default stack.
void setScratchReservedForDynamicVGPRs(unsigned SizeInBytes)
MCRegister getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const
bool checkIndexInPrologEpilogSGPRSpills(int FI) const
const ReservedRegSet & getWWMReservedRegs() const
Register getImplicitBufferPtrUserSGPR() const
const PrologEpilogSGPRSaveRestoreInfo & getPrologEpilogSGPRSaveRestoreInfo(Register Reg) const
void setIsStackRealigned(bool Realigned=true)
unsigned getGITPtrHigh() const
bool hasSpilledSGPRs() const
void addToPrologEpilogSGPRSpills(Register Reg, PrologEpilogSGPRSaveRestoreInfo SI)
Register getScratchSGPRCopyDstReg(Register Reg) const
void setScratchRSrcReg(Register Reg)
void reserveWWMRegister(Register Reg)
Register getFrameRegister(const MachineFunction &MF) const override
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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.
bool test(unsigned Idx) const
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
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 bool hasReservedCallFrame(const MachineFunction &MF) const
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void restoreCalleeSavedRegister(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const CalleeSavedInfo &CS, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned getVGPRAllocGranule(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset)
Convert ByteOffset to dwords if the subtarget uses dword SMRD immediate offsets.
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ ScalablePredicateVector
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
constexpr RegState getKillRegState(bool B)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
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.
void clearDebugInfoForSpillFIs(MachineFrameInfo &MFI, MachineBasicBlock &MBB, const BitVector &SpillFIs)
Replace frame index operands with null registers in debug value instructions for the specified spill ...
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
@ And
Bitwise or logical AND of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
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...
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
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
@ PRIVATE_SEGMENT_WAVE_BYTE_OFFSET
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.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.