33#include "llvm/IR/IntrinsicsAMDGPU.h"
42#define DEBUG_TYPE "si-instr-info"
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#define GET_GFX1250BlockingCyclesTable_DECL
51#define GET_GFX1250BlockingCyclesTable_IMPL
58#include "AMDGPUGenSearchableTables.inc"
66 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
69 "amdgpu-fix-16-bit-physreg-copies",
70 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
86 unsigned N =
Node->getNumOperands();
87 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
99 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
100 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
102 if (Op0Idx == -1 && Op1Idx == -1)
106 if ((Op0Idx == -1 && Op1Idx != -1) ||
107 (Op1Idx == -1 && Op0Idx != -1))
128 return !
MI.memoperands_empty() &&
130 return MMO->isLoad() && MMO->isInvariant();
139static std::tuple<unsigned, unsigned, unsigned>
147 unsigned LoReloc, HiReloc;
177 return {BaseFlags, LoReloc, HiReloc};
195 if (!
MI.hasImplicitDef() &&
196 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
197 !
MI.mayRaiseFPException())
206 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
221 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
222 MI.hasUnmodeledSideEffects())
227 if (
MI.isInlineAsm())
231 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
246 if (Reg.isPhysical()) {
251 if (!
MRI.isConstantPhysReg(Reg))
262 if (MO.isDef() && Reg != DefReg)
272 case AMDGPU::V_SUBREV_U16_e32:
273 case AMDGPU::V_SUBREV_U16_e64:
275 case AMDGPU::V_SUBREV_U32_e32:
276 case AMDGPU::V_SUBREV_U32_e64:
278 case AMDGPU::V_SUBREV_CO_U32_e32:
279 case AMDGPU::V_SUBREV_CO_U32_e64:
281 case AMDGPU::V_SUBBREV_U32_e32:
282 case AMDGPU::V_SUBBREV_U32_e64:
285 case AMDGPU::V_ASHRREV_I16_e32:
286 case AMDGPU::V_ASHRREV_I16_e64:
287 case AMDGPU::V_ASHRREV_I32_e32:
288 case AMDGPU::V_ASHRREV_I32_e64:
289 case AMDGPU::V_ASHRREV_I64_e64:
290 case AMDGPU::V_LSHLREV_B16_e32:
291 case AMDGPU::V_LSHLREV_B16_e64:
292 case AMDGPU::V_LSHLREV_B32_e32:
293 case AMDGPU::V_LSHLREV_B32_e64:
294 case AMDGPU::V_LSHLREV_B64_e64:
295 case AMDGPU::V_LSHRREV_B16_e32:
296 case AMDGPU::V_LSHRREV_B16_e64:
297 case AMDGPU::V_LSHRREV_B32_e32:
298 case AMDGPU::V_LSHRREV_B32_e64:
299 case AMDGPU::V_LSHRREV_B64_e64:
300 return !ST.hasGFX11Insts();
307bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
311 if (
MI.isConvergent())
339 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
344 for (
auto Op :
MI.uses()) {
345 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
346 RI.isSGPRClass(
MRI.getRegClass(
Op.getReg()))) {
359 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
379 int64_t &Offset1)
const {
387 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
391 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
407 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
408 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
409 if (Offset0Idx == -1 || Offset1Idx == -1)
416 Offset0Idx -=
get(Opc0).NumDefs;
417 Offset1Idx -=
get(Opc1).NumDefs;
447 if (!Load0Offset || !Load1Offset)
464 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
465 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
467 if (OffIdx0 == -1 || OffIdx1 == -1)
473 OffIdx0 -=
get(Opc0).NumDefs;
474 OffIdx1 -=
get(Opc1).NumDefs;
493 case AMDGPU::DS_READ2ST64_B32:
494 case AMDGPU::DS_READ2ST64_B64:
495 case AMDGPU::DS_WRITE2ST64_B32:
496 case AMDGPU::DS_WRITE2ST64_B64:
510 OffsetIsScalable =
false;
527 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
529 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
530 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
543 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
544 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
545 if (Offset0 + 1 != Offset1)
556 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
557 EltSize = RI.getRegSizeInBits(*
getOpRegClass(LdSt, Data0Idx)) / 8;
564 Offset = EltSize * Offset0;
566 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
567 if (DataOpIdx == -1) {
568 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
570 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
586 if (BaseOp && !BaseOp->
isFI())
594 if (SOffset->
isReg())
600 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
602 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
611 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
612 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
614 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
615 if (VAddr0Idx >= 0) {
617 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
624 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
639 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
656 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
658 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
675 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
683 if (MO1->getAddrSpace() != MO2->getAddrSpace())
686 const auto *Base1 = MO1->getValue();
687 const auto *Base2 = MO2->getValue();
688 if (!Base1 || !Base2)
696 return Base1 == Base2;
707 *BaseOps2.
front()->getParent(), BaseOps2);
711 int64_t Offset1,
bool OffsetIsScalable1,
713 int64_t Offset2,
bool OffsetIsScalable2,
714 unsigned ClusterSize,
715 unsigned NumBytes)
const {
725 if (!BaseOps1.
empty()) {
727 MaxMemoryClusterDWords =
745 const unsigned LoadSize = NumBytes / ClusterSize;
746 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
747 return NumDWords <= MaxMemoryClusterDWords;
761 int64_t Offset0, int64_t Offset1,
762 unsigned NumLoads)
const {
763 assert(Offset1 > Offset0 &&
764 "Second offset should be larger than first offset!");
769 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
776 const char *
Msg =
"illegal VGPR to SGPR copy") {
795 assert((
TII.getSubtarget().hasMAIInsts() &&
796 !
TII.getSubtarget().hasGFX90AInsts()) &&
797 "Expected GFX908 subtarget.");
800 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
801 "Source register of the copy should be either an SGPR or an AGPR.");
804 "Destination register of the copy should be an AGPR.");
813 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
816 if (!Def->modifiesRegister(SrcReg, &RI))
819 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
820 Def->getOperand(0).getReg() != SrcReg)
827 bool SafeToPropagate =
true;
830 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
831 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
832 SafeToPropagate =
false;
834 if (!SafeToPropagate)
837 for (
auto I = Def;
I !=
MI; ++
I)
838 I->clearRegisterKills(DefOp.
getReg(), &RI);
846 if (ImpUseSuperReg) {
847 Builder.addReg(ImpUseSuperReg,
855 RS.enterBasicBlockEnd(
MBB);
856 RS.backward(std::next(
MI));
865 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
868 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
869 "VGPR used for an intermediate copy should have been reserved.");
874 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
884 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
885 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
886 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
893 if (ImpUseSuperReg) {
894 UseBuilder.
addReg(ImpUseSuperReg,
911 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
912 int16_t SubIdx = BaseIndices[Idx];
913 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
914 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
915 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
916 unsigned Opcode = AMDGPU::S_MOV_B32;
919 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
920 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
921 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
925 DestSubReg = RI.getSubReg(DestReg, SubIdx);
926 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
927 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
928 Opcode = AMDGPU::S_MOV_B64;
943 assert(FirstMI && LastMI);
948 LastMI->addRegisterKilled(SrcReg, &RI);
954 Register SrcReg,
bool KillSrc,
bool RenamableDest,
955 bool RenamableSrc)
const {
957 unsigned Size = RI.getRegSizeInBits(*RC);
959 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
965 if (((
Size == 16) != (SrcSize == 16))) {
967 assert(ST.useRealTrue16Insts());
969 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
972 if (DestReg == SrcReg) {
978 RC = RI.getPhysRegBaseClass(DestReg);
979 Size = RI.getRegSizeInBits(*RC);
980 SrcRC = RI.getPhysRegBaseClass(SrcReg);
981 SrcSize = RI.getRegSizeInBits(*SrcRC);
985 if (RC == &AMDGPU::VGPR_32RegClass) {
987 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
988 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
989 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
990 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
996 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
997 RC == &AMDGPU::SReg_32RegClass) {
998 if (SrcReg == AMDGPU::SCC) {
1005 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
1006 if (DestReg == AMDGPU::VCC_LO) {
1024 if (RC == &AMDGPU::SReg_64RegClass) {
1025 if (SrcReg == AMDGPU::SCC) {
1032 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1033 if (DestReg == AMDGPU::VCC) {
1051 if (DestReg == AMDGPU::SCC) {
1054 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1058 assert(ST.hasScalarCompareEq64());
1072 if (RC == &AMDGPU::AGPR_32RegClass) {
1073 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1074 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1080 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1089 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1096 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1097 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1099 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1100 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1101 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1102 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1105 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1106 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1119 if (IsAGPRDst || IsAGPRSrc) {
1120 if (!DstLow || !SrcLow) {
1122 "Cannot use hi16 subreg with an AGPR!");
1129 if (ST.useRealTrue16Insts()) {
1135 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1136 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1148 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1149 if (!DstLow || !SrcLow) {
1151 "Cannot use hi16 subreg on VI!");
1177 unsigned SrcOp = 1) {
1181 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1185 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1186 if (ST.hasVMovB64Inst() &&
1187 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1192 if (ST.hasPkMovB32() &&
1193 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1209 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1210 if (RI.isSGPRClass(RC)) {
1211 if (!RI.isSGPRClass(SrcRC)) {
1215 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1221 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1222 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1223 if (RI.isAGPRClass(RC)) {
1224 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1225 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1226 else if (RI.hasVGPRs(SrcRC) ||
1227 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1228 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1230 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1231 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1232 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1233 }
else if (RI.isVGPRClass(RC)) {
1234 if (ST.hasVMovB64Inst())
1235 WideOpcode = AMDGPU::V_MOV_B64_e32;
1236 else if (ST.hasPkMovB32())
1237 WideOpcode = AMDGPU::V_PK_MOV_B32;
1241 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1243 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1250 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1251 const bool CanKillSuperReg = KillSrc && !Overlap;
1258 std::unique_ptr<RegScavenger> RS;
1259 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1260 RS = std::make_unique<RegScavenger>();
1264 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1265 unsigned NumRegs = 1;
1266 unsigned ThisOpcode = Opcode;
1268 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1270 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1271 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1275 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1276 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1277 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1279 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1280 WideSrcRC->contains(WideSrc)) {
1281 SubIdx = WideSubIdx;
1283 ThisOpcode = WideOpcode;
1287 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1288 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1289 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1292 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1294 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1297 *RS, Overlap, ImpUseSuper);
1298 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1339 int64_t &ImmVal)
const {
1340 switch (
MI.getOpcode()) {
1341 case AMDGPU::V_MOV_B32_e32:
1342 case AMDGPU::S_MOV_B32:
1343 case AMDGPU::S_MOVK_I32:
1344 case AMDGPU::S_MOV_B64:
1345 case AMDGPU::V_MOV_B64_e32:
1346 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1347 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1348 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1350 case AMDGPU::V_MOV_B64_PSEUDO:
1351 case AMDGPU::V_MOV_B16_t16_e32: {
1354 ImmVal = Src0.getImm();
1355 return MI.getOperand(0).getReg() == Reg;
1360 case AMDGPU::V_MOV_B16_t16_e64: {
1362 if (Src0.isImm() && !
MI.getOperand(1).getImm()) {
1363 ImmVal = Src0.getImm();
1364 return MI.getOperand(0).getReg() == Reg;
1369 case AMDGPU::S_BREV_B32:
1370 case AMDGPU::V_BFREV_B32_e32:
1371 case AMDGPU::V_BFREV_B32_e64: {
1375 return MI.getOperand(0).getReg() == Reg;
1380 case AMDGPU::S_NOT_B32:
1381 case AMDGPU::V_NOT_B32_e32:
1382 case AMDGPU::V_NOT_B32_e64: {
1385 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.getImm()));
1386 return MI.getOperand(0).getReg() == Reg;
1396std::optional<int64_t>
1406 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1407 return std::nullopt;
1409 if (Def && Def->isMoveImmediate()) {
1411 if (ImmSrc.
isImm()) {
1418 return std::nullopt;
1421std::optional<int64_t>
1430 if (RI.isAGPRClass(DstRC))
1431 return AMDGPU::COPY;
1432 if (RI.getRegSizeInBits(*DstRC) == 16) {
1435 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1437 if (RI.getRegSizeInBits(*DstRC) == 32)
1438 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1439 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1440 return AMDGPU::S_MOV_B64;
1441 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1442 return AMDGPU::V_MOV_B64_PSEUDO;
1443 return AMDGPU::COPY;
1448 bool IsIndirectSrc)
const {
1449 if (IsIndirectSrc) {
1451 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1453 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1455 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1457 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1459 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1461 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1463 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1465 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1467 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1469 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1471 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1473 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1475 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1476 if (VecSize <= 1024)
1477 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1483 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1485 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1487 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1489 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1491 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1493 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1495 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1497 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1499 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1501 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1503 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1505 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1507 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1508 if (VecSize <= 1024)
1509 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1516 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1518 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1520 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1522 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1524 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1526 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1528 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1530 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1532 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1534 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1536 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1538 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1540 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1541 if (VecSize <= 1024)
1542 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1549 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1551 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1553 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1555 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1557 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1559 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1561 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1563 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1565 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1567 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1569 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1571 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1573 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1574 if (VecSize <= 1024)
1575 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1582 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1584 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1586 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1588 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1589 if (VecSize <= 1024)
1590 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1597 bool IsSGPR)
const {
1609 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1616 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1618 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1620 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1622 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1623 : AMDGPU::SI_SPILL_S128_SAVE;
1625 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1626 : AMDGPU::SI_SPILL_S160_SAVE;
1628 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1629 : AMDGPU::SI_SPILL_S192_SAVE;
1631 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1632 : AMDGPU::SI_SPILL_S224_SAVE;
1634 return AMDGPU::SI_SPILL_S256_SAVE;
1636 return AMDGPU::SI_SPILL_S288_SAVE;
1638 return AMDGPU::SI_SPILL_S320_SAVE;
1640 return AMDGPU::SI_SPILL_S352_SAVE;
1642 return AMDGPU::SI_SPILL_S384_SAVE;
1644 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1645 : AMDGPU::SI_SPILL_S512_SAVE;
1647 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1648 : AMDGPU::SI_SPILL_S1024_SAVE;
1657 return AMDGPU::SI_SPILL_V16_SAVE;
1659 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1663 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1665 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1666 : AMDGPU::SI_SPILL_V128_SAVE;
1668 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1669 : AMDGPU::SI_SPILL_V160_SAVE;
1671 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1672 : AMDGPU::SI_SPILL_V192_SAVE;
1674 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1675 : AMDGPU::SI_SPILL_V224_SAVE;
1677 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1678 : AMDGPU::SI_SPILL_V256_SAVE;
1680 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1681 : AMDGPU::SI_SPILL_V288_SAVE;
1683 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1684 : AMDGPU::SI_SPILL_V320_SAVE;
1686 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1687 : AMDGPU::SI_SPILL_V352_SAVE;
1689 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1690 : AMDGPU::SI_SPILL_V384_SAVE;
1692 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1693 : AMDGPU::SI_SPILL_V512_SAVE;
1695 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1696 : AMDGPU::SI_SPILL_V1024_SAVE;
1705 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1706 : AMDGPU::SI_SPILL_AV32_SAVE;
1708 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1709 : AMDGPU::SI_SPILL_AV64_SAVE;
1711 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1712 : AMDGPU::SI_SPILL_AV96_SAVE;
1714 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1715 : AMDGPU::SI_SPILL_AV128_SAVE;
1717 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1718 : AMDGPU::SI_SPILL_AV160_SAVE;
1720 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1721 : AMDGPU::SI_SPILL_AV192_SAVE;
1723 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1724 : AMDGPU::SI_SPILL_AV224_SAVE;
1726 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1727 : AMDGPU::SI_SPILL_AV256_SAVE;
1729 return AMDGPU::SI_SPILL_AV288_SAVE;
1731 return AMDGPU::SI_SPILL_AV320_SAVE;
1733 return AMDGPU::SI_SPILL_AV352_SAVE;
1735 return AMDGPU::SI_SPILL_AV384_SAVE;
1737 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1738 : AMDGPU::SI_SPILL_AV512_SAVE;
1740 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1741 : AMDGPU::SI_SPILL_AV1024_SAVE;
1748 bool IsVectorSuperClass) {
1753 if (IsVectorSuperClass)
1754 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1756 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1762 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1769 if (ST.hasMAIInsts())
1775void SIInstrInfo::storeRegToStackSlotImpl(
1788 FrameInfo.getObjectAlign(FrameIndex));
1789 unsigned SpillSize = RI.getSpillSize(*RC);
1795 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1796 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1797 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1806 if (SrcReg.
isVirtual() && SpillSize == 4) {
1807 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1820 SpillSize, *MFI, NeedsCFI);
1835 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1844 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1851 return AMDGPU::SI_SPILL_S32_RESTORE;
1853 return AMDGPU::SI_SPILL_S64_RESTORE;
1855 return AMDGPU::SI_SPILL_S96_RESTORE;
1857 return AMDGPU::SI_SPILL_S128_RESTORE;
1859 return AMDGPU::SI_SPILL_S160_RESTORE;
1861 return AMDGPU::SI_SPILL_S192_RESTORE;
1863 return AMDGPU::SI_SPILL_S224_RESTORE;
1865 return AMDGPU::SI_SPILL_S256_RESTORE;
1867 return AMDGPU::SI_SPILL_S288_RESTORE;
1869 return AMDGPU::SI_SPILL_S320_RESTORE;
1871 return AMDGPU::SI_SPILL_S352_RESTORE;
1873 return AMDGPU::SI_SPILL_S384_RESTORE;
1875 return AMDGPU::SI_SPILL_S512_RESTORE;
1877 return AMDGPU::SI_SPILL_S1024_RESTORE;
1886 return AMDGPU::SI_SPILL_V16_RESTORE;
1888 return AMDGPU::SI_SPILL_V32_RESTORE;
1890 return AMDGPU::SI_SPILL_V64_RESTORE;
1892 return AMDGPU::SI_SPILL_V96_RESTORE;
1894 return AMDGPU::SI_SPILL_V128_RESTORE;
1896 return AMDGPU::SI_SPILL_V160_RESTORE;
1898 return AMDGPU::SI_SPILL_V192_RESTORE;
1900 return AMDGPU::SI_SPILL_V224_RESTORE;
1902 return AMDGPU::SI_SPILL_V256_RESTORE;
1904 return AMDGPU::SI_SPILL_V288_RESTORE;
1906 return AMDGPU::SI_SPILL_V320_RESTORE;
1908 return AMDGPU::SI_SPILL_V352_RESTORE;
1910 return AMDGPU::SI_SPILL_V384_RESTORE;
1912 return AMDGPU::SI_SPILL_V512_RESTORE;
1914 return AMDGPU::SI_SPILL_V1024_RESTORE;
1923 return AMDGPU::SI_SPILL_AV32_RESTORE;
1925 return AMDGPU::SI_SPILL_AV64_RESTORE;
1927 return AMDGPU::SI_SPILL_AV96_RESTORE;
1929 return AMDGPU::SI_SPILL_AV128_RESTORE;
1931 return AMDGPU::SI_SPILL_AV160_RESTORE;
1933 return AMDGPU::SI_SPILL_AV192_RESTORE;
1935 return AMDGPU::SI_SPILL_AV224_RESTORE;
1937 return AMDGPU::SI_SPILL_AV256_RESTORE;
1939 return AMDGPU::SI_SPILL_AV288_RESTORE;
1941 return AMDGPU::SI_SPILL_AV320_RESTORE;
1943 return AMDGPU::SI_SPILL_AV352_RESTORE;
1945 return AMDGPU::SI_SPILL_AV384_RESTORE;
1947 return AMDGPU::SI_SPILL_AV512_RESTORE;
1949 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1956 bool IsVectorSuperClass) {
1961 if (IsVectorSuperClass)
1962 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1964 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1970 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1977 if (ST.hasMAIInsts())
1980 assert(!RI.isAGPRClass(RC));
1994 unsigned SpillSize = RI.getSpillSize(*RC);
2001 FrameInfo.getObjectAlign(FrameIndex));
2003 if (RI.isSGPRClass(RC)) {
2006 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
2007 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2008 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
2013 if (DestReg.
isVirtual() && SpillSize == 4) {
2015 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2042 unsigned Quantity)
const {
2044 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2045 while (Quantity > 0) {
2046 unsigned Arg = std::min(Quantity, MaxSNopCount);
2057 constexpr unsigned DoorbellIDMask = 0x3ff;
2058 constexpr unsigned ECQueueWaveAbort = 0x400;
2063 if (!
MBB.succ_empty() ||
2065 false) !=
MBB.end()) {
2066 MBB.splitAt(
MI,
false);
2070 MBB.addSuccessor(TrapBB);
2076 Register DoorbellReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2080 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2083 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2084 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2089 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2090 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2091 .
addUse(DoorbellRegMasked)
2092 .
addImm(ECQueueWaveAbort)
2094 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2095 .
addUse(SetWaveAbortBit);
2098 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2109 return MBB.getNextNode();
2113 switch (
MI.getOpcode()) {
2115 if (
MI.isMetaInstruction())
2120 return MI.getOperand(0).getImm() + 1;
2131 switch (
MI.getOpcode()) {
2133 case AMDGPU::S_MOV_B64_term:
2136 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2139 case AMDGPU::S_MOV_B32_term:
2142 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2145 case AMDGPU::S_XOR_B64_term:
2148 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2151 case AMDGPU::S_XOR_B32_term:
2154 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2156 case AMDGPU::S_OR_B64_term:
2159 MI.setDesc(
get(AMDGPU::S_OR_B64));
2161 case AMDGPU::S_OR_B32_term:
2164 MI.setDesc(
get(AMDGPU::S_OR_B32));
2167 case AMDGPU::S_ANDN2_B64_term:
2170 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2173 case AMDGPU::S_ANDN2_B32_term:
2176 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2179 case AMDGPU::S_AND_B64_term:
2182 MI.setDesc(
get(AMDGPU::S_AND_B64));
2185 case AMDGPU::S_AND_B32_term:
2188 MI.setDesc(
get(AMDGPU::S_AND_B32));
2191 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2194 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2197 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2200 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2203 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2204 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2206 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2207 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2210 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2211 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2214 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2215 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2217 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2221 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2224 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2227 int64_t
Imm =
MI.getOperand(1).getImm();
2229 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2230 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2235 MI.eraseFromParent();
2241 case AMDGPU::V_MOV_B64_PSEUDO: {
2243 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2244 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2252 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2253 MI.setDesc(Mov64Desc);
2257 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2260 if (
SrcOp.isGlobal()) {
2265 unsigned BaseFlags, LoReloc, HiReloc;
2266 std::tie(BaseFlags, LoReloc, HiReloc) =
2273 }
else if (
SrcOp.isImm()) {
2275 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2276 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2300 if (ST.hasPkMovB32() &&
2319 MI.eraseFromParent();
2322 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2326 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2330 if (ST.has64BitLiterals()) {
2331 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2335 if (
SrcOp.isGlobal()) {
2337 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2338 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2341 unsigned BaseFlags, LoReloc, HiReloc;
2342 std::tie(BaseFlags, LoReloc, HiReloc) =
2349 MI.eraseFromParent();
2356 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2361 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2362 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2364 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2365 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2370 MI.eraseFromParent();
2373 case AMDGPU::V_SET_INACTIVE_B32: {
2377 .
add(
MI.getOperand(3))
2378 .
add(
MI.getOperand(4))
2379 .
add(
MI.getOperand(1))
2380 .
add(
MI.getOperand(2))
2381 .
add(
MI.getOperand(5));
2382 MI.eraseFromParent();
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2398 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2417 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2421 if (RI.hasVGPRs(EltRC)) {
2422 Opc = AMDGPU::V_MOVRELD_B32_e32;
2424 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2425 : AMDGPU::S_MOVRELD_B32;
2430 bool IsUndef =
MI.getOperand(1).isUndef();
2431 unsigned SubReg =
MI.getOperand(3).getImm();
2432 assert(VecReg ==
MI.getOperand(1).getReg());
2437 .
add(
MI.getOperand(2))
2441 const int ImpDefIdx =
2443 const int ImpUseIdx = ImpDefIdx + 1;
2445 MI.eraseFromParent();
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2461 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2462 assert(ST.useVGPRIndexMode());
2464 bool IsUndef =
MI.getOperand(1).isUndef();
2473 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2477 .
add(
MI.getOperand(2))
2481 const int ImpDefIdx =
2483 const int ImpUseIdx = ImpDefIdx + 1;
2490 MI.eraseFromParent();
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2506 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2507 assert(ST.useVGPRIndexMode());
2510 bool IsUndef =
MI.getOperand(1).isUndef();
2514 .
add(
MI.getOperand(2))
2527 MI.eraseFromParent();
2530 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2533 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2534 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2553 if (ST.hasGetPCZeroExtension()) {
2557 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2564 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2574 MI.eraseFromParent();
2577 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2587 Op.setOffset(
Op.getOffset() + 4);
2589 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2593 MI.eraseFromParent();
2596 case AMDGPU::ENTER_STRICT_WWM: {
2602 case AMDGPU::ENTER_STRICT_WQM: {
2609 MI.eraseFromParent();
2612 case AMDGPU::EXIT_STRICT_WWM:
2613 case AMDGPU::EXIT_STRICT_WQM: {
2619 case AMDGPU::SI_RETURN: {
2633 MI.eraseFromParent();
2637 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2638 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2639 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2642 case AMDGPU::S_GETPC_B64_pseudo:
2643 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2644 if (ST.hasGetPCZeroExtension()) {
2646 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2655 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2656 assert(ST.hasBF16PackedInsts());
2657 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2668 case AMDGPU::GET_STACK_BASE:
2671 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2678 Register DestReg =
MI.getOperand(0).getReg();
2688 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2689 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2690 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2693 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2696 MI.getNumExplicitOperands());
2714 case AMDGPU::S_MOV_B64:
2715 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2724 if (UsedLanes.
all())
2729 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2730 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2732 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2733 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2735 if (NeedLo && NeedHi)
2739 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2741 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2750 case AMDGPU::S_LOAD_DWORDX16_IMM:
2751 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2752 if (SubIdx != 0 || UsedLanes.
all())
2763 assert(
MRI.use_nodbg_empty(DestReg) &&
"DestReg should have no users yet.");
2770 UseMO !=
I->findRegisterUseOperand(RegToFind,
nullptr) ||
2771 UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2775 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2777 unsigned NewOpcode = -1;
2778 if (SubregSize == 256)
2779 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2780 else if (SubregSize == 128)
2781 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2788 MRI.setRegClass(DestReg, NewRC);
2791 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2796 MI->getOperand(0).setReg(DestReg);
2797 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2801 OffsetMO->
setImm(FinalOffset);
2807 MI->setMemRefs(*MF, NewMMOs);
2820std::pair<MachineInstr*, MachineInstr*>
2822 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2824 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2827 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2828 return std::pair(&
MI,
nullptr);
2839 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2841 if (Dst.isPhysical()) {
2842 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2845 auto Tmp =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2849 for (
unsigned I = 1;
I <= 2; ++
I) {
2852 if (
SrcOp.isImm()) {
2854 Imm.ashrInPlace(Part * 32);
2855 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2859 if (Src.isPhysical())
2860 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2867 MovDPP.addImm(MO.getImm());
2869 Split[Part] = MovDPP;
2873 if (Dst.isVirtual())
2880 MI.eraseFromParent();
2881 return std::pair(Split[0], Split[1]);
2884std::optional<DestSourcePair>
2886 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2889 return std::nullopt;
2893 AMDGPU::OpName Src0OpName,
2895 AMDGPU::OpName Src1OpName)
const {
2902 "All commutable instructions have both src0 and src1 modifiers");
2904 int Src0ModsVal = Src0Mods->
getImm();
2905 int Src1ModsVal = Src1Mods->
getImm();
2907 Src1Mods->
setImm(Src0ModsVal);
2908 Src0Mods->
setImm(Src1ModsVal);
2917 bool IsKill = RegOp.
isKill();
2919 bool IsUndef = RegOp.
isUndef();
2920 bool IsDebug = RegOp.
isDebug();
2922 if (NonRegOp.
isImm())
2924 else if (NonRegOp.
isFI())
2945 int64_t NonRegVal = NonRegOp1.
getImm();
2948 NonRegOp2.
setImm(NonRegVal);
2958 bool CheckSwappedSrc =
false) {
2959 unsigned Opc =
MI.getOpcode();
2960 if (!
TII.getSubtarget().hasPkF32InvalidOpSel() ||
2961 (
Opc != AMDGPU::V_PK_ADD_F32 &&
Opc != AMDGPU::V_PK_MUL_F32 &&
2962 Opc != AMDGPU::V_PK_FMA_F32))
2965 auto Mods = [&](AMDGPU::OpName Name) {
2967 return Op ?
static_cast<unsigned>(
Op->getImm()) : 0u;
2969 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2970 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2971 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2973 if (CheckSwappedSrc)
2976 if (
Opc == AMDGPU::V_PK_FMA_F32)
2982 unsigned OpIdx1)
const {
2987 unsigned Opc =
MI.getOpcode();
2988 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2989 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2993 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2994 ((
int)OpIdx0 == Src1Idx && (
int)OpIdx1 == Src0Idx);
3006 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
3009 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
3014 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
3020 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3042 unsigned Src1Idx)
const {
3043 assert(!NewMI &&
"this should never be used");
3048 unsigned Opc =
MI.getOpcode();
3050 if (CommutedOpcode == -1)
3053 if (Src0Idx > Src1Idx)
3056 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3057 static_cast<int>(Src0Idx) &&
3058 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3059 static_cast<int>(Src1Idx) &&
3060 "inconsistency with findCommutedOpIndices");
3068 if (Src0.isReg() && Src1.isReg()) {
3072 }
else if (Src0.isReg() && !Src1.isReg()) {
3074 }
else if (!Src0.isReg() && Src1.isReg()) {
3076 }
else if (Src0.isImm() && Src1.isImm()) {
3085 Src1, AMDGPU::OpName::src1_modifiers);
3088 AMDGPU::OpName::src1_sel);
3100 unsigned &SrcOpIdx0,
3101 unsigned &SrcOpIdx1)
const {
3109 unsigned &SrcOpIdx0,
3110 unsigned &SrcOpIdx1)
const {
3111 if (!
Desc.isCommutable())
3114 unsigned Opc =
Desc.getOpcode();
3115 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3119 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3123 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3127 int64_t BrOffset)
const {
3144 return MI.getOperand(0).getMBB();
3149 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3150 MI.getOpcode() == AMDGPU::SI_LOOP ||
3151 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3163 "new block should be inserted for expanding unconditional branch");
3166 "restore block should be inserted for restoring clobbered registers");
3174 if (ST.useAddPCI64Inst()) {
3176 MCCtx.createTempSymbol(
"offset",
true);
3180 MCCtx.createTempSymbol(
"post_addpc",
true);
3181 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3185 Offset->setVariableValue(OffsetExpr);
3189 assert(RS &&
"RegScavenger required for long branching");
3193 Register PCReg =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3197 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3198 ST.hasVALUReadSGPRHazard();
3199 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3200 if (FlushSGPRWrites)
3208 ApplyHazardWorkarounds();
3211 MCCtx.createTempSymbol(
"post_getpc",
true);
3215 MCCtx.createTempSymbol(
"offset_lo",
true);
3217 MCCtx.createTempSymbol(
"offset_hi",
true);
3220 .
addReg(PCReg, {}, AMDGPU::sub0)
3224 .
addReg(PCReg, {}, AMDGPU::sub1)
3226 ApplyHazardWorkarounds();
3267 if (LongBranchReservedReg) {
3268 RS->enterBasicBlock(
MBB);
3269 Scav = LongBranchReservedReg;
3271 RS->enterBasicBlockEnd(
MBB);
3272 Scav = RS->scavengeRegisterBackwards(
3277 RS->setRegUsed(Scav);
3278 MRI.replaceRegWith(PCReg, Scav);
3279 MRI.clearVirtRegs();
3285 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3286 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3287 MRI.clearVirtRegs();
3302unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3304 case SIInstrInfo::SCC_TRUE:
3305 return AMDGPU::S_CBRANCH_SCC1;
3306 case SIInstrInfo::SCC_FALSE:
3307 return AMDGPU::S_CBRANCH_SCC0;
3308 case SIInstrInfo::VCCNZ:
3309 return AMDGPU::S_CBRANCH_VCCNZ;
3310 case SIInstrInfo::VCCZ:
3311 return AMDGPU::S_CBRANCH_VCCZ;
3312 case SIInstrInfo::EXECNZ:
3313 return AMDGPU::S_CBRANCH_EXECNZ;
3314 case SIInstrInfo::EXECZ:
3315 return AMDGPU::S_CBRANCH_EXECZ;
3321SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3323 case AMDGPU::S_CBRANCH_SCC0:
3325 case AMDGPU::S_CBRANCH_SCC1:
3327 case AMDGPU::S_CBRANCH_VCCNZ:
3329 case AMDGPU::S_CBRANCH_VCCZ:
3331 case AMDGPU::S_CBRANCH_EXECNZ:
3333 case AMDGPU::S_CBRANCH_EXECZ:
3345 bool AllowModify)
const {
3346 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3348 TBB =
I->getOperand(0).getMBB();
3352 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3353 if (Pred == INVALID_BR)
3358 Cond.push_back(
I->getOperand(1));
3362 if (
I ==
MBB.end()) {
3368 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3370 FBB =
I->getOperand(0).getMBB();
3380 bool AllowModify)
const {
3388 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3389 switch (
I->getOpcode()) {
3390 case AMDGPU::S_MOV_B64_term:
3391 case AMDGPU::S_XOR_B64_term:
3392 case AMDGPU::S_OR_B64_term:
3393 case AMDGPU::S_ANDN2_B64_term:
3394 case AMDGPU::S_AND_B64_term:
3395 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3396 case AMDGPU::S_MOV_B32_term:
3397 case AMDGPU::S_XOR_B32_term:
3398 case AMDGPU::S_OR_B32_term:
3399 case AMDGPU::S_ANDN2_B32_term:
3400 case AMDGPU::S_AND_B32_term:
3401 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3402 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3403 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3406 case AMDGPU::SI_ELSE:
3407 case AMDGPU::SI_KILL_I1_TERMINATOR:
3408 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3425 int *BytesRemoved)
const {
3427 unsigned RemovedSize = 0;
3430 if (
MI.isBranch() ||
MI.isReturn()) {
3432 MI.eraseFromParent();
3438 *BytesRemoved = RemovedSize;
3455 int *BytesAdded)
const {
3456 if (!FBB &&
Cond.empty()) {
3460 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3467 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3479 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3497 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3504 if (
Cond.size() != 2) {
3508 if (
Cond[0].isImm()) {
3529 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3533 std::optional<bool> createTripCountGreaterCondition(
3534 int TC, MachineBasicBlock &
MBB,
3535 SmallVectorImpl<MachineOperand> &CondParam)
override {
3536 CondParam = this->
Cond;
3540 void adjustTripCount(
int TripCountAdjust)
override {}
3542 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3546std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3555 if (
TBB == LoopBB && FBB == LoopBB)
3562 assert((
TBB == LoopBB || FBB == LoopBB) &&
3563 "The Loop must be a single-basic-block loop");
3566 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3567 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3572 if (
MI.isCall() ||
MI.isInlineAsm())
3587 if (CmpI == Instructions.end() || CmpI->isPHI())
3591 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3598 SelectExpansion &Exp)
const {
3604 if (
MRI.getRegClass(FalseReg) != RC)
3608 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3611 return RI.hasVGPRs(RC) && NumInsts <= 6;
3619 if (
MRI.getRegClass(FalseReg) != RC)
3625 if (NumInsts % 2 == 0)
3628 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3629 return RI.isSGPRClass(RC);
3640 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3641 if (Pred == VCCZ || Pred == SCC_FALSE) {
3642 Pred =
static_cast<BranchPredicate
>(-Pred);
3648 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3650 if (DstSize == 32) {
3652 if (Pred == SCC_TRUE) {
3667 if (DstSize == 64 && Pred == SCC_TRUE) {
3677 static const int16_t Sub0_15[] = {
3678 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3679 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3680 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3681 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3684 static const int16_t Sub0_15_64[] = {
3685 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3686 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3687 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3688 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3691 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3693 const int16_t *SubIndices = Sub0_15;
3694 int NElts = DstSize / 32;
3698 if (Pred == SCC_TRUE) {
3700 SelOp = AMDGPU::S_CSELECT_B32;
3701 EltRC = &AMDGPU::SGPR_32RegClass;
3703 SelOp = AMDGPU::S_CSELECT_B64;
3704 EltRC = &AMDGPU::SGPR_64RegClass;
3705 SubIndices = Sub0_15_64;
3711 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3716 for (
int Idx = 0; Idx != NElts; ++Idx) {
3717 Register DstElt =
MRI.createVirtualRegister(EltRC);
3720 unsigned SubIdx = SubIndices[Idx];
3723 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3725 .
addReg(FalseReg, {}, SubIdx)
3726 .addReg(TrueReg, {}, SubIdx);
3729 .
addReg(TrueReg, {}, SubIdx)
3730 .addReg(FalseReg, {}, SubIdx);
3743 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3746 switch (
MI.getOpcode()) {
3747 case AMDGPU::S_ENDPGM:
3748 case AMDGPU::S_ENDPGM_SAVED:
3749 case AMDGPU::S_TRAP:
3750 case AMDGPU::S_GETREG_B32:
3751 case AMDGPU::S_SETREG_B32:
3752 case AMDGPU::S_SETREG_B32_mode:
3753 case AMDGPU::S_SETREG_IMM32_B32:
3754 case AMDGPU::S_SETREG_IMM32_B32_mode:
3755 case AMDGPU::S_SENDMSG:
3756 case AMDGPU::S_SENDMSGHALT:
3757 case AMDGPU::S_SENDMSG_RTN_B32:
3758 case AMDGPU::S_SENDMSG_RTN_B64:
3759 case AMDGPU::S_BARRIER_WAIT:
3760 case AMDGPU::S_BARRIER_SIGNAL_M0:
3761 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3762 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3763 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3771 switch (
MI.getOpcode()) {
3772 case AMDGPU::V_MOV_B16_t16_e32:
3773 case AMDGPU::V_MOV_B16_t16_e64:
3774 case AMDGPU::V_MOV_B32_e32:
3775 case AMDGPU::V_MOV_B32_e64:
3776 case AMDGPU::V_MOV_B64_PSEUDO:
3777 case AMDGPU::V_MOV_B64_e32:
3778 case AMDGPU::V_MOV_B64_e64:
3779 case AMDGPU::S_MOV_B32:
3780 case AMDGPU::S_MOV_B64:
3781 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3783 case AMDGPU::WWM_COPY:
3784 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3785 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3786 case AMDGPU::V_ACCVGPR_MOV_B32:
3787 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3788 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3796 switch (
MI.getOpcode()) {
3797 case AMDGPU::V_MOV_B16_t16_e32:
3798 case AMDGPU::V_MOV_B16_t16_e64:
3800 case AMDGPU::V_MOV_B32_e32:
3801 case AMDGPU::V_MOV_B32_e64:
3802 case AMDGPU::V_MOV_B64_PSEUDO:
3803 case AMDGPU::V_MOV_B64_e32:
3804 case AMDGPU::V_MOV_B64_e64:
3805 case AMDGPU::S_MOV_B32:
3806 case AMDGPU::S_MOV_B64:
3807 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3809 case AMDGPU::WWM_COPY:
3810 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3811 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3812 case AMDGPU::V_ACCVGPR_MOV_B32:
3813 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3814 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3822 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3823 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3824 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3827 unsigned Opc =
MI.getOpcode();
3829 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3831 MI.removeOperand(Idx);
3837 MI.setDesc(NewDesc);
3843 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3844 Desc.implicit_defs().size();
3846 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3847 MI.removeOperand(
I);
3851 unsigned SubRegIndex) {
3852 switch (SubRegIndex) {
3853 case AMDGPU::NoSubRegister:
3863 case AMDGPU::sub1_lo16:
3865 case AMDGPU::sub1_hi16:
3868 return std::nullopt;
3876 case AMDGPU::V_MAC_F16_e32:
3877 case AMDGPU::V_MAC_F16_e64:
3878 case AMDGPU::V_MAD_F16_e64:
3879 return AMDGPU::V_MADAK_F16;
3880 case AMDGPU::V_MAC_F32_e32:
3881 case AMDGPU::V_MAC_F32_e64:
3882 case AMDGPU::V_MAD_F32_e64:
3883 return AMDGPU::V_MADAK_F32;
3884 case AMDGPU::V_FMAC_F32_e32:
3885 case AMDGPU::V_FMAC_F32_e64:
3886 case AMDGPU::V_FMA_F32_e64:
3887 return AMDGPU::V_FMAAK_F32;
3888 case AMDGPU::V_FMAC_F16_e32:
3889 case AMDGPU::V_FMAC_F16_e64:
3890 case AMDGPU::V_FMAC_F16_t16_e64:
3891 case AMDGPU::V_FMAC_F16_fake16_e64:
3892 case AMDGPU::V_FMAC_F16_t16_e32:
3893 case AMDGPU::V_FMAC_F16_fake16_e32:
3894 case AMDGPU::V_FMA_F16_e64:
3895 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3896 ? AMDGPU::V_FMAAK_F16_t16
3897 : AMDGPU::V_FMAAK_F16_fake16
3898 : AMDGPU::V_FMAAK_F16;
3899 case AMDGPU::V_FMAC_F64_e32:
3900 case AMDGPU::V_FMAC_F64_e64:
3901 case AMDGPU::V_FMA_F64_e64:
3902 return AMDGPU::V_FMAAK_F64;
3910 case AMDGPU::V_MAC_F16_e32:
3911 case AMDGPU::V_MAC_F16_e64:
3912 case AMDGPU::V_MAD_F16_e64:
3913 return AMDGPU::V_MADMK_F16;
3914 case AMDGPU::V_MAC_F32_e32:
3915 case AMDGPU::V_MAC_F32_e64:
3916 case AMDGPU::V_MAD_F32_e64:
3917 return AMDGPU::V_MADMK_F32;
3918 case AMDGPU::V_FMAC_F32_e32:
3919 case AMDGPU::V_FMAC_F32_e64:
3920 case AMDGPU::V_FMA_F32_e64:
3921 return AMDGPU::V_FMAMK_F32;
3922 case AMDGPU::V_FMAC_F16_e32:
3923 case AMDGPU::V_FMAC_F16_e64:
3924 case AMDGPU::V_FMAC_F16_t16_e64:
3925 case AMDGPU::V_FMAC_F16_fake16_e64:
3926 case AMDGPU::V_FMAC_F16_t16_e32:
3927 case AMDGPU::V_FMAC_F16_fake16_e32:
3928 case AMDGPU::V_FMA_F16_e64:
3929 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3930 ? AMDGPU::V_FMAMK_F16_t16
3931 : AMDGPU::V_FMAMK_F16_fake16
3932 : AMDGPU::V_FMAMK_F16;
3933 case AMDGPU::V_FMAC_F64_e32:
3934 case AMDGPU::V_FMAC_F64_e64:
3935 case AMDGPU::V_FMA_F64_e64:
3936 return AMDGPU::V_FMAMK_F64;
3948 const bool HasMultipleUses = !
MRI->hasOneNonDBGUse(Reg);
3950 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3953 if (
Opc == AMDGPU::COPY) {
3954 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3961 if (HasMultipleUses) {
3964 unsigned ImmDefSize = RI.getRegSizeInBits(*
MRI->getRegClass(Reg));
3967 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3975 if (ImmDefSize == 32 &&
3980 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3981 RI.getSubRegIdxSize(UseSubReg) == 16;
3984 if (RI.hasVGPRs(DstRC))
3987 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3993 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
4000 for (
unsigned MovOp :
4001 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4002 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4010 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4014 if (MovDstPhysReg) {
4018 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4025 if (MovDstPhysReg) {
4026 if (!MovDstRC->
contains(MovDstPhysReg))
4028 }
else if (!
MRI->constrainRegClass(DstReg, MovDstRC)) {
4042 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4050 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4054 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4056 UseMI.getOperand(0).setReg(MovDstPhysReg);
4061 UseMI.setDesc(NewMCID);
4062 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4063 UseMI.addImplicitDefUseOperands(*MF);
4067 if (HasMultipleUses)
4070 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4071 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4072 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4073 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4074 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4075 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4076 Opc == AMDGPU::V_FMAC_F64_e64) {
4085 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4096 auto CopyRegOperandToNarrowerRC =
4099 if (!
MI.getOperand(OpNo).isReg())
4103 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4106 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4107 get(AMDGPU::COPY), Tmp)
4109 MI.getOperand(OpNo).setReg(Tmp);
4113 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4114 (Src1->isReg() && Src1->getReg() == Reg)) {
4116 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4117 if (!RegSrc->
isReg())
4119 if (RI.isSGPRClass(
MRI->getRegClass(RegSrc->
getReg())) &&
4120 ST.getConstantBusLimit(
Opc) < 2)
4123 if (!Src2->isReg() || RI.isSGPRClass(
MRI->getRegClass(Src2->getReg())))
4135 if (Def && Def->isMoveImmediate() &&
4144 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4150 unsigned SrcSubReg = RegSrc->
getSubReg();
4151 Src0->setReg(SrcReg);
4152 Src0->setSubReg(SrcSubReg);
4153 Src0->setIsKill(RegSrc->
isKill());
4155 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4156 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4157 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4158 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4159 UseMI.untieRegOperand(
4160 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4162 Src1->ChangeToImmediate(*SubRegImm);
4167 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4168 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4172 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4173 UseMI.getOperand(0).getReg())
4175 UseMI.getOperand(0).setReg(Tmp);
4176 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4177 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4180 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4182 DefMI.eraseFromParent();
4188 if (Src2->isReg() && Src2->getReg() == Reg) {
4189 if (ST.getConstantBusLimit(
Opc) < 2) {
4192 bool Src0Inlined =
false;
4193 if (Src0->isReg()) {
4198 if (Def && Def->isMoveImmediate() &&
4200 MRI->hasOneNonDBGUse(Src0->getReg())) {
4201 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4203 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4204 RI.isSGPRReg(*
MRI, Src0->getReg())) {
4210 if (Src1->isReg() && !Src0Inlined) {
4213 if (Def && Def->isMoveImmediate() &&
4215 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(
UseMI))
4216 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4217 else if (RI.isSGPRReg(*
MRI, Src1->getReg()))
4230 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4231 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4232 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4233 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4234 UseMI.untieRegOperand(
4235 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4237 const std::optional<int64_t> SubRegImm =
4241 Src2->ChangeToImmediate(*SubRegImm);
4247 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4248 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4252 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4253 UseMI.getOperand(0).getReg())
4255 UseMI.getOperand(0).setReg(Tmp);
4256 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4257 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4266 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4270 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4272 DefMI.eraseFromParent();
4284 if (BaseOps1.
size() != BaseOps2.
size())
4286 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4287 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4295 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4296 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4297 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4299 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4302bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4305 int64_t Offset0, Offset1;
4308 bool Offset0IsScalable, Offset1IsScalable;
4322 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4323 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4330 "MIa must load from or modify a memory location");
4332 "MIb must load from or modify a memory location");
4354 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4361 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4371 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4385 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4396 case AMDGPU::V_MAC_F16_e32:
4397 case AMDGPU::V_MAC_F16_e64:
4398 return AMDGPU::V_MAD_F16_e64;
4399 case AMDGPU::V_MAC_F32_e32:
4400 case AMDGPU::V_MAC_F32_e64:
4401 return AMDGPU::V_MAD_F32_e64;
4402 case AMDGPU::V_MAC_LEGACY_F32_e32:
4403 case AMDGPU::V_MAC_LEGACY_F32_e64:
4404 return AMDGPU::V_MAD_LEGACY_F32_e64;
4405 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4406 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4407 return AMDGPU::V_FMA_LEGACY_F32_e64;
4408 case AMDGPU::V_FMAC_F16_e32:
4409 case AMDGPU::V_FMAC_F16_e64:
4410 case AMDGPU::V_FMAC_F16_t16_e64:
4411 case AMDGPU::V_FMAC_F16_fake16_e64:
4412 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4413 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4414 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4415 : AMDGPU::V_FMA_F16_gfx9_e64;
4416 case AMDGPU::V_FMAC_F32_e32:
4417 case AMDGPU::V_FMAC_F32_e64:
4418 return AMDGPU::V_FMA_F32_e64;
4419 case AMDGPU::V_FMAC_F64_e32:
4420 case AMDGPU::V_FMAC_F64_e64:
4421 return AMDGPU::V_FMA_F64_e64;
4440 if (
MI.isBundle()) {
4443 if (
MI.getBundleSize() != 1)
4445 CandidateMI =
MI.getNextNode();
4449 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4453 if (
MI.isBundle()) {
4458 MI.untieRegOperand(MO.getOperandNo());
4465 if (Def.isEarlyClobber() && Def.isReg() &&
4470 auto UpdateDefIndex = [&](
LiveRange &LR) {
4471 auto *S = LR.find(OldIndex);
4472 if (S != LR.end() && S->start == OldIndex) {
4473 assert(S->valno && S->valno->def == OldIndex);
4474 S->start = NewIndex;
4475 S->valno->def = NewIndex;
4479 for (
auto &SR : LI.subranges())
4489 "expected a tied def in the two-address form");
4494 SlotIndex OldEnd = Idx.getRegSlot(
true);
4496 auto UpdateUseIndex = [&](
LiveRange &LR) {
4498 if (S && S->
end == OldEnd)
4509 if (U.RemoveMIUse) {
4512 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4514 if (
MRI.hasOneNonDBGUse(DefReg)) {
4516 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4517 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4518 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4519 U.RemoveMIUse->removeOperand(
I);
4522 if (
MI.isBundle()) {
4526 if (MO.isReg() && MO.getReg() == DefReg) {
4527 assert(MO.getSubReg() == 0 &&
4528 "tied sub-registers in bundles currently not supported");
4529 MI.removeOperand(MO.getOperandNo());
4544 Register DummyReg =
MRI.cloneVirtualRegister(DefReg);
4546 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4547 MIOp.setIsUndef(
true);
4548 MIOp.setReg(DummyReg);
4552 if (
MI.isBundle()) {
4556 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4557 MIOp.setIsUndef(
true);
4558 MIOp.setReg(DummyReg);
4571 return MI.isBundle() ? &
MI : NewMI;
4576 ThreeAddressUpdates &U)
const {
4578 unsigned Opc =
MI.getOpcode();
4582 if (NewMFMAOpc != -1) {
4585 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4586 MIB.
add(
MI.getOperand(
I));
4594 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4599 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4600 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4601 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4605 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4606 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4607 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4608 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4609 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4610 bool Src0Literal =
false;
4615 case AMDGPU::V_MAC_F16_e64:
4616 case AMDGPU::V_FMAC_F16_e64:
4617 case AMDGPU::V_FMAC_F16_t16_e64:
4618 case AMDGPU::V_FMAC_F16_fake16_e64:
4619 case AMDGPU::V_MAC_F32_e64:
4620 case AMDGPU::V_MAC_LEGACY_F32_e64:
4621 case AMDGPU::V_FMAC_F32_e64:
4622 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4623 case AMDGPU::V_FMAC_F64_e64:
4625 case AMDGPU::V_MAC_F16_e32:
4626 case AMDGPU::V_FMAC_F16_e32:
4627 case AMDGPU::V_MAC_F32_e32:
4628 case AMDGPU::V_MAC_LEGACY_F32_e32:
4629 case AMDGPU::V_FMAC_F32_e32:
4630 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4631 case AMDGPU::V_FMAC_F64_e32: {
4632 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4633 AMDGPU::OpName::src0);
4634 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4635 if (!
Src0->isReg() && !
Src0->isImm())
4645 MachineInstrBuilder MIB;
4648 const MachineOperand *Src0Mods =
4651 const MachineOperand *Src1Mods =
4654 const MachineOperand *Src2Mods =
4660 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4661 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4663 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4665 MachineInstr *
DefMI =
nullptr;
4667 std::optional<int64_t> ImmOpt;
4702 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4718 if (Src0Literal && !ST.hasVOP3Literal())
4746 switch (
MI.getOpcode()) {
4747 case AMDGPU::S_SET_GPR_IDX_ON:
4748 case AMDGPU::S_SET_GPR_IDX_MODE:
4749 case AMDGPU::S_SET_GPR_IDX_OFF:
4767 if (
MI.isTerminator() ||
MI.isPosition())
4771 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4774 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4780 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4781 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4782 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4783 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4784 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4789 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4790 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4791 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4805 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4810 if (
MI.memoperands_empty())
4815 unsigned AS = Memop->getAddrSpace();
4816 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4817 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4818 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4819 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4834 if (
MI.memoperands_empty())
4843 unsigned AS = Memop->getAddrSpace();
4853 bool TgSplit)
const {
4866 if (
MI.memoperands_empty())
4871 unsigned AS = Memop->getAddrSpace();
4889 switch (
MI.getOpcode()) {
4891 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8:
4892 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8_SADDR:
4893 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32:
4894 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32_SADDR:
4895 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64:
4896 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64_SADDR:
4897 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128:
4898 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128_SADDR:
4900 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8:
4901 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8_SADDR:
4902 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32:
4903 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32_SADDR:
4904 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64:
4905 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64_SADDR:
4906 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128:
4907 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128_SADDR:
4909 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8:
4910 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8_SADDR:
4911 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32:
4912 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32_SADDR:
4913 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64:
4914 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64_SADDR:
4915 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128:
4916 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128_SADDR:
4931 unsigned Opcode =
MI.getOpcode();
4946 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4947 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4948 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4949 Opcode == AMDGPU::S_SETHALT)
4952 if (
MI.isCall() ||
MI.isInlineAsm())
4958 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4974 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4975 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4976 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4977 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4985 if (
MI.isMetaInstruction())
4989 if (
MI.isCopyLike()) {
4990 if (!RI.isSGPRReg(
MRI,
MI.getOperand(0).getReg()))
4994 return MI.readsRegister(AMDGPU::EXEC, &RI);
5005 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
5009 switch (
Imm.getBitWidth()) {
5015 ST.hasInv2PiInlineImm());
5018 ST.hasInv2PiInlineImm());
5020 return ST.has16BitInsts() &&
5022 ST.hasInv2PiInlineImm());
5029 APInt IntImm =
Imm.bitcastToAPInt();
5031 bool HasInv2Pi = ST.hasInv2PiInlineImm();
5039 return ST.has16BitInsts() &&
5042 return ST.has16BitInsts() &&
5052 switch (OperandType) {
5062 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5106 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5107 return ST.has16BitInsts() &&
5116 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5117 return ST.has16BitInsts() &&
5169 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5175 return ST.hasVOP3Literal();
5179 int64_t ImmVal)
const {
5181 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5182 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5183 OpNo ==
static_cast<unsigned>(Src1Idx))
5188 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5189 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5190 AMDGPU::OpName::src2))
5193 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5200 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5212 "unexpected imm-like operand kind");
5225 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5245 return Op32 != -1 &&
TII.isVOPC(Op32);
5250 unsigned Depth)
const {
5251 assert(
MRI.isSSA() &&
"isMaskedByExec requires SSA form");
5260 constexpr unsigned MaxDepth = 6;
5261 if (
Depth >= MaxDepth || !Reg.isVirtual())
5267 if (!Def || Def->getParent() !=
MBB)
5275 auto Recurse = [&](
unsigned OpIdx) {
5281 unsigned Opc = Def->getOpcode();
5282 if (
Opc == AMDGPU::COPY && Recurse(1))
5284 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5304 AMDGPU::OpName
OpName)
const {
5306 return Mods && Mods->
getImm();
5319 switch (
MI.getOpcode()) {
5320 default:
return false;
5322 case AMDGPU::V_ADDC_U32_e64:
5323 case AMDGPU::V_SUBB_U32_e64:
5324 case AMDGPU::V_SUBBREV_U32_e64: {
5327 if (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()))
5332 case AMDGPU::V_MAC_F16_e64:
5333 case AMDGPU::V_MAC_F32_e64:
5334 case AMDGPU::V_MAC_LEGACY_F32_e64:
5335 case AMDGPU::V_FMAC_F16_e64:
5336 case AMDGPU::V_FMAC_F16_t16_e64:
5337 case AMDGPU::V_FMAC_F16_fake16_e64:
5338 case AMDGPU::V_FMAC_F32_e64:
5339 case AMDGPU::V_FMAC_F64_e64:
5340 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5341 if (!Src2->isReg() || !RI.isVGPR(
MRI, Src2->getReg()) ||
5346 case AMDGPU::V_CNDMASK_B32_e64:
5352 if (Src1 && (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()) ||
5365 if (Src0 && Src0->isImm()) {
5368 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5390 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5399 unsigned Op32)
const {
5413 Inst32.
add(
MI.getOperand(
I));
5417 int Idx =
MI.getNumExplicitDefs();
5419 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5424 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5444 if (OldSDst && OldSDst->
isDead()) {
5447 NewVCC->setIsDead();
5456 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5464 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5467 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5468 AMDGPU::SReg_64RegClass.contains(Reg);
5474 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5486 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5496 switch (MO.getReg()) {
5498 case AMDGPU::VCC_LO:
5499 case AMDGPU::VCC_HI:
5501 case AMDGPU::FLAT_SCR:
5514 switch (
MI.getOpcode()) {
5515 case AMDGPU::V_READLANE_B32:
5516 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5517 case AMDGPU::V_WRITELANE_B32:
5518 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5525 if (
MI.isPreISelOpcode() ||
5526 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5544 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5555 if (RI.isVectorRegister(
MRI, SrcReg) && RI.isSGPRReg(
MRI, DstReg)) {
5556 ErrInfo =
"illegal copy from vector register to SGPR";
5574 if (!
MRI.isSSA() &&
MI.isCopy())
5575 return verifyCopy(
MI,
MRI, ErrInfo);
5577 if (SIInstrInfo::isGenericOpcode(Opcode))
5580 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5581 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5582 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5584 if (Src0Idx == -1) {
5586 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5587 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5588 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5589 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5594 if (!
Desc.isVariadic() &&
5595 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5596 ErrInfo =
"Instruction has wrong number of operands.";
5600 if (
MI.isInlineAsm()) {
5613 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5614 ErrInfo =
"inlineasm operand has incorrect register class.";
5622 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5623 ErrInfo =
"missing memory operand from image instruction.";
5628 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5631 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5632 "all fp values to integers.";
5638 switch (OpInfo.OperandType) {
5640 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5641 ErrInfo =
"Illegal immediate value for operand.";
5673 ErrInfo =
"Illegal immediate value for operand.";
5682 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5685 OpInfo.OperandType ==
5687 ErrInfo =
"illegal 64-bit immediate value for operand.";
5694 ErrInfo =
"Expected inline constant for operand.";
5708 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5709 ErrInfo =
"Expected immediate, but got non-immediate";
5718 if (OpInfo.isGenericType())
5726 if (!ST.hasSDWA()) {
5727 ErrInfo =
"SDWA is not supported on this target";
5731 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5732 AMDGPU::OpName::dst_sel}) {
5738 ErrInfo =
"Invalid SDWA selection";
5743 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5745 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5750 if (!ST.hasSDWAScalar()) {
5752 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(
MRI, MO.
getReg()))) {
5753 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5760 "Only reg allowed as operands in SDWA instructions on GFX9+";
5766 if (!ST.hasSDWAOmod()) {
5769 if (OMod !=
nullptr &&
5771 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5776 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5777 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5778 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5779 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5782 unsigned Mods = Src0ModsMO->
getImm();
5785 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5791 if (
isVOPC(BasicOpcode)) {
5792 if (!ST.hasSDWASdst() && DstIdx != -1) {
5795 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5796 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5799 }
else if (!ST.hasSDWAOutModsVOPC()) {
5802 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5803 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5809 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5810 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5817 if (DstUnused && DstUnused->isImm() &&
5820 if (!Dst.isReg() || !Dst.isTied()) {
5821 ErrInfo =
"Dst register should have tied register";
5826 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5829 "Dst register should be tied to implicit use of preserved register";
5833 ErrInfo =
"Dst register should use same physical register as preserved";
5839 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5842 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5845 if (Src1MO.
isImm()) {
5846 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5852 if (
isImage(Opcode) && !
MI.mayStore()) {
5857 uint64_t DMaskImm = DMask->
getImm();
5864 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5872 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5876 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5877 if (RegCount > DstSize) {
5878 ErrInfo =
"Image instruction returns too many registers for dst "
5888 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5889 unsigned ConstantBusCount = 0;
5890 bool UsesLiteral =
false;
5893 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5897 LiteralVal = &
MI.getOperand(ImmIdx);
5906 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5917 }
else if (!MO.
isFI()) {
5924 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5934 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5935 return !RI.regsOverlap(SGPRUsed, SGPR);
5944 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5945 Opcode != AMDGPU::V_WRITELANE_B32) {
5946 ErrInfo =
"VOP* instruction violates constant bus restriction";
5950 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5951 ErrInfo =
"VOP3 instruction uses literal";
5958 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5959 unsigned SGPRCount = 0;
5962 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5970 if (MO.
getReg() != SGPRUsed)
5975 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5976 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5982 if (Opcode == AMDGPU::ASYNCMARK || Opcode == AMDGPU::WAIT_ASYNCMARK) {
5983 int64_t Mask =
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm();
5985 ErrInfo =
"invalid asyncmark stage mask";
5991 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5992 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5996 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5999 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
6009 ErrInfo =
"ABS not allowed in VOP3B instructions";
6021 !Src0.isIdenticalTo(Src1)) {
6022 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
6029 if (
Desc.isBranch()) {
6031 ErrInfo =
"invalid branch target for SOPK instruction";
6035 uint64_t
Imm =
Op->getImm();
6038 ErrInfo =
"invalid immediate for SOPK instruction";
6043 ErrInfo =
"invalid immediate for SOPK instruction";
6050 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
6051 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
6052 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6053 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
6054 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6055 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
6057 const unsigned StaticNumOps =
6058 Desc.getNumOperands() +
Desc.implicit_uses().size();
6059 const unsigned NumImplicitOps = IsDst ? 2 : 1;
6065 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
6066 ErrInfo =
"missing implicit register operands";
6072 if (!Dst->isUse()) {
6073 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
6078 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6079 UseOpIdx != StaticNumOps + 1) {
6080 ErrInfo =
"movrel implicit operands should be tied";
6087 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6089 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6090 ErrInfo =
"src0 should be subreg of implicit vector use";
6098 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6099 ErrInfo =
"VALU instruction does not implicitly read exec mask";
6105 if (
MI.mayStore() &&
6110 if (Soff && Soff->
getReg() != AMDGPU::M0) {
6111 ErrInfo =
"scalar stores must use m0 as offset register";
6117 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6119 if (
Offset->getImm() != 0) {
6120 ErrInfo =
"subtarget does not support offsets in flat instructions";
6125 if (
isDS(
MI) && !ST.hasGDS()) {
6127 if (GDSOp && GDSOp->
getImm() != 0) {
6128 ErrInfo =
"GDS is not supported on this subtarget";
6136 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6137 AMDGPU::OpName::vaddr0);
6138 AMDGPU::OpName RSrcOpName =
6139 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6140 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6148 ErrInfo =
"dim is out of range";
6153 if (ST.hasR128A16()) {
6155 IsA16 = R128A16->
getImm() != 0;
6156 }
else if (ST.hasA16()) {
6158 IsA16 = A16->
getImm() != 0;
6161 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6163 unsigned AddrWords =
6166 unsigned VAddrWords;
6168 VAddrWords = RsrcIdx - VAddr0Idx;
6169 if (ST.hasPartialNSAEncoding() &&
6171 unsigned LastVAddrIdx = RsrcIdx - 1;
6172 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6180 if (VAddrWords != AddrWords) {
6182 <<
" but got " << VAddrWords <<
"\n");
6183 ErrInfo =
"bad vaddr size";
6193 unsigned DC = DppCt->
getImm();
6194 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6195 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6196 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6197 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6198 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6199 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6200 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6201 ErrInfo =
"Invalid dpp_ctrl value";
6204 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6205 !ST.hasDPPWavefrontShifts()) {
6206 ErrInfo =
"Invalid dpp_ctrl value: "
6207 "wavefront shifts are not supported on GFX10+";
6210 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6211 !ST.hasDPPBroadcasts()) {
6212 ErrInfo =
"Invalid dpp_ctrl value: "
6213 "broadcasts are not supported on GFX10+";
6216 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6218 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6219 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6220 !ST.hasGFX90AInsts()) {
6221 ErrInfo =
"Invalid dpp_ctrl value: "
6222 "row_newbroadcast/row_share is not supported before "
6226 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6227 ErrInfo =
"Invalid dpp_ctrl value: "
6228 "row_share and row_xmask are not supported before GFX10";
6233 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6235 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6237 ErrInfo =
"Invalid dpp_ctrl value: "
6238 "DP ALU dpp only support row_newbcast";
6245 AMDGPU::OpName DataName =
6246 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6252 if (!ST.hasGFX90AInsts()) {
6253 if ((Dst && RI.isAGPR(
MRI, Dst->getReg())) ||
6255 (Data2 && RI.isAGPR(
MRI, Data2->
getReg()))) {
6256 ErrInfo =
"Invalid register class: "
6257 "agpr loads and stores not supported on this GPU";
6263 if (ST.needsAlignedVGPRs()) {
6264 const auto isAlignedReg = [&
MI, &
MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6269 if (Reg.isPhysical())
6270 return !(RI.getHWRegIndex(Reg) & 1);
6272 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6273 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6277 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6278 ErrInfo =
"Subtarget requires even aligned vector registers "
6279 "for vaddr operand of image instructions";
6285 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6287 if (Src->isReg() && RI.isSGPRReg(
MRI, Src->getReg())) {
6288 ErrInfo =
"Invalid register class: "
6289 "v_accvgpr_write with an SGPR is not supported on this GPU";
6294 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6297 ErrInfo =
"pseudo expects only physical SGPRs";
6304 if (!ST.hasScaleOffset()) {
6305 ErrInfo =
"Subtarget does not support offset scaling";
6309 ErrInfo =
"Instruction does not support offset scaling";
6317 for (
unsigned I = 0;
I < 3; ++
I) {
6323 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6324 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6326 if ((Dst && RI.getRegClassForReg(
MRI, Dst->getReg()) ==
6327 &AMDGPU::SReg_64RegClass) ||
6328 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6329 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6336 ErrInfo =
"GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6344 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6346 return MI.getOperand(1).isReg() || RI.isAGPR(
MRI,
MI.getOperand(0).getReg())
6348 : AMDGPU::V_MOV_B32_e32;
6358 default:
return AMDGPU::INSTRUCTION_LIST_END;
6359 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6360 case AMDGPU::COPY:
return AMDGPU::COPY;
6361 case AMDGPU::PHI:
return AMDGPU::PHI;
6362 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6363 case AMDGPU::WQM:
return AMDGPU::WQM;
6364 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6365 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6366 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6367 case AMDGPU::S_ADD_I32:
6368 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6369 case AMDGPU::S_ADDC_U32:
6370 return AMDGPU::V_ADDC_U32_e32;
6371 case AMDGPU::S_SUB_I32:
6372 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6375 case AMDGPU::S_ADD_U32:
6376 return AMDGPU::V_ADD_CO_U32_e32;
6377 case AMDGPU::S_SUB_U32:
6378 return AMDGPU::V_SUB_CO_U32_e32;
6379 case AMDGPU::S_ADD_U64_PSEUDO:
6380 return AMDGPU::V_ADD_U64_PSEUDO;
6381 case AMDGPU::S_SUB_U64_PSEUDO:
6382 return AMDGPU::V_SUB_U64_PSEUDO;
6383 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6384 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6385 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6386 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6387 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6388 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6389 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6390 case AMDGPU::S_XNOR_B32:
6391 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6392 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6393 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6394 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6395 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6396 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6397 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6398 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6399 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6400 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6401 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6402 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6403 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6404 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6405 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6406 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6407 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6408 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6409 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6410 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6411 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6412 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6413 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6414 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6415 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6416 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6417 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6418 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6419 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6420 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6421 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6422 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6423 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6424 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6425 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6426 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6427 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6428 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6429 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6430 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6431 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6432 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6433 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6434 case AMDGPU::S_CVT_F32_F16:
6435 case AMDGPU::S_CVT_HI_F32_F16:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6437 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6438 case AMDGPU::S_CVT_F16_F32:
6439 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6440 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6441 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6442 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6443 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6444 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6445 case AMDGPU::S_CEIL_F16:
6446 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6447 : AMDGPU::V_CEIL_F16_fake16_e64;
6448 case AMDGPU::S_FLOOR_F16:
6449 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6450 : AMDGPU::V_FLOOR_F16_fake16_e64;
6451 case AMDGPU::S_TRUNC_F16:
6452 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6453 : AMDGPU::V_TRUNC_F16_fake16_e64;
6454 case AMDGPU::S_RNDNE_F16:
6455 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6456 : AMDGPU::V_RNDNE_F16_fake16_e64;
6457 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6458 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6459 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6460 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6461 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6462 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6463 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6464 case AMDGPU::S_ADD_F16:
6465 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6466 : AMDGPU::V_ADD_F16_fake16_e64;
6467 case AMDGPU::S_SUB_F16:
6468 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6469 : AMDGPU::V_SUB_F16_fake16_e64;
6470 case AMDGPU::S_MIN_F16:
6471 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6472 : AMDGPU::V_MIN_F16_fake16_e64;
6473 case AMDGPU::S_MAX_F16:
6474 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6475 : AMDGPU::V_MAX_F16_fake16_e64;
6476 case AMDGPU::S_MINIMUM_F16:
6477 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6478 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6479 case AMDGPU::S_MAXIMUM_F16:
6480 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6481 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6482 case AMDGPU::S_MUL_F16:
6483 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6484 : AMDGPU::V_MUL_F16_fake16_e64;
6485 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6486 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6487 case AMDGPU::S_FMAC_F16:
6488 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6489 : AMDGPU::V_FMAC_F16_fake16_e64;
6490 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6491 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6492 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6493 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6494 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6495 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6496 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6497 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6498 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6499 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6500 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6501 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6502 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6503 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6504 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6505 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6506 case AMDGPU::S_CMP_LT_F16:
6507 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6508 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6509 case AMDGPU::S_CMP_EQ_F16:
6510 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6511 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6512 case AMDGPU::S_CMP_LE_F16:
6513 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6514 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6515 case AMDGPU::S_CMP_GT_F16:
6516 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6517 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6518 case AMDGPU::S_CMP_LG_F16:
6519 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6520 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6521 case AMDGPU::S_CMP_GE_F16:
6522 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6523 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6524 case AMDGPU::S_CMP_O_F16:
6525 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6526 : AMDGPU::V_CMP_O_F16_fake16_e64;
6527 case AMDGPU::S_CMP_U_F16:
6528 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6529 : AMDGPU::V_CMP_U_F16_fake16_e64;
6530 case AMDGPU::S_CMP_NGE_F16:
6531 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6532 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6533 case AMDGPU::S_CMP_NLG_F16:
6534 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6535 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6536 case AMDGPU::S_CMP_NGT_F16:
6537 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6538 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6539 case AMDGPU::S_CMP_NLE_F16:
6540 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6541 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6542 case AMDGPU::S_CMP_NEQ_F16:
6543 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6544 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6545 case AMDGPU::S_CMP_NLT_F16:
6546 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6547 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6548 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6549 case AMDGPU::V_S_EXP_F16_e64:
6550 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6551 : AMDGPU::V_EXP_F16_fake16_e64;
6552 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6553 case AMDGPU::V_S_LOG_F16_e64:
6554 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6555 : AMDGPU::V_LOG_F16_fake16_e64;
6556 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6557 case AMDGPU::V_S_RCP_F16_e64:
6558 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6559 : AMDGPU::V_RCP_F16_fake16_e64;
6560 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6561 case AMDGPU::V_S_RSQ_F16_e64:
6562 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6563 : AMDGPU::V_RSQ_F16_fake16_e64;
6564 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6565 case AMDGPU::V_S_SQRT_F16_e64:
6566 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6567 : AMDGPU::V_SQRT_F16_fake16_e64;
6570 "Unexpected scalar opcode without corresponding vector one!");
6619 "Not a whole wave func");
6622 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6623 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6630 unsigned OpNo)
const {
6632 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6633 Desc.operands()[OpNo].RegClass == -1) {
6636 if (Reg.isVirtual()) {
6638 return MRI.getRegClass(Reg);
6640 return RI.getPhysRegBaseClass(Reg);
6643 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6644 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6649 constexpr AMDGPU::OpName OpNames[] = {
6650 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6653 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6654 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6666 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6668 unsigned Size = RI.getRegSizeInBits(*RC);
6669 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6670 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6671 : AMDGPU::V_MOV_B32_e32;
6673 Opcode = AMDGPU::COPY;
6674 else if (RI.isSGPRClass(RC))
6675 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6694 Register Low64 =
MRI.createVirtualRegister(VRC64);
6700 .
addImm(AMDGPU::sub0_sub1)
6702 .
addImm(AMDGPU::sub2_sub3);
6703 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6720 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6724 Register SubReg =
MRI.createVirtualRegister(SubRC);
6726 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6737 if (SubIdx == AMDGPU::sub0)
6739 if (SubIdx == AMDGPU::sub1)
6751void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6767 if (Reg.isPhysical())
6774 RI.getLargestLegalSuperClass(RC,
MRI.getMF());
6777 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6780 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6787 unsigned Opc =
MI.getOpcode();
6800 bool IsAGPR = RI.isAGPR(
MRI, MO.
getReg());
6801 if (IsAGPR && !ST.hasMAIInsts())
6803 if (IsAGPR && (!ST.hasGFX90AInsts() || !
MRI.reservedRegsFrozen()) &&
6807 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6808 const int DataIdx = AMDGPU::getNamedOperandIdx(
6809 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6810 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6811 MI.getOperand(DataIdx).isReg() &&
6812 RI.isAGPR(
MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6814 if ((
int)OpIdx == DataIdx) {
6815 if (VDstIdx != -1 &&
6816 RI.isAGPR(
MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6819 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6820 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6821 RI.isAGPR(
MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6826 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6827 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6831 if (ST.hasFlatScratchHiInB64InstHazard() &&
6838 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6842 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6851 constexpr unsigned NumOps = 3;
6852 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6853 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6854 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6855 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6860 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6863 MO = &
MI.getOperand(SrcIdx);
6870 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6874 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6878 return !OpSel && !OpSelHi;
6887 int64_t RegClass = getOpRegClassID(OpInfo);
6889 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6891 MO = &
MI.getOperand(OpIdx);
6895 if (
isVALU(
MI,
false) && !IsInlineConst &&
6899 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6900 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6904 if (!LiteralLimit--)
6914 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6922 if (--ConstantBusLimit <= 0)
6934 if (!LiteralLimit--)
6936 if (--ConstantBusLimit <= 0)
6942 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6946 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6948 !
Op.isIdenticalTo(*MO))
6970 bool Is64BitOp = Is64BitFPOp ||
6978 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6987 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
7005 bool IsGFX950Only = ST.hasGFX950Insts();
7006 bool IsGFX940Only = ST.hasGFX940Insts();
7008 if (!IsGFX950Only && !IsGFX940Only)
7026 unsigned Opcode =
MI.getOpcode();
7028 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7029 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7030 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7031 case AMDGPU::V_MQSAD_U32_U8_e64:
7032 case AMDGPU::V_PK_ADD_F16:
7033 case AMDGPU::V_PK_ADD_F32:
7034 case AMDGPU::V_PK_ADD_I16:
7035 case AMDGPU::V_PK_ADD_U16:
7036 case AMDGPU::V_PK_ASHRREV_I16:
7037 case AMDGPU::V_PK_FMA_F16:
7038 case AMDGPU::V_PK_FMA_F32:
7039 case AMDGPU::V_PK_FMAC_F16_e32:
7040 case AMDGPU::V_PK_FMAC_F16_e64:
7041 case AMDGPU::V_PK_LSHLREV_B16:
7042 case AMDGPU::V_PK_LSHRREV_B16:
7043 case AMDGPU::V_PK_MAD_I16:
7044 case AMDGPU::V_PK_MAD_U16:
7045 case AMDGPU::V_PK_MAX_F16:
7046 case AMDGPU::V_PK_MAX_I16:
7047 case AMDGPU::V_PK_MAX_U16:
7048 case AMDGPU::V_PK_MIN_F16:
7049 case AMDGPU::V_PK_MIN_I16:
7050 case AMDGPU::V_PK_MIN_U16:
7051 case AMDGPU::V_PK_MOV_B32:
7052 case AMDGPU::V_PK_MUL_F16:
7053 case AMDGPU::V_PK_MUL_F32:
7054 case AMDGPU::V_PK_MUL_LO_U16:
7055 case AMDGPU::V_PK_SUB_I16:
7056 case AMDGPU::V_PK_SUB_U16:
7057 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7066 unsigned Opc =
MI.getOpcode();
7069 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
7072 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7078 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7079 RI.isSGPRReg(
MRI, Src0.getReg()))
7085 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7087 if (Src0.isReg() && RI.isVGPR(
MRI, Src0.getReg())) {
7088 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7091 Src0.ChangeToRegister(Reg,
false);
7093 if (Src1.isReg() && RI.isVGPR(
MRI, Src1.getReg())) {
7094 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7098 Src1.ChangeToRegister(Reg,
false);
7104 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7105 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7106 if (!RI.isVGPR(
MRI,
MI.getOperand(Src2Idx).getReg()))
7118 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7119 RI.isVGPR(
MRI, Src1.getReg())) {
7120 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7124 Src1.ChangeToRegister(Reg,
false);
7132 if (HasImplicitSGPR || !
MI.isCommutable()) {
7142 if ((!Src1.isImm() && !Src1.isReg()) ||
7149 if (CommutedOpc == -1) {
7154 MI.setDesc(
get(CommutedOpc));
7157 unsigned Src0SubReg = Src0.getSubReg();
7158 bool Src0Kill = Src0.isKill();
7161 Src0.ChangeToImmediate(Src1.getImm());
7162 else if (Src1.isReg()) {
7163 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7164 Src0.setSubReg(Src1.getSubReg());
7168 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7169 Src1.setSubReg(Src0SubReg);
7177 unsigned Opc =
MI.getOpcode();
7180 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7181 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7182 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7185 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7186 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7187 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7188 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7189 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7190 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7191 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7195 if (Src1.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src1.getReg()))) {
7196 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7199 Src1.ChangeToRegister(Reg,
false);
7201 if (VOP3Idx[2] != -1) {
7203 if (Src2.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src2.getReg()))) {
7204 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7207 Src2.ChangeToRegister(Reg,
false);
7213 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7214 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7216 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7218 SGPRsUsed.
insert(SGPRReg);
7222 for (
int Idx : VOP3Idx) {
7231 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7243 if (!RI.isSGPRClass(RI.getRegClassForReg(
MRI, MO.
getReg())))
7250 if (ConstantBusLimit > 0) {
7262 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7263 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7264 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7265 !RI.isVGPR(
MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7271 for (
unsigned I = 0;
I < 3; ++
I) {
7284 SRC = RI.getCommonSubClass(SRC, DstRC);
7287 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7289 if (RI.hasAGPRs(VRC)) {
7290 VRC = RI.getEquivalentVGPRClass(VRC);
7291 Register NewSrcReg =
MRI.createVirtualRegister(VRC);
7293 get(TargetOpcode::COPY), NewSrcReg)
7300 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7306 for (
unsigned i = 0; i < SubRegs; ++i) {
7307 Register SGPR =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7309 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7310 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7316 get(AMDGPU::REG_SEQUENCE), DstReg);
7317 for (
unsigned i = 0; i < SubRegs; ++i) {
7319 MIB.
addImm(RI.getSubRegFromChannel(i));
7332 if (SBase && !RI.isSGPRClass(
MRI.getRegClass(SBase->getReg()))) {
7334 SBase->setReg(SGPR);
7337 if (SOff && !RI.isSGPRReg(
MRI, SOff->
getReg())) {
7345 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7346 if (OldSAddrIdx < 0)
7362 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7363 if (NewVAddrIdx < 0)
7366 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7370 if (OldVAddrIdx >= 0) {
7372 VAddrDef =
MRI.getUniqueVRegDef(VAddr.
getReg());
7384 if (OldVAddrIdx == NewVAddrIdx) {
7387 MRI.removeRegOperandFromUseList(&NewVAddr);
7388 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7392 MRI.removeRegOperandFromUseList(&NewVAddr);
7393 MRI.addRegOperandToUseList(&NewVAddr);
7395 assert(OldSAddrIdx == NewVAddrIdx);
7397 if (OldVAddrIdx >= 0) {
7398 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7399 AMDGPU::OpName::vdst_in);
7403 if (NewVDstIn != -1) {
7404 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7410 if (NewVDstIn != -1) {
7411 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7432 if (!SAddr || RI.isSGPRClass(
MRI.getRegClass(SAddr->
getReg())))
7452 unsigned OpSubReg =
Op.getSubReg();
7455 RI.getRegClassForReg(
MRI, OpReg), OpSubReg);
7461 Register DstReg =
MRI.createVirtualRegister(DstRC);
7462 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7463 .
addReg(OpReg, {}, OpSubReg);
7465 Op.setSubReg(AMDGPU::NoSubRegister);
7472 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7475 bool ImpDef = Def->isImplicitDef();
7476 while (!ImpDef && Def && Def->isCopy()) {
7477 if (Def->getOperand(1).getReg().isPhysical())
7479 Def =
MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7480 ImpDef = Def && Def->isImplicitDef();
7482 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7498 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7503 bool UseNewExecInstructions =
7512 if (UseNewExecInstructions) {
7547 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7548 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(),
MRI);
7549 unsigned NumSubRegs =
RegSize / 32;
7550 Register VScalarOp = ScalarOp->getReg();
7553 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7555 if (NumSubRegs == 1) {
7558 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7559 Common != VScalarOpRC) {
7566 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7569 if (UseNewExecInstructions) {
7571 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7574 if (
I == LoopBB.
end())
7579 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7585 CondReg = NewCondReg;
7597 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7598 ScalarOp->setReg(CurReg);
7601 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7602 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7604 ScalarOp->setReg(PhySGPRs[Idx]);
7609 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7610 "Unhandled register size");
7612 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7619 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7620 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7623 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7624 .
addReg(VScalarOp, VScalarOpUndef,
7625 TRI->getSubRegFromChannel(Idx + 1));
7632 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7639 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7641 if (UseNewExecInstructions) {
7643 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7645 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7646 if (
I == LoopBB.
end())
7650 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7652 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7656 CondReg = NewCondReg;
7668 const auto *SScalarOpRC =
7674 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7675 unsigned Channel = 0;
7676 for (
Register Piece : ReadlanePieces) {
7677 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7681 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7682 ScalarOp->setReg(SScalarOp);
7684 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7685 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7687 ScalarOp->setReg(PhySGPRs[Idx]);
7695 if (!UseNewExecInstructions) {
7708 if (UseNewExecInstructions) {
7741 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7742 "Physical SGPRs must be empty or match the number of scalar operands");
7748 if (!Begin.isValid())
7750 if (!
End.isValid()) {
7756 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7765 std::numeric_limits<unsigned>::max()) !=
7811 for (
auto &Succ : RemainderBB->
successors()) {
7836static std::tuple<unsigned, unsigned>
7844 TII.buildExtractSubReg(
MI,
MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7845 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7848 Register Zero64 =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7849 Register SRsrcFormatLo =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7850 Register SRsrcFormatHi =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7851 Register NewSRsrc =
MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7852 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7869 .
addImm(AMDGPU::sub0_sub1)
7875 return std::tuple(RsrcPtr, NewSRsrc);
7886 if (ST.useRealTrue16Insts())
7916 if (
MI.getOpcode() == AMDGPU::PHI) {
7918 assert(!RI.isSGPRClass(VRC));
7921 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7923 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7939 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7942 if (RI.hasVGPRs(DstRC)) {
7946 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7948 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7965 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7970 if (DstRC != Src0RC) {
7979 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7981 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
7987 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7988 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7989 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7990 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7991 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7992 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7993 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7995 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8008 ? AMDGPU::OpName::rsrc
8009 : AMDGPU::OpName::srsrc;
8011 if (SRsrc && !RI.isSGPRClass(
MRI.getRegClass(SRsrc->
getReg())))
8014 AMDGPU::OpName SampOpName =
8015 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8017 if (SSamp && !RI.isSGPRClass(
MRI.getRegClass(SSamp->
getReg())))
8024 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8026 if (!RI.isSGPRClass(
MRI.getRegClass(Dest->
getReg()))) {
8032 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8034 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8036 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
8040 Src0.ChangeToRegister(Reg,
false);
8046 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8047 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8048 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8049 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8051 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8058 bool isSoffsetLegal =
true;
8060 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
8061 if (SoffsetIdx != -1) {
8064 !RI.isSGPRClass(
MRI.getRegClass(Soffset->
getReg()))) {
8065 isSoffsetLegal =
false;
8069 bool isRsrcLegal =
true;
8071 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8072 if (RsrcIdx != -1) {
8075 isRsrcLegal =
false;
8079 if (isRsrcLegal && isSoffsetLegal)
8103 Register NewVAddrLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8104 Register NewVAddrHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8105 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8107 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8108 Register CondReg0 =
MRI.createVirtualRegister(BoolXExecRC);
8109 Register CondReg1 =
MRI.createVirtualRegister(BoolXExecRC);
8111 unsigned RsrcPtr, NewSRsrc;
8118 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8119 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8125 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8126 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8139 }
else if (!VAddr && ST.hasAddr64()) {
8143 "FIXME: Need to emit flat atomics here");
8145 unsigned RsrcPtr, NewSRsrc;
8148 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8171 MIB.
addImm(CPol->getImm());
8176 MIB.
addImm(TFE->getImm());
8196 MI.removeFromParent();
8201 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8202 .addImm(AMDGPU::sub0)
8203 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8204 .addImm(AMDGPU::sub1);
8207 if (!isSoffsetLegal) {
8218 if (!isSoffsetLegal) {
8227 if (InSet.insert(
MI).second)
8231 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8232 if (RsrcIdx != -1) {
8233 DeferredList.insert(
MI);
8238 return DeferredList.contains(
MI);
8248 if (!ST.useRealTrue16Insts())
8251 unsigned Opcode =
MI.getOpcode();
8254 if (OpIdx >=
MI.getNumExplicitOperands() ||
8255 OpIdx >=
get(Opcode).getNumOperands() ||
8256 get(Opcode).operands()[OpIdx].RegClass == -1)
8260 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8264 if (!RI.isVGPRClass(CurrRC))
8267 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8269 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8271 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8272 Op.setSubReg(AMDGPU::lo16);
8277 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8278 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8280 Register NewDstReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8288 Op.setReg(NewDstReg);
8289 Op.setSubReg(AMDGPU::NoSubRegister);
8294 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8302 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8303 "This only handle waterfall for SI_CALL_ISEL");
8310 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8313 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8318 while (
End !=
MBB.end() &&
End->isCopy() &&
8319 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8329 while (!Worklist.
empty()) {
8335 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8341 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8343 "Deferred MachineInstr are not supposed to re-populate worklist");
8346 for (
auto &Entry : WaterFalls) {
8347 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8349 Entry.second.SGPRs);
8352 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8354 Entry.first->eraseFromParent();
8362 if (SubRegIndices.
size() <= 1) {
8363 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8365 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8372 for (int16_t Indice : SubRegIndices) {
8373 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8375 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8382 get(AMDGPU::REG_SEQUENCE), DstReg);
8383 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8385 MIB.
addImm(RI.getSubRegFromChannel(i));
8395 if (DstReg == AMDGPU::M0) {
8408 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8410 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8411 if (
UseMI->getOperand(i).isReg() &&
8412 UseMI->getOperand(i).getReg() == DstReg) {
8416 V2SCopyInfo.MOs.push_back(MO);
8417 V2SCopyInfo.SGPRs.push_back(DstReg);
8421 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8422 I->getOperand(0).isReg() &&
8423 I->getOperand(0).getReg() == DstReg) {
8426 }
else if (
I->readsRegister(DstReg, &RI)) {
8428 V2SPhyCopiesToErase[&Inst] =
false;
8430 if (
I->findRegisterDefOperand(DstReg, &RI))
8452 case AMDGPU::S_ADD_I32:
8453 case AMDGPU::S_SUB_I32: {
8457 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8465 case AMDGPU::S_MUL_U64:
8466 if (ST.useVMulU64Inst()) {
8467 NewOpcode = AMDGPU::V_MUL_U64_e64;
8471 splitScalarSMulU64(Worklist, Inst, MDT);
8475 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8476 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8479 splitScalarSMulPseudo(Worklist, Inst, MDT);
8483 case AMDGPU::S_AND_B64:
8484 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8488 case AMDGPU::S_OR_B64:
8489 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8493 case AMDGPU::S_XOR_B64:
8494 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8498 case AMDGPU::S_NAND_B64:
8499 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8503 case AMDGPU::S_NOR_B64:
8504 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8508 case AMDGPU::S_XNOR_B64:
8509 if (ST.hasDLInsts())
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8512 splitScalar64BitXnor(Worklist, Inst, MDT);
8516 case AMDGPU::S_ANDN2_B64:
8517 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8521 case AMDGPU::S_ORN2_B64:
8522 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8526 case AMDGPU::S_BREV_B64:
8527 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8531 case AMDGPU::S_NOT_B64:
8532 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8536 case AMDGPU::S_BCNT1_I32_B64:
8537 splitScalar64BitBCNT(Worklist, Inst);
8541 case AMDGPU::S_BFE_I64:
8542 splitScalar64BitBFE(Worklist, Inst);
8546 case AMDGPU::S_FLBIT_I32_B64:
8547 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8550 case AMDGPU::S_FF1_I32_B64:
8551 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8555 case AMDGPU::S_LSHL_B32:
8556 if (ST.hasOnlyRevVALUShifts()) {
8557 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8561 case AMDGPU::S_ASHR_I32:
8562 if (ST.hasOnlyRevVALUShifts()) {
8563 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8567 case AMDGPU::S_LSHR_B32:
8568 if (ST.hasOnlyRevVALUShifts()) {
8569 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8573 case AMDGPU::S_LSHL_B64:
8574 if (ST.hasOnlyRevVALUShifts()) {
8576 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8577 : AMDGPU::V_LSHLREV_B64_e64;
8581 case AMDGPU::S_ASHR_I64:
8582 if (ST.hasOnlyRevVALUShifts()) {
8583 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8587 case AMDGPU::S_LSHR_B64:
8588 if (ST.hasOnlyRevVALUShifts()) {
8589 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8594 case AMDGPU::S_ABS_I32:
8595 lowerScalarAbs(Worklist, Inst);
8599 case AMDGPU::S_ABSDIFF_I32:
8600 lowerScalarAbsDiff(Worklist, Inst);
8604 case AMDGPU::S_CBRANCH_SCC0:
8605 case AMDGPU::S_CBRANCH_SCC1: {
8608 bool IsSCC = CondReg == AMDGPU::SCC;
8617 case AMDGPU::S_BFE_U64:
8618 case AMDGPU::S_BFM_B64:
8621 case AMDGPU::S_PACK_LL_B32_B16:
8622 case AMDGPU::S_PACK_LH_B32_B16:
8623 case AMDGPU::S_PACK_HL_B32_B16:
8624 case AMDGPU::S_PACK_HH_B32_B16:
8625 movePackToVALU(Worklist,
MRI, Inst);
8629 case AMDGPU::S_XNOR_B32:
8630 lowerScalarXnor(Worklist, Inst);
8634 case AMDGPU::S_NAND_B32:
8635 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8639 case AMDGPU::S_NOR_B32:
8640 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8644 case AMDGPU::S_ANDN2_B32:
8645 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8649 case AMDGPU::S_ORN2_B32:
8650 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8658 case AMDGPU::S_ADD_CO_PSEUDO:
8659 case AMDGPU::S_SUB_CO_PSEUDO: {
8660 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8661 ? AMDGPU::V_ADDC_U32_e64
8662 : AMDGPU::V_SUBB_U32_e64;
8663 const auto *CarryRC = RI.getWaveMaskRegClass();
8666 if (!
MRI.constrainRegClass(CarryInReg, CarryRC)) {
8667 Register NewCarryReg =
MRI.createVirtualRegister(CarryRC);
8674 Register DestReg =
MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8685 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8689 case AMDGPU::S_UADDO_PSEUDO:
8690 case AMDGPU::S_USUBO_PSEUDO: {
8696 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8697 ? AMDGPU::V_ADD_CO_U32_e64
8698 : AMDGPU::V_SUB_CO_U32_e64;
8700 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest0.
getReg()));
8701 Register DestReg =
MRI.createVirtualRegister(NewRC);
8709 MRI.replaceRegWith(Dest0.
getReg(), DestReg);
8710 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8714 case AMDGPU::S_LSHL1_ADD_U32:
8715 case AMDGPU::S_LSHL2_ADD_U32:
8716 case AMDGPU::S_LSHL3_ADD_U32:
8717 case AMDGPU::S_LSHL4_ADD_U32: {
8721 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8722 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8723 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8727 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest.
getReg()));
8728 Register DestReg =
MRI.createVirtualRegister(NewRC);
8736 MRI.replaceRegWith(Dest.
getReg(), DestReg);
8737 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8741 case AMDGPU::S_CSELECT_B32:
8742 case AMDGPU::S_CSELECT_B64:
8743 lowerSelect(Worklist, Inst, MDT);
8746 case AMDGPU::S_CMP_EQ_I32:
8747 case AMDGPU::S_CMP_LG_I32:
8748 case AMDGPU::S_CMP_GT_I32:
8749 case AMDGPU::S_CMP_GE_I32:
8750 case AMDGPU::S_CMP_LT_I32:
8751 case AMDGPU::S_CMP_LE_I32:
8752 case AMDGPU::S_CMP_EQ_U32:
8753 case AMDGPU::S_CMP_LG_U32:
8754 case AMDGPU::S_CMP_GT_U32:
8755 case AMDGPU::S_CMP_GE_U32:
8756 case AMDGPU::S_CMP_LT_U32:
8757 case AMDGPU::S_CMP_LE_U32:
8758 case AMDGPU::S_CMP_EQ_U64:
8759 case AMDGPU::S_CMP_LG_U64:
8760 case AMDGPU::S_CMP_LT_F32:
8761 case AMDGPU::S_CMP_EQ_F32:
8762 case AMDGPU::S_CMP_LE_F32:
8763 case AMDGPU::S_CMP_GT_F32:
8764 case AMDGPU::S_CMP_LG_F32:
8765 case AMDGPU::S_CMP_GE_F32:
8766 case AMDGPU::S_CMP_O_F32:
8767 case AMDGPU::S_CMP_U_F32:
8768 case AMDGPU::S_CMP_NGE_F32:
8769 case AMDGPU::S_CMP_NLG_F32:
8770 case AMDGPU::S_CMP_NGT_F32:
8771 case AMDGPU::S_CMP_NLE_F32:
8772 case AMDGPU::S_CMP_NEQ_F32:
8773 case AMDGPU::S_CMP_NLT_F32: {
8774 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8778 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8792 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8796 case AMDGPU::S_CMP_LT_F16:
8797 case AMDGPU::S_CMP_EQ_F16:
8798 case AMDGPU::S_CMP_LE_F16:
8799 case AMDGPU::S_CMP_GT_F16:
8800 case AMDGPU::S_CMP_LG_F16:
8801 case AMDGPU::S_CMP_GE_F16:
8802 case AMDGPU::S_CMP_O_F16:
8803 case AMDGPU::S_CMP_U_F16:
8804 case AMDGPU::S_CMP_NGE_F16:
8805 case AMDGPU::S_CMP_NLG_F16:
8806 case AMDGPU::S_CMP_NGT_F16:
8807 case AMDGPU::S_CMP_NLE_F16:
8808 case AMDGPU::S_CMP_NEQ_F16:
8809 case AMDGPU::S_CMP_NLT_F16: {
8810 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8831 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8835 case AMDGPU::S_CVT_HI_F32_F16: {
8836 Register TmpReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8837 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8838 if (ST.useRealTrue16Insts()) {
8843 .
addReg(TmpReg, {}, AMDGPU::hi16)
8859 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8863 case AMDGPU::S_MINIMUM_F32:
8864 case AMDGPU::S_MAXIMUM_F32: {
8865 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8876 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8880 case AMDGPU::S_MINIMUM_F16:
8881 case AMDGPU::S_MAXIMUM_F16: {
8882 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8883 ? &AMDGPU::VGPR_16RegClass
8884 : &AMDGPU::VGPR_32RegClass);
8895 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8899 case AMDGPU::V_S_EXP_F16_e64:
8900 case AMDGPU::V_S_LOG_F16_e64:
8901 case AMDGPU::V_S_RCP_F16_e64:
8902 case AMDGPU::V_S_RSQ_F16_e64:
8903 case AMDGPU::V_S_SQRT_F16_e64: {
8904 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8905 ? &AMDGPU::VGPR_16RegClass
8906 : &AMDGPU::VGPR_32RegClass);
8917 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8923 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8931 if (NewOpcode == Opcode) {
8938 V2SPhyCopiesToErase);
8946 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8953 addUsersToMoveToVALUWorklist(DstReg,
MRI, Worklist);
8959 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8960 UseMO.setReg(NewDstReg);
8965 if (!
MRI.constrainRegClass(NewDstReg, CommonRC))
8978 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8981 MRI.constrainRegClass(NewDstReg, OpRC);
8991 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8995 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8996 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9001 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9007 MRI.replaceRegWith(DstReg, NewDstReg);
9008 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9010 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9013 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9014 MRI.replaceRegWith(DstReg, NewDstReg);
9015 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9020 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9021 MRI.replaceRegWith(DstReg, NewDstReg);
9023 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9033 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9034 AMDGPU::OpName::src0_modifiers) >= 0)
9038 NewInstr->addOperand(Src);
9041 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9044 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9046 NewInstr.addImm(
Size);
9047 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9051 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9056 "Scalar BFE is only implemented for constant width and offset");
9064 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9065 AMDGPU::OpName::src1_modifiers) >= 0)
9067 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9069 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9070 AMDGPU::OpName::src2_modifiers) >= 0)
9072 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9074 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9076 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9078 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9084 NewInstr->addOperand(
Op);
9090 bool DeadSCCDef =
false;
9092 if (
Op.getReg() == AMDGPU::SCC) {
9098 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9102 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9107 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9108 Register DstReg = NewInstr->getOperand(0).getReg();
9113 NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9114 MRI.replaceRegWith(DstReg, NewDstReg);
9122 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9123 VCCDef->setIsDead();
9129 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9133std::pair<bool, MachineBasicBlock *>
9136 if (ST.hasAddNoCarryInsts()) {
9145 Register ResultReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9148 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9150 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9151 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9159 MRI.replaceRegWith(OldDstReg, ResultReg);
9162 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9163 return std::pair(
true, NewBB);
9166 return std::pair(
false,
nullptr);
9183 bool IsSCC = (CondReg == AMDGPU::SCC);
9189 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9190 (
Src1.getImm() == 0)) {
9191 for (MachineOperand &UseMO :
9193 MachineInstr &
UseMI = *UseMO.getParent();
9194 switch (
UseMI.getOpcode()) {
9195 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9196 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9197 case AMDGPU::V_CNDMASK_B16_t16_e32:
9198 case AMDGPU::V_CNDMASK_B16_t16_e64:
9199 case AMDGPU::V_CNDMASK_B32_e32:
9200 case AMDGPU::V_CNDMASK_B32_e64:
9201 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9202 if (UseMO.isImplicit() ||
9204 UseMO.setReg(CondReg);
9218 bool CopyFound =
false;
9219 for (MachineInstr &CandI :
9222 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9224 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9226 .
addReg(CandI.getOperand(1).getReg());
9238 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9247 MachineInstr *NewInst;
9248 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9249 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9264 addUsersToMoveToVALUWorklist(NewDestReg,
MRI, Worklist);
9279 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9281 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9283 MachineInstrBuilder
Sub =
9293 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9310 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9312 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9314 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9318 MachineInstrBuilder Sub2 =
9331 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9345 if (ST.hasDLInsts()) {
9355 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9361 bool Src0IsSGPR =
Src0.isReg() &&
9363 bool Src1IsSGPR =
Src1.isReg() &&
9377 }
else if (Src1IsSGPR) {
9395 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9401 unsigned Opcode)
const {
9425 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9430 unsigned Opcode)
const {
9454 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9469 const MCInstrDesc &InstDesc =
get(Opcode);
9472 &AMDGPU::SGPR_32RegClass;
9475 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9478 AMDGPU::sub0, Src0SubRC);
9483 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9486 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9489 AMDGPU::sub1, Src0SubRC);
9492 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9506 Worklist.
insert(&LoHalf);
9507 Worklist.
insert(&HiHalf);
9513 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9537 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9538 if (RI.isSGPRClass(Src0SubRC))
9539 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9541 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9542 if (RI.isSGPRClass(Src1SubRC))
9543 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9547 MachineOperand Op0L =
9549 MachineOperand Op1L =
9551 MachineOperand Op0H =
9553 MachineOperand Op1H =
9572 MachineInstr *Op1L_Op0H =
9578 MachineInstr *Op1H_Op0L =
9584 MachineInstr *Carry =
9589 MachineInstr *LoHalf =
9599 MachineInstr *HiHalf =
9622 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9646 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9647 if (RI.isSGPRClass(Src0SubRC))
9648 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9650 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9651 if (RI.isSGPRClass(Src1SubRC))
9652 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9656 MachineOperand Op0L =
9658 MachineOperand Op1L =
9662 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9663 ? AMDGPU::V_MUL_HI_U32_e64
9664 : AMDGPU::V_MUL_HI_I32_e64;
9665 MachineInstr *HiHalf =
9668 MachineInstr *LoHalf =
9687 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9703 const MCInstrDesc &InstDesc =
get(Opcode);
9706 &AMDGPU::SGPR_32RegClass;
9709 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9712 &AMDGPU::SGPR_32RegClass;
9715 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9718 AMDGPU::sub0, Src0SubRC);
9720 AMDGPU::sub0, Src1SubRC);
9722 AMDGPU::sub1, Src0SubRC);
9724 AMDGPU::sub1, Src1SubRC);
9729 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9732 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9737 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9750 Worklist.
insert(&LoHalf);
9751 Worklist.
insert(&HiHalf);
9754 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9774 MachineOperand* Op0;
9775 MachineOperand* Op1;
9777 if (
Src0.isReg() && RI.isSGPRReg(
MRI,
Src0.getReg())) {
9810 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9813 &AMDGPU::SGPR_32RegClass;
9819 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9822 AMDGPU::sub0, SrcSubRC);
9824 AMDGPU::sub1, SrcSubRC);
9834 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9853 Offset == 0 &&
"Not implemented");
9876 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9886 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9889 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9895 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9914 const MCInstrDesc &InstDesc =
get(Opcode);
9916 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9919 Src.isReg() ?
MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9921 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9923 MachineOperand SrcRegSub0 =
9925 MachineOperand SrcRegSub1 =
9939 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9943 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9947 addUsersToMoveToVALUWorklist(MidReg4,
MRI, Worklist);
9950void SIInstrInfo::addUsersToMoveToVALUWorklist(
9954 MachineInstr &
UseMI = *MO.getParent();
9958 switch (
UseMI.getOpcode()) {
9961 case AMDGPU::SOFT_WQM:
9962 case AMDGPU::STRICT_WWM:
9963 case AMDGPU::STRICT_WQM:
9964 case AMDGPU::REG_SEQUENCE:
9966 case AMDGPU::INSERT_SUBREG:
9969 OpNo = MO.getOperandNo();
9976 if (!RI.hasVectorRegisters(OpRC))
9993 if (ST.useRealTrue16Insts()) {
9995 if (!
Src0.isReg() || !RI.isVGPR(
MRI,
Src0.getReg())) {
9998 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10001 SrcReg0 =
Src0.getReg();
10004 if (!
Src1.isReg() || !RI.isVGPR(
MRI,
Src1.getReg())) {
10007 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10010 SrcReg1 =
Src1.getReg();
10016 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
10018 case AMDGPU::S_PACK_LL_B32_B16:
10020 .addReg(SrcReg0, {},
10021 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10022 .addImm(AMDGPU::lo16)
10023 .addReg(SrcReg1, {},
10024 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10025 .addImm(AMDGPU::hi16);
10027 case AMDGPU::S_PACK_LH_B32_B16:
10029 .addReg(SrcReg0, {},
10030 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10031 .addImm(AMDGPU::lo16)
10032 .addReg(SrcReg1, {}, AMDGPU::hi16)
10033 .addImm(AMDGPU::hi16);
10035 case AMDGPU::S_PACK_HL_B32_B16:
10036 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10037 .addImm(AMDGPU::lo16)
10038 .addReg(SrcReg1, {},
10039 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10040 .addImm(AMDGPU::hi16);
10042 case AMDGPU::S_PACK_HH_B32_B16:
10043 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10044 .addImm(AMDGPU::lo16)
10045 .addReg(SrcReg1, {}, AMDGPU::hi16)
10046 .addImm(AMDGPU::hi16);
10054 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10059 case AMDGPU::S_PACK_LL_B32_B16: {
10078 case AMDGPU::S_PACK_LH_B32_B16: {
10088 case AMDGPU::S_PACK_HL_B32_B16: {
10099 case AMDGPU::S_PACK_HH_B32_B16: {
10119 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10128 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10129 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10130 SmallVector<MachineInstr *, 4> CopyToDelete;
10133 for (MachineInstr &
MI :
10137 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10138 if (SCCIdx != -1) {
10141 Register DestReg =
MI.getOperand(0).getReg();
10148 MI.getOperand(SCCIdx).setReg(NewCond);
10154 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10157 for (
auto &Copy : CopyToDelete)
10158 Copy->eraseFromParent();
10166void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10172 for (MachineInstr &
MI :
10175 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10177 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10194 case AMDGPU::REG_SEQUENCE:
10195 case AMDGPU::INSERT_SUBREG:
10197 case AMDGPU::SOFT_WQM:
10198 case AMDGPU::STRICT_WWM:
10199 case AMDGPU::STRICT_WQM: {
10201 if (RI.isAGPRClass(SrcRC)) {
10202 if (RI.isAGPRClass(NewDstRC))
10207 case AMDGPU::REG_SEQUENCE:
10208 case AMDGPU::INSERT_SUBREG:
10209 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10212 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10218 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10221 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10235 int OpIndices[3])
const {
10236 const MCInstrDesc &
Desc =
MI.getDesc();
10254 for (
unsigned i = 0; i < 3; ++i) {
10255 int Idx = OpIndices[i];
10259 const MachineOperand &MO =
MI.getOperand(Idx);
10266 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10267 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10268 if (IsRequiredSGPR)
10274 if (RI.isSGPRClass(RegRC))
10275 UsedSGPRs[i] =
Reg;
10291 if (UsedSGPRs[0]) {
10292 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10293 SGPRReg = UsedSGPRs[0];
10296 if (!SGPRReg && UsedSGPRs[1]) {
10297 if (UsedSGPRs[1] == UsedSGPRs[2])
10298 SGPRReg = UsedSGPRs[1];
10305 AMDGPU::OpName OperandName)
const {
10306 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10309 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10313 return &
MI.getOperand(Idx);
10327 if (ST.isAmdHsaOS()) {
10330 RsrcDataFormat |= (1ULL << 56);
10335 RsrcDataFormat |= (2ULL << 59);
10338 return RsrcDataFormat;
10348 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10353 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10360 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10366 unsigned Opc =
MI.getOpcode();
10372 return get(
Opc).mayLoad() &&
10379 if (!Addr || !Addr->
isFI())
10388 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10390 return MI.getOperand(VDataIdx).getReg();
10400 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10402 return MI.getOperand(DataIdx).getReg();
10423 if (!
MI.mayStore())
10436 unsigned Opc =
MI.getOpcode();
10438 unsigned DescSize =
Desc.getSize();
10443 unsigned Size = DescSize;
10447 if (
MI.isBranch() && ST.hasOffset3fBug())
10458 bool HasLiteral =
false;
10459 unsigned LiteralSize = 4;
10460 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10465 if (ST.has64BitLiterals()) {
10466 switch (OpInfo.OperandType) {
10491 return HasLiteral ? DescSize + LiteralSize : DescSize;
10496 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10500 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10501 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10505 case TargetOpcode::BUNDLE:
10506 return getInstBundleSize(
MI);
10507 case TargetOpcode::INLINEASM:
10508 case TargetOpcode::INLINEASM_BR: {
10510 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10514 if (
MI.isMetaInstruction())
10518 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10521 unsigned LoInstOpcode = D16Info->LoOp;
10523 DescSize =
Desc.getSize();
10527 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10530 DescSize =
Desc.getSize();
10539 if (
MI.isBranch() && ST.hasOffset3fBug())
10540 return InstSizeVerifyMode::NoVerify;
10541 return InstSizeVerifyMode::ExactSize;
10546 static const std::pair<int, const char *> TargetIndices[] = {
10586std::pair<unsigned, unsigned>
10593 static const std::pair<unsigned, const char *> TargetFlags[] = {
10611 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10629 return AMDGPU::WWM_COPY;
10631 return AMDGPU::COPY;
10648 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10652 if (RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg)))
10653 return IsLRSplitInst;
10666 bool IsNullOrVectorRegister =
true;
10670 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg));
10673 return IsNullOrVectorRegister &&
10675 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10676 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10684 if (ST.hasAddNoCarryInsts())
10688 Register UnusedCarry =
MRI.createVirtualRegister(RI.getBoolRC());
10689 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10700 if (ST.hasAddNoCarryInsts())
10704 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10706 : RS.scavengeRegisterBackwards(
10707 *RI.getBoolRC(),
I,
false,
10720 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10721 case AMDGPU::SI_KILL_I1_TERMINATOR:
10730 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10731 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10732 case AMDGPU::SI_KILL_I1_PSEUDO:
10733 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10745 const unsigned OffsetBits =
10747 return (1 << OffsetBits) - 1;
10751 if (!ST.isWave32())
10754 if (
MI.isInlineAsm())
10757 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10760 for (
auto &
Op :
MI.implicit_operands()) {
10761 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10762 Op.setReg(AMDGPU::VCC_LO);
10771 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10775 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10776 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10792 if (
Imm > MaxImm) {
10793 if (
Imm <= MaxImm + 64) {
10795 Overflow =
Imm - MaxImm;
10810 Overflow =
High - Alignment.value();
10814 if (Overflow > 0) {
10822 if (ST.hasRestrictedSOffset())
10827 SOffset = Overflow;
10865 if (!ST.hasFlatInstOffsets())
10869 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10874 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10875 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10886std::pair<int64_t, int64_t>
10889 int64_t RemainderOffset = COffsetVal;
10890 int64_t ImmField = 0;
10895 if (AllowNegative) {
10897 int64_t
D = 1LL << NumBits;
10898 RemainderOffset = (COffsetVal /
D) *
D;
10899 ImmField = COffsetVal - RemainderOffset;
10901 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10903 (ImmField % 4) != 0) {
10905 RemainderOffset += ImmField % 4;
10906 ImmField -= ImmField % 4;
10908 }
else if (COffsetVal >= 0) {
10910 RemainderOffset = COffsetVal - ImmField;
10914 assert(RemainderOffset + ImmField == COffsetVal);
10915 return {ImmField, RemainderOffset};
10920 if (ST.hasNegativeScratchOffsetBug() &&
10928 switch (ST.getGeneration()) {
10962 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10963 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10964 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10965 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10966 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10967 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10968 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10969 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10976#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10977 case OPCODE##_dpp: \
10978 case OPCODE##_e32: \
10992 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10993 case AMDGPU::V_FMA_F16_gfx9_e64:
10994 case AMDGPU::V_INTERP_P2_F16:
10995 case AMDGPU::V_MAD_F16_e64:
10996 case AMDGPU::V_MAD_U16_e64:
10997 case AMDGPU::V_MAD_I16_e64:
10998 case AMDGPU::V_MAD_U16_gfx9_e64:
10999 case AMDGPU::V_MAD_I16_gfx9_e64:
11008 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11016 switch (ST.getGeneration()) {
11029 if (
isMAI(Opcode)) {
11043 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11046 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11053 if (ST.hasGFX90AInsts()) {
11054 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11055 if (ST.hasGFX940Insts())
11057 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11059 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11061 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11067 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11086 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11087 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11088 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11100 switch (
MI.getOpcode()) {
11102 case AMDGPU::REG_SEQUENCE:
11106 case AMDGPU::INSERT_SUBREG:
11107 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11124 if (!
P.Reg.isVirtual())
11128 auto *DefInst =
MRI.getVRegDef(RSR.Reg);
11129 while (
auto *
MI = DefInst) {
11131 switch (
MI->getOpcode()) {
11133 case AMDGPU::V_MOV_B32_e32: {
11134 auto &Op1 =
MI->getOperand(1);
11139 DefInst =
MRI.getVRegDef(RSR.Reg);
11147 DefInst =
MRI.getVRegDef(RSR.Reg);
11160 assert(
MRI.isSSA() &&
"Must be run on SSA");
11162 auto *
TRI =
MRI.getTargetRegisterInfo();
11163 auto *DefBB =
DefMI.getParent();
11167 if (
UseMI.getParent() != DefBB)
11170 const int MaxInstScan = 20;
11174 auto E =
UseMI.getIterator();
11175 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11176 if (
I->isDebugInstr())
11179 if (++NumInst > MaxInstScan)
11182 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11192 assert(
MRI.isSSA() &&
"Must be run on SSA");
11194 auto *
TRI =
MRI.getTargetRegisterInfo();
11195 auto *DefBB =
DefMI.getParent();
11197 const int MaxUseScan = 10;
11200 for (
auto &
Use :
MRI.use_nodbg_operands(VReg)) {
11201 auto &UseInst = *
Use.getParent();
11204 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11207 if (++NumUse > MaxUseScan)
11214 const int MaxInstScan = 20;
11218 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11221 if (
I->isDebugInstr())
11224 if (++NumInst > MaxInstScan)
11237 if (Reg == VReg && --NumUse == 0)
11239 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11248 auto Cur =
MBB.begin();
11249 if (Cur !=
MBB.end())
11251 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11254 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11263 if (InsPt !=
MBB.end() &&
11264 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11265 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11266 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11267 InsPt->definesRegister(Src,
nullptr)) {
11271 .
addReg(Src, {}, SrcSubReg)
11314 if (isFullCopyInstr(
MI)) {
11315 Register DstReg =
MI.getOperand(0).getReg();
11316 Register SrcReg =
MI.getOperand(1).getReg();
11323 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11327 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11338 unsigned *PredCost)
const {
11339 if (
MI.isBundle()) {
11342 unsigned Lat = 0,
Count = 0;
11343 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11345 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11347 return Lat +
Count - 1;
11350 return SchedModel.computeInstrLatency(&
MI);
11354 if (!ST.hasGFX1250VALUBlockingCycles())
11361 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11362 return Entry->GFX1250BlockingCycles;
11370 return *CallAddrOp;
11377 unsigned Opcode =
MI.getOpcode();
11382 LLT DstTy =
MRI.getType(Dst);
11383 LLT SrcTy =
MRI.getType(Src);
11385 unsigned SrcAS = SrcTy.getAddressSpace();
11388 ST.hasGloballyAddressableScratch()
11396 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11397 return HandleAddrSpaceCast(
MI);
11400 auto IID = GI->getIntrinsicID();
11407 case Intrinsic::amdgcn_if:
11408 case Intrinsic::amdgcn_else:
11422 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11423 Opcode == AMDGPU::G_SEXTLOAD) {
11424 if (
MI.memoperands_empty())
11428 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11429 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11437 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11438 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11439 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11445 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11448 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11456 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11457 return Formatter.get();
11465 unsigned opcode =
MI.getOpcode();
11466 if (opcode == AMDGPU::V_READLANE_B32 ||
11467 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11468 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11473 if (
MI.isInlineAsm()) {
11479 if (!RC || !RI.isSGPRClass(RC))
11484 if (isCopyInstr(
MI)) {
11488 RI.getPhysRegBaseClass(srcOp.
getReg());
11496 if (
MI.isPreISelOpcode())
11511 if (
MI.memoperands_empty())
11515 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11516 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11531 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11533 if (!
SrcOp.isReg())
11537 if (!Reg || !
SrcOp.readsReg())
11543 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11570 F,
"ds_ordered_count unsupported for this calling conv"));
11584 Register &SrcReg2, int64_t &CmpMask,
11585 int64_t &CmpValue)
const {
11586 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11589 switch (
MI.getOpcode()) {
11592 case AMDGPU::S_CMP_EQ_U32:
11593 case AMDGPU::S_CMP_EQ_I32:
11594 case AMDGPU::S_CMP_LG_U32:
11595 case AMDGPU::S_CMP_LG_I32:
11596 case AMDGPU::S_CMP_LT_U32:
11597 case AMDGPU::S_CMP_LT_I32:
11598 case AMDGPU::S_CMP_GT_U32:
11599 case AMDGPU::S_CMP_GT_I32:
11600 case AMDGPU::S_CMP_LE_U32:
11601 case AMDGPU::S_CMP_LE_I32:
11602 case AMDGPU::S_CMP_GE_U32:
11603 case AMDGPU::S_CMP_GE_I32:
11604 case AMDGPU::S_CMP_EQ_U64:
11605 case AMDGPU::S_CMP_LG_U64:
11606 SrcReg =
MI.getOperand(0).getReg();
11607 if (
MI.getOperand(1).isReg()) {
11608 if (
MI.getOperand(1).getSubReg())
11610 SrcReg2 =
MI.getOperand(1).getReg();
11612 }
else if (
MI.getOperand(1).isImm()) {
11614 CmpValue =
MI.getOperand(1).getImm();
11620 case AMDGPU::S_CMPK_EQ_U32:
11621 case AMDGPU::S_CMPK_EQ_I32:
11622 case AMDGPU::S_CMPK_LG_U32:
11623 case AMDGPU::S_CMPK_LG_I32:
11624 case AMDGPU::S_CMPK_LT_U32:
11625 case AMDGPU::S_CMPK_LT_I32:
11626 case AMDGPU::S_CMPK_GT_U32:
11627 case AMDGPU::S_CMPK_GT_I32:
11628 case AMDGPU::S_CMPK_LE_U32:
11629 case AMDGPU::S_CMPK_LE_I32:
11630 case AMDGPU::S_CMPK_GE_U32:
11631 case AMDGPU::S_CMPK_GE_I32:
11632 SrcReg =
MI.getOperand(0).getReg();
11634 CmpValue =
MI.getOperand(1).getImm();
11644 if (S->isLiveIn(AMDGPU::SCC))
11653bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11656 bool SCCIsDead =
false;
11659 constexpr unsigned ScanLimit = 12;
11660 unsigned Count = 0;
11663 if (++
Count > ScanLimit)
11665 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11666 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11667 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11668 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11669 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11674 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11687 for (MachineInstr *
MI : InvertInstr) {
11688 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11689 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11691 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11692 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11693 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11694 ? AMDGPU::S_CBRANCH_SCC1
11695 : AMDGPU::S_CBRANCH_SCC0));
11708 bool NeedInversion)
const {
11709 MachineInstr *KillsSCC =
nullptr;
11714 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11716 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11719 if (NeedInversion && !invertSCCUse(SCCRedefine))
11721 if (MachineOperand *SccDef =
11723 SccDef->setIsDead(
false);
11732static std::optional<std::pair<int64_t, int64_t>>
11736 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11738 std::optional<int64_t>
A =
11742 std::optional<int64_t>
B =
11746 if (
Opc == AMDGPU::S_CSELECT_B32) {
11752 return std::pair(*
A, *
B);
11756 unsigned &NewDefOpc) {
11759 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11760 Def.getOpcode() != AMDGPU::S_ADD_U32)
11766 Def.getMF()->getSubtarget().getInstrInfo());
11768 auto Imm1 =
TII->getImmOrMaterializedImm(
MRI, AddSrc1);
11769 auto Imm2 =
TII->getImmOrMaterializedImm(
MRI, AddSrc2);
11770 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11773 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11775 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11778 NewDefOpc = AMDGPU::S_ADD_U32;
11780 NeedInversion = !NeedInversion;
11785 Register SrcReg2, int64_t CmpMask,
11795 CmpValue = *ImmOpt;
11798 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue,
MRI,
11799 this](
bool NeedInversion) ->
bool {
11804 unsigned NewDefOpc = Def->getOpcode();
11811 auto [
A,
B] = *Consts;
11812 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11815 NeedInversion = !NeedInversion;
11827 if (CmpValue != 0 ||
11833 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11836 if (NewDefOpc != Def->getOpcode())
11837 Def->setDesc(
get(NewDefOpc));
11846 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11847 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11853 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11862 auto [
A,
B] = *Consts;
11863 if (
A == 0 ||
B == 0)
11864 optimizeSCC(
Select, Def,
A == 0);
11873 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue,
MRI,
11874 this](int64_t ExpectedValue,
unsigned SrcSize,
11875 bool IsReversible,
bool IsSigned) ->
bool {
11903 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11904 Def->getOpcode() != AMDGPU::S_AND_B64)
11908 const auto isMask = [&Mask, SrcSize,
MRI,
11920 SrcOp = &Def->getOperand(2);
11921 else if (isMask(&Def->getOperand(2)))
11922 SrcOp = &Def->getOperand(1);
11930 if (IsSigned && BitNo == SrcSize - 1)
11933 ExpectedValue <<= BitNo;
11935 bool IsReversedCC =
false;
11936 if (CmpValue != ExpectedValue) {
11939 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11944 Register DefReg = Def->getOperand(0).getReg();
11945 if (IsReversedCC && !
MRI->hasOneNonDBGUse(DefReg))
11948 if (!optimizeSCC(Def, &CmpInstr,
false))
11951 if (!
MRI->use_nodbg_empty(DefReg)) {
11959 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11960 : AMDGPU::S_BITCMP1_B32
11961 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11962 : AMDGPU::S_BITCMP1_B64;
11967 Def->eraseFromParent();
11975 case AMDGPU::S_CMP_EQ_U32:
11976 case AMDGPU::S_CMP_EQ_I32:
11977 case AMDGPU::S_CMPK_EQ_U32:
11978 case AMDGPU::S_CMPK_EQ_I32:
11979 return optimizeCmpAnd(1, 32,
true,
false) ||
11980 optimizeCmpSelect(
true);
11981 case AMDGPU::S_CMP_GE_U32:
11982 case AMDGPU::S_CMPK_GE_U32:
11983 return optimizeCmpAnd(1, 32,
false,
false);
11984 case AMDGPU::S_CMP_GE_I32:
11985 case AMDGPU::S_CMPK_GE_I32:
11986 return optimizeCmpAnd(1, 32,
false,
true);
11987 case AMDGPU::S_CMP_EQ_U64:
11988 return optimizeCmpAnd(1, 64,
true,
false) ||
11989 optimizeCmpSelect(
true);
11990 case AMDGPU::S_CMP_LG_U32:
11991 case AMDGPU::S_CMP_LG_I32:
11992 case AMDGPU::S_CMPK_LG_U32:
11993 case AMDGPU::S_CMPK_LG_I32:
11994 return optimizeCmpAnd(0, 32,
true,
false) ||
11995 optimizeCmpSelect(
false);
11996 case AMDGPU::S_CMP_GT_U32:
11997 case AMDGPU::S_CMPK_GT_U32:
11998 return optimizeCmpAnd(0, 32,
false,
false);
11999 case AMDGPU::S_CMP_GT_I32:
12000 case AMDGPU::S_CMPK_GT_I32:
12001 return optimizeCmpAnd(0, 32,
false,
true);
12002 case AMDGPU::S_CMP_LG_U64:
12003 return optimizeCmpAnd(0, 64,
true,
false) ||
12004 optimizeCmpSelect(
false);
12011 AMDGPU::OpName
OpName)
const {
12012 if (!ST.needsAlignedVGPRs())
12015 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
12027 bool IsAGPR = RI.isAGPR(
MRI, DataReg);
12029 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12032 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12033 : &AMDGPU::VReg_64_Align2RegClass);
12035 .
addReg(DataReg, {},
Op.getSubReg())
12040 Op.setSubReg(AMDGPU::sub0);
12045 if (!SchedModel.hasInstrSchedModel())
12051 unsigned RepeatRate = 0;
12053 PI = SchedModel.getWriteProcResBegin(SCDesc),
12054 PE = SchedModel.getWriteProcResEnd(SCDesc);
12056 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12073 if (ST.hasGFX1250Insts())
12080 unsigned Opcode =
MI.getOpcode();
12086 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12087 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12090 if (!ST.hasGFX940Insts())
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Shared AMDGPU asyncmark stage definitions.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
static Register UseReg(const MachineOperand &MO)
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
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const unsigned AndN2WrExecOpc
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned MovTermOpc
const unsigned OrSaveExecOpc
const unsigned AndSaveExecOpc
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
This class is the base class for the comparison instructions.
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
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.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
iterator_range< subrange_iterator > subranges()
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void setVariableValue(const MCExpr *Value)
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
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.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & 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 & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) 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.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
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.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
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.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
static bool usesTENSOR_CNT(const MachineInstr &MI)
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
bool isNonCommutableDPP(const MachineInstr &MI) const
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, SelectExpansion &Exp) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getBlockingCycles(const MachineInstr &MI) const
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVPermPk16(unsigned Opcode)
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
AMDGPU::AsyncStages getAsyncStage(const MachineInstr &MI) const
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
static bool usesASYNC_CNT(const MachineInstr &MI)
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isMaskedByExec(Register Reg, const MachineInstr &Use, const MachineRegisterInfo &MRI, unsigned Depth=0) const
Return true if Reg is a lane mask that already has 0 in every bit corresponding to a lane that is ina...
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool isAsync(const MachineInstr &MI) const
bool memOpsHaveSameBase(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2) const
Return true if the memory operations described by BaseOps1 and BaseOps2 (as returned by getMemOperand...
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Register getLongBranchReservedReg() const
bool isWholeWaveFunction() const
Register getStackPtrOffsetReg() const
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
constexpr bool isValidAsyncStageMask(int64_t Mask)
AsyncStages
Bit mask of the async stages tracked by the asyncmark / wait_asyncmark intrinsics.
@ GLOBAL_LOAD_ASYNC_TO_LDS
@ GLOBAL_LOAD_ASYNC_TO_LDS_MCAST
@ GLOBAL_STORE_ASYNC_FROM_LDS
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_IMM_NOINLINE_FP16
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
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.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
static const MachineMemOperand::Flags MOCFSB1
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 bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
@ End
Run the machine verifier once, at the end of the pipeline.
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
@ AlwaysUniform
The result value is always uniform.
@ NeverUniform
The result value can never be assumed to be uniform.
@ Default
The result value is uniform if and only if all operands are uniform.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
uint8_t GFX1250BlockingCycles
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr bool all() const
This represents a simple continuous liveness interval for a value.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
MachineInstr * top() const
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.