27#define DEBUG_TYPE "amdgpu-si-register-info"
31#define GET_REGINFO_TARGET_DESC
32#include "AMDGPUGenRegisterInfo.inc"
35 "amdgpu-spill-sgpr-to-vgpr",
36 cl::desc(
"Enable spilling SGPRs to VGPRs"),
41 "amdgpu-spill-cfi-saved-regs",
42 cl::desc(
"Enable spilling the registers required for CFI emission"),
47 cl::desc(
"Limit VGPRs to N registers by reserving the rest"));
51 cl::desc(
"Limit AGPRs to N registers by reserving the rest"));
55 cl::desc(
"Limit SGPRs to N registers by reserving the rest"));
57std::array<std::vector<int16_t>, 32> SIRegisterInfo::RegSplitParts;
58std::array<std::array<uint16_t, 32>, 9> SIRegisterInfo::SubRegFromChannelTable;
65 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 9};
68 const Twine &ErrMsg) {
141 MI->getOperand(0).isKill(),
Index,
RS) {}
156 MovOpc = AMDGPU::S_MOV_B32;
157 NotOpc = AMDGPU::S_NOT_B32;
160 MovOpc = AMDGPU::S_MOV_B64;
161 NotOpc = AMDGPU::S_NOT_B64;
166 SuperReg != AMDGPU::EXEC &&
"exec should never spill");
197 assert(
RS &&
"Cannot spill SGPR to memory without RegScavenger");
198 TmpVGPR =
RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
false,
226 IsWave32 ? AMDGPU::SGPR_32RegClass : AMDGPU::SGPR_64RegClass;
246 if (
RS->isRegUsed(AMDGPU::SCC))
248 "unhandled SGPR spill to memory");
258 I->getOperand(2).setIsDead();
293 I->getOperand(2).setIsDead();
322 if (
RS->isRegUsed(AMDGPU::SCC))
324 "unhandled SGPR spill to memory");
349 ST.getAMDGPUDwarfFlavour(),
354 assert(getSubRegIndexLaneMask(AMDGPU::sub0).getAsInteger() == 3 &&
355 getSubRegIndexLaneMask(AMDGPU::sub31).getAsInteger() == (3ULL << 62) &&
356 (getSubRegIndexLaneMask(AMDGPU::lo16) |
357 getSubRegIndexLaneMask(AMDGPU::hi16)).getAsInteger() ==
358 getSubRegIndexLaneMask(AMDGPU::sub0).getAsInteger() &&
359 "getNumCoveredRegs() will not work with generated subreg masks!");
361 RegPressureIgnoredUnits.resize(getNumRegUnits());
362 RegPressureIgnoredUnits.set(
364 for (
auto Reg : AMDGPU::VGPR_16RegClass) {
366 RegPressureIgnoredUnits.set(
367 static_cast<unsigned>(*regunits(Reg).begin()));
373 static auto InitializeRegSplitPartsOnce = [
this]() {
374 for (
unsigned Idx = 1, E = getNumSubRegIndices() - 1; Idx < E; ++Idx) {
375 unsigned Size = getSubRegIdxSize(Idx);
378 std::vector<int16_t> &Vec = RegSplitParts[
Size / 16 - 1];
379 unsigned Pos = getSubRegIdxOffset(Idx);
384 unsigned MaxNumParts = 1024 /
Size;
385 Vec.resize(MaxNumParts);
393 static auto InitializeSubRegFromChannelTableOnce = [
this]() {
394 for (
auto &Row : SubRegFromChannelTable)
395 Row.fill(AMDGPU::NoSubRegister);
396 for (
unsigned Idx = 1; Idx < getNumSubRegIndices(); ++Idx) {
397 unsigned Width = getSubRegIdxSize(Idx) / 32;
398 unsigned Offset = getSubRegIdxOffset(Idx) / 32;
403 unsigned TableIdx = Width - 1;
404 assert(TableIdx < SubRegFromChannelTable.size());
406 SubRegFromChannelTable[TableIdx][
Offset] = Idx;
410 llvm::call_once(InitializeRegSplitPartsFlag, InitializeRegSplitPartsOnce);
412 InitializeSubRegFromChannelTableOnce);
429 return ST.hasGFX90AInsts() ? CSR_AMDGPU_GFX90AInsts_SaveList
430 : CSR_AMDGPU_SaveList;
433 return ST.hasGFX90AInsts() ? CSR_AMDGPU_SI_Gfx_GFX90AInsts_SaveList
434 : CSR_AMDGPU_SI_Gfx_SaveList;
436 return CSR_AMDGPU_CS_ChainPreserve_SaveList;
439 static const MCPhysReg NoCalleeSavedReg = AMDGPU::NoRegister;
440 return &NoCalleeSavedReg;
456 return ST.hasGFX90AInsts() ? CSR_AMDGPU_GFX90AInsts_RegMask
457 : CSR_AMDGPU_RegMask;
460 return ST.hasGFX90AInsts() ? CSR_AMDGPU_SI_Gfx_GFX90AInsts_RegMask
461 : CSR_AMDGPU_SI_Gfx_RegMask;
466 return AMDGPU_AllVGPRs_RegMask;
473 return CSR_AMDGPU_NoRegs_RegMask;
477 return VGPR >= AMDGPU::VGPR0 && VGPR < AMDGPU::VGPR8;
488 if (RC == &AMDGPU::VGPR_32RegClass || RC == &AMDGPU::AGPR_32RegClass)
489 return &AMDGPU::AV_32RegClass;
490 if (RC == &AMDGPU::VReg_64RegClass || RC == &AMDGPU::AReg_64RegClass)
491 return &AMDGPU::AV_64RegClass;
492 if (RC == &AMDGPU::VReg_64_Align2RegClass ||
493 RC == &AMDGPU::AReg_64_Align2RegClass)
494 return &AMDGPU::AV_64_Align2RegClass;
495 if (RC == &AMDGPU::VReg_96RegClass || RC == &AMDGPU::AReg_96RegClass)
496 return &AMDGPU::AV_96RegClass;
497 if (RC == &AMDGPU::VReg_96_Align2RegClass ||
498 RC == &AMDGPU::AReg_96_Align2RegClass)
499 return &AMDGPU::AV_96_Align2RegClass;
500 if (RC == &AMDGPU::VReg_128RegClass || RC == &AMDGPU::AReg_128RegClass)
501 return &AMDGPU::AV_128RegClass;
502 if (RC == &AMDGPU::VReg_128_Align2RegClass ||
503 RC == &AMDGPU::AReg_128_Align2RegClass)
504 return &AMDGPU::AV_128_Align2RegClass;
505 if (RC == &AMDGPU::VReg_160RegClass || RC == &AMDGPU::AReg_160RegClass)
506 return &AMDGPU::AV_160RegClass;
507 if (RC == &AMDGPU::VReg_160_Align2RegClass ||
508 RC == &AMDGPU::AReg_160_Align2RegClass)
509 return &AMDGPU::AV_160_Align2RegClass;
510 if (RC == &AMDGPU::VReg_192RegClass || RC == &AMDGPU::AReg_192RegClass)
511 return &AMDGPU::AV_192RegClass;
512 if (RC == &AMDGPU::VReg_192_Align2RegClass ||
513 RC == &AMDGPU::AReg_192_Align2RegClass)
514 return &AMDGPU::AV_192_Align2RegClass;
515 if (RC == &AMDGPU::VReg_256RegClass || RC == &AMDGPU::AReg_256RegClass)
516 return &AMDGPU::AV_256RegClass;
517 if (RC == &AMDGPU::VReg_256_Align2RegClass ||
518 RC == &AMDGPU::AReg_256_Align2RegClass)
519 return &AMDGPU::AV_256_Align2RegClass;
520 if (RC == &AMDGPU::VReg_512RegClass || RC == &AMDGPU::AReg_512RegClass)
521 return &AMDGPU::AV_512RegClass;
522 if (RC == &AMDGPU::VReg_512_Align2RegClass ||
523 RC == &AMDGPU::AReg_512_Align2RegClass)
524 return &AMDGPU::AV_512_Align2RegClass;
525 if (RC == &AMDGPU::VReg_1024RegClass || RC == &AMDGPU::AReg_1024RegClass)
526 return &AMDGPU::AV_1024RegClass;
527 if (RC == &AMDGPU::VReg_1024_Align2RegClass ||
528 RC == &AMDGPU::AReg_1024_Align2RegClass)
529 return &AMDGPU::AV_1024_Align2RegClass;
559 return AMDGPU_AllVGPRs_RegMask;
563 return AMDGPU_AllAGPRs_RegMask;
567 return AMDGPU_AllVectorRegs_RegMask;
574 assert(NumRegIndex &&
"Not implemented");
575 assert(Channel < SubRegFromChannelTable[NumRegIndex - 1].
size());
576 return SubRegFromChannelTable[NumRegIndex - 1][Channel];
585 const unsigned Align,
588 MCRegister BaseReg(AMDGPU::SGPR_32RegClass.getRegister(BaseIdx));
589 return getMatchingSuperReg(BaseReg, AMDGPU::sub0, RC);
607 reserveRegisterTuples(
Reserved, AMDGPU::EXEC);
608 reserveRegisterTuples(
Reserved, AMDGPU::FLAT_SCR);
611 reserveRegisterTuples(
Reserved, AMDGPU::M0);
614 reserveRegisterTuples(
Reserved, AMDGPU::SRC_VCCZ);
615 reserveRegisterTuples(
Reserved, AMDGPU::SRC_EXECZ);
616 reserveRegisterTuples(
Reserved, AMDGPU::SRC_SCC);
619 reserveRegisterTuples(
Reserved, AMDGPU::SRC_SHARED_BASE);
620 reserveRegisterTuples(
Reserved, AMDGPU::SRC_SHARED_LIMIT);
621 reserveRegisterTuples(
Reserved, AMDGPU::SRC_PRIVATE_BASE);
622 reserveRegisterTuples(
Reserved, AMDGPU::SRC_PRIVATE_LIMIT);
623 reserveRegisterTuples(
Reserved, AMDGPU::SRC_FLAT_SCRATCH_BASE_LO);
624 reserveRegisterTuples(
Reserved, AMDGPU::SRC_FLAT_SCRATCH_BASE_HI);
627 reserveRegisterTuples(
Reserved, AMDGPU::ASYNCcnt);
628 reserveRegisterTuples(
Reserved, AMDGPU::TENSORcnt);
631 reserveRegisterTuples(
Reserved, AMDGPU::SRC_POPS_EXITING_WAVE_ID);
634 reserveRegisterTuples(
Reserved, AMDGPU::XNACK_MASK);
637 reserveRegisterTuples(
Reserved, AMDGPU::LDS_DIRECT);
640 reserveRegisterTuples(
Reserved, AMDGPU::TBA);
641 reserveRegisterTuples(
Reserved, AMDGPU::TMA);
642 reserveRegisterTuples(
Reserved, AMDGPU::TTMP0_TTMP1);
643 reserveRegisterTuples(
Reserved, AMDGPU::TTMP2_TTMP3);
644 reserveRegisterTuples(
Reserved, AMDGPU::TTMP4_TTMP5);
645 reserveRegisterTuples(
Reserved, AMDGPU::TTMP6_TTMP7);
646 reserveRegisterTuples(
Reserved, AMDGPU::TTMP8_TTMP9);
647 reserveRegisterTuples(
Reserved, AMDGPU::TTMP10_TTMP11);
648 reserveRegisterTuples(
Reserved, AMDGPU::TTMP12_TTMP13);
649 reserveRegisterTuples(
Reserved, AMDGPU::TTMP14_TTMP15);
652 reserveRegisterTuples(
Reserved, AMDGPU::SGPR_NULL64);
656 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
659 unsigned TotalNumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
662 unsigned NumRegs =
divideCeil(getRegSizeInBits(RC), 32);
665 if (Index + NumRegs > MaxNumSGPRs && Index < TotalNumSGPRs &&
666 Reg != AMDGPU::VCC_LO && Reg != AMDGPU::VCC_HI &&
674 if (ScratchRSrcReg != AMDGPU::NoRegister) {
678 reserveRegisterTuples(
Reserved, ScratchRSrcReg);
682 if (LongBranchReservedReg)
683 reserveRegisterTuples(
Reserved, LongBranchReservedReg);
690 reserveRegisterTuples(
Reserved, StackPtrReg);
691 assert(!isSubRegister(ScratchRSrcReg, StackPtrReg));
696 reserveRegisterTuples(
Reserved, FrameReg);
697 assert(!isSubRegister(ScratchRSrcReg, FrameReg));
702 reserveRegisterTuples(
Reserved, BasePtrReg);
703 assert(!isSubRegister(ScratchRSrcReg, BasePtrReg));
710 reserveRegisterTuples(
Reserved, ExecCopyReg);
714 auto [MaxNumVGPRs, MaxNumAGPRs] = ST.getMaxNumVectorRegs(MF.
getFunction());
724 unsigned NumRegs =
divideCeil(getRegSizeInBits(RC), 32);
727 if (Index + NumRegs > MaxNumVGPRs)
734 if (!ST.hasMAIInsts())
738 unsigned NumRegs =
divideCeil(getRegSizeInBits(RC), 32);
741 if (Index + NumRegs > MaxNumAGPRs)
749 if (ST.hasMAIInsts() && !ST.hasGFX90AInsts()) {
757 if (!PerLaneVGPRMask.
empty()) {
758 for (
unsigned RegI = AMDGPU::VGPR0, RegE = AMDGPU::VGPR0 + MaxNumVGPRs;
759 RegI < RegE; ++RegI) {
760 if (PerLaneVGPRMask.
test(RegI))
761 reserveRegisterTuples(
Reserved, RegI);
766 reserveRegisterTuples(
Reserved, Reg);
770 reserveRegisterTuples(
Reserved, Reg);
773 reserveRegisterTuples(
Reserved, Reg);
790 if (Info->isBottomOfStack())
798 if (Info->isEntryFunction()) {
831 int OffIdx = AMDGPU::getNamedOperandIdx(
MI->getOpcode(),
832 AMDGPU::OpName::offset);
833 return MI->getOperand(OffIdx).getImm();
838 switch (
MI->getOpcode()) {
839 case AMDGPU::V_ADD_U32_e32:
840 case AMDGPU::V_ADD_U32_e64:
841 case AMDGPU::V_ADD_CO_U32_e32: {
842 int OtherIdx = Idx == 1 ? 2 : 1;
846 case AMDGPU::V_ADD_CO_U32_e64: {
847 int OtherIdx = Idx == 2 ? 3 : 2;
858 assert((Idx == AMDGPU::getNamedOperandIdx(
MI->getOpcode(),
859 AMDGPU::OpName::vaddr) ||
860 (Idx == AMDGPU::getNamedOperandIdx(
MI->getOpcode(),
861 AMDGPU::OpName::saddr))) &&
862 "Should never see frame index on non-address operand");
874 return Src1.isImm() || (Src1.isReg() &&
TRI.isVGPR(
MI.getMF()->getRegInfo(),
879 return Src0.isImm() || (Src0.isReg() &&
TRI.isVGPR(
MI.getMF()->getRegInfo(),
888 switch (
MI->getOpcode()) {
889 case AMDGPU::V_ADD_U32_e32: {
892 if (ST.getConstantBusLimit(AMDGPU::V_ADD_U32_e32) < 2 &&
897 case AMDGPU::V_ADD_U32_e64:
907 return !ST.hasFlatScratchEnabled();
908 case AMDGPU::V_ADD_CO_U32_e32:
909 if (ST.getConstantBusLimit(AMDGPU::V_ADD_CO_U32_e32) < 2 &&
914 return MI->getOperand(3).isDead();
915 case AMDGPU::V_ADD_CO_U32_e64:
917 return MI->getOperand(1).isDead();
929 return !
TII->isLegalMUBUFImmOffset(FullOffset);
941 if (Ins !=
MBB->end())
942 DL = Ins->getDebugLoc();
948 ST.hasFlatScratchEnabled() ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
951 ST.hasFlatScratchEnabled() ? &AMDGPU::SReg_32_XEXEC_HIRegClass
952 : &AMDGPU::VGPR_32RegClass);
960 Register OffsetReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
962 Register FIReg =
MRI.createVirtualRegister(ST.hasFlatScratchEnabled()
963 ? &AMDGPU::SReg_32_XM0RegClass
964 : &AMDGPU::VGPR_32RegClass);
971 if (ST.hasFlatScratchEnabled()) {
980 TII->getAddNoCarry(*
MBB, Ins,
DL, BaseReg)
992 switch (
MI.getOpcode()) {
993 case AMDGPU::V_ADD_U32_e32:
994 case AMDGPU::V_ADD_CO_U32_e32: {
1000 if (!ImmOp->
isImm()) {
1003 TII->legalizeOperandsVOP2(
MI.getMF()->getRegInfo(),
MI);
1008 if (TotalOffset == 0) {
1009 MI.setDesc(
TII->get(AMDGPU::COPY));
1010 for (
unsigned I =
MI.getNumOperands() - 1;
I != 1; --
I)
1011 MI.removeOperand(
I);
1013 MI.getOperand(1).ChangeToRegister(BaseReg,
false);
1017 ImmOp->
setImm(TotalOffset);
1029 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1032 MI.getOperand(2).ChangeToRegister(BaseRegVGPR,
false);
1034 MI.getOperand(2).ChangeToRegister(BaseReg,
false);
1038 case AMDGPU::V_ADD_U32_e64:
1039 case AMDGPU::V_ADD_CO_U32_e64: {
1040 int Src0Idx =
MI.getNumExplicitDefs();
1046 if (!ImmOp->
isImm()) {
1048 TII->legalizeOperandsVOP3(
MI.getMF()->getRegInfo(),
MI);
1053 if (TotalOffset == 0) {
1054 MI.setDesc(
TII->get(AMDGPU::COPY));
1056 for (
unsigned I =
MI.getNumOperands() - 1;
I != 1; --
I)
1057 MI.removeOperand(
I);
1059 MI.getOperand(1).ChangeToRegister(BaseReg,
false);
1062 ImmOp->
setImm(TotalOffset);
1071 bool IsFlat =
TII->isFLATScratch(
MI);
1075 bool SeenFI =
false;
1087 TII->getNamedOperand(
MI, IsFlat ? AMDGPU::OpName::saddr
1088 : AMDGPU::OpName::vaddr);
1093 assert(FIOp && FIOp->
isFI() &&
"frame index must be address operand");
1099 "offset should be legal");
1110 assert(
TII->isLegalMUBUFImmOffset(NewOffset) &&
"offset should be legal");
1120 switch (
MI->getOpcode()) {
1121 case AMDGPU::V_ADD_U32_e32:
1122 case AMDGPU::V_ADD_CO_U32_e32:
1124 case AMDGPU::V_ADD_U32_e64:
1125 case AMDGPU::V_ADD_CO_U32_e64:
1138 return TII->isLegalMUBUFImmOffset(NewOffset);
1146 return RC == &AMDGPU::SCC_CLASSRegClass ? &AMDGPU::SReg_32RegClass : RC;
1152 unsigned Op =
MI.getOpcode();
1154 case AMDGPU::SI_BLOCK_SPILL_V1024_SAVE:
1155 case AMDGPU::SI_BLOCK_SPILL_V1024_CFI_SAVE:
1156 case AMDGPU::SI_BLOCK_SPILL_V1024_RESTORE:
1161 (
uint64_t)
TII->getNamedOperand(
MI, AMDGPU::OpName::mask)->getImm());
1162 case AMDGPU::SI_SPILL_S1024_SAVE:
1163 case AMDGPU::SI_SPILL_S1024_CFI_SAVE:
1164 case AMDGPU::SI_SPILL_S1024_RESTORE:
1165 case AMDGPU::SI_SPILL_V1024_SAVE:
1166 case AMDGPU::SI_SPILL_V1024_CFI_SAVE:
1167 case AMDGPU::SI_SPILL_V1024_RESTORE:
1168 case AMDGPU::SI_SPILL_A1024_SAVE:
1169 case AMDGPU::SI_SPILL_A1024_CFI_SAVE:
1170 case AMDGPU::SI_SPILL_A1024_RESTORE:
1171 case AMDGPU::SI_SPILL_AV1024_SAVE:
1172 case AMDGPU::SI_SPILL_AV1024_CFI_SAVE:
1173 case AMDGPU::SI_SPILL_AV1024_RESTORE:
1175 case AMDGPU::SI_SPILL_S512_SAVE:
1176 case AMDGPU::SI_SPILL_S512_CFI_SAVE:
1177 case AMDGPU::SI_SPILL_S512_RESTORE:
1178 case AMDGPU::SI_SPILL_V512_SAVE:
1179 case AMDGPU::SI_SPILL_V512_CFI_SAVE:
1180 case AMDGPU::SI_SPILL_V512_RESTORE:
1181 case AMDGPU::SI_SPILL_A512_SAVE:
1182 case AMDGPU::SI_SPILL_A512_CFI_SAVE:
1183 case AMDGPU::SI_SPILL_A512_RESTORE:
1184 case AMDGPU::SI_SPILL_AV512_SAVE:
1185 case AMDGPU::SI_SPILL_AV512_CFI_SAVE:
1186 case AMDGPU::SI_SPILL_AV512_RESTORE:
1188 case AMDGPU::SI_SPILL_S384_SAVE:
1189 case AMDGPU::SI_SPILL_S384_RESTORE:
1190 case AMDGPU::SI_SPILL_V384_SAVE:
1191 case AMDGPU::SI_SPILL_V384_RESTORE:
1192 case AMDGPU::SI_SPILL_A384_SAVE:
1193 case AMDGPU::SI_SPILL_A384_RESTORE:
1194 case AMDGPU::SI_SPILL_AV384_SAVE:
1195 case AMDGPU::SI_SPILL_AV384_RESTORE:
1197 case AMDGPU::SI_SPILL_S352_SAVE:
1198 case AMDGPU::SI_SPILL_S352_RESTORE:
1199 case AMDGPU::SI_SPILL_V352_SAVE:
1200 case AMDGPU::SI_SPILL_V352_RESTORE:
1201 case AMDGPU::SI_SPILL_A352_SAVE:
1202 case AMDGPU::SI_SPILL_A352_RESTORE:
1203 case AMDGPU::SI_SPILL_AV352_SAVE:
1204 case AMDGPU::SI_SPILL_AV352_RESTORE:
1206 case AMDGPU::SI_SPILL_S320_SAVE:
1207 case AMDGPU::SI_SPILL_S320_RESTORE:
1208 case AMDGPU::SI_SPILL_V320_SAVE:
1209 case AMDGPU::SI_SPILL_V320_RESTORE:
1210 case AMDGPU::SI_SPILL_A320_SAVE:
1211 case AMDGPU::SI_SPILL_A320_RESTORE:
1212 case AMDGPU::SI_SPILL_AV320_SAVE:
1213 case AMDGPU::SI_SPILL_AV320_RESTORE:
1215 case AMDGPU::SI_SPILL_S288_SAVE:
1216 case AMDGPU::SI_SPILL_S288_RESTORE:
1217 case AMDGPU::SI_SPILL_V288_SAVE:
1218 case AMDGPU::SI_SPILL_V288_RESTORE:
1219 case AMDGPU::SI_SPILL_A288_SAVE:
1220 case AMDGPU::SI_SPILL_A288_RESTORE:
1221 case AMDGPU::SI_SPILL_AV288_SAVE:
1222 case AMDGPU::SI_SPILL_AV288_RESTORE:
1224 case AMDGPU::SI_SPILL_S256_SAVE:
1225 case AMDGPU::SI_SPILL_S256_CFI_SAVE:
1226 case AMDGPU::SI_SPILL_S256_RESTORE:
1227 case AMDGPU::SI_SPILL_V256_SAVE:
1228 case AMDGPU::SI_SPILL_V256_CFI_SAVE:
1229 case AMDGPU::SI_SPILL_V256_RESTORE:
1230 case AMDGPU::SI_SPILL_A256_SAVE:
1231 case AMDGPU::SI_SPILL_A256_CFI_SAVE:
1232 case AMDGPU::SI_SPILL_A256_RESTORE:
1233 case AMDGPU::SI_SPILL_AV256_SAVE:
1234 case AMDGPU::SI_SPILL_AV256_CFI_SAVE:
1235 case AMDGPU::SI_SPILL_AV256_RESTORE:
1237 case AMDGPU::SI_SPILL_S224_SAVE:
1238 case AMDGPU::SI_SPILL_S224_CFI_SAVE:
1239 case AMDGPU::SI_SPILL_S224_RESTORE:
1240 case AMDGPU::SI_SPILL_V224_SAVE:
1241 case AMDGPU::SI_SPILL_V224_CFI_SAVE:
1242 case AMDGPU::SI_SPILL_V224_RESTORE:
1243 case AMDGPU::SI_SPILL_A224_SAVE:
1244 case AMDGPU::SI_SPILL_A224_CFI_SAVE:
1245 case AMDGPU::SI_SPILL_A224_RESTORE:
1246 case AMDGPU::SI_SPILL_AV224_SAVE:
1247 case AMDGPU::SI_SPILL_AV224_CFI_SAVE:
1248 case AMDGPU::SI_SPILL_AV224_RESTORE:
1250 case AMDGPU::SI_SPILL_S192_SAVE:
1251 case AMDGPU::SI_SPILL_S192_CFI_SAVE:
1252 case AMDGPU::SI_SPILL_S192_RESTORE:
1253 case AMDGPU::SI_SPILL_V192_SAVE:
1254 case AMDGPU::SI_SPILL_V192_CFI_SAVE:
1255 case AMDGPU::SI_SPILL_V192_RESTORE:
1256 case AMDGPU::SI_SPILL_A192_SAVE:
1257 case AMDGPU::SI_SPILL_A192_CFI_SAVE:
1258 case AMDGPU::SI_SPILL_A192_RESTORE:
1259 case AMDGPU::SI_SPILL_AV192_SAVE:
1260 case AMDGPU::SI_SPILL_AV192_CFI_SAVE:
1261 case AMDGPU::SI_SPILL_AV192_RESTORE:
1263 case AMDGPU::SI_SPILL_S160_SAVE:
1264 case AMDGPU::SI_SPILL_S160_CFI_SAVE:
1265 case AMDGPU::SI_SPILL_S160_RESTORE:
1266 case AMDGPU::SI_SPILL_V160_SAVE:
1267 case AMDGPU::SI_SPILL_V160_CFI_SAVE:
1268 case AMDGPU::SI_SPILL_V160_RESTORE:
1269 case AMDGPU::SI_SPILL_A160_SAVE:
1270 case AMDGPU::SI_SPILL_A160_CFI_SAVE:
1271 case AMDGPU::SI_SPILL_A160_RESTORE:
1272 case AMDGPU::SI_SPILL_AV160_SAVE:
1273 case AMDGPU::SI_SPILL_AV160_CFI_SAVE:
1274 case AMDGPU::SI_SPILL_AV160_RESTORE:
1276 case AMDGPU::SI_SPILL_S128_SAVE:
1277 case AMDGPU::SI_SPILL_S128_CFI_SAVE:
1278 case AMDGPU::SI_SPILL_S128_RESTORE:
1279 case AMDGPU::SI_SPILL_V128_SAVE:
1280 case AMDGPU::SI_SPILL_V128_CFI_SAVE:
1281 case AMDGPU::SI_SPILL_V128_RESTORE:
1282 case AMDGPU::SI_SPILL_A128_SAVE:
1283 case AMDGPU::SI_SPILL_A128_CFI_SAVE:
1284 case AMDGPU::SI_SPILL_A128_RESTORE:
1285 case AMDGPU::SI_SPILL_AV128_SAVE:
1286 case AMDGPU::SI_SPILL_AV128_CFI_SAVE:
1287 case AMDGPU::SI_SPILL_AV128_RESTORE:
1289 case AMDGPU::SI_SPILL_S96_SAVE:
1290 case AMDGPU::SI_SPILL_S96_CFI_SAVE:
1291 case AMDGPU::SI_SPILL_S96_RESTORE:
1292 case AMDGPU::SI_SPILL_V96_SAVE:
1293 case AMDGPU::SI_SPILL_V96_CFI_SAVE:
1294 case AMDGPU::SI_SPILL_V96_RESTORE:
1295 case AMDGPU::SI_SPILL_A96_SAVE:
1296 case AMDGPU::SI_SPILL_A96_CFI_SAVE:
1297 case AMDGPU::SI_SPILL_A96_RESTORE:
1298 case AMDGPU::SI_SPILL_AV96_SAVE:
1299 case AMDGPU::SI_SPILL_AV96_CFI_SAVE:
1300 case AMDGPU::SI_SPILL_AV96_RESTORE:
1302 case AMDGPU::SI_SPILL_S64_SAVE:
1303 case AMDGPU::SI_SPILL_S64_CFI_SAVE:
1304 case AMDGPU::SI_SPILL_S64_RESTORE:
1305 case AMDGPU::SI_SPILL_V64_SAVE:
1306 case AMDGPU::SI_SPILL_V64_CFI_SAVE:
1307 case AMDGPU::SI_SPILL_V64_RESTORE:
1308 case AMDGPU::SI_SPILL_A64_SAVE:
1309 case AMDGPU::SI_SPILL_A64_CFI_SAVE:
1310 case AMDGPU::SI_SPILL_A64_RESTORE:
1311 case AMDGPU::SI_SPILL_AV64_SAVE:
1312 case AMDGPU::SI_SPILL_AV64_CFI_SAVE:
1313 case AMDGPU::SI_SPILL_AV64_RESTORE:
1315 case AMDGPU::SI_SPILL_S32_SAVE:
1316 case AMDGPU::SI_SPILL_S32_CFI_SAVE:
1317 case AMDGPU::SI_SPILL_S32_RESTORE:
1318 case AMDGPU::SI_SPILL_V32_SAVE:
1319 case AMDGPU::SI_SPILL_V32_CFI_SAVE:
1320 case AMDGPU::SI_SPILL_V32_RESTORE:
1321 case AMDGPU::SI_SPILL_A32_SAVE:
1322 case AMDGPU::SI_SPILL_A32_CFI_SAVE:
1323 case AMDGPU::SI_SPILL_A32_RESTORE:
1324 case AMDGPU::SI_SPILL_AV32_SAVE:
1325 case AMDGPU::SI_SPILL_AV32_CFI_SAVE:
1326 case AMDGPU::SI_SPILL_AV32_RESTORE:
1327 case AMDGPU::SI_SPILL_WWM_V32_SAVE:
1328 case AMDGPU::SI_SPILL_WWM_V32_RESTORE:
1329 case AMDGPU::SI_SPILL_WWM_AV32_SAVE:
1330 case AMDGPU::SI_SPILL_WWM_AV32_RESTORE:
1331 case AMDGPU::SI_SPILL_V16_SAVE:
1332 case AMDGPU::SI_SPILL_V16_RESTORE:
1340 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
1341 return AMDGPU::BUFFER_STORE_DWORD_OFFSET;
1342 case AMDGPU::BUFFER_STORE_BYTE_OFFEN:
1343 return AMDGPU::BUFFER_STORE_BYTE_OFFSET;
1344 case AMDGPU::BUFFER_STORE_SHORT_OFFEN:
1345 return AMDGPU::BUFFER_STORE_SHORT_OFFSET;
1346 case AMDGPU::BUFFER_STORE_DWORDX2_OFFEN:
1347 return AMDGPU::BUFFER_STORE_DWORDX2_OFFSET;
1348 case AMDGPU::BUFFER_STORE_DWORDX3_OFFEN:
1349 return AMDGPU::BUFFER_STORE_DWORDX3_OFFSET;
1350 case AMDGPU::BUFFER_STORE_DWORDX4_OFFEN:
1351 return AMDGPU::BUFFER_STORE_DWORDX4_OFFSET;
1352 case AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFEN:
1353 return AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFSET;
1354 case AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFEN:
1355 return AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFSET;
1363 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
1364 return AMDGPU::BUFFER_LOAD_DWORD_OFFSET;
1365 case AMDGPU::BUFFER_LOAD_UBYTE_OFFEN:
1366 return AMDGPU::BUFFER_LOAD_UBYTE_OFFSET;
1367 case AMDGPU::BUFFER_LOAD_SBYTE_OFFEN:
1368 return AMDGPU::BUFFER_LOAD_SBYTE_OFFSET;
1369 case AMDGPU::BUFFER_LOAD_USHORT_OFFEN:
1370 return AMDGPU::BUFFER_LOAD_USHORT_OFFSET;
1371 case AMDGPU::BUFFER_LOAD_SSHORT_OFFEN:
1372 return AMDGPU::BUFFER_LOAD_SSHORT_OFFSET;
1373 case AMDGPU::BUFFER_LOAD_DWORDX2_OFFEN:
1374 return AMDGPU::BUFFER_LOAD_DWORDX2_OFFSET;
1375 case AMDGPU::BUFFER_LOAD_DWORDX3_OFFEN:
1376 return AMDGPU::BUFFER_LOAD_DWORDX3_OFFSET;
1377 case AMDGPU::BUFFER_LOAD_DWORDX4_OFFEN:
1378 return AMDGPU::BUFFER_LOAD_DWORDX4_OFFSET;
1379 case AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFEN:
1380 return AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFSET;
1381 case AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFEN:
1382 return AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFSET;
1383 case AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFEN:
1384 return AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFSET;
1385 case AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFEN:
1386 return AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFSET;
1387 case AMDGPU::BUFFER_LOAD_SHORT_D16_OFFEN:
1388 return AMDGPU::BUFFER_LOAD_SHORT_D16_OFFSET;
1389 case AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFEN:
1390 return AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFSET;
1398 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
1399 return AMDGPU::BUFFER_STORE_DWORD_OFFEN;
1400 case AMDGPU::BUFFER_STORE_BYTE_OFFSET:
1401 return AMDGPU::BUFFER_STORE_BYTE_OFFEN;
1402 case AMDGPU::BUFFER_STORE_SHORT_OFFSET:
1403 return AMDGPU::BUFFER_STORE_SHORT_OFFEN;
1404 case AMDGPU::BUFFER_STORE_DWORDX2_OFFSET:
1405 return AMDGPU::BUFFER_STORE_DWORDX2_OFFEN;
1406 case AMDGPU::BUFFER_STORE_DWORDX3_OFFSET:
1407 return AMDGPU::BUFFER_STORE_DWORDX3_OFFEN;
1408 case AMDGPU::BUFFER_STORE_DWORDX4_OFFSET:
1409 return AMDGPU::BUFFER_STORE_DWORDX4_OFFEN;
1410 case AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFSET:
1411 return AMDGPU::BUFFER_STORE_SHORT_D16_HI_OFFEN;
1412 case AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFSET:
1413 return AMDGPU::BUFFER_STORE_BYTE_D16_HI_OFFEN;
1421 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
1422 return AMDGPU::BUFFER_LOAD_DWORD_OFFEN;
1423 case AMDGPU::BUFFER_LOAD_UBYTE_OFFSET:
1424 return AMDGPU::BUFFER_LOAD_UBYTE_OFFEN;
1425 case AMDGPU::BUFFER_LOAD_SBYTE_OFFSET:
1426 return AMDGPU::BUFFER_LOAD_SBYTE_OFFEN;
1427 case AMDGPU::BUFFER_LOAD_USHORT_OFFSET:
1428 return AMDGPU::BUFFER_LOAD_USHORT_OFFEN;
1429 case AMDGPU::BUFFER_LOAD_SSHORT_OFFSET:
1430 return AMDGPU::BUFFER_LOAD_SSHORT_OFFEN;
1431 case AMDGPU::BUFFER_LOAD_DWORDX2_OFFSET:
1432 return AMDGPU::BUFFER_LOAD_DWORDX2_OFFEN;
1433 case AMDGPU::BUFFER_LOAD_DWORDX3_OFFSET:
1434 return AMDGPU::BUFFER_LOAD_DWORDX3_OFFEN;
1435 case AMDGPU::BUFFER_LOAD_DWORDX4_OFFSET:
1436 return AMDGPU::BUFFER_LOAD_DWORDX4_OFFEN;
1437 case AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFSET:
1438 return AMDGPU::BUFFER_LOAD_UBYTE_D16_OFFEN;
1439 case AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFSET:
1440 return AMDGPU::BUFFER_LOAD_UBYTE_D16_HI_OFFEN;
1441 case AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFSET:
1442 return AMDGPU::BUFFER_LOAD_SBYTE_D16_OFFEN;
1443 case AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFSET:
1444 return AMDGPU::BUFFER_LOAD_SBYTE_D16_HI_OFFEN;
1445 case AMDGPU::BUFFER_LOAD_SHORT_D16_OFFSET:
1446 return AMDGPU::BUFFER_LOAD_SHORT_D16_OFFEN;
1447 case AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFSET:
1448 return AMDGPU::BUFFER_LOAD_SHORT_D16_HI_OFFEN;
1457 unsigned ValueReg,
bool IsKill,
bool NeedsCFI) {
1465 if (
Reg == AMDGPU::NoRegister)
1468 bool IsStore =
MI->mayStore();
1472 unsigned Dst = IsStore ?
Reg : ValueReg;
1473 unsigned Src = IsStore ? ValueReg :
Reg;
1476 if (IsVGPR ==
TRI->isVGPR(
MRI, ValueReg)) {
1488 unsigned Opc = (IsStore ^ IsVGPR) ? AMDGPU::V_ACCVGPR_WRITE_B32_e64
1489 : AMDGPU::V_ACCVGPR_READ_B32_e64;
1509 bool IsStore =
MI->mayStore();
1511 unsigned Opc =
MI->getOpcode();
1512 int LoadStoreOp = IsStore ?
1514 if (LoadStoreOp == -1)
1525 .
add(*
TII->getNamedOperand(*
MI, AMDGPU::OpName::srsrc))
1526 .
add(*
TII->getNamedOperand(*
MI, AMDGPU::OpName::soffset))
1533 AMDGPU::OpName::vdata_in);
1535 NewMI.
add(*VDataIn);
1540 unsigned LoadStoreOp,
1542 bool IsStore =
TII->get(LoadStoreOp).mayStore();
1548 if (
TII->isBlockLoadStore(LoadStoreOp))
1553 LoadStoreOp = IsStore ? AMDGPU::SCRATCH_STORE_DWORD_SADDR
1554 : AMDGPU::SCRATCH_LOAD_DWORD_SADDR;
1557 LoadStoreOp = IsStore ? AMDGPU::SCRATCH_STORE_DWORDX2_SADDR
1558 : AMDGPU::SCRATCH_LOAD_DWORDX2_SADDR;
1561 LoadStoreOp = IsStore ? AMDGPU::SCRATCH_STORE_DWORDX3_SADDR
1562 : AMDGPU::SCRATCH_LOAD_DWORDX3_SADDR;
1565 LoadStoreOp = IsStore ? AMDGPU::SCRATCH_STORE_DWORDX4_SADDR
1566 : AMDGPU::SCRATCH_LOAD_DWORDX4_SADDR;
1582 unsigned LoadStoreOp,
int Index,
Register ValueReg,
bool IsKill,
1585 assert((!RS || !LiveUnits) &&
"Only RS or LiveUnits can be set but not both");
1594 bool IsStore =
Desc->mayStore();
1595 bool IsFlat =
TII->isFLATScratch(LoadStoreOp);
1596 bool IsBlock =
TII->isBlockLoadStore(LoadStoreOp);
1598 bool CanClobberSCC =
false;
1599 bool Scavenged =
false;
1604 const bool IsAGPR = !ST.hasGFX90AInsts() &&
isAGPRClass(RC);
1615 bool IsRegMisaligned =
false;
1616 if (!IsBlock && !IsAGPR && RegWidth > 4 && IsFlat) {
1617 unsigned SpillOpcode =
1620 IsStore ? AMDGPU::getNamedOperandIdx(SpillOpcode, AMDGPU::OpName::vdata)
1623 TII->getRegClass(
TII->get(SpillOpcode), VDataIdx);
1624 if (!ExpectedRC->
contains(ValueReg)) {
1628 getMatchingSuperRegClass(RC, ExpectedRC, SubIdx);
1629 if (!MatchRC || !MatchRC->
contains(ValueReg))
1630 IsRegMisaligned =
true;
1634 if (IsRegMisaligned)
1639 unsigned EltSize = IsBlock ? RegWidth
1640 : (IsFlat && !IsAGPR) ? std::min(RegWidth, 16u)
1642 unsigned NumSubRegs = RegWidth / EltSize;
1643 unsigned Size = NumSubRegs * EltSize;
1644 unsigned RemSize = RegWidth -
Size;
1645 unsigned NumRemSubRegs = RemSize ? 1 : 0;
1647 if (IsRegMisaligned)
1650 int64_t MaterializedOffset =
Offset;
1655 int64_t MaxOffset =
Offset +
Size - (RemSize ? 0 : EltSize);
1656 int64_t ScratchOffsetRegDelta = 0;
1657 int64_t AdditionalCFIOffset = 0;
1659 if (IsFlat && EltSize > 4) {
1661 Desc = &
TII->get(LoadStoreOp);
1668 "unexpected VGPR spill offset");
1675 bool UseVGPROffset =
false;
1682 if (IsFlat && SGPRBase) {
1687 if (ST.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) >= 2) {
1706 bool IsOffsetLegal =
1709 :
TII->isLegalMUBUFImmOffset(MaxOffset);
1710 if (!IsOffsetLegal || (IsFlat && !SOffset && !ST.hasFlatScratchSTMode())) {
1718 SOffset = RS->scavengeRegisterBackwards(AMDGPU::SGPR_32RegClass,
MI,
false, 0,
false);
1721 CanClobberSCC = !RS->isRegUsed(AMDGPU::SCC);
1722 }
else if (LiveUnits) {
1723 CanClobberSCC = LiveUnits->
available(AMDGPU::SCC);
1724 for (
MCRegister Reg : AMDGPU::SGPR_32RegClass) {
1732 if (ScratchOffsetReg != AMDGPU::NoRegister && !CanClobberSCC)
1736 UseVGPROffset =
true;
1739 TmpOffsetVGPR = RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
false, 0);
1742 for (
MCRegister Reg : AMDGPU::VGPR_32RegClass) {
1744 TmpOffsetVGPR = Reg;
1751 }
else if (!SOffset && CanClobberSCC) {
1762 if (!ScratchOffsetReg)
1764 SOffset = ScratchOffsetReg;
1765 ScratchOffsetRegDelta =
Offset;
1770 AdditionalCFIOffset =
Offset;
1774 if (!IsFlat && !UseVGPROffset)
1775 Offset *= ST.getWavefrontSize();
1777 if (!UseVGPROffset && !SOffset)
1780 if (UseVGPROffset) {
1782 MaterializeVOffset(ScratchOffsetReg, TmpOffsetVGPR,
Offset);
1783 }
else if (ScratchOffsetReg == AMDGPU::NoRegister) {
1788 .
addReg(ScratchOffsetReg)
1790 Add->getOperand(3).setIsDead();
1796 if (IsFlat && SOffset == AMDGPU::NoRegister) {
1797 assert(AMDGPU::getNamedOperandIdx(LoadStoreOp, AMDGPU::OpName::vaddr) < 0
1798 &&
"Unexpected vaddr for flat scratch with a FI operand");
1800 if (UseVGPROffset) {
1803 assert(ST.hasFlatScratchSTMode());
1804 assert(!
TII->isBlockLoadStore(LoadStoreOp) &&
"Block ops don't have ST");
1808 Desc = &
TII->get(LoadStoreOp);
1813 unsigned OrigEltSize = EltSize;
1814 for (
unsigned i = 0, e = NumSubRegs + NumRemSubRegs, RegOffset = 0; i != e;
1815 ++i, RegOffset += EltSize) {
1816 if (IsRegMisaligned) {
1824 IsRegMisaligned =
false;
1825 EltSize = OrigEltSize;
1829 if (i == NumSubRegs) {
1833 Desc = &
TII->get(LoadStoreOp);
1835 if (!IsFlat && UseVGPROffset) {
1838 Desc = &
TII->get(NewLoadStoreOp);
1841 if (UseVGPROffset && TmpOffsetVGPR == TmpIntermediateVGPR) {
1848 MaterializeVOffset(ScratchOffsetReg, TmpOffsetVGPR, MaterializedOffset);
1851 unsigned NumRegs = EltSize / 4;
1859 const bool IsLastSubReg = i + 1 == e;
1860 const bool IsFirstSubReg = i == 0;
1869 bool NeedSuperRegDef = e > 1 && IsStore && IsFirstSubReg;
1870 bool NeedSuperRegImpOperand = e > 1;
1874 unsigned RemEltSize = EltSize;
1882 for (
int LaneS = (RegOffset + EltSize) / 4 - 1, Lane = LaneS,
1883 LaneE = RegOffset / 4;
1884 Lane >= LaneE; --Lane) {
1885 bool IsSubReg = e > 1 || EltSize > 4;
1891 if (!MIB.getInstr())
1893 if (NeedSuperRegDef || (IsSubReg && IsStore && Lane == LaneS && IsFirstSubReg)) {
1895 NeedSuperRegDef =
false;
1897 if ((IsSubReg || NeedSuperRegImpOperand) && (IsFirstSubReg || IsLastSubReg)) {
1898 NeedSuperRegImpOperand =
true;
1900 if (!IsLastSubReg || (Lane != LaneE))
1902 if (!IsFirstSubReg || (Lane != LaneS))
1912 if (RemEltSize != EltSize) {
1913 assert(IsFlat && EltSize > 4);
1915 unsigned NumRegs = RemEltSize / 4;
1916 SubReg =
Register(getSubReg(ValueReg,
1922 unsigned FinalReg = SubReg;
1927 if (!TmpIntermediateVGPR) {
1933 TII->get(AMDGPU::V_ACCVGPR_READ_B32_e64),
1934 TmpIntermediateVGPR)
1936 if (NeedSuperRegDef)
1938 if (NeedSuperRegImpOperand && (IsFirstSubReg || IsLastSubReg))
1942 SubReg = TmpIntermediateVGPR;
1943 }
else if (UseVGPROffset) {
1944 if (!TmpOffsetVGPR) {
1945 TmpOffsetVGPR = RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
1947 RS->setRegUsed(TmpOffsetVGPR);
1952 if (LoadStoreOp == AMDGPU::SCRATCH_LOAD_USHORT_SADDR ||
1953 LoadStoreOp == AMDGPU::SCRATCH_LOAD_USHORT_ST) {
1957 RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
false, 0);
1973 if (UseVGPROffset) {
1982 if (SOffset == AMDGPU::NoRegister) {
1984 if (UseVGPROffset && ScratchOffsetReg) {
1985 MIB.addReg(ScratchOffsetReg);
1992 MIB.addReg(SOffset, SOffsetRegState);
2002 MIB.addMemOperand(NewMMO);
2004 if (FinalValueReg != ValueReg) {
2006 ValueReg = getSubReg(ValueReg, AMDGPU::lo16);
2012 ValueReg = FinalValueReg;
2015 if (IsStore && NeedsCFI) {
2016 if (
TII->isBlockLoadStore(LoadStoreOp)) {
2018 "expected whole register block to be treated as single element");
2023 (
Offset + RegOffset) * ST.getWavefrontSize() + AdditionalCFIOffset);
2027 if (!IsAGPR && NeedSuperRegDef)
2030 if (!IsStore && IsAGPR && TmpIntermediateVGPR != AMDGPU::NoRegister) {
2038 bool PartialReloadCopy = (RemEltSize != EltSize) && !IsStore;
2039 if (NeedSuperRegImpOperand &&
2040 (IsFirstSubReg || (IsLastSubReg && !IsSrcDstDef))) {
2042 if (PartialReloadCopy)
2067 if (!IsStore &&
MI !=
MBB.end() &&
MI->isReturn() &&
2068 MI->readsRegister(SubReg,
this)) {
2070 MIB->tieOperands(0, MIB->getNumOperands() - 1);
2078 if (!IsStore &&
TII->isBlockLoadStore(LoadStoreOp))
2082 if (ScratchOffsetRegDelta != 0) {
2086 .
addImm(-ScratchOffsetRegDelta);
2095 Register BaseVGPR = getSubReg(BlockReg, AMDGPU::sub0);
2096 for (
unsigned RegOffset = 1; RegOffset < 32; ++RegOffset)
2097 if (!(Mask & (1 << RegOffset)) &&
2098 isCalleeSavedPhysReg(BaseVGPR + RegOffset, *MF))
2109 Register BaseVGPR = getSubReg(BlockReg, AMDGPU::sub0);
2110 for (
unsigned RegOffset = 0; RegOffset < 32; ++RegOffset) {
2111 Register VGPR = BaseVGPR + RegOffset;
2112 if (Mask & (1 << RegOffset)) {
2113 assert(isCalleeSavedPhysReg(VGPR, *MF));
2114 ST.getFrameLowering()->buildCFIForVGPRToVMEMSpill(
2116 (
Offset + RegOffset) * ST.getWavefrontSize());
2117 }
else if (isCalleeSavedPhysReg(VGPR, *MF)) {
2122 BaseVGPR + RegOffset);
2129 bool IsKill)
const {
2139 Align Alignment = FrameInfo.getObjectAlign(Index);
2146 unsigned Opc = ST.hasFlatScratchEnabled()
2147 ? AMDGPU::SCRATCH_LOAD_DWORD_SADDR
2148 : AMDGPU::BUFFER_LOAD_DWORD_OFFSET;
2152 unsigned Opc = ST.hasFlatScratchEnabled()
2153 ? AMDGPU::SCRATCH_STORE_DWORD_SADDR
2154 : AMDGPU::BUFFER_STORE_DWORD_OFFSET;
2165 bool SpillToPhysVGPRLane,
bool NeedsCFI)
const {
2166 assert(!
MI->getOperand(0).isUndef() &&
2167 "undef spill should have been deleted earlier");
2174 bool SpillToVGPR = !VGPRSpills.
empty();
2175 if (OnlyToVGPR && !SpillToVGPR)
2190 "Num of SGPRs spilled should be less than or equal to num of "
2193 for (
unsigned i = 0, e = SB.
NumSubRegs; i < e; ++i) {
2200 bool IsFirstSubreg = i == 0;
2202 bool UseKill = SB.
IsKill && IsLastSubreg;
2208 SB.
TII.get(AMDGPU::SI_SPILL_S32_TO_VGPR), Spill.VGPR)
2218 AMDGPU::PC_REG, VGPRSpills);
2221 Spill.VGPR, Spill.Lane);
2241 if (SB.
NumSubRegs > 1 && (IsFirstSubreg || IsLastSubreg))
2261 for (
unsigned i =
Offset * PVD.PerVGPR,
2271 SB.
TII.get(AMDGPU::SI_SPILL_S32_TO_VGPR), SB.
TmpVGPR)
2272 .
addReg(SubReg, SubKillState)
2303 ST.getWavefrontSize();
2305 AMDGPU::PC_REG, CFIOffset);
2314 MI->eraseFromParent();
2326 bool SpillToPhysVGPRLane)
const {
2332 bool SpillToVGPR = !VGPRSpills.
empty();
2333 if (OnlyToVGPR && !SpillToVGPR)
2337 for (
unsigned i = 0, e = SB.
NumSubRegs; i < e; ++i) {
2345 SB.
TII.get(AMDGPU::SI_RESTORE_S32_FROM_VGPR), SubReg)
2368 for (
unsigned i =
Offset * PVD.PerVGPR,
2376 bool LastSubReg = (i + 1 == e);
2378 SB.
TII.get(AMDGPU::SI_RESTORE_S32_FROM_VGPR), SubReg)
2395 MI->eraseFromParent();
2415 for (
unsigned i =
Offset * PVD.PerVGPR,
2426 .
addReg(SubReg, SubKillState)
2444 MI = RestoreMBB.
end();
2450 for (
unsigned i =
Offset * PVD.PerVGPR,
2459 bool LastSubReg = (i + 1 == e);
2480 bool NeedsCFI =
false;
2481 switch (
MI->getOpcode()) {
2482 case AMDGPU::SI_SPILL_S1024_CFI_SAVE:
2483 case AMDGPU::SI_SPILL_S512_CFI_SAVE:
2484 case AMDGPU::SI_SPILL_S256_CFI_SAVE:
2485 case AMDGPU::SI_SPILL_S224_CFI_SAVE:
2486 case AMDGPU::SI_SPILL_S192_CFI_SAVE:
2487 case AMDGPU::SI_SPILL_S160_CFI_SAVE:
2488 case AMDGPU::SI_SPILL_S128_CFI_SAVE:
2489 case AMDGPU::SI_SPILL_S96_CFI_SAVE:
2490 case AMDGPU::SI_SPILL_S64_CFI_SAVE:
2491 case AMDGPU::SI_SPILL_S32_CFI_SAVE:
2494 case AMDGPU::SI_SPILL_S1024_SAVE:
2495 case AMDGPU::SI_SPILL_S512_SAVE:
2496 case AMDGPU::SI_SPILL_S384_SAVE:
2497 case AMDGPU::SI_SPILL_S352_SAVE:
2498 case AMDGPU::SI_SPILL_S320_SAVE:
2499 case AMDGPU::SI_SPILL_S288_SAVE:
2500 case AMDGPU::SI_SPILL_S256_SAVE:
2501 case AMDGPU::SI_SPILL_S224_SAVE:
2502 case AMDGPU::SI_SPILL_S192_SAVE:
2503 case AMDGPU::SI_SPILL_S160_SAVE:
2504 case AMDGPU::SI_SPILL_S128_SAVE:
2505 case AMDGPU::SI_SPILL_S96_SAVE:
2506 case AMDGPU::SI_SPILL_S64_SAVE:
2507 case AMDGPU::SI_SPILL_S32_SAVE:
2508 return spillSGPR(
MI, FI, RS, Indexes, LIS,
true, SpillToPhysVGPRLane,
2510 case AMDGPU::SI_SPILL_S1024_RESTORE:
2511 case AMDGPU::SI_SPILL_S512_RESTORE:
2512 case AMDGPU::SI_SPILL_S384_RESTORE:
2513 case AMDGPU::SI_SPILL_S352_RESTORE:
2514 case AMDGPU::SI_SPILL_S320_RESTORE:
2515 case AMDGPU::SI_SPILL_S288_RESTORE:
2516 case AMDGPU::SI_SPILL_S256_RESTORE:
2517 case AMDGPU::SI_SPILL_S224_RESTORE:
2518 case AMDGPU::SI_SPILL_S192_RESTORE:
2519 case AMDGPU::SI_SPILL_S160_RESTORE:
2520 case AMDGPU::SI_SPILL_S128_RESTORE:
2521 case AMDGPU::SI_SPILL_S96_RESTORE:
2522 case AMDGPU::SI_SPILL_S64_RESTORE:
2523 case AMDGPU::SI_SPILL_S32_RESTORE:
2524 return restoreSGPR(
MI, FI, RS, Indexes, LIS,
true, SpillToPhysVGPRLane);
2547 return (RS.isRegUsed(AMDGPU::SCC) &&
2548 !
MI.definesRegister(AMDGPU::SCC,
nullptr)) ||
2549 MI.readsRegister(AMDGPU::SCC,
nullptr);
2553 int SPAdj,
unsigned FIOperandNum,
2562 assert(SPAdj == 0 &&
"unhandled SP adjustment in call sequence?");
2565 "unreserved scratch RSRC register");
2568 int Index =
MI->getOperand(FIOperandNum).getIndex();
2574 bool NeedsCFI =
false;
2576 switch (
MI->getOpcode()) {
2578 case AMDGPU::SI_SPILL_S1024_CFI_SAVE:
2579 case AMDGPU::SI_SPILL_S512_CFI_SAVE:
2580 case AMDGPU::SI_SPILL_S256_CFI_SAVE:
2581 case AMDGPU::SI_SPILL_S224_CFI_SAVE:
2582 case AMDGPU::SI_SPILL_S192_CFI_SAVE:
2583 case AMDGPU::SI_SPILL_S160_CFI_SAVE:
2584 case AMDGPU::SI_SPILL_S128_CFI_SAVE:
2585 case AMDGPU::SI_SPILL_S96_CFI_SAVE:
2586 case AMDGPU::SI_SPILL_S64_CFI_SAVE:
2587 case AMDGPU::SI_SPILL_S32_CFI_SAVE: {
2591 case AMDGPU::SI_SPILL_S1024_SAVE:
2592 case AMDGPU::SI_SPILL_S512_SAVE:
2593 case AMDGPU::SI_SPILL_S384_SAVE:
2594 case AMDGPU::SI_SPILL_S352_SAVE:
2595 case AMDGPU::SI_SPILL_S320_SAVE:
2596 case AMDGPU::SI_SPILL_S288_SAVE:
2597 case AMDGPU::SI_SPILL_S256_SAVE:
2598 case AMDGPU::SI_SPILL_S224_SAVE:
2599 case AMDGPU::SI_SPILL_S192_SAVE:
2600 case AMDGPU::SI_SPILL_S160_SAVE:
2601 case AMDGPU::SI_SPILL_S128_SAVE:
2602 case AMDGPU::SI_SPILL_S96_SAVE:
2603 case AMDGPU::SI_SPILL_S64_SAVE:
2604 case AMDGPU::SI_SPILL_S32_SAVE: {
2611 case AMDGPU::SI_SPILL_S1024_RESTORE:
2612 case AMDGPU::SI_SPILL_S512_RESTORE:
2613 case AMDGPU::SI_SPILL_S384_RESTORE:
2614 case AMDGPU::SI_SPILL_S352_RESTORE:
2615 case AMDGPU::SI_SPILL_S320_RESTORE:
2616 case AMDGPU::SI_SPILL_S288_RESTORE:
2617 case AMDGPU::SI_SPILL_S256_RESTORE:
2618 case AMDGPU::SI_SPILL_S224_RESTORE:
2619 case AMDGPU::SI_SPILL_S192_RESTORE:
2620 case AMDGPU::SI_SPILL_S160_RESTORE:
2621 case AMDGPU::SI_SPILL_S128_RESTORE:
2622 case AMDGPU::SI_SPILL_S96_RESTORE:
2623 case AMDGPU::SI_SPILL_S64_RESTORE:
2624 case AMDGPU::SI_SPILL_S32_RESTORE: {
2626 FrameInfo.getStackID(Index) ==
2631 case AMDGPU::SI_BLOCK_SPILL_V1024_CFI_SAVE:
2632 case AMDGPU::SI_SPILL_V1024_CFI_SAVE:
2633 case AMDGPU::SI_SPILL_V512_CFI_SAVE:
2634 case AMDGPU::SI_SPILL_V256_CFI_SAVE:
2635 case AMDGPU::SI_SPILL_V224_CFI_SAVE:
2636 case AMDGPU::SI_SPILL_V192_CFI_SAVE:
2637 case AMDGPU::SI_SPILL_V160_CFI_SAVE:
2638 case AMDGPU::SI_SPILL_V128_CFI_SAVE:
2639 case AMDGPU::SI_SPILL_V96_CFI_SAVE:
2640 case AMDGPU::SI_SPILL_V64_CFI_SAVE:
2641 case AMDGPU::SI_SPILL_V32_CFI_SAVE:
2642 case AMDGPU::SI_SPILL_A1024_CFI_SAVE:
2643 case AMDGPU::SI_SPILL_A512_CFI_SAVE:
2644 case AMDGPU::SI_SPILL_A256_CFI_SAVE:
2645 case AMDGPU::SI_SPILL_A224_CFI_SAVE:
2646 case AMDGPU::SI_SPILL_A192_CFI_SAVE:
2647 case AMDGPU::SI_SPILL_A160_CFI_SAVE:
2648 case AMDGPU::SI_SPILL_A128_CFI_SAVE:
2649 case AMDGPU::SI_SPILL_A96_CFI_SAVE:
2650 case AMDGPU::SI_SPILL_A64_CFI_SAVE:
2651 case AMDGPU::SI_SPILL_A32_CFI_SAVE:
2652 case AMDGPU::SI_SPILL_AV1024_CFI_SAVE:
2653 case AMDGPU::SI_SPILL_AV512_CFI_SAVE:
2654 case AMDGPU::SI_SPILL_AV256_CFI_SAVE:
2655 case AMDGPU::SI_SPILL_AV224_CFI_SAVE:
2656 case AMDGPU::SI_SPILL_AV192_CFI_SAVE:
2657 case AMDGPU::SI_SPILL_AV160_CFI_SAVE:
2658 case AMDGPU::SI_SPILL_AV128_CFI_SAVE:
2659 case AMDGPU::SI_SPILL_AV96_CFI_SAVE:
2660 case AMDGPU::SI_SPILL_AV64_CFI_SAVE:
2661 case AMDGPU::SI_SPILL_AV32_CFI_SAVE:
2664 case AMDGPU::SI_BLOCK_SPILL_V1024_SAVE:
2665 case AMDGPU::SI_SPILL_V1024_SAVE:
2666 case AMDGPU::SI_SPILL_V512_SAVE:
2667 case AMDGPU::SI_SPILL_V384_SAVE:
2668 case AMDGPU::SI_SPILL_V352_SAVE:
2669 case AMDGPU::SI_SPILL_V320_SAVE:
2670 case AMDGPU::SI_SPILL_V288_SAVE:
2671 case AMDGPU::SI_SPILL_V256_SAVE:
2672 case AMDGPU::SI_SPILL_V224_SAVE:
2673 case AMDGPU::SI_SPILL_V192_SAVE:
2674 case AMDGPU::SI_SPILL_V160_SAVE:
2675 case AMDGPU::SI_SPILL_V128_SAVE:
2676 case AMDGPU::SI_SPILL_V96_SAVE:
2677 case AMDGPU::SI_SPILL_V64_SAVE:
2678 case AMDGPU::SI_SPILL_V32_SAVE:
2679 case AMDGPU::SI_SPILL_V16_SAVE:
2680 case AMDGPU::SI_SPILL_A1024_SAVE:
2681 case AMDGPU::SI_SPILL_A512_SAVE:
2682 case AMDGPU::SI_SPILL_A384_SAVE:
2683 case AMDGPU::SI_SPILL_A352_SAVE:
2684 case AMDGPU::SI_SPILL_A320_SAVE:
2685 case AMDGPU::SI_SPILL_A288_SAVE:
2686 case AMDGPU::SI_SPILL_A256_SAVE:
2687 case AMDGPU::SI_SPILL_A224_SAVE:
2688 case AMDGPU::SI_SPILL_A192_SAVE:
2689 case AMDGPU::SI_SPILL_A160_SAVE:
2690 case AMDGPU::SI_SPILL_A128_SAVE:
2691 case AMDGPU::SI_SPILL_A96_SAVE:
2692 case AMDGPU::SI_SPILL_A64_SAVE:
2693 case AMDGPU::SI_SPILL_A32_SAVE:
2694 case AMDGPU::SI_SPILL_AV1024_SAVE:
2695 case AMDGPU::SI_SPILL_AV512_SAVE:
2696 case AMDGPU::SI_SPILL_AV384_SAVE:
2697 case AMDGPU::SI_SPILL_AV352_SAVE:
2698 case AMDGPU::SI_SPILL_AV320_SAVE:
2699 case AMDGPU::SI_SPILL_AV288_SAVE:
2700 case AMDGPU::SI_SPILL_AV256_SAVE:
2701 case AMDGPU::SI_SPILL_AV224_SAVE:
2702 case AMDGPU::SI_SPILL_AV192_SAVE:
2703 case AMDGPU::SI_SPILL_AV160_SAVE:
2704 case AMDGPU::SI_SPILL_AV128_SAVE:
2705 case AMDGPU::SI_SPILL_AV96_SAVE:
2706 case AMDGPU::SI_SPILL_AV64_SAVE:
2707 case AMDGPU::SI_SPILL_AV32_SAVE:
2708 case AMDGPU::SI_SPILL_WWM_V32_SAVE:
2709 case AMDGPU::SI_SPILL_WWM_AV32_SAVE: {
2711 MI->getOpcode() != AMDGPU::SI_BLOCK_SPILL_V1024_SAVE &&
2712 "block spill does not currenty support spilling non-CSR registers");
2714 if (
MI->getOpcode() == AMDGPU::SI_BLOCK_SPILL_V1024_CFI_SAVE)
2718 .
add(*
TII->getNamedOperand(*
MI, AMDGPU::OpName::mask));
2721 AMDGPU::OpName::vdata);
2723 MI->eraseFromParent();
2727 assert(
TII->getNamedOperand(*
MI, AMDGPU::OpName::soffset)->getReg() ==
2731 if (
MI->getOpcode() == AMDGPU::SI_SPILL_V16_SAVE) {
2732 assert(ST.hasFlatScratchEnabled() &&
"Flat Scratch is not enabled!");
2733 Opc = AMDGPU::SCRATCH_STORE_SHORT_SADDR_t16;
2735 Opc =
MI->getOpcode() == AMDGPU::SI_BLOCK_SPILL_V1024_CFI_SAVE
2736 ? AMDGPU::SCRATCH_STORE_BLOCK_SADDR
2737 : ST.hasFlatScratchEnabled() ? AMDGPU::SCRATCH_STORE_DWORD_SADDR
2738 : AMDGPU::BUFFER_STORE_DWORD_OFFSET;
2741 auto *
MBB =
MI->getParent();
2742 bool IsWWMRegSpill =
TII->isWWMRegSpillOpcode(
MI->getOpcode());
2743 if (IsWWMRegSpill) {
2745 RS->isRegUsed(AMDGPU::SCC));
2749 TII->getNamedOperand(*
MI, AMDGPU::OpName::offset)->getImm(),
2750 *
MI->memoperands_begin(), RS,
nullptr, NeedsCFI);
2755 MI->eraseFromParent();
2758 case AMDGPU::SI_BLOCK_SPILL_V1024_RESTORE: {
2762 .
add(*
TII->getNamedOperand(*
MI, AMDGPU::OpName::mask));
2765 case AMDGPU::SI_SPILL_V16_RESTORE:
2766 case AMDGPU::SI_SPILL_V32_RESTORE:
2767 case AMDGPU::SI_SPILL_V64_RESTORE:
2768 case AMDGPU::SI_SPILL_V96_RESTORE:
2769 case AMDGPU::SI_SPILL_V128_RESTORE:
2770 case AMDGPU::SI_SPILL_V160_RESTORE:
2771 case AMDGPU::SI_SPILL_V192_RESTORE:
2772 case AMDGPU::SI_SPILL_V224_RESTORE:
2773 case AMDGPU::SI_SPILL_V256_RESTORE:
2774 case AMDGPU::SI_SPILL_V288_RESTORE:
2775 case AMDGPU::SI_SPILL_V320_RESTORE:
2776 case AMDGPU::SI_SPILL_V352_RESTORE:
2777 case AMDGPU::SI_SPILL_V384_RESTORE:
2778 case AMDGPU::SI_SPILL_V512_RESTORE:
2779 case AMDGPU::SI_SPILL_V1024_RESTORE:
2780 case AMDGPU::SI_SPILL_A32_RESTORE:
2781 case AMDGPU::SI_SPILL_A64_RESTORE:
2782 case AMDGPU::SI_SPILL_A96_RESTORE:
2783 case AMDGPU::SI_SPILL_A128_RESTORE:
2784 case AMDGPU::SI_SPILL_A160_RESTORE:
2785 case AMDGPU::SI_SPILL_A192_RESTORE:
2786 case AMDGPU::SI_SPILL_A224_RESTORE:
2787 case AMDGPU::SI_SPILL_A256_RESTORE:
2788 case AMDGPU::SI_SPILL_A288_RESTORE:
2789 case AMDGPU::SI_SPILL_A320_RESTORE:
2790 case AMDGPU::SI_SPILL_A352_RESTORE:
2791 case AMDGPU::SI_SPILL_A384_RESTORE:
2792 case AMDGPU::SI_SPILL_A512_RESTORE:
2793 case AMDGPU::SI_SPILL_A1024_RESTORE:
2794 case AMDGPU::SI_SPILL_AV32_RESTORE:
2795 case AMDGPU::SI_SPILL_AV64_RESTORE:
2796 case AMDGPU::SI_SPILL_AV96_RESTORE:
2797 case AMDGPU::SI_SPILL_AV128_RESTORE:
2798 case AMDGPU::SI_SPILL_AV160_RESTORE:
2799 case AMDGPU::SI_SPILL_AV192_RESTORE:
2800 case AMDGPU::SI_SPILL_AV224_RESTORE:
2801 case AMDGPU::SI_SPILL_AV256_RESTORE:
2802 case AMDGPU::SI_SPILL_AV288_RESTORE:
2803 case AMDGPU::SI_SPILL_AV320_RESTORE:
2804 case AMDGPU::SI_SPILL_AV352_RESTORE:
2805 case AMDGPU::SI_SPILL_AV384_RESTORE:
2806 case AMDGPU::SI_SPILL_AV512_RESTORE:
2807 case AMDGPU::SI_SPILL_AV1024_RESTORE:
2808 case AMDGPU::SI_SPILL_WWM_V32_RESTORE:
2809 case AMDGPU::SI_SPILL_WWM_AV32_RESTORE: {
2811 AMDGPU::OpName::vdata);
2812 assert(
TII->getNamedOperand(*
MI, AMDGPU::OpName::soffset)->getReg() ==
2816 if (
MI->getOpcode() == AMDGPU::SI_SPILL_V16_RESTORE) {
2817 assert(ST.hasFlatScratchEnabled() &&
"Flat Scratch is not enabled!");
2818 Opc = ST.d16PreservesUnusedBits()
2819 ? AMDGPU::SCRATCH_LOAD_SHORT_D16_SADDR_t16
2820 : AMDGPU::SCRATCH_LOAD_USHORT_SADDR;
2822 Opc =
MI->getOpcode() == AMDGPU::SI_BLOCK_SPILL_V1024_RESTORE
2823 ? AMDGPU::SCRATCH_LOAD_BLOCK_SADDR
2824 : ST.hasFlatScratchEnabled() ? AMDGPU::SCRATCH_LOAD_DWORD_SADDR
2825 : AMDGPU::BUFFER_LOAD_DWORD_OFFSET;
2828 auto *
MBB =
MI->getParent();
2829 bool IsWWMRegSpill =
TII->isWWMRegSpillOpcode(
MI->getOpcode());
2830 if (IsWWMRegSpill) {
2832 RS->isRegUsed(AMDGPU::SCC));
2837 TII->getNamedOperand(*
MI, AMDGPU::OpName::offset)->getImm(),
2838 *
MI->memoperands_begin(), RS);
2843 MI->eraseFromParent();
2846 case AMDGPU::V_ADD_U32_e32:
2847 case AMDGPU::V_ADD_U32_e64:
2848 case AMDGPU::V_ADD_CO_U32_e32:
2849 case AMDGPU::V_ADD_CO_U32_e64: {
2851 unsigned NumDefs =
MI->getNumExplicitDefs();
2852 unsigned Src0Idx = NumDefs;
2854 bool HasClamp =
false;
2857 switch (
MI->getOpcode()) {
2858 case AMDGPU::V_ADD_U32_e32:
2860 case AMDGPU::V_ADD_U32_e64:
2861 HasClamp =
MI->getOperand(3).getImm();
2863 case AMDGPU::V_ADD_CO_U32_e32:
2864 VCCOp = &
MI->getOperand(3);
2866 case AMDGPU::V_ADD_CO_U32_e64:
2867 VCCOp = &
MI->getOperand(1);
2868 HasClamp =
MI->getOperand(4).getImm();
2873 bool DeadVCC = !VCCOp || VCCOp->
isDead();
2877 unsigned OtherOpIdx =
2878 FIOperandNum == Src0Idx ? FIOperandNum + 1 : Src0Idx;
2881 unsigned Src1Idx = Src0Idx + 1;
2882 Register MaterializedReg = FrameReg;
2885 int64_t
Offset = FrameInfo.getObjectOffset(Index);
2889 if ((!DeadVCC || HasClamp) &&
2896 if (OtherOp->
isImm()) {
2907 OtherOp->
setImm(TotalOffset);
2911 if (FrameReg && !ST.hasFlatScratchEnabled()) {
2919 ScavengedVGPR = RS->scavengeRegisterBackwards(
2920 AMDGPU::VGPR_32RegClass,
MI,
false, 0);
2926 .
addImm(ST.getWavefrontSizeLog2())
2928 MaterializedReg = ScavengedVGPR;
2931 if ((!OtherOp->
isImm() || OtherOp->
getImm() != 0) && MaterializedReg) {
2932 if (OtherOp->
isImm()) {
2934 FIOp->
setIsKill(MaterializedReg != FrameReg);
2936 if (ST.hasFlatScratchEnabled() &&
2937 !
TII->isOperandLegal(*
MI, Src1Idx, OtherOp)) {
2945 if (!ScavengedVGPR) {
2946 ScavengedVGPR = RS->scavengeRegisterBackwards(
2947 AMDGPU::VGPR_32RegClass,
MI,
false,
2951 assert(ScavengedVGPR != DstReg);
2957 MaterializedReg = ScavengedVGPR;
2966 AddI32.
add(
MI->getOperand(1));
2971 if (
isVGPRClass(getPhysRegBaseClass(MaterializedReg))) {
2974 AddI32.add(*OtherOp).addReg(MaterializedReg, MaterializedRegFlags);
2978 AddI32.addReg(MaterializedReg, MaterializedRegFlags).add(*OtherOp);
2981 if (
MI->getOpcode() == AMDGPU::V_ADD_CO_U32_e64 ||
2982 MI->getOpcode() == AMDGPU::V_ADD_U32_e64)
2985 if (
MI->getOpcode() == AMDGPU::V_ADD_CO_U32_e32)
2986 AddI32.setOperandDead(3);
2988 MaterializedReg = DstReg;
2995 }
else if (
Offset != 0) {
2996 assert(!MaterializedReg);
3000 if (DeadVCC && !HasClamp) {
3005 if (OtherOp->
isReg() && OtherOp->
getReg() == DstReg) {
3007 MI->eraseFromParent();
3012 MI->setDesc(
TII->get(AMDGPU::V_MOV_B32_e32));
3013 MI->removeOperand(FIOperandNum);
3015 unsigned NumOps =
MI->getNumOperands();
3016 for (
unsigned I =
NumOps - 2;
I >= NumDefs + 1; --
I)
3017 MI->removeOperand(
I);
3020 MI->removeOperand(1);
3032 if (!
TII->isOperandLegal(*
MI, Src1Idx) &&
TII->commuteInstruction(*
MI)) {
3040 for (
unsigned SrcIdx : {FIOperandNum, OtherOpIdx}) {
3041 if (!
TII->isOperandLegal(*
MI, SrcIdx)) {
3045 if (!ScavengedVGPR) {
3046 ScavengedVGPR = RS->scavengeRegisterBackwards(
3047 AMDGPU::VGPR_32RegClass,
MI,
false,
3051 assert(ScavengedVGPR != DstReg);
3057 Src.ChangeToRegister(ScavengedVGPR,
false);
3058 Src.setIsKill(
true);
3064 if (FIOp->
isImm() && FIOp->
getImm() == 0 && DeadVCC && !HasClamp) {
3065 if (OtherOp->
isReg() && OtherOp->
getReg() != DstReg) {
3069 MI->eraseFromParent();
3074 case AMDGPU::S_ADD_I32:
3075 case AMDGPU::S_ADD_U32: {
3077 unsigned OtherOpIdx = FIOperandNum == 1 ? 2 : 1;
3084 Register MaterializedReg = FrameReg;
3086 int64_t
Offset = FrameInfo.getObjectOffset(Index);
3089 bool DeadSCC =
MI->getOperand(3).isDead();
3100 if (FrameReg && !ST.hasFlatScratchEnabled()) {
3105 TmpReg = RS->scavengeRegisterBackwards(AMDGPU::SReg_32_XM0RegClass,
3112 .
addImm(ST.getWavefrontSizeLog2())
3115 MaterializedReg = TmpReg;
3121 if (OtherOp.
isImm()) {
3125 if (MaterializedReg)
3129 }
else if (MaterializedReg) {
3133 if (!TmpReg && MaterializedReg == FrameReg) {
3134 TmpReg = RS->scavengeRegisterBackwards(AMDGPU::SReg_32_XM0RegClass,
3148 MaterializedReg = DstReg;
3161 if (DeadSCC && OtherOp.
isImm() && OtherOp.
getImm() == 0) {
3163 MI->removeOperand(3);
3164 MI->removeOperand(OtherOpIdx);
3166 MI->setDesc(
TII->get(Src.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32));
3167 }
else if (DeadSCC && FIOp->
isImm() && FIOp->
getImm() == 0) {
3169 MI->removeOperand(3);
3170 MI->removeOperand(FIOperandNum);
3172 MI->setDesc(
TII->get(Src.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32));
3183 int64_t
Offset = FrameInfo.getObjectOffset(Index);
3184 if (ST.hasFlatScratchEnabled()) {
3185 if (
TII->isFLATScratch(*
MI)) {
3187 (int16_t)FIOperandNum ==
3188 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::saddr));
3195 TII->getNamedOperand(*
MI, AMDGPU::OpName::offset);
3206 unsigned Opc =
MI->getOpcode();
3210 }
else if (ST.hasFlatScratchSTMode()) {
3220 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
3221 bool TiedVDst = VDstIn != -1 &&
MI->getOperand(VDstIn).isReg() &&
3222 MI->getOperand(VDstIn).isTied();
3224 MI->untieRegOperand(VDstIn);
3227 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr));
3231 AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
3233 AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst_in);
3234 assert(NewVDst != -1 && NewVDstIn != -1 &&
"Must be tied!");
3235 MI->tieOperands(NewVDst, NewVDstIn);
3237 MI->setDesc(
TII->get(NewOpc));
3245 if (
TII->isOperandLegal(*
MI, FIOperandNum, FIOp))
3252 bool UseSGPR =
TII->isOperandLegal(*
MI, FIOperandNum, FIOp);
3254 if (!
Offset && FrameReg && UseSGPR) {
3260 UseSGPR ? &AMDGPU::SReg_32_XM0RegClass : &AMDGPU::VGPR_32RegClass;
3263 RS->scavengeRegisterBackwards(*RC,
MI,
false, 0, !UseSGPR);
3267 if ((!FrameReg || !
Offset) && TmpReg) {
3268 unsigned Opc = UseSGPR ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
3271 MIB.addReg(FrameReg);
3282 : RS->scavengeRegisterBackwards(AMDGPU::SReg_32_XM0RegClass,
3283 MI,
false, 0, !UseSGPR);
3289 if ((!TmpSReg && !FrameReg) || (!TmpReg && !UseSGPR)) {
3290 int SVfromSSOpcode =
3292 int SVfromSVSOpcode =
3294 int SVOpcode = SVfromSSOpcode != -1 ? SVfromSSOpcode : SVfromSVSOpcode;
3295 if (ST.hasFlatScratchSVSMode() && SVOpcode != -1) {
3302 "SV-form fallback cannot encode a frame register");
3308 int64_t FullOffset =
3310 TII->getNamedOperand(*
MI, AMDGPU::OpName::offset)->getImm();
3311 auto [ImmOffset, RemainderOffset] =
3317 TII->getNamedOperand(*
MI, AMDGPU::OpName::vaddr)) {
3319 TII->getNamedOperand(*
MI, AMDGPU::OpName::vdata);
3323 bool CanReuseVAddr = VAddr->isKill() &&
3324 !(VData && regsOverlap(Src, VData->
getReg()));
3326 : RS->scavengeRegisterBackwards(
3327 AMDGPU::VGPR_32RegClass,
MI,
3335 UsedVAddr = RS->scavengeRegisterBackwards(
3336 AMDGPU::VGPR_32RegClass,
MI,
false, 0,
true);
3338 .
addImm(RemainderOffset);
3341 .
add(
MI->getOperand(0))
3344 .
add(*
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol));
3345 MI->eraseFromParent();
3359 assert(!(
Offset & 0x1) &&
"Flat scratch offset must be aligned!");
3379 if (TmpSReg == FrameReg) {
3382 !
MI->registerDefIsDead(AMDGPU::SCC,
nullptr)) {
3406 bool IsMUBUF =
TII->isMUBUF(*
MI);
3415 bool SCCLiveAfterMI = RS->isRegUsed(AMDGPU::SCC);
3417 ? &AMDGPU::SReg_32RegClass
3418 : &AMDGPU::VGPR_32RegClass;
3419 bool IsCopy =
MI->getOpcode() == AMDGPU::V_MOV_B32_e32 ||
3420 MI->getOpcode() == AMDGPU::V_MOV_B32_e64 ||
3421 MI->getOpcode() == AMDGPU::S_MOV_B32;
3423 int64_t
Offset = FrameInfo.getObjectOffset(Index);
3428 bool CanUseFrameRegAsSGPRScratch = IsSALU && FrameReg &&
3429 !
MI->readsRegister(FrameReg,
this) &&
3430 !
MI->modifiesRegister(FrameReg,
this);
3433 bool CanUseFrameRegAsScratch = CanUseFrameRegAsSGPRScratch && !LiveSCC;
3435 bool RestoreFrameReg =
false;
3439 ResultReg =
MI->getOperand(0).getReg();
3441 ResultReg = RS->scavengeRegisterBackwards(*RC,
MI,
false, 0,
3444 if (CanUseFrameRegAsScratch) {
3447 ResultReg = FrameReg;
3448 RestoreFrameReg =
true;
3450 ResultReg = RS->scavengeRegisterBackwards(*RC,
MI,
false, 0);
3459 isWave32 ?
Add.getReg(1)
3460 :
Register(getSubReg(
Add.getReg(1), AMDGPU::sub0));
3463 return ConstOffsetReg;
3468 IsSALU && !LiveSCC ? AMDGPU::S_LSHR_B32 : AMDGPU::V_LSHRREV_B32_e64;
3470 if (IsSALU && LiveSCC) {
3471 TmpResultReg = RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
3476 if (OpCode == AMDGPU::V_LSHRREV_B32_e64)
3479 Shift.addImm(ST.getWavefrontSizeLog2()).addReg(FrameReg);
3481 Shift.addReg(FrameReg).addImm(ST.getWavefrontSizeLog2());
3482 if (IsSALU && !LiveSCC)
3483 Shift.getInstr()->getOperand(3).setIsDead();
3484 if (IsSALU && LiveSCC) {
3488 NewDest = ResultReg;
3493 NewDest = RS->scavengeRegisterBackwards(AMDGPU::SReg_32_XM0RegClass,
3497 if (CanUseFrameRegAsSGPRScratch) {
3499 RestoreFrameReg =
true;
3504 "unhandled SGPR spill to memory");
3505 NewDest = RS->scavengeRegisterBackwards(
3506 AMDGPU::SReg_32_XM0RegClass, Shift,
false, 0);
3512 ResultReg = NewDest;
3517 if ((MIB =
TII->getAddNoCarry(*
MBB,
MI,
DL, ResultReg, *RS)) !=
3524 .
addImm(ST.getWavefrontSizeLog2())
3527 const bool IsVOP2 = MIB->
getOpcode() == AMDGPU::V_ADD_U32_e32;
3539 "Need to reuse carry out register");
3547 if (!MIB || IsSALU) {
3554 Register TmpScaledReg = IsCopy && IsSALU
3556 : RS->scavengeRegisterBackwards(
3557 AMDGPU::SReg_32_XM0RegClass,
MI,
3563 ScaledReg = IsSALU ? ResultReg : FrameReg;
3569 .
addImm(ST.getWavefrontSizeLog2());
3574 TmpResultReg = RS->scavengeRegisterBackwards(
3575 AMDGPU::VGPR_32RegClass,
MI,
false, 0,
true);
3578 if ((
Add =
TII->getAddNoCarry(*
MBB,
MI,
DL, TmpResultReg, *RS))) {
3581 .
addImm(ST.getWavefrontSizeLog2())
3583 if (
Add->getOpcode() == AMDGPU::V_ADD_CO_U32_e64) {
3591 "offset is unsafe for v_mad_u32_u24");
3600 bool IsInlinableLiteral =
3602 if (!IsInlinableLiteral) {
3611 if (!IsInlinableLiteral) {
3617 Add.addImm(ST.getWavefrontSize()).addReg(FrameReg).addImm(0);
3620 .
addImm(ST.getWavefrontSizeLog2())
3626 NewDest = ResultReg;
3629 NewDest = RS->scavengeRegisterBackwards(
3630 AMDGPU::SReg_32_XM0RegClass, *
Add,
false, 0,
3633 if (CanUseFrameRegAsSGPRScratch) {
3635 RestoreFrameReg =
true;
3639 "unhandled SGPR spill to memory");
3640 NewDest = RS->scavengeRegisterBackwards(
3641 AMDGPU::SReg_32_XM0RegClass, *
Add,
false, 0);
3649 ResultReg = NewDest;
3657 if (!TmpScaledReg.
isValid()) {
3663 .
addImm(ST.getWavefrontSizeLog2());
3669 if (RestoreFrameReg) {
3678 .
addImm(ST.getWavefrontSize());
3681 int64_t ScaledOffset = -
Offset * ST.getWavefrontSize();
3682 if (!SCCLiveAfterMI) {
3702 MI->eraseFromParent();
3713 static_cast<int>(FIOperandNum) ==
3714 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::vaddr));
3716 auto &SOffset = *
TII->getNamedOperand(*
MI, AMDGPU::OpName::soffset);
3717 assert((SOffset.isImm() && SOffset.getImm() == 0));
3719 if (FrameReg != AMDGPU::NoRegister)
3720 SOffset.ChangeToRegister(FrameReg,
false);
3722 int64_t
Offset = FrameInfo.getObjectOffset(Index);
3724 TII->getNamedOperand(*
MI, AMDGPU::OpName::offset)->getImm();
3725 int64_t NewOffset = OldImm +
Offset;
3727 if (
TII->isLegalMUBUFImmOffset(NewOffset) &&
3729 MI->eraseFromParent();
3740 if (!
TII->isOperandLegal(*
MI, FIOperandNum, FIOp)) {
3742 TII->getRegClass(
MI->getDesc(), FIOperandNum);
3746 UseSGPR ? &AMDGPU::SReg_32_XM0RegClass : &AMDGPU::VGPR_32RegClass;
3747 Register TmpReg = RS->scavengeRegisterBackwards(*RC,
MI,
false, 0);
3749 TII->get(UseSGPR ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32),
3769 return &AMDGPU::VReg_64RegClass;
3771 return &AMDGPU::VReg_96RegClass;
3773 return &AMDGPU::VReg_128RegClass;
3775 return &AMDGPU::VReg_160RegClass;
3777 return &AMDGPU::VReg_192RegClass;
3779 return &AMDGPU::VReg_224RegClass;
3781 return &AMDGPU::VReg_256RegClass;
3783 return &AMDGPU::VReg_288RegClass;
3785 return &AMDGPU::VReg_320RegClass;
3787 return &AMDGPU::VReg_352RegClass;
3789 return &AMDGPU::VReg_384RegClass;
3791 return &AMDGPU::VReg_512RegClass;
3793 return &AMDGPU::VReg_1024RegClass;
3801 return &AMDGPU::VReg_64_Align2RegClass;
3803 return &AMDGPU::VReg_96_Align2RegClass;
3805 return &AMDGPU::VReg_128_Align2RegClass;
3807 return &AMDGPU::VReg_160_Align2RegClass;
3809 return &AMDGPU::VReg_192_Align2RegClass;
3811 return &AMDGPU::VReg_224_Align2RegClass;
3813 return &AMDGPU::VReg_256_Align2RegClass;
3815 return &AMDGPU::VReg_288_Align2RegClass;
3817 return &AMDGPU::VReg_320_Align2RegClass;
3819 return &AMDGPU::VReg_352_Align2RegClass;
3821 return &AMDGPU::VReg_384_Align2RegClass;
3823 return &AMDGPU::VReg_512_Align2RegClass;
3825 return &AMDGPU::VReg_1024_Align2RegClass;
3833 return &AMDGPU::VReg_1RegClass;
3835 return &AMDGPU::VGPR_16RegClass;
3837 return &AMDGPU::VGPR_32RegClass;
3845 return &AMDGPU::VGPR_32_Lo256RegClass;
3847 return &AMDGPU::VReg_64_Lo256_Align2RegClass;
3849 return &AMDGPU::VReg_96_Lo256_Align2RegClass;
3851 return &AMDGPU::VReg_128_Lo256_Align2RegClass;
3853 return &AMDGPU::VReg_160_Lo256_Align2RegClass;
3855 return &AMDGPU::VReg_192_Lo256_Align2RegClass;
3857 return &AMDGPU::VReg_224_Lo256_Align2RegClass;
3859 return &AMDGPU::VReg_256_Lo256_Align2RegClass;
3861 return &AMDGPU::VReg_288_Lo256_Align2RegClass;
3863 return &AMDGPU::VReg_320_Lo256_Align2RegClass;
3865 return &AMDGPU::VReg_352_Lo256_Align2RegClass;
3867 return &AMDGPU::VReg_384_Lo256_Align2RegClass;
3869 return &AMDGPU::VReg_512_Lo256_Align2RegClass;
3871 return &AMDGPU::VReg_1024_Lo256_Align2RegClass;
3879 return &AMDGPU::AReg_64RegClass;
3881 return &AMDGPU::AReg_96RegClass;
3883 return &AMDGPU::AReg_128RegClass;
3885 return &AMDGPU::AReg_160RegClass;
3887 return &AMDGPU::AReg_192RegClass;
3889 return &AMDGPU::AReg_224RegClass;
3891 return &AMDGPU::AReg_256RegClass;
3893 return &AMDGPU::AReg_288RegClass;
3895 return &AMDGPU::AReg_320RegClass;
3897 return &AMDGPU::AReg_352RegClass;
3899 return &AMDGPU::AReg_384RegClass;
3901 return &AMDGPU::AReg_512RegClass;
3903 return &AMDGPU::AReg_1024RegClass;
3911 return &AMDGPU::AReg_64_Align2RegClass;
3913 return &AMDGPU::AReg_96_Align2RegClass;
3915 return &AMDGPU::AReg_128_Align2RegClass;
3917 return &AMDGPU::AReg_160_Align2RegClass;
3919 return &AMDGPU::AReg_192_Align2RegClass;
3921 return &AMDGPU::AReg_224_Align2RegClass;
3923 return &AMDGPU::AReg_256_Align2RegClass;
3925 return &AMDGPU::AReg_288_Align2RegClass;
3927 return &AMDGPU::AReg_320_Align2RegClass;
3929 return &AMDGPU::AReg_352_Align2RegClass;
3931 return &AMDGPU::AReg_384_Align2RegClass;
3933 return &AMDGPU::AReg_512_Align2RegClass;
3935 return &AMDGPU::AReg_1024_Align2RegClass;
3943 return &AMDGPU::AGPR_LO16RegClass;
3945 return &AMDGPU::AGPR_32RegClass;
3953 return &AMDGPU::AV_64RegClass;
3955 return &AMDGPU::AV_96RegClass;
3957 return &AMDGPU::AV_128RegClass;
3959 return &AMDGPU::AV_160RegClass;
3961 return &AMDGPU::AV_192RegClass;
3963 return &AMDGPU::AV_224RegClass;
3965 return &AMDGPU::AV_256RegClass;
3967 return &AMDGPU::AV_288RegClass;
3969 return &AMDGPU::AV_320RegClass;
3971 return &AMDGPU::AV_352RegClass;
3973 return &AMDGPU::AV_384RegClass;
3975 return &AMDGPU::AV_512RegClass;
3977 return &AMDGPU::AV_1024RegClass;
3985 return &AMDGPU::AV_64_Align2RegClass;
3987 return &AMDGPU::AV_96_Align2RegClass;
3989 return &AMDGPU::AV_128_Align2RegClass;
3991 return &AMDGPU::AV_160_Align2RegClass;
3993 return &AMDGPU::AV_192_Align2RegClass;
3995 return &AMDGPU::AV_224_Align2RegClass;
3997 return &AMDGPU::AV_256_Align2RegClass;
3999 return &AMDGPU::AV_288_Align2RegClass;
4001 return &AMDGPU::AV_320_Align2RegClass;
4003 return &AMDGPU::AV_352_Align2RegClass;
4005 return &AMDGPU::AV_384_Align2RegClass;
4007 return &AMDGPU::AV_512_Align2RegClass;
4009 return &AMDGPU::AV_1024_Align2RegClass;
4017 return &AMDGPU::AV_32RegClass;
4018 return ST.needsAlignedVGPRs()
4037 return &AMDGPU::SReg_32RegClass;
4039 return &AMDGPU::SReg_64RegClass;
4041 return &AMDGPU::SGPR_96RegClass;
4043 return &AMDGPU::SGPR_128RegClass;
4045 return &AMDGPU::SGPR_160RegClass;
4047 return &AMDGPU::SGPR_192RegClass;
4049 return &AMDGPU::SGPR_224RegClass;
4051 return &AMDGPU::SGPR_256RegClass;
4053 return &AMDGPU::SGPR_288RegClass;
4055 return &AMDGPU::SGPR_320RegClass;
4057 return &AMDGPU::SGPR_352RegClass;
4059 return &AMDGPU::SGPR_384RegClass;
4061 return &AMDGPU::SGPR_512RegClass;
4063 return &AMDGPU::SGPR_1024RegClass;
4071 if (Reg.isVirtual())
4072 RC =
MRI.getRegClass(Reg);
4074 RC = getPhysRegBaseClass(Reg);
4080 unsigned Size = getRegSizeInBits(*SRC);
4082 switch (SRC->
getID()) {
4085 case AMDGPU::VS_16_Lo128RegClassID:
4086 return getAllocatableClass(&AMDGPU::VGPR_16_Lo128RegClass);
4087 case AMDGPU::VS_32_Lo128RegClassID:
4088 return getAllocatableClass(&AMDGPU::VGPR_32_Lo128RegClass);
4089 case AMDGPU::VS_32_Lo256RegClassID:
4090 case AMDGPU::VS_64_Lo256RegClassID:
4096 assert(VRC &&
"Invalid register class size");
4102 unsigned Size = getRegSizeInBits(*SRC);
4104 assert(ARC &&
"Invalid register class size");
4110 unsigned Size = getRegSizeInBits(*SRC);
4112 assert(ARC &&
"Invalid register class size");
4118 unsigned Size = getRegSizeInBits(*VRC);
4120 return &AMDGPU::SGPR_32RegClass;
4122 assert(SRC &&
"Invalid register class size");
4129 unsigned SubIdx)
const {
4132 getMatchingSuperRegClass(SuperRC, SubRC, SubIdx);
4133 return MatchRC && MatchRC->
hasSubClassEq(SuperRC) ? MatchRC :
nullptr;
4139 return !ST.hasMFMAInlineLiteralBug();
4160 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::VCC_HI;
4163 if (ReserveHighestRegister) {
4165 if (
MRI.isAllocatable(Reg) && !
MRI.isPhysRegUsed(Reg) && !isVCC(Reg))
4169 if (
MRI.isAllocatable(Reg) && !
MRI.isPhysRegUsed(Reg) && !isVCC(Reg))
4186 unsigned EltSize)
const {
4188 assert(RegBitWidth >= 32 && RegBitWidth <= 1024 && EltSize >= 2);
4190 const unsigned RegHalves = RegBitWidth / 16;
4191 const unsigned EltHalves = EltSize / 2;
4192 assert(RegSplitParts.size() + 1 >= EltHalves);
4194 const std::vector<int16_t> &Parts = RegSplitParts[EltHalves - 1];
4195 const unsigned NumParts = RegHalves / EltHalves;
4203 return Reg.isVirtual() ?
MRI.getRegClass(Reg) : getPhysRegBaseClass(Reg);
4210 return getSubRegisterClass(SrcRC, MO.
getSubReg());
4230 unsigned MinOcc = ST.getOccupancyWithWorkGroupSizes(MF).first;
4231 switch (RC->
getID()) {
4233 return AMDGPUGenRegisterInfo::getRegPressureLimit(RC, MF);
4234 case AMDGPU::VGPR_32RegClassID:
4239 ST.getMaxNumVGPRs(MF));
4240 case AMDGPU::SGPR_32RegClassID:
4241 case AMDGPU::SGPR_LO16RegClassID:
4242 return std::min(ST.getMaxNumSGPRs(MinOcc,
true), ST.getMaxNumSGPRs(MF));
4247 unsigned Idx)
const {
4248 switch (
static_cast<AMDGPU::RegisterPressureSets
>(Idx)) {
4249 case AMDGPU::RegisterPressureSets::VGPR_32:
4250 case AMDGPU::RegisterPressureSets::AGPR_32:
4253 case AMDGPU::RegisterPressureSets::SReg_32:
4262 static const int Empty[] = { -1 };
4264 if (RegPressureIgnoredUnits[
static_cast<unsigned>(RegUnit)])
4267 return AMDGPUGenRegisterInfo::getRegUnitPressureSets(RegUnit);
4280 std::pair<unsigned, Register> Hint =
MRI.getRegAllocationHint(VirtReg);
4282 switch (Hint.first) {
4289 getMatchingSuperReg(Paired, AMDGPU::lo16, &AMDGPU::VGPR_32RegClass);
4290 }
else if (VRM && VRM->
hasPhys(Paired)) {
4291 PairedPhys = getMatchingSuperReg(VRM->
getPhys(Paired), AMDGPU::lo16,
4292 &AMDGPU::VGPR_32RegClass);
4299 Hints.
insert(PairedPhys);
4307 PairedPhys =
TRI->getSubReg(Paired, AMDGPU::lo16);
4308 }
else if (VRM && VRM->
hasPhys(Paired)) {
4309 PairedPhys =
TRI->getSubReg(VRM->
getPhys(Paired), AMDGPU::lo16);
4314 Hints.
insert(PairedPhys);
4324 if (AMDGPU::VGPR_16RegClass.
contains(PhysReg) &&
4325 !
MRI.isReserved(PhysReg))
4339 unsigned &MaxVGPRsForCurrentOccupancy)
const {
4344 unsigned CurrentOccupancy =
4345 ST.getOccupancyWithNumVGPRs(NumAllocatedVGPRs, DynamicVGPRBlockSize);
4346 MaxVGPRsForCurrentOccupancy =
4347 ST.getMaxNumVGPRs(CurrentOccupancy, DynamicVGPRBlockSize);
4349 LLVM_DEBUG(
dbgs() <<
"anti-hints: VGPRs allocated = " << NumAllocatedVGPRs
4350 <<
", RecordedMaxOccupancy = " << RecordedMaxOccupancy
4351 <<
", current occupancy = " << CurrentOccupancy <<
'\n');
4355 if (CurrentOccupancy == 1)
4364 unsigned MaxVGPRsCutOffForRecordedMaxOccupancy =
4365 (ST.getMaxNumVGPRs(RecordedMaxOccupancy, DynamicVGPRBlockSize) * 80) /
4367 unsigned MaxVGPRsCutOffForCurrentOccupancy =
4368 (MaxVGPRsForCurrentOccupancy * 95) / 100;
4370 if (NumAllocatedVGPRs >= MaxVGPRsCutOffForRecordedMaxOccupancy) {
4372 << MaxVGPRsCutOffForRecordedMaxOccupancy
4373 <<
" VGPR cutoff for RecordedMaxOccupancy\n");
4377 if (NumAllocatedVGPRs >= MaxVGPRsCutOffForCurrentOccupancy) {
4379 << MaxVGPRsCutOffForCurrentOccupancy
4380 <<
" VGPR cutoff for current occupancy\n");
4388bool SIRegisterInfo::isRegWithinOccupancyBudget(
4389 MCPhysReg Reg,
unsigned NumVGPRs,
unsigned NumAGPRs,
4390 unsigned MaxVGPRsForCurrentOccupancy)
const {
4397 unsigned RegEndIndex =
4400 unsigned MaxVGPR = NumVGPRs;
4401 unsigned MaxAGPR = NumAGPRs;
4404 MaxAGPR = std::max(MaxAGPR, RegEndIndex);
4406 MaxVGPR = std::max(MaxVGPR, RegEndIndex);
4408 return static_cast<unsigned>(
4410 MaxVGPRsForCurrentOccupancy;
4419 return isAntiHintedReg(Reg, AntiHintedRegUnits);
4425 "SGPR anti-hints are not handled");
4426 unsigned NumVGPRs = 0;
4427 unsigned NumAGPRs = 0;
4429 assert(
Matrix &&
"LiveRegMatrix required to compute occupancy");
4430 assert(RegClassInfo &&
"RegClassInfo required to compute occupancy");
4432 if (
Matrix->isPhysRegUsed(Reg) ||
4433 MRI.isPhysRegUsed(Reg,
true))
4438 if (
Matrix->isPhysRegUsed(Reg) ||
4439 MRI.isPhysRegUsed(Reg,
true))
4443 unsigned NumAllocatedVGPRs =
4447 unsigned MaxVGPRsForCurrentOccupancy = 0;
4453 auto *BeyondBudgetStart = std::stable_partition(
4455 return isRegWithinOccupancyBudget(Reg, NumVGPRs, NumAGPRs,
4456 MaxVGPRsForCurrentOccupancy);
4459 [[maybe_unused]]
auto *PartitionPoint = std::stable_partition(
4460 CustomOrder.
begin(), BeyondBudgetStart,
4461 [&](
MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
4464 size_t NonAntiHintedCount =
4465 std::distance(CustomOrder.
begin(), PartitionPoint);
4466 size_t AntiHintedCount = std::distance(PartitionPoint, BeyondBudgetStart);
4467 size_t BeyondBudgetCount =
4468 std::distance(BeyondBudgetStart, CustomOrder.
end());
4469 dbgs() <<
"Added " << NonAntiHintedCount
4470 <<
" non-anti-hinted registers first\n"
4471 <<
"Added " << AntiHintedCount
4472 <<
" anti-hinted registers at the end\n"
4473 <<
"Beyond current occupancy budget, left: " << BeyondBudgetCount
4480 return AMDGPU::SGPR30_SGPR31;
4486 unsigned SizeEnc =
static_cast<unsigned>(
Size);
4487 switch (RB.
getID()) {
4488 case AMDGPU::VGPRRegBankID:
4490 std::max(ST.useRealTrue16Insts() ? 16u : 32u, SizeEnc));
4491 case AMDGPU::VCCRegBankID:
4494 case AMDGPU::SGPRRegBankID:
4496 case AMDGPU::AGPRRegBankID:
4510 return getAllocatableClass(RC);
4516 return isWave32 ? AMDGPU::VCC_LO : AMDGPU::VCC;
4520 return isWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
4525 return ST.needsAlignedVGPRs() ? &AMDGPU::VReg_64_Align2RegClass
4526 : &AMDGPU::VReg_64RegClass;
4538 if (Reg.isVirtual()) {
4542 LaneBitmask SubLanes = SubReg ? getSubRegIndexLaneMask(SubReg)
4543 :
MRI.getMaxLaneMaskForVReg(Reg);
4547 if ((S.LaneMask & SubLanes) == SubLanes) {
4548 V = S.getVNInfoAt(UseIdx);
4560 for (MCRegUnit Unit : regunits(Reg.asMCReg())) {
4575 if (!Def || !MDT.dominates(Def, &
Use))
4578 assert(Def->modifiesRegister(Reg,
this));
4584 assert(getRegSizeInBits(*getPhysRegBaseClass(Reg)) <= 32);
4587 {&AMDGPU::VGPR_32RegClass, &AMDGPU::SReg_32RegClass,
4588 &AMDGPU::AGPR_32RegClass}) {
4589 if (
MCRegister Super = getMatchingSuperReg(Reg, AMDGPU::lo16, RC))
4593 getMatchingSuperReg(Reg, AMDGPU::hi16, &AMDGPU::VGPR_32RegClass)) {
4597 return AMDGPU::NoRegister;
4601 if (!ST.needsAlignedVGPRs())
4612 assert(&RC != &AMDGPU::VS_64RegClass);
4619 return ArrayRef(AMDGPU::SGPR_128RegClass.begin(), ST.getMaxNumSGPRs(MF) / 4);
4624 return ArrayRef(AMDGPU::SGPR_64RegClass.begin(), ST.getMaxNumSGPRs(MF) / 2);
4629 return ArrayRef(AMDGPU::SGPR_32RegClass.begin(), ST.getMaxNumSGPRs(MF));
4634 unsigned SubReg)
const {
4637 return std::min(128u, getSubRegIdxSize(SubReg));
4641 return std::min(32u, getSubRegIdxSize(SubReg));
4650 bool IncludeCalls)
const {
4651 unsigned NumArchVGPRs = ST.getAddressableNumArchVGPRs();
4653 (RC.
getID() == AMDGPU::VGPR_32RegClassID)
4657 if (Reg != AMDGPU::VCC_LO && Reg != AMDGPU::VCC_HI &&
4658 MRI.isPhysRegUsed(Reg, !IncludeCalls))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
AMDGPU Reserve WWM Registers
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineRegisterInfo & MRI
This file declares the machine register scavenger class.
static MachineInstrBuilder spillVGPRtoAGPR(const GCNSubtarget &ST, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, int Index, unsigned Lane, unsigned ValueReg, bool IsKill, bool NeedsCFI)
static int getOffenMUBUFStore(unsigned Opc)
static bool wrapsAround32(int64_t LHS, int64_t RHS)
static const TargetRegisterClass * getAnyAGPRClassForBitWidth(unsigned BitWidth)
static bool isSCCLiveInto(const RegScavenger &RS, const MachineInstr &MI)
static int getOffsetMUBUFLoad(unsigned Opc)
static const std::array< unsigned, 17 > SubRegFromChannelTableWidthMap
static unsigned getNumSubRegsForSpillOp(const MachineInstr &MI, const SIInstrInfo *TII)
static cl::opt< bool > EnableSpillCFISavedRegs("amdgpu-spill-cfi-saved-regs", cl::desc("Enable spilling the registers required for CFI emission"), cl::ReallyHidden, cl::init(false))
static void emitUnsupportedError(const Function &Fn, const MachineInstr &MI, const Twine &ErrMsg)
static const TargetRegisterClass * getAlignedAGPRClassForBitWidth(unsigned BitWidth)
static bool buildMUBUFOffsetLoadStore(const GCNSubtarget &ST, MachineFrameInfo &MFI, MachineBasicBlock::iterator MI, int Index, int64_t Offset)
static unsigned getFlatScratchSpillOpcode(const SIInstrInfo *TII, unsigned LoadStoreOp, unsigned EltSize)
static const TargetRegisterClass * getAlignedVGPRClassForBitWidth(unsigned BitWidth)
static int getOffsetMUBUFStore(unsigned Opc)
static const TargetRegisterClass * getAnyVGPRClassForBitWidth(unsigned BitWidth)
static cl::opt< unsigned > StressSGPRLimit("amdgpu-stress-sgpr", cl::Hidden, cl::init(0), cl::desc("Limit SGPRs to N registers by reserving the rest"))
static cl::opt< bool > EnableSpillSGPRToVGPR("amdgpu-spill-sgpr-to-vgpr", cl::desc("Enable spilling SGPRs to VGPRs"), cl::ReallyHidden, cl::init(true))
static const TargetRegisterClass * getAlignedVectorSuperClassForBitWidth(unsigned BitWidth)
static const TargetRegisterClass * getAnyVectorSuperClassForBitWidth(unsigned BitWidth)
static cl::opt< unsigned > StressAGPRLimit("amdgpu-stress-agpr", cl::Hidden, cl::init(0), cl::desc("Limit AGPRs to N registers by reserving the rest"))
static cl::opt< unsigned > StressVGPRLimit("amdgpu-stress-vgpr", cl::Hidden, cl::init(0), cl::desc("Limit VGPRs to N registers by reserving the rest"))
static bool foldingOffsetChangesCarry(const MachineOperand &OtherOp, int64_t Offset, Register FrameReg)
static bool isFIPlusImmOrVGPR(const SIRegisterInfo &TRI, const MachineInstr &MI)
static int getOffenMUBUFLoad(unsigned Opc)
Interface definition for SIRegisterInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
static const char * getRegisterName(MCRegister Reg)
bool isBottomOfStack() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
bool empty() const
Returns whether there are no bits in this bitvector.
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...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasSubRanges() const
Returns true if subregister liveness information is available.
iterator_range< subrange_iterator > subranges()
void removeAllRegUnitsForPhysReg(MCRegister Reg)
Remove associated live ranges for the register units associated with Reg.
bool hasInterval(Register Reg) const
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
MachineDominatorTree & getDomTree()
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LiveRange & getRegUnit(MCRegUnit Unit)
Return the live range for register unit Unit.
This class represents the liveness of a register, stack slot, etc.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
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.
Describe properties that are true of each instruction in the target description file.
MCRegAliasIterator enumerates all registers aliasing Reg.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
unsigned getID() const
getID() - Return the register class ID number.
ArrayRef< MCPhysReg > getRegisters() const
const uint8_t TSFlags
Configurable target specific flags.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Wrapper class representing physical registers. Should be passed by value.
static MCRegister from(unsigned Val)
Check the provided unsigned value is a valid MCRegister.
Generic base class for all target subtargets.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasCalls() const
Return true if the current function has any function calls.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool hasStackObjects() const
Return true if there are any stack objects in this function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
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...
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 & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void setAsmPrinterFlag(AsmPrinterFlagTy Flag)
Set a flag for the AsmPrinter.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
void setImm(int64_t immVal)
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Holds all the information related to register banks.
virtual bool isDivergentRegBank(const RegisterBank *RB) const
Returns true if the register bank is considered divergent.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
ArrayRef< MCPhysReg > getOrder(const TargetRegisterClass *RC) const
getOrder - Returns the preferred allocation order for RC.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
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.
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...
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 ...
static bool isFLATScratch(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
static bool isVOP3(const MCInstrDesc &Desc)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
ArrayRef< MCPhysReg > getAGPRSpillVGPRs() const
unsigned getOccupancy() const
MCPhysReg getVGPRToAGPRSpill(int FrameIndex, unsigned Lane) const
Register getLongBranchReservedReg() const
unsigned getDynamicVGPRBlockSize() const
Register getStackPtrOffsetReg() const
Register getScratchRSrcReg() const
Returns the physical register reserved for use as the resource descriptor for scratch accesses.
ArrayRef< MCPhysReg > getVGPRSpillAGPRs() const
ArrayRef< SIRegisterInfo::SpilledReg > getSGPRSpillToVirtualVGPRLanes(int FrameIndex) const
uint32_t getMaskForVGPRBlockOps(Register RegisterBlock) const
Register getSGPRForEXECCopy() const
ArrayRef< SIRegisterInfo::SpilledReg > getSGPRSpillToPhysicalVGPRLanes(int FrameIndex) const
Register getVGPRForAGPRCopy() const
Register getFrameOffsetReg() const
BitVector getPerLaneVGPRMask() const
bool checkFlag(Register Reg, uint8_t Flag) const
void addToSpilledVGPRs(unsigned num)
const ReservedRegSet & getWWMReservedRegs() const
void addToSpilledSGPRs(unsigned num)
Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, int64_t Offset) const override
const TargetRegisterClass * getRegClassForSizeOnBank(uint64_t Size, const RegisterBank &Bank) const
int64_t getScratchInstrOffset(const MachineInstr *MI) const
bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, int64_t Offset) const override
const TargetRegisterClass * getCompatibleSubRegClass(const TargetRegisterClass *SuperRC, const TargetRegisterClass *SubRC, unsigned SubIdx) const
Returns a register class which is compatible with SuperRC, such that a subregister exists with class ...
ArrayRef< MCPhysReg > getAllSGPR64(const MachineFunction &MF) const
Return all SGPR64 which satisfy the waves per execution unit requirement of the subtarget.
MCRegister findUnusedRegister(const MachineRegisterInfo &MRI, const TargetRegisterClass *RC, const MachineFunction &MF, bool ReserveHighestVGPR=false) const
Returns a lowest register that is not used at any point in the function.
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
void buildSpillLoadStore(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, unsigned LoadStoreOp, int Index, Register ValueReg, bool ValueIsKill, MCRegister ScratchOffsetReg, int64_t InstrOffset, MachineMemOperand *MMO, RegScavenger *RS, LiveRegUnits *LiveUnits=nullptr, bool NeedsCFI=false) const
bool requiresFrameIndexReplacementScavenging(const MachineFunction &MF) const override
bool shouldRealignStack(const MachineFunction &MF) const override
bool restoreSGPR(MachineBasicBlock::iterator MI, int FI, RegScavenger *RS, SlotIndexes *Indexes=nullptr, LiveIntervals *LIS=nullptr, bool OnlyToVGPR=false, bool SpillToPhysVGPRLane=false) const
bool isProperlyAlignedRC(const TargetRegisterClass &RC) const
static bool hasVectorRegisters(const TargetRegisterClass *RC)
const TargetRegisterClass * getEquivalentVGPRClass(const TargetRegisterClass *SRC) const
Register getFrameRegister(const MachineFunction &MF) const override
LLVM_READONLY const TargetRegisterClass * getVectorSuperClassForBitWidth(unsigned BitWidth) const
bool spillEmergencySGPR(MachineBasicBlock::iterator MI, MachineBasicBlock &RestoreMBB, Register SGPR, RegScavenger *RS) const
SIRegisterInfo(const GCNSubtarget &ST)
const uint32_t * getAllVGPRRegMask() const
MCRegister getReturnAddressReg(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
bool hasBasePointer(const MachineFunction &MF) const
const TargetRegisterClass * getCrossCopyRegClass(const TargetRegisterClass *RC) const override
Returns a legal register class to copy a register in the specified class to or from.
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
ArrayRef< MCPhysReg > getAllSGPR32(const MachineFunction &MF) const
Return all SGPR32 which satisfy the waves per execution unit requirement of the subtarget.
const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, const MachineFunction &MF) const override
MCRegister reservedPrivateSegmentBufferReg(const MachineFunction &MF) const
Return the end register initially reserved for the scratch buffer in case spilling is needed.
bool eliminateSGPRToVGPRSpillFrameIndex(MachineBasicBlock::iterator MI, int FI, RegScavenger *RS, SlotIndexes *Indexes=nullptr, LiveIntervals *LIS=nullptr, bool SpillToPhysVGPRLane=false) const
Special case of eliminateFrameIndex.
bool isVGPR(const MachineRegisterInfo &MRI, Register Reg) const
bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallSetVector< MCPhysReg, 16 > &Hints, const MachineFunction &MF, const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const override
bool isAsmClobberable(const MachineFunction &MF, MCRegister PhysReg) const override
LLVM_READONLY const TargetRegisterClass * getAGPRClassForBitWidth(unsigned BitWidth) const
static bool isChainScratchRegister(Register VGPR)
MCRegister get32BitRegister(MCRegister Reg) const
bool requiresRegisterScavenging(const MachineFunction &Fn) const override
bool opCanUseInlineConstant(unsigned OpType) const
bool isUniformReg(const MachineRegisterInfo &MRI, const RegisterBankInfo &RBI, Register Reg) const override
const uint32_t * getNoPreservedMask() const override
bool shouldApplyAntiHints(const MachineFunction &MF, unsigned NumAllocatedVGPRs, unsigned &MaxVGPRsForCurrentOccupancy) const
StringRef getRegAsmName(MCRegister Reg) const override
MCRegister getAlignedHighSGPRForRC(const MachineFunction &MF, const unsigned Align, const TargetRegisterClass *RC) const
Return the largest available SGPR aligned to Align for the register class RC.
void buildCFIForBlockCSRStore(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register BlockReg, int64_t Offset) const
const TargetRegisterClass * getRegClassForReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getHWRegIndex(MCRegister Reg) const
const MCPhysReg * getCalleeSavedRegsViaCopy(const MachineFunction *MF) const
const uint32_t * getAllVectorRegMask() const
const TargetRegisterClass * getEquivalentAGPRClass(const TargetRegisterClass *SRC) const
void filterAndSortForAntiHintedRegs(Register VirtReg, MutableArrayRef< MCPhysReg > CustomOrder, const BitVector &AntiHintedRegUnits, const MachineFunction &MF, const LiveRegMatrix *Matrix=nullptr, const RegisterClassInfo *RegClassInfo=nullptr) const override
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
const TargetRegisterClass * getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank) const
bool opCanUseLiteralConstant(unsigned OpType) const
Register getBaseRegister() const
LLVM_READONLY const TargetRegisterClass * getAlignedLo256VGPRClassForBitWidth(unsigned BitWidth) const
LLVM_READONLY const TargetRegisterClass * getVGPRClassForBitWidth(unsigned BitWidth) const
const TargetRegisterClass * getEquivalentAVClass(const TargetRegisterClass *SRC) const
bool requiresFrameIndexScavenging(const MachineFunction &MF) const override
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
static bool isVGPRClass(const TargetRegisterClass *RC)
MachineInstr * findReachingDef(Register Reg, unsigned SubReg, MachineInstr &Use, MachineRegisterInfo &MRI, LiveIntervals *LIS) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
const TargetRegisterClass * getEquivalentSGPRClass(const TargetRegisterClass *VRC) const
SmallVector< StringLiteral > getVRegFlagsOfReg(Register Reg, const MachineFunction &MF) const override
LLVM_READONLY const TargetRegisterClass * getDefaultVectorSuperClassForBitWidth(unsigned BitWidth) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
ArrayRef< MCPhysReg > getAllSGPR128(const MachineFunction &MF) const
Return all SGPR128 which satisfy the waves per execution unit requirement of the subtarget.
unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override
const TargetRegisterClass * getRegClassForOperandReg(const MachineRegisterInfo &MRI, const MachineOperand &MO) const
void addImplicitUsesForBlockCSRLoad(MachineInstrBuilder &MIB, Register BlockReg) const
unsigned getNumUsedPhysRegs(const MachineRegisterInfo &MRI, const TargetRegisterClass &RC, bool IncludeCalls=true) const
const uint32_t * getAllAGPRRegMask() const
const int * getRegUnitPressureSets(MCRegUnit RegUnit) const override
bool isAGPR(const MachineRegisterInfo &MRI, Register Reg) const
bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const override
bool spillSGPR(MachineBasicBlock::iterator MI, int FI, RegScavenger *RS, SlotIndexes *Indexes=nullptr, LiveIntervals *LIS=nullptr, bool OnlyToVGPR=false, bool SpillToPhysVGPRLane=false, bool NeedsCFI=false) const
If OnlyToVGPR is true, this will only succeed if this manages to find a free VGPR lane to spill.
MCRegister getExec() const
MCRegister getVCC() const
int64_t getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const override
bool isVectorSuperClass(const TargetRegisterClass *RC) const
const TargetRegisterClass * getWaveMaskRegClass() const
unsigned getSubRegAlignmentNumBits(const TargetRegisterClass *RC, unsigned SubReg) const
void resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const override
bool requiresVirtualBaseRegisters(const MachineFunction &Fn) const override
const TargetRegisterClass * getVGPR64Class() const
void buildVGPRSpillLoadStore(SGPRSpillBuilder &SB, int Index, int Offset, bool IsLoad, bool IsKill=true) const
bool isCFISavedRegsSpillEnabled() const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
const TargetRegisterClass * getConstrainedRegClassForReg(Register Reg, const MachineRegisterInfo &MRI) const override
bool insert(const value_type &X)
Insert a new element into the SetVector.
SlotIndex - An opaque wrapper around machine indexes.
bool isValid() const
Returns true if this is a valid index.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
SlotIndex replaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in maps used by register allocat...
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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 const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, const MachineFunction &) const
Returns the largest super class of RC that is legal to use in the current sub-target and has the same...
virtual bool shouldRealignStack(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
virtual bool getRegAllocationHints(Register VirtReg, ArrayRef< MCPhysReg > Order, SmallSetVector< MCPhysReg, 16 > &Hints, const MachineFunction &MF, const VirtRegMap *VRM=nullptr, const LiveRegMatrix *Matrix=nullptr) const
Get a list of 'hint' registers that the register allocator should try first when allocating a physica...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
VNInfo - Value Number Information.
MCRegister getPhys(Register virtReg) const
returns the physical register mapped to the specified virtual register
bool hasPhys(Register virtReg) const
returns true if the specified virtual register is mapped to a physical register
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ PRIVATE_ADDRESS
Address space for private memory.
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_ABI unsigned getTotalNumVGPRs(GPUKind AK, bool IsWave32)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
@ OPERAND_REG_INLINE_AC_FIRST
@ OPERAND_REG_INLINE_AC_LAST
LLVM_READONLY int32_t getFlatScratchInstSVfromSVS(uint32_t Opcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
LLVM_READONLY int32_t getFlatScratchInstSTfromSS(uint32_t Opcode)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
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.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
constexpr bool hasRegState(RegState Value, RegState Test)
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ Sub
Subtraction 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 >
void call_once(once_flag &flag, Function &&F, Args &&... ArgList)
Execute the function specified as a parameter once.
constexpr unsigned BitWidth
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
void setMI(MachineBasicBlock *NewMBB, MachineBasicBlock::iterator NewMI)
ArrayRef< int16_t > SplitParts
SIMachineFunctionInfo & MFI
SGPRSpillBuilder(const SIRegisterInfo &TRI, const SIInstrInfo &TII, bool IsWave32, MachineBasicBlock::iterator MI, int Index, RegScavenger *RS)
SGPRSpillBuilder(const SIRegisterInfo &TRI, const SIInstrInfo &TII, bool IsWave32, MachineBasicBlock::iterator MI, Register Reg, bool IsKill, int Index, RegScavenger *RS)
PerVGPRData getPerVGPRData()
MachineBasicBlock::iterator MI
void readWriteTmpVGPR(unsigned Offset, bool IsLoad)
const SIRegisterInfo & TRI
The llvm::once_flag structure.