33#include "llvm/IR/IntrinsicsAMDGPU.h"
41#define DEBUG_TYPE "si-instr-info"
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
57#include "AMDGPUGenSearchableTables.inc"
65 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
68 "amdgpu-fix-16-bit-physreg-copies",
69 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
85 unsigned N =
Node->getNumOperands();
86 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
98 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
99 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
101 if (Op0Idx == -1 && Op1Idx == -1)
105 if ((Op0Idx == -1 && Op1Idx != -1) ||
106 (Op1Idx == -1 && Op0Idx != -1))
127 return !
MI.memoperands_empty() &&
129 return MMO->isLoad() && MMO->isInvariant();
138static std::tuple<unsigned, unsigned, unsigned>
146 unsigned LoReloc, HiReloc;
176 return {BaseFlags, LoReloc, HiReloc};
194 if (!
MI.hasImplicitDef() &&
195 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
196 !
MI.mayRaiseFPException())
205 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
220 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
221 MI.hasUnmodeledSideEffects())
226 if (
MI.isInlineAsm())
230 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
245 if (Reg.isPhysical()) {
250 if (!
MRI.isConstantPhysReg(Reg))
261 if (MO.isDef() && Reg != DefReg)
271 case AMDGPU::V_SUBREV_U16_e32:
272 case AMDGPU::V_SUBREV_U16_e64:
274 case AMDGPU::V_SUBREV_U32_e32:
275 case AMDGPU::V_SUBREV_U32_e64:
277 case AMDGPU::V_SUBREV_CO_U32_e32:
278 case AMDGPU::V_SUBREV_CO_U32_e64:
280 case AMDGPU::V_SUBBREV_U32_e32:
281 case AMDGPU::V_SUBBREV_U32_e64:
284 case AMDGPU::V_ASHRREV_I16_e32:
285 case AMDGPU::V_ASHRREV_I16_e64:
286 case AMDGPU::V_ASHRREV_I32_e32:
287 case AMDGPU::V_ASHRREV_I32_e64:
288 case AMDGPU::V_ASHRREV_I64_e64:
289 case AMDGPU::V_LSHLREV_B16_e32:
290 case AMDGPU::V_LSHLREV_B16_e64:
291 case AMDGPU::V_LSHLREV_B32_e32:
292 case AMDGPU::V_LSHLREV_B32_e64:
293 case AMDGPU::V_LSHLREV_B64_e64:
294 case AMDGPU::V_LSHRREV_B16_e32:
295 case AMDGPU::V_LSHRREV_B16_e64:
296 case AMDGPU::V_LSHRREV_B32_e32:
297 case AMDGPU::V_LSHRREV_B32_e64:
298 case AMDGPU::V_LSHRREV_B64_e64:
299 return !ST.hasGFX11Insts();
306bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
310 if (
MI.isConvergent())
338 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
343 for (
auto Op :
MI.uses()) {
344 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
345 RI.isSGPRClass(
MRI.getRegClass(
Op.getReg()))) {
358 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
378 int64_t &Offset1)
const {
386 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
390 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
406 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
407 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
408 if (Offset0Idx == -1 || Offset1Idx == -1)
415 Offset0Idx -=
get(Opc0).NumDefs;
416 Offset1Idx -=
get(Opc1).NumDefs;
446 if (!Load0Offset || !Load1Offset)
463 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
464 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
466 if (OffIdx0 == -1 || OffIdx1 == -1)
472 OffIdx0 -=
get(Opc0).NumDefs;
473 OffIdx1 -=
get(Opc1).NumDefs;
492 case AMDGPU::DS_READ2ST64_B32:
493 case AMDGPU::DS_READ2ST64_B64:
494 case AMDGPU::DS_WRITE2ST64_B32:
495 case AMDGPU::DS_WRITE2ST64_B64:
509 OffsetIsScalable =
false;
526 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
528 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
529 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
542 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
543 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
544 if (Offset0 + 1 != Offset1)
555 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
556 EltSize = RI.getRegSizeInBits(*
getOpRegClass(LdSt, Data0Idx)) / 8;
563 Offset = EltSize * Offset0;
565 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
566 if (DataOpIdx == -1) {
567 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
569 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
585 if (BaseOp && !BaseOp->
isFI())
593 if (SOffset->
isReg())
599 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
601 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
610 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
611 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
613 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
614 if (VAddr0Idx >= 0) {
616 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
623 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
638 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
655 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
657 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
674 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
682 if (MO1->getAddrSpace() != MO2->getAddrSpace())
685 const auto *Base1 = MO1->getValue();
686 const auto *Base2 = MO2->getValue();
687 if (!Base1 || !Base2)
695 return Base1 == Base2;
706 *BaseOps2.
front()->getParent(), BaseOps2);
710 int64_t Offset1,
bool OffsetIsScalable1,
712 int64_t Offset2,
bool OffsetIsScalable2,
713 unsigned ClusterSize,
714 unsigned NumBytes)
const {
724 if (!BaseOps1.
empty()) {
726 MaxMemoryClusterDWords =
744 const unsigned LoadSize = NumBytes / ClusterSize;
745 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
746 return NumDWords <= MaxMemoryClusterDWords;
760 int64_t Offset0, int64_t Offset1,
761 unsigned NumLoads)
const {
762 assert(Offset1 > Offset0 &&
763 "Second offset should be larger than first offset!");
768 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
775 const char *
Msg =
"illegal VGPR to SGPR copy") {
794 assert((
TII.getSubtarget().hasMAIInsts() &&
795 !
TII.getSubtarget().hasGFX90AInsts()) &&
796 "Expected GFX908 subtarget.");
799 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
800 "Source register of the copy should be either an SGPR or an AGPR.");
803 "Destination register of the copy should be an AGPR.");
812 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
815 if (!Def->modifiesRegister(SrcReg, &RI))
818 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
819 Def->getOperand(0).getReg() != SrcReg)
826 bool SafeToPropagate =
true;
829 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
830 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
831 SafeToPropagate =
false;
833 if (!SafeToPropagate)
836 for (
auto I = Def;
I !=
MI; ++
I)
837 I->clearRegisterKills(DefOp.
getReg(), &RI);
845 if (ImpUseSuperReg) {
846 Builder.addReg(ImpUseSuperReg,
854 RS.enterBasicBlockEnd(
MBB);
855 RS.backward(std::next(
MI));
864 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
867 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
868 "VGPR used for an intermediate copy should have been reserved.");
873 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
883 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
884 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
885 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
892 if (ImpUseSuperReg) {
893 UseBuilder.
addReg(ImpUseSuperReg,
910 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
911 int16_t SubIdx = BaseIndices[Idx];
912 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
913 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
914 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
915 unsigned Opcode = AMDGPU::S_MOV_B32;
918 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
919 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
920 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
924 DestSubReg = RI.getSubReg(DestReg, SubIdx);
925 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
926 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
927 Opcode = AMDGPU::S_MOV_B64;
942 assert(FirstMI && LastMI);
947 LastMI->addRegisterKilled(SrcReg, &RI);
953 Register SrcReg,
bool KillSrc,
bool RenamableDest,
954 bool RenamableSrc)
const {
956 unsigned Size = RI.getRegSizeInBits(*RC);
958 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
964 if (((
Size == 16) != (SrcSize == 16))) {
966 assert(ST.useRealTrue16Insts());
968 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
971 if (DestReg == SrcReg) {
977 RC = RI.getPhysRegBaseClass(DestReg);
978 Size = RI.getRegSizeInBits(*RC);
979 SrcRC = RI.getPhysRegBaseClass(SrcReg);
980 SrcSize = RI.getRegSizeInBits(*SrcRC);
984 if (RC == &AMDGPU::VGPR_32RegClass) {
986 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
987 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
988 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
989 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
995 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
996 RC == &AMDGPU::SReg_32RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
1004 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC_LO) {
1023 if (RC == &AMDGPU::SReg_64RegClass) {
1024 if (SrcReg == AMDGPU::SCC) {
1031 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1032 if (DestReg == AMDGPU::VCC) {
1050 if (DestReg == AMDGPU::SCC) {
1053 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1057 assert(ST.hasScalarCompareEq64());
1071 if (RC == &AMDGPU::AGPR_32RegClass) {
1072 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1073 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1079 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1088 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1095 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1096 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1098 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1099 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1100 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1101 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1104 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1105 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1118 if (IsAGPRDst || IsAGPRSrc) {
1119 if (!DstLow || !SrcLow) {
1121 "Cannot use hi16 subreg with an AGPR!");
1128 if (ST.useRealTrue16Insts()) {
1134 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1135 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1147 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1148 if (!DstLow || !SrcLow) {
1150 "Cannot use hi16 subreg on VI!");
1176 unsigned SrcOp = 1) {
1180 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1184 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1185 if (ST.hasVMovB64Inst() &&
1186 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1191 if (ST.hasPkMovB32() &&
1192 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1208 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1209 if (RI.isSGPRClass(RC)) {
1210 if (!RI.isSGPRClass(SrcRC)) {
1214 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1220 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1221 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1222 if (RI.isAGPRClass(RC)) {
1223 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1224 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1225 else if (RI.hasVGPRs(SrcRC) ||
1226 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1227 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1229 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1230 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1231 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1232 }
else if (RI.isVGPRClass(RC)) {
1233 if (ST.hasVMovB64Inst())
1234 WideOpcode = AMDGPU::V_MOV_B64_e32;
1235 else if (ST.hasPkMovB32())
1236 WideOpcode = AMDGPU::V_PK_MOV_B32;
1240 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1242 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1249 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1250 const bool CanKillSuperReg = KillSrc && !Overlap;
1257 std::unique_ptr<RegScavenger> RS;
1258 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1259 RS = std::make_unique<RegScavenger>();
1263 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1264 unsigned NumRegs = 1;
1265 unsigned ThisOpcode = Opcode;
1267 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1269 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1270 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1274 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1275 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1276 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1278 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1279 WideSrcRC->contains(WideSrc)) {
1280 SubIdx = WideSubIdx;
1282 ThisOpcode = WideOpcode;
1286 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1287 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1288 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1291 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1293 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1296 *RS, Overlap, ImpUseSuper);
1297 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1338 int64_t &ImmVal)
const {
1339 switch (
MI.getOpcode()) {
1340 case AMDGPU::V_MOV_B32_e32:
1341 case AMDGPU::S_MOV_B32:
1342 case AMDGPU::S_MOVK_I32:
1343 case AMDGPU::S_MOV_B64:
1344 case AMDGPU::V_MOV_B64_e32:
1345 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1346 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1347 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1348 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::V_MOV_B64_PSEUDO:
1350 case AMDGPU::V_MOV_B16_t16_e32: {
1353 ImmVal = Src0.getImm();
1354 return MI.getOperand(0).getReg() == Reg;
1359 case AMDGPU::V_MOV_B16_t16_e64: {
1361 if (Src0.isImm() && !
MI.getOperand(1).getImm()) {
1362 ImmVal = Src0.getImm();
1363 return MI.getOperand(0).getReg() == Reg;
1368 case AMDGPU::S_BREV_B32:
1369 case AMDGPU::V_BFREV_B32_e32:
1370 case AMDGPU::V_BFREV_B32_e64: {
1374 return MI.getOperand(0).getReg() == Reg;
1379 case AMDGPU::S_NOT_B32:
1380 case AMDGPU::V_NOT_B32_e32:
1381 case AMDGPU::V_NOT_B32_e64: {
1384 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.getImm()));
1385 return MI.getOperand(0).getReg() == Reg;
1395std::optional<int64_t>
1405 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1406 return std::nullopt;
1408 if (Def && Def->isMoveImmediate()) {
1410 if (ImmSrc.
isImm()) {
1417 return std::nullopt;
1420std::optional<int64_t>
1429 if (RI.isAGPRClass(DstRC))
1430 return AMDGPU::COPY;
1431 if (RI.getRegSizeInBits(*DstRC) == 16) {
1434 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1436 if (RI.getRegSizeInBits(*DstRC) == 32)
1437 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1438 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1439 return AMDGPU::S_MOV_B64;
1440 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1441 return AMDGPU::V_MOV_B64_PSEUDO;
1442 return AMDGPU::COPY;
1447 bool IsIndirectSrc)
const {
1448 if (IsIndirectSrc) {
1450 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1452 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1454 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1456 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1458 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1460 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1462 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1464 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1466 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1468 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1470 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1472 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1474 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1475 if (VecSize <= 1024)
1476 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1482 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1484 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1486 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1488 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1490 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1492 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1494 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1496 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1498 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1500 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1502 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1504 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1506 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1507 if (VecSize <= 1024)
1508 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1515 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1517 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1519 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1521 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1523 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1525 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1527 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1529 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1531 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1533 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1535 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1537 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1539 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1540 if (VecSize <= 1024)
1541 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1548 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1550 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1552 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1564 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1573 if (VecSize <= 1024)
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1581 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1583 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1585 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1587 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1588 if (VecSize <= 1024)
1589 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1596 bool IsSGPR)
const {
1608 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1621 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1622 : AMDGPU::SI_SPILL_S128_SAVE;
1624 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1625 : AMDGPU::SI_SPILL_S160_SAVE;
1627 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1628 : AMDGPU::SI_SPILL_S192_SAVE;
1630 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1631 : AMDGPU::SI_SPILL_S224_SAVE;
1633 return AMDGPU::SI_SPILL_S256_SAVE;
1635 return AMDGPU::SI_SPILL_S288_SAVE;
1637 return AMDGPU::SI_SPILL_S320_SAVE;
1639 return AMDGPU::SI_SPILL_S352_SAVE;
1641 return AMDGPU::SI_SPILL_S384_SAVE;
1643 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1644 : AMDGPU::SI_SPILL_S512_SAVE;
1646 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1647 : AMDGPU::SI_SPILL_S1024_SAVE;
1656 return AMDGPU::SI_SPILL_V16_SAVE;
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1662 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V128_SAVE;
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V160_SAVE;
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V192_SAVE;
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V224_SAVE;
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V256_SAVE;
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V288_SAVE;
1682 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1683 : AMDGPU::SI_SPILL_V320_SAVE;
1685 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1686 : AMDGPU::SI_SPILL_V352_SAVE;
1688 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1689 : AMDGPU::SI_SPILL_V384_SAVE;
1691 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1692 : AMDGPU::SI_SPILL_V512_SAVE;
1694 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1695 : AMDGPU::SI_SPILL_V1024_SAVE;
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV32_SAVE;
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV64_SAVE;
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV96_SAVE;
1713 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1714 : AMDGPU::SI_SPILL_AV128_SAVE;
1716 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1717 : AMDGPU::SI_SPILL_AV160_SAVE;
1719 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1720 : AMDGPU::SI_SPILL_AV192_SAVE;
1722 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1723 : AMDGPU::SI_SPILL_AV224_SAVE;
1725 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1726 : AMDGPU::SI_SPILL_AV256_SAVE;
1728 return AMDGPU::SI_SPILL_AV288_SAVE;
1730 return AMDGPU::SI_SPILL_AV320_SAVE;
1732 return AMDGPU::SI_SPILL_AV352_SAVE;
1734 return AMDGPU::SI_SPILL_AV384_SAVE;
1736 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1737 : AMDGPU::SI_SPILL_AV512_SAVE;
1739 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1740 : AMDGPU::SI_SPILL_AV1024_SAVE;
1747 bool IsVectorSuperClass) {
1752 if (IsVectorSuperClass)
1753 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1755 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1761 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1768 if (ST.hasMAIInsts())
1774void SIInstrInfo::storeRegToStackSlotImpl(
1787 FrameInfo.getObjectAlign(FrameIndex));
1788 unsigned SpillSize = RI.getSpillSize(*RC);
1794 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1795 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1796 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1805 if (SrcReg.
isVirtual() && SpillSize == 4) {
1806 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1819 SpillSize, *MFI, NeedsCFI);
1834 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1843 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1850 return AMDGPU::SI_SPILL_S32_RESTORE;
1852 return AMDGPU::SI_SPILL_S64_RESTORE;
1854 return AMDGPU::SI_SPILL_S96_RESTORE;
1856 return AMDGPU::SI_SPILL_S128_RESTORE;
1858 return AMDGPU::SI_SPILL_S160_RESTORE;
1860 return AMDGPU::SI_SPILL_S192_RESTORE;
1862 return AMDGPU::SI_SPILL_S224_RESTORE;
1864 return AMDGPU::SI_SPILL_S256_RESTORE;
1866 return AMDGPU::SI_SPILL_S288_RESTORE;
1868 return AMDGPU::SI_SPILL_S320_RESTORE;
1870 return AMDGPU::SI_SPILL_S352_RESTORE;
1872 return AMDGPU::SI_SPILL_S384_RESTORE;
1874 return AMDGPU::SI_SPILL_S512_RESTORE;
1876 return AMDGPU::SI_SPILL_S1024_RESTORE;
1885 return AMDGPU::SI_SPILL_V16_RESTORE;
1887 return AMDGPU::SI_SPILL_V32_RESTORE;
1889 return AMDGPU::SI_SPILL_V64_RESTORE;
1891 return AMDGPU::SI_SPILL_V96_RESTORE;
1893 return AMDGPU::SI_SPILL_V128_RESTORE;
1895 return AMDGPU::SI_SPILL_V160_RESTORE;
1897 return AMDGPU::SI_SPILL_V192_RESTORE;
1899 return AMDGPU::SI_SPILL_V224_RESTORE;
1901 return AMDGPU::SI_SPILL_V256_RESTORE;
1903 return AMDGPU::SI_SPILL_V288_RESTORE;
1905 return AMDGPU::SI_SPILL_V320_RESTORE;
1907 return AMDGPU::SI_SPILL_V352_RESTORE;
1909 return AMDGPU::SI_SPILL_V384_RESTORE;
1911 return AMDGPU::SI_SPILL_V512_RESTORE;
1913 return AMDGPU::SI_SPILL_V1024_RESTORE;
1922 return AMDGPU::SI_SPILL_AV32_RESTORE;
1924 return AMDGPU::SI_SPILL_AV64_RESTORE;
1926 return AMDGPU::SI_SPILL_AV96_RESTORE;
1928 return AMDGPU::SI_SPILL_AV128_RESTORE;
1930 return AMDGPU::SI_SPILL_AV160_RESTORE;
1932 return AMDGPU::SI_SPILL_AV192_RESTORE;
1934 return AMDGPU::SI_SPILL_AV224_RESTORE;
1936 return AMDGPU::SI_SPILL_AV256_RESTORE;
1938 return AMDGPU::SI_SPILL_AV288_RESTORE;
1940 return AMDGPU::SI_SPILL_AV320_RESTORE;
1942 return AMDGPU::SI_SPILL_AV352_RESTORE;
1944 return AMDGPU::SI_SPILL_AV384_RESTORE;
1946 return AMDGPU::SI_SPILL_AV512_RESTORE;
1948 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1955 bool IsVectorSuperClass) {
1960 if (IsVectorSuperClass)
1961 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1963 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1969 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1976 if (ST.hasMAIInsts())
1979 assert(!RI.isAGPRClass(RC));
1993 unsigned SpillSize = RI.getSpillSize(*RC);
2000 FrameInfo.getObjectAlign(FrameIndex));
2002 if (RI.isSGPRClass(RC)) {
2005 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
2006 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2007 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
2012 if (DestReg.
isVirtual() && SpillSize == 4) {
2014 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2041 unsigned Quantity)
const {
2043 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2044 while (Quantity > 0) {
2045 unsigned Arg = std::min(Quantity, MaxSNopCount);
2056 constexpr unsigned DoorbellIDMask = 0x3ff;
2057 constexpr unsigned ECQueueWaveAbort = 0x400;
2062 if (!
MBB.succ_empty() ||
2064 false) !=
MBB.end()) {
2065 MBB.splitAt(
MI,
false);
2069 MBB.addSuccessor(TrapBB);
2075 Register DoorbellReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2079 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2082 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2083 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2088 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2089 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2090 .
addUse(DoorbellRegMasked)
2091 .
addImm(ECQueueWaveAbort)
2093 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2094 .
addUse(SetWaveAbortBit);
2097 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2108 return MBB.getNextNode();
2112 switch (
MI.getOpcode()) {
2114 if (
MI.isMetaInstruction())
2119 return MI.getOperand(0).getImm() + 1;
2130 switch (
MI.getOpcode()) {
2132 case AMDGPU::S_MOV_B64_term:
2135 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2138 case AMDGPU::S_MOV_B32_term:
2141 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2144 case AMDGPU::S_XOR_B64_term:
2147 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2150 case AMDGPU::S_XOR_B32_term:
2153 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2155 case AMDGPU::S_OR_B64_term:
2158 MI.setDesc(
get(AMDGPU::S_OR_B64));
2160 case AMDGPU::S_OR_B32_term:
2163 MI.setDesc(
get(AMDGPU::S_OR_B32));
2166 case AMDGPU::S_ANDN2_B64_term:
2169 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2172 case AMDGPU::S_ANDN2_B32_term:
2175 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2178 case AMDGPU::S_AND_B64_term:
2181 MI.setDesc(
get(AMDGPU::S_AND_B64));
2184 case AMDGPU::S_AND_B32_term:
2187 MI.setDesc(
get(AMDGPU::S_AND_B32));
2190 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2193 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2196 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2199 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2202 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2203 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2205 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2206 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2209 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2210 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2213 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2214 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2216 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2220 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2223 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2226 int64_t
Imm =
MI.getOperand(1).getImm();
2228 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2229 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2234 MI.eraseFromParent();
2240 case AMDGPU::V_MOV_B64_PSEUDO: {
2242 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2243 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2251 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2252 MI.setDesc(Mov64Desc);
2256 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2259 if (
SrcOp.isGlobal()) {
2264 unsigned BaseFlags, LoReloc, HiReloc;
2265 std::tie(BaseFlags, LoReloc, HiReloc) =
2272 }
else if (
SrcOp.isImm()) {
2274 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2275 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2299 if (ST.hasPkMovB32() &&
2318 MI.eraseFromParent();
2321 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2325 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2329 if (ST.has64BitLiterals()) {
2330 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2334 if (
SrcOp.isGlobal()) {
2336 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2337 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2340 unsigned BaseFlags, LoReloc, HiReloc;
2341 std::tie(BaseFlags, LoReloc, HiReloc) =
2348 MI.eraseFromParent();
2355 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2360 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2361 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2363 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2364 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2369 MI.eraseFromParent();
2372 case AMDGPU::V_SET_INACTIVE_B32: {
2376 .
add(
MI.getOperand(3))
2377 .
add(
MI.getOperand(4))
2378 .
add(
MI.getOperand(1))
2379 .
add(
MI.getOperand(2))
2380 .
add(
MI.getOperand(5));
2381 MI.eraseFromParent();
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2420 if (RI.hasVGPRs(EltRC)) {
2421 Opc = AMDGPU::V_MOVRELD_B32_e32;
2423 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2424 : AMDGPU::S_MOVRELD_B32;
2429 bool IsUndef =
MI.getOperand(1).isUndef();
2430 unsigned SubReg =
MI.getOperand(3).getImm();
2431 assert(VecReg ==
MI.getOperand(1).getReg());
2436 .
add(
MI.getOperand(2))
2440 const int ImpDefIdx =
2442 const int ImpUseIdx = ImpDefIdx + 1;
2444 MI.eraseFromParent();
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2461 assert(ST.useVGPRIndexMode());
2463 bool IsUndef =
MI.getOperand(1).isUndef();
2472 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2476 .
add(
MI.getOperand(2))
2480 const int ImpDefIdx =
2482 const int ImpUseIdx = ImpDefIdx + 1;
2489 MI.eraseFromParent();
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2506 assert(ST.useVGPRIndexMode());
2509 bool IsUndef =
MI.getOperand(1).isUndef();
2513 .
add(
MI.getOperand(2))
2526 MI.eraseFromParent();
2529 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2532 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2533 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2552 if (ST.hasGetPCZeroExtension()) {
2556 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2563 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2573 MI.eraseFromParent();
2576 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2586 Op.setOffset(
Op.getOffset() + 4);
2588 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2592 MI.eraseFromParent();
2595 case AMDGPU::ENTER_STRICT_WWM: {
2601 case AMDGPU::ENTER_STRICT_WQM: {
2608 MI.eraseFromParent();
2611 case AMDGPU::EXIT_STRICT_WWM:
2612 case AMDGPU::EXIT_STRICT_WQM: {
2618 case AMDGPU::SI_RETURN: {
2632 MI.eraseFromParent();
2636 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2637 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2638 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2641 case AMDGPU::S_GETPC_B64_pseudo:
2642 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2643 if (ST.hasGetPCZeroExtension()) {
2645 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2654 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2655 assert(ST.hasBF16PackedInsts());
2656 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2667 case AMDGPU::GET_STACK_BASE:
2670 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2677 Register DestReg =
MI.getOperand(0).getReg();
2687 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2688 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2689 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2692 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2695 MI.getNumExplicitOperands());
2713 case AMDGPU::S_MOV_B64:
2714 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2723 if (UsedLanes.
all())
2728 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2729 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2731 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2732 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2734 if (NeedLo && NeedHi)
2738 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2740 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2749 case AMDGPU::S_LOAD_DWORDX16_IMM:
2750 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2751 if (SubIdx != 0 || UsedLanes.
all())
2762 assert(
MRI.use_nodbg_empty(DestReg) &&
"DestReg should have no users yet.");
2769 UseMO !=
I->findRegisterUseOperand(RegToFind,
nullptr) ||
2770 UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2776 unsigned NewOpcode = -1;
2777 if (SubregSize == 256)
2778 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2779 else if (SubregSize == 128)
2780 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2787 MRI.setRegClass(DestReg, NewRC);
2790 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2795 MI->getOperand(0).setReg(DestReg);
2796 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2800 OffsetMO->
setImm(FinalOffset);
2806 MI->setMemRefs(*MF, NewMMOs);
2819std::pair<MachineInstr*, MachineInstr*>
2821 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2823 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2826 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2827 return std::pair(&
MI,
nullptr);
2838 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2840 if (Dst.isPhysical()) {
2841 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2844 auto Tmp =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2848 for (
unsigned I = 1;
I <= 2; ++
I) {
2851 if (
SrcOp.isImm()) {
2853 Imm.ashrInPlace(Part * 32);
2854 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2858 if (Src.isPhysical())
2859 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2866 MovDPP.addImm(MO.getImm());
2868 Split[Part] = MovDPP;
2872 if (Dst.isVirtual())
2879 MI.eraseFromParent();
2880 return std::pair(Split[0], Split[1]);
2883std::optional<DestSourcePair>
2885 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2888 return std::nullopt;
2892 AMDGPU::OpName Src0OpName,
2894 AMDGPU::OpName Src1OpName)
const {
2901 "All commutable instructions have both src0 and src1 modifiers");
2903 int Src0ModsVal = Src0Mods->
getImm();
2904 int Src1ModsVal = Src1Mods->
getImm();
2906 Src1Mods->
setImm(Src0ModsVal);
2907 Src0Mods->
setImm(Src1ModsVal);
2916 bool IsKill = RegOp.
isKill();
2918 bool IsUndef = RegOp.
isUndef();
2919 bool IsDebug = RegOp.
isDebug();
2921 if (NonRegOp.
isImm())
2923 else if (NonRegOp.
isFI())
2944 int64_t NonRegVal = NonRegOp1.
getImm();
2947 NonRegOp2.
setImm(NonRegVal);
2954 unsigned OpIdx1)
const {
2959 unsigned Opc =
MI.getOpcode();
2960 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2970 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2973 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2978 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2984 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3006 unsigned Src1Idx)
const {
3007 assert(!NewMI &&
"this should never be used");
3012 unsigned Opc =
MI.getOpcode();
3014 if (CommutedOpcode == -1)
3017 if (Src0Idx > Src1Idx)
3020 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3021 static_cast<int>(Src0Idx) &&
3022 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3023 static_cast<int>(Src1Idx) &&
3024 "inconsistency with findCommutedOpIndices");
3032 if (Src0.isReg() && Src1.isReg()) {
3036 }
else if (Src0.isReg() && !Src1.isReg()) {
3038 }
else if (!Src0.isReg() && Src1.isReg()) {
3040 }
else if (Src0.isImm() && Src1.isImm()) {
3049 Src1, AMDGPU::OpName::src1_modifiers);
3052 AMDGPU::OpName::src1_sel);
3064 unsigned &SrcOpIdx0,
3065 unsigned &SrcOpIdx1)
const {
3073 unsigned &SrcOpIdx0,
3074 unsigned &SrcOpIdx1)
const {
3075 if (!
Desc.isCommutable())
3078 unsigned Opc =
Desc.getOpcode();
3079 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3083 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3087 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3091 int64_t BrOffset)
const {
3108 return MI.getOperand(0).getMBB();
3113 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3114 MI.getOpcode() == AMDGPU::SI_LOOP ||
3115 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3127 "new block should be inserted for expanding unconditional branch");
3130 "restore block should be inserted for restoring clobbered registers");
3138 if (ST.useAddPCI64Inst()) {
3140 MCCtx.createTempSymbol(
"offset",
true);
3144 MCCtx.createTempSymbol(
"post_addpc",
true);
3145 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3149 Offset->setVariableValue(OffsetExpr);
3153 assert(RS &&
"RegScavenger required for long branching");
3157 Register PCReg =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3161 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3162 ST.hasVALUReadSGPRHazard();
3163 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3164 if (FlushSGPRWrites)
3172 ApplyHazardWorkarounds();
3175 MCCtx.createTempSymbol(
"post_getpc",
true);
3179 MCCtx.createTempSymbol(
"offset_lo",
true);
3181 MCCtx.createTempSymbol(
"offset_hi",
true);
3184 .
addReg(PCReg, {}, AMDGPU::sub0)
3188 .
addReg(PCReg, {}, AMDGPU::sub1)
3190 ApplyHazardWorkarounds();
3231 if (LongBranchReservedReg) {
3232 RS->enterBasicBlock(
MBB);
3233 Scav = LongBranchReservedReg;
3235 RS->enterBasicBlockEnd(
MBB);
3236 Scav = RS->scavengeRegisterBackwards(
3241 RS->setRegUsed(Scav);
3242 MRI.replaceRegWith(PCReg, Scav);
3243 MRI.clearVirtRegs();
3249 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3250 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3251 MRI.clearVirtRegs();
3266unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3268 case SIInstrInfo::SCC_TRUE:
3269 return AMDGPU::S_CBRANCH_SCC1;
3270 case SIInstrInfo::SCC_FALSE:
3271 return AMDGPU::S_CBRANCH_SCC0;
3272 case SIInstrInfo::VCCNZ:
3273 return AMDGPU::S_CBRANCH_VCCNZ;
3274 case SIInstrInfo::VCCZ:
3275 return AMDGPU::S_CBRANCH_VCCZ;
3276 case SIInstrInfo::EXECNZ:
3277 return AMDGPU::S_CBRANCH_EXECNZ;
3278 case SIInstrInfo::EXECZ:
3279 return AMDGPU::S_CBRANCH_EXECZ;
3285SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3287 case AMDGPU::S_CBRANCH_SCC0:
3289 case AMDGPU::S_CBRANCH_SCC1:
3291 case AMDGPU::S_CBRANCH_VCCNZ:
3293 case AMDGPU::S_CBRANCH_VCCZ:
3295 case AMDGPU::S_CBRANCH_EXECNZ:
3297 case AMDGPU::S_CBRANCH_EXECZ:
3309 bool AllowModify)
const {
3310 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3312 TBB =
I->getOperand(0).getMBB();
3316 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3317 if (Pred == INVALID_BR)
3322 Cond.push_back(
I->getOperand(1));
3326 if (
I ==
MBB.end()) {
3332 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3334 FBB =
I->getOperand(0).getMBB();
3344 bool AllowModify)
const {
3352 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3353 switch (
I->getOpcode()) {
3354 case AMDGPU::S_MOV_B64_term:
3355 case AMDGPU::S_XOR_B64_term:
3356 case AMDGPU::S_OR_B64_term:
3357 case AMDGPU::S_ANDN2_B64_term:
3358 case AMDGPU::S_AND_B64_term:
3359 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3360 case AMDGPU::S_MOV_B32_term:
3361 case AMDGPU::S_XOR_B32_term:
3362 case AMDGPU::S_OR_B32_term:
3363 case AMDGPU::S_ANDN2_B32_term:
3364 case AMDGPU::S_AND_B32_term:
3365 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3366 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3367 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3370 case AMDGPU::SI_ELSE:
3371 case AMDGPU::SI_KILL_I1_TERMINATOR:
3372 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3389 int *BytesRemoved)
const {
3391 unsigned RemovedSize = 0;
3394 if (
MI.isBranch() ||
MI.isReturn()) {
3396 MI.eraseFromParent();
3402 *BytesRemoved = RemovedSize;
3419 int *BytesAdded)
const {
3420 if (!FBB &&
Cond.empty()) {
3424 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3431 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3443 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3461 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3468 if (
Cond.size() != 2) {
3472 if (
Cond[0].isImm()) {
3493 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3497 std::optional<bool> createTripCountGreaterCondition(
3498 int TC, MachineBasicBlock &
MBB,
3499 SmallVectorImpl<MachineOperand> &CondParam)
override {
3500 CondParam = this->
Cond;
3504 void adjustTripCount(
int TripCountAdjust)
override {}
3506 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3510std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3519 if (
TBB == LoopBB && FBB == LoopBB)
3526 assert((
TBB == LoopBB || FBB == LoopBB) &&
3527 "The Loop must be a single-basic-block loop");
3530 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3531 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3536 if (
MI.isCall() ||
MI.isInlineAsm())
3551 if (CmpI == Instructions.end() || CmpI->isPHI())
3555 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3562 SelectExpansion &Exp)
const {
3568 if (
MRI.getRegClass(FalseReg) != RC)
3572 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3575 return RI.hasVGPRs(RC) && NumInsts <= 6;
3583 if (
MRI.getRegClass(FalseReg) != RC)
3589 if (NumInsts % 2 == 0)
3592 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3593 return RI.isSGPRClass(RC);
3604 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3605 if (Pred == VCCZ || Pred == SCC_FALSE) {
3606 Pred =
static_cast<BranchPredicate
>(-Pred);
3612 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3614 if (DstSize == 32) {
3616 if (Pred == SCC_TRUE) {
3631 if (DstSize == 64 && Pred == SCC_TRUE) {
3641 static const int16_t Sub0_15[] = {
3642 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3643 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3644 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3645 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3648 static const int16_t Sub0_15_64[] = {
3649 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3650 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3651 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3652 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3655 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3657 const int16_t *SubIndices = Sub0_15;
3658 int NElts = DstSize / 32;
3662 if (Pred == SCC_TRUE) {
3664 SelOp = AMDGPU::S_CSELECT_B32;
3665 EltRC = &AMDGPU::SGPR_32RegClass;
3667 SelOp = AMDGPU::S_CSELECT_B64;
3668 EltRC = &AMDGPU::SGPR_64RegClass;
3669 SubIndices = Sub0_15_64;
3675 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3680 for (
int Idx = 0; Idx != NElts; ++Idx) {
3681 Register DstElt =
MRI.createVirtualRegister(EltRC);
3684 unsigned SubIdx = SubIndices[Idx];
3687 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3689 .
addReg(FalseReg, {}, SubIdx)
3690 .addReg(TrueReg, {}, SubIdx);
3693 .
addReg(TrueReg, {}, SubIdx)
3694 .addReg(FalseReg, {}, SubIdx);
3707 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3710 switch (
MI.getOpcode()) {
3711 case AMDGPU::S_ENDPGM:
3712 case AMDGPU::S_ENDPGM_SAVED:
3713 case AMDGPU::S_TRAP:
3714 case AMDGPU::S_GETREG_B32:
3715 case AMDGPU::S_SETREG_B32:
3716 case AMDGPU::S_SETREG_B32_mode:
3717 case AMDGPU::S_SETREG_IMM32_B32:
3718 case AMDGPU::S_SETREG_IMM32_B32_mode:
3719 case AMDGPU::S_SENDMSG:
3720 case AMDGPU::S_SENDMSGHALT:
3721 case AMDGPU::S_SENDMSG_RTN_B32:
3722 case AMDGPU::S_SENDMSG_RTN_B64:
3723 case AMDGPU::S_BARRIER_WAIT:
3724 case AMDGPU::S_BARRIER_SIGNAL_M0:
3725 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3726 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3727 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3735 switch (
MI.getOpcode()) {
3736 case AMDGPU::V_MOV_B16_t16_e32:
3737 case AMDGPU::V_MOV_B16_t16_e64:
3738 case AMDGPU::V_MOV_B32_e32:
3739 case AMDGPU::V_MOV_B32_e64:
3740 case AMDGPU::V_MOV_B64_PSEUDO:
3741 case AMDGPU::V_MOV_B64_e32:
3742 case AMDGPU::V_MOV_B64_e64:
3743 case AMDGPU::S_MOV_B32:
3744 case AMDGPU::S_MOV_B64:
3745 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3747 case AMDGPU::WWM_COPY:
3748 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3749 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3750 case AMDGPU::V_ACCVGPR_MOV_B32:
3751 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3752 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3760 switch (
MI.getOpcode()) {
3761 case AMDGPU::V_MOV_B16_t16_e32:
3762 case AMDGPU::V_MOV_B16_t16_e64:
3764 case AMDGPU::V_MOV_B32_e32:
3765 case AMDGPU::V_MOV_B32_e64:
3766 case AMDGPU::V_MOV_B64_PSEUDO:
3767 case AMDGPU::V_MOV_B64_e32:
3768 case AMDGPU::V_MOV_B64_e64:
3769 case AMDGPU::S_MOV_B32:
3770 case AMDGPU::S_MOV_B64:
3771 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3773 case AMDGPU::WWM_COPY:
3774 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3775 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3776 case AMDGPU::V_ACCVGPR_MOV_B32:
3777 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3778 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3786 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3787 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3788 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3791 unsigned Opc =
MI.getOpcode();
3793 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3795 MI.removeOperand(Idx);
3801 MI.setDesc(NewDesc);
3807 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3808 Desc.implicit_defs().size();
3810 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3811 MI.removeOperand(
I);
3815 unsigned SubRegIndex) {
3816 switch (SubRegIndex) {
3817 case AMDGPU::NoSubRegister:
3827 case AMDGPU::sub1_lo16:
3829 case AMDGPU::sub1_hi16:
3832 return std::nullopt;
3840 case AMDGPU::V_MAC_F16_e32:
3841 case AMDGPU::V_MAC_F16_e64:
3842 case AMDGPU::V_MAD_F16_e64:
3843 return AMDGPU::V_MADAK_F16;
3844 case AMDGPU::V_MAC_F32_e32:
3845 case AMDGPU::V_MAC_F32_e64:
3846 case AMDGPU::V_MAD_F32_e64:
3847 return AMDGPU::V_MADAK_F32;
3848 case AMDGPU::V_FMAC_F32_e32:
3849 case AMDGPU::V_FMAC_F32_e64:
3850 case AMDGPU::V_FMA_F32_e64:
3851 return AMDGPU::V_FMAAK_F32;
3852 case AMDGPU::V_FMAC_F16_e32:
3853 case AMDGPU::V_FMAC_F16_e64:
3854 case AMDGPU::V_FMAC_F16_t16_e64:
3855 case AMDGPU::V_FMAC_F16_fake16_e64:
3856 case AMDGPU::V_FMAC_F16_t16_e32:
3857 case AMDGPU::V_FMAC_F16_fake16_e32:
3858 case AMDGPU::V_FMA_F16_e64:
3859 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3860 ? AMDGPU::V_FMAAK_F16_t16
3861 : AMDGPU::V_FMAAK_F16_fake16
3862 : AMDGPU::V_FMAAK_F16;
3863 case AMDGPU::V_FMAC_F64_e32:
3864 case AMDGPU::V_FMAC_F64_e64:
3865 case AMDGPU::V_FMA_F64_e64:
3866 return AMDGPU::V_FMAAK_F64;
3874 case AMDGPU::V_MAC_F16_e32:
3875 case AMDGPU::V_MAC_F16_e64:
3876 case AMDGPU::V_MAD_F16_e64:
3877 return AMDGPU::V_MADMK_F16;
3878 case AMDGPU::V_MAC_F32_e32:
3879 case AMDGPU::V_MAC_F32_e64:
3880 case AMDGPU::V_MAD_F32_e64:
3881 return AMDGPU::V_MADMK_F32;
3882 case AMDGPU::V_FMAC_F32_e32:
3883 case AMDGPU::V_FMAC_F32_e64:
3884 case AMDGPU::V_FMA_F32_e64:
3885 return AMDGPU::V_FMAMK_F32;
3886 case AMDGPU::V_FMAC_F16_e32:
3887 case AMDGPU::V_FMAC_F16_e64:
3888 case AMDGPU::V_FMAC_F16_t16_e64:
3889 case AMDGPU::V_FMAC_F16_fake16_e64:
3890 case AMDGPU::V_FMAC_F16_t16_e32:
3891 case AMDGPU::V_FMAC_F16_fake16_e32:
3892 case AMDGPU::V_FMA_F16_e64:
3893 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3894 ? AMDGPU::V_FMAMK_F16_t16
3895 : AMDGPU::V_FMAMK_F16_fake16
3896 : AMDGPU::V_FMAMK_F16;
3897 case AMDGPU::V_FMAC_F64_e32:
3898 case AMDGPU::V_FMAC_F64_e64:
3899 case AMDGPU::V_FMA_F64_e64:
3900 return AMDGPU::V_FMAMK_F64;
3912 const bool HasMultipleUses = !
MRI->hasOneNonDBGUse(Reg);
3914 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3917 if (
Opc == AMDGPU::COPY) {
3918 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3925 if (HasMultipleUses) {
3928 unsigned ImmDefSize = RI.getRegSizeInBits(*
MRI->getRegClass(Reg));
3931 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3939 if (ImmDefSize == 32 &&
3944 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3945 RI.getSubRegIdxSize(UseSubReg) == 16;
3948 if (RI.hasVGPRs(DstRC))
3951 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3957 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3964 for (
unsigned MovOp :
3965 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3966 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3974 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3978 if (MovDstPhysReg) {
3982 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3989 if (MovDstPhysReg) {
3990 if (!MovDstRC->
contains(MovDstPhysReg))
3992 }
else if (!
MRI->constrainRegClass(DstReg, MovDstRC)) {
4006 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4014 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4018 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4020 UseMI.getOperand(0).setReg(MovDstPhysReg);
4025 UseMI.setDesc(NewMCID);
4026 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4027 UseMI.addImplicitDefUseOperands(*MF);
4031 if (HasMultipleUses)
4034 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4035 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4036 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4037 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4038 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4039 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4040 Opc == AMDGPU::V_FMAC_F64_e64) {
4049 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4060 auto CopyRegOperandToNarrowerRC =
4063 if (!
MI.getOperand(OpNo).isReg())
4067 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4070 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4071 get(AMDGPU::COPY), Tmp)
4073 MI.getOperand(OpNo).setReg(Tmp);
4077 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4078 (Src1->isReg() && Src1->getReg() == Reg)) {
4080 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4081 if (!RegSrc->
isReg())
4083 if (RI.isSGPRClass(
MRI->getRegClass(RegSrc->
getReg())) &&
4084 ST.getConstantBusLimit(
Opc) < 2)
4087 if (!Src2->isReg() || RI.isSGPRClass(
MRI->getRegClass(Src2->getReg())))
4099 if (Def && Def->isMoveImmediate() &&
4108 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4114 unsigned SrcSubReg = RegSrc->
getSubReg();
4115 Src0->setReg(SrcReg);
4116 Src0->setSubReg(SrcSubReg);
4117 Src0->setIsKill(RegSrc->
isKill());
4119 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4120 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4121 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4122 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4123 UseMI.untieRegOperand(
4124 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4126 Src1->ChangeToImmediate(*SubRegImm);
4131 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4132 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4136 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4137 UseMI.getOperand(0).getReg())
4139 UseMI.getOperand(0).setReg(Tmp);
4140 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4141 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4144 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4146 DefMI.eraseFromParent();
4152 if (Src2->isReg() && Src2->getReg() == Reg) {
4153 if (ST.getConstantBusLimit(
Opc) < 2) {
4156 bool Src0Inlined =
false;
4157 if (Src0->isReg()) {
4162 if (Def && Def->isMoveImmediate() &&
4164 MRI->hasOneNonDBGUse(Src0->getReg())) {
4165 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4167 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4168 RI.isSGPRReg(*
MRI, Src0->getReg())) {
4174 if (Src1->isReg() && !Src0Inlined) {
4177 if (Def && Def->isMoveImmediate() &&
4179 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(
UseMI))
4180 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4181 else if (RI.isSGPRReg(*
MRI, Src1->getReg()))
4194 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4195 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4196 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4197 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4198 UseMI.untieRegOperand(
4199 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4201 const std::optional<int64_t> SubRegImm =
4205 Src2->ChangeToImmediate(*SubRegImm);
4211 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4212 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4216 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4217 UseMI.getOperand(0).getReg())
4219 UseMI.getOperand(0).setReg(Tmp);
4220 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4221 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4230 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4234 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4236 DefMI.eraseFromParent();
4248 if (BaseOps1.
size() != BaseOps2.
size())
4250 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4251 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4259 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4260 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4261 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4263 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4266bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4269 int64_t Offset0, Offset1;
4272 bool Offset0IsScalable, Offset1IsScalable;
4286 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4287 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4294 "MIa must load from or modify a memory location");
4296 "MIb must load from or modify a memory location");
4318 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4325 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4335 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4349 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4360 case AMDGPU::V_MAC_F16_e32:
4361 case AMDGPU::V_MAC_F16_e64:
4362 return AMDGPU::V_MAD_F16_e64;
4363 case AMDGPU::V_MAC_F32_e32:
4364 case AMDGPU::V_MAC_F32_e64:
4365 return AMDGPU::V_MAD_F32_e64;
4366 case AMDGPU::V_MAC_LEGACY_F32_e32:
4367 case AMDGPU::V_MAC_LEGACY_F32_e64:
4368 return AMDGPU::V_MAD_LEGACY_F32_e64;
4369 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4370 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4371 return AMDGPU::V_FMA_LEGACY_F32_e64;
4372 case AMDGPU::V_FMAC_F16_e32:
4373 case AMDGPU::V_FMAC_F16_e64:
4374 case AMDGPU::V_FMAC_F16_t16_e64:
4375 case AMDGPU::V_FMAC_F16_fake16_e64:
4376 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4377 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4378 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4379 : AMDGPU::V_FMA_F16_gfx9_e64;
4380 case AMDGPU::V_FMAC_F32_e32:
4381 case AMDGPU::V_FMAC_F32_e64:
4382 return AMDGPU::V_FMA_F32_e64;
4383 case AMDGPU::V_FMAC_F64_e32:
4384 case AMDGPU::V_FMAC_F64_e64:
4385 return AMDGPU::V_FMA_F64_e64;
4404 if (
MI.isBundle()) {
4407 if (
MI.getBundleSize() != 1)
4409 CandidateMI =
MI.getNextNode();
4413 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4417 if (
MI.isBundle()) {
4422 MI.untieRegOperand(MO.getOperandNo());
4429 if (Def.isEarlyClobber() && Def.isReg() &&
4434 auto UpdateDefIndex = [&](
LiveRange &LR) {
4435 auto *S = LR.find(OldIndex);
4436 if (S != LR.end() && S->start == OldIndex) {
4437 assert(S->valno && S->valno->def == OldIndex);
4438 S->start = NewIndex;
4439 S->valno->def = NewIndex;
4443 for (
auto &SR : LI.subranges())
4449 if (U.RemoveMIUse) {
4452 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4454 if (
MRI.hasOneNonDBGUse(DefReg)) {
4456 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4457 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4458 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4459 U.RemoveMIUse->removeOperand(
I);
4462 if (
MI.isBundle()) {
4466 if (MO.isReg() && MO.getReg() == DefReg) {
4467 assert(MO.getSubReg() == 0 &&
4468 "tied sub-registers in bundles currently not supported");
4469 MI.removeOperand(MO.getOperandNo());
4484 Register DummyReg =
MRI.cloneVirtualRegister(DefReg);
4486 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4487 MIOp.setIsUndef(
true);
4488 MIOp.setReg(DummyReg);
4492 if (
MI.isBundle()) {
4496 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4497 MIOp.setIsUndef(
true);
4498 MIOp.setReg(DummyReg);
4511 return MI.isBundle() ? &
MI : NewMI;
4516 ThreeAddressUpdates &U)
const {
4518 unsigned Opc =
MI.getOpcode();
4522 if (NewMFMAOpc != -1) {
4525 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4526 MIB.
add(
MI.getOperand(
I));
4534 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4539 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4540 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4541 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4545 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4546 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4547 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4548 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4549 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4550 bool Src0Literal =
false;
4555 case AMDGPU::V_MAC_F16_e64:
4556 case AMDGPU::V_FMAC_F16_e64:
4557 case AMDGPU::V_FMAC_F16_t16_e64:
4558 case AMDGPU::V_FMAC_F16_fake16_e64:
4559 case AMDGPU::V_MAC_F32_e64:
4560 case AMDGPU::V_MAC_LEGACY_F32_e64:
4561 case AMDGPU::V_FMAC_F32_e64:
4562 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4563 case AMDGPU::V_FMAC_F64_e64:
4565 case AMDGPU::V_MAC_F16_e32:
4566 case AMDGPU::V_FMAC_F16_e32:
4567 case AMDGPU::V_MAC_F32_e32:
4568 case AMDGPU::V_MAC_LEGACY_F32_e32:
4569 case AMDGPU::V_FMAC_F32_e32:
4570 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4571 case AMDGPU::V_FMAC_F64_e32: {
4572 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4573 AMDGPU::OpName::src0);
4574 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4575 if (!
Src0->isReg() && !
Src0->isImm())
4585 MachineInstrBuilder MIB;
4588 const MachineOperand *Src0Mods =
4591 const MachineOperand *Src1Mods =
4594 const MachineOperand *Src2Mods =
4600 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4601 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4603 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4605 MachineInstr *
DefMI =
nullptr;
4607 std::optional<int64_t> ImmOpt;
4642 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4658 if (Src0Literal && !ST.hasVOP3Literal())
4686 switch (
MI.getOpcode()) {
4687 case AMDGPU::S_SET_GPR_IDX_ON:
4688 case AMDGPU::S_SET_GPR_IDX_MODE:
4689 case AMDGPU::S_SET_GPR_IDX_OFF:
4707 if (
MI.isTerminator() ||
MI.isPosition())
4711 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4714 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4720 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4721 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4722 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4723 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4724 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4729 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4730 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4731 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4745 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4750 if (
MI.memoperands_empty())
4755 unsigned AS = Memop->getAddrSpace();
4756 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4757 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4758 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4759 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4774 if (
MI.memoperands_empty())
4783 unsigned AS = Memop->getAddrSpace();
4793 bool TgSplit)
const {
4806 if (
MI.memoperands_empty())
4811 unsigned AS = Memop->getAddrSpace();
4827 unsigned Opcode =
MI.getOpcode();
4842 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4843 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4844 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4845 Opcode == AMDGPU::S_SETHALT)
4848 if (
MI.isCall() ||
MI.isInlineAsm())
4854 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4870 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4871 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4872 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4873 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4881 if (
MI.isMetaInstruction())
4885 if (
MI.isCopyLike()) {
4886 if (!RI.isSGPRReg(
MRI,
MI.getOperand(0).getReg()))
4890 return MI.readsRegister(AMDGPU::EXEC, &RI);
4901 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4905 switch (
Imm.getBitWidth()) {
4911 ST.hasInv2PiInlineImm());
4914 ST.hasInv2PiInlineImm());
4916 return ST.has16BitInsts() &&
4918 ST.hasInv2PiInlineImm());
4925 APInt IntImm =
Imm.bitcastToAPInt();
4927 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4935 return ST.has16BitInsts() &&
4938 return ST.has16BitInsts() &&
4948 switch (OperandType) {
4958 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5002 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5003 return ST.has16BitInsts() &&
5012 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5013 return ST.has16BitInsts() &&
5065 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5071 return ST.hasVOP3Literal();
5075 int64_t ImmVal)
const {
5077 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5078 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5079 OpNo ==
static_cast<unsigned>(Src1Idx))
5084 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5085 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5086 AMDGPU::OpName::src2))
5089 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5096 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5108 "unexpected imm-like operand kind");
5121 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5141 return Op32 != -1 &&
TII.isVOPC(Op32);
5146 unsigned Depth)
const {
5147 assert(
MRI.isSSA() &&
"isMaskedByExec requires SSA form");
5156 constexpr unsigned MaxDepth = 6;
5157 if (
Depth >= MaxDepth || !Reg.isVirtual())
5163 if (!Def || Def->getParent() !=
MBB)
5171 auto Recurse = [&](
unsigned OpIdx) {
5177 unsigned Opc = Def->getOpcode();
5178 if (
Opc == AMDGPU::COPY && Recurse(1))
5180 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5200 AMDGPU::OpName
OpName)
const {
5202 return Mods && Mods->
getImm();
5215 switch (
MI.getOpcode()) {
5216 default:
return false;
5218 case AMDGPU::V_ADDC_U32_e64:
5219 case AMDGPU::V_SUBB_U32_e64:
5220 case AMDGPU::V_SUBBREV_U32_e64: {
5223 if (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()))
5228 case AMDGPU::V_MAC_F16_e64:
5229 case AMDGPU::V_MAC_F32_e64:
5230 case AMDGPU::V_MAC_LEGACY_F32_e64:
5231 case AMDGPU::V_FMAC_F16_e64:
5232 case AMDGPU::V_FMAC_F16_t16_e64:
5233 case AMDGPU::V_FMAC_F16_fake16_e64:
5234 case AMDGPU::V_FMAC_F32_e64:
5235 case AMDGPU::V_FMAC_F64_e64:
5236 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5237 if (!Src2->isReg() || !RI.isVGPR(
MRI, Src2->getReg()) ||
5242 case AMDGPU::V_CNDMASK_B32_e64:
5248 if (Src1 && (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()) ||
5261 if (Src0 && Src0->isImm()) {
5264 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5286 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5295 unsigned Op32)
const {
5309 Inst32.
add(
MI.getOperand(
I));
5313 int Idx =
MI.getNumExplicitDefs();
5315 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5320 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5340 if (OldSDst && OldSDst->
isDead()) {
5343 NewVCC->setIsDead();
5352 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5360 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5363 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5364 AMDGPU::SReg_64RegClass.contains(Reg);
5370 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5382 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5392 switch (MO.getReg()) {
5394 case AMDGPU::VCC_LO:
5395 case AMDGPU::VCC_HI:
5397 case AMDGPU::FLAT_SCR:
5410 switch (
MI.getOpcode()) {
5411 case AMDGPU::V_READLANE_B32:
5412 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5413 case AMDGPU::V_WRITELANE_B32:
5414 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5421 if (
MI.isPreISelOpcode() ||
5422 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5440 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5451 if (RI.isVectorRegister(
MRI, SrcReg) && RI.isSGPRReg(
MRI, DstReg)) {
5452 ErrInfo =
"illegal copy from vector register to SGPR";
5470 if (!
MRI.isSSA() &&
MI.isCopy())
5471 return verifyCopy(
MI,
MRI, ErrInfo);
5473 if (SIInstrInfo::isGenericOpcode(Opcode))
5476 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5477 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5478 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5480 if (Src0Idx == -1) {
5482 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5483 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5484 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5485 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5490 if (!
Desc.isVariadic() &&
5491 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5492 ErrInfo =
"Instruction has wrong number of operands.";
5496 if (
MI.isInlineAsm()) {
5509 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5510 ErrInfo =
"inlineasm operand has incorrect register class.";
5518 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5519 ErrInfo =
"missing memory operand from image instruction.";
5524 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5527 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5528 "all fp values to integers.";
5534 switch (OpInfo.OperandType) {
5536 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5537 ErrInfo =
"Illegal immediate value for operand.";
5569 ErrInfo =
"Illegal immediate value for operand.";
5578 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5581 OpInfo.OperandType ==
5583 ErrInfo =
"illegal 64-bit immediate value for operand.";
5590 ErrInfo =
"Expected inline constant for operand.";
5604 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5605 ErrInfo =
"Expected immediate, but got non-immediate";
5614 if (OpInfo.isGenericType())
5622 if (!ST.hasSDWA()) {
5623 ErrInfo =
"SDWA is not supported on this target";
5627 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5628 AMDGPU::OpName::dst_sel}) {
5634 ErrInfo =
"Invalid SDWA selection";
5639 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5641 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5646 if (!ST.hasSDWAScalar()) {
5648 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(
MRI, MO.
getReg()))) {
5649 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5656 "Only reg allowed as operands in SDWA instructions on GFX9+";
5662 if (!ST.hasSDWAOmod()) {
5665 if (OMod !=
nullptr &&
5667 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5672 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5673 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5674 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5675 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5678 unsigned Mods = Src0ModsMO->
getImm();
5681 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5687 if (
isVOPC(BasicOpcode)) {
5688 if (!ST.hasSDWASdst() && DstIdx != -1) {
5691 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5692 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5695 }
else if (!ST.hasSDWAOutModsVOPC()) {
5698 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5699 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5705 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5706 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5713 if (DstUnused && DstUnused->isImm() &&
5716 if (!Dst.isReg() || !Dst.isTied()) {
5717 ErrInfo =
"Dst register should have tied register";
5722 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5725 "Dst register should be tied to implicit use of preserved register";
5729 ErrInfo =
"Dst register should use same physical register as preserved";
5735 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5738 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5741 if (Src1MO.
isImm()) {
5742 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5748 if (
isImage(Opcode) && !
MI.mayStore()) {
5753 uint64_t DMaskImm = DMask->
getImm();
5760 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5768 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5772 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5773 if (RegCount > DstSize) {
5774 ErrInfo =
"Image instruction returns too many registers for dst "
5784 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5785 unsigned ConstantBusCount = 0;
5786 bool UsesLiteral =
false;
5789 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5793 LiteralVal = &
MI.getOperand(ImmIdx);
5802 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5813 }
else if (!MO.
isFI()) {
5820 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5830 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5831 return !RI.regsOverlap(SGPRUsed, SGPR);
5840 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5841 Opcode != AMDGPU::V_WRITELANE_B32) {
5842 ErrInfo =
"VOP* instruction violates constant bus restriction";
5846 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5847 ErrInfo =
"VOP3 instruction uses literal";
5854 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5855 unsigned SGPRCount = 0;
5858 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5866 if (MO.
getReg() != SGPRUsed)
5871 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5872 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5879 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5880 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5884 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5887 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5897 ErrInfo =
"ABS not allowed in VOP3B instructions";
5909 !Src0.isIdenticalTo(Src1)) {
5910 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5917 if (
Desc.isBranch()) {
5919 ErrInfo =
"invalid branch target for SOPK instruction";
5923 uint64_t
Imm =
Op->getImm();
5926 ErrInfo =
"invalid immediate for SOPK instruction";
5931 ErrInfo =
"invalid immediate for SOPK instruction";
5938 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5939 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5940 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5941 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5942 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5943 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5945 const unsigned StaticNumOps =
5946 Desc.getNumOperands() +
Desc.implicit_uses().size();
5947 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5953 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5954 ErrInfo =
"missing implicit register operands";
5960 if (!Dst->isUse()) {
5961 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5966 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5967 UseOpIdx != StaticNumOps + 1) {
5968 ErrInfo =
"movrel implicit operands should be tied";
5975 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5977 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5978 ErrInfo =
"src0 should be subreg of implicit vector use";
5986 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5987 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5993 if (
MI.mayStore() &&
5998 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5999 ErrInfo =
"scalar stores must use m0 as offset register";
6005 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6007 if (
Offset->getImm() != 0) {
6008 ErrInfo =
"subtarget does not support offsets in flat instructions";
6013 if (
isDS(
MI) && !ST.hasGDS()) {
6015 if (GDSOp && GDSOp->
getImm() != 0) {
6016 ErrInfo =
"GDS is not supported on this subtarget";
6024 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6025 AMDGPU::OpName::vaddr0);
6026 AMDGPU::OpName RSrcOpName =
6027 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6028 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6036 ErrInfo =
"dim is out of range";
6041 if (ST.hasR128A16()) {
6043 IsA16 = R128A16->
getImm() != 0;
6044 }
else if (ST.hasA16()) {
6046 IsA16 = A16->
getImm() != 0;
6049 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6051 unsigned AddrWords =
6054 unsigned VAddrWords;
6056 VAddrWords = RsrcIdx - VAddr0Idx;
6057 if (ST.hasPartialNSAEncoding() &&
6059 unsigned LastVAddrIdx = RsrcIdx - 1;
6060 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6068 if (VAddrWords != AddrWords) {
6070 <<
" but got " << VAddrWords <<
"\n");
6071 ErrInfo =
"bad vaddr size";
6081 unsigned DC = DppCt->
getImm();
6082 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6083 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6084 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6085 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6086 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6087 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6088 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6089 ErrInfo =
"Invalid dpp_ctrl value";
6092 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6093 !ST.hasDPPWavefrontShifts()) {
6094 ErrInfo =
"Invalid dpp_ctrl value: "
6095 "wavefront shifts are not supported on GFX10+";
6098 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6099 !ST.hasDPPBroadcasts()) {
6100 ErrInfo =
"Invalid dpp_ctrl value: "
6101 "broadcasts are not supported on GFX10+";
6104 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6106 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6107 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6108 !ST.hasGFX90AInsts()) {
6109 ErrInfo =
"Invalid dpp_ctrl value: "
6110 "row_newbroadcast/row_share is not supported before "
6114 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6115 ErrInfo =
"Invalid dpp_ctrl value: "
6116 "row_share and row_xmask are not supported before GFX10";
6121 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6123 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6125 ErrInfo =
"Invalid dpp_ctrl value: "
6126 "DP ALU dpp only support row_newbcast";
6133 AMDGPU::OpName DataName =
6134 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6140 if (!ST.hasGFX90AInsts()) {
6141 if ((Dst && RI.isAGPR(
MRI, Dst->getReg())) ||
6143 (Data2 && RI.isAGPR(
MRI, Data2->
getReg()))) {
6144 ErrInfo =
"Invalid register class: "
6145 "agpr loads and stores not supported on this GPU";
6151 if (ST.needsAlignedVGPRs()) {
6152 const auto isAlignedReg = [&
MI, &
MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6157 if (Reg.isPhysical())
6158 return !(RI.getHWRegIndex(Reg) & 1);
6160 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6161 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6165 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6166 ErrInfo =
"Subtarget requires even aligned vector registers "
6167 "for vaddr operand of image instructions";
6173 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6175 if (Src->isReg() && RI.isSGPRReg(
MRI, Src->getReg())) {
6176 ErrInfo =
"Invalid register class: "
6177 "v_accvgpr_write with an SGPR is not supported on this GPU";
6182 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6185 ErrInfo =
"pseudo expects only physical SGPRs";
6192 if (!ST.hasScaleOffset()) {
6193 ErrInfo =
"Subtarget does not support offset scaling";
6197 ErrInfo =
"Instruction does not support offset scaling";
6205 for (
unsigned I = 0;
I < 3; ++
I) {
6211 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6212 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6214 if ((Dst && RI.getRegClassForReg(
MRI, Dst->getReg()) ==
6215 &AMDGPU::SReg_64RegClass) ||
6216 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6217 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6226 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6228 return MI.getOperand(1).isReg() || RI.isAGPR(
MRI,
MI.getOperand(0).getReg())
6230 : AMDGPU::V_MOV_B32_e32;
6240 default:
return AMDGPU::INSTRUCTION_LIST_END;
6241 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6242 case AMDGPU::COPY:
return AMDGPU::COPY;
6243 case AMDGPU::PHI:
return AMDGPU::PHI;
6244 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6245 case AMDGPU::WQM:
return AMDGPU::WQM;
6246 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6247 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6248 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6249 case AMDGPU::S_ADD_I32:
6250 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6251 case AMDGPU::S_ADDC_U32:
6252 return AMDGPU::V_ADDC_U32_e32;
6253 case AMDGPU::S_SUB_I32:
6254 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6257 case AMDGPU::S_ADD_U32:
6258 return AMDGPU::V_ADD_CO_U32_e32;
6259 case AMDGPU::S_SUB_U32:
6260 return AMDGPU::V_SUB_CO_U32_e32;
6261 case AMDGPU::S_ADD_U64_PSEUDO:
6262 return AMDGPU::V_ADD_U64_PSEUDO;
6263 case AMDGPU::S_SUB_U64_PSEUDO:
6264 return AMDGPU::V_SUB_U64_PSEUDO;
6265 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6266 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6267 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6268 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6269 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6270 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6271 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6272 case AMDGPU::S_XNOR_B32:
6273 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6274 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6275 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6276 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6277 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6278 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6279 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6280 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6281 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6282 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6283 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6284 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6285 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6286 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6287 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6288 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6289 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6290 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6291 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6292 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6293 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6294 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6295 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6296 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6297 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6298 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6299 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6300 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6301 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6302 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6303 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6304 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6305 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6306 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6307 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6308 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6309 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6310 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6311 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6312 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6313 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6314 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6315 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6316 case AMDGPU::S_CVT_F32_F16:
6317 case AMDGPU::S_CVT_HI_F32_F16:
6318 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6319 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6320 case AMDGPU::S_CVT_F16_F32:
6321 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6322 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6323 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6324 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6325 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6326 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6327 case AMDGPU::S_CEIL_F16:
6328 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6329 : AMDGPU::V_CEIL_F16_fake16_e64;
6330 case AMDGPU::S_FLOOR_F16:
6331 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6332 : AMDGPU::V_FLOOR_F16_fake16_e64;
6333 case AMDGPU::S_TRUNC_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6335 : AMDGPU::V_TRUNC_F16_fake16_e64;
6336 case AMDGPU::S_RNDNE_F16:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6338 : AMDGPU::V_RNDNE_F16_fake16_e64;
6339 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6340 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6341 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6342 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6343 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6344 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6345 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6346 case AMDGPU::S_ADD_F16:
6347 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6348 : AMDGPU::V_ADD_F16_fake16_e64;
6349 case AMDGPU::S_SUB_F16:
6350 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6351 : AMDGPU::V_SUB_F16_fake16_e64;
6352 case AMDGPU::S_MIN_F16:
6353 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6354 : AMDGPU::V_MIN_F16_fake16_e64;
6355 case AMDGPU::S_MAX_F16:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6357 : AMDGPU::V_MAX_F16_fake16_e64;
6358 case AMDGPU::S_MINIMUM_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6360 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6361 case AMDGPU::S_MAXIMUM_F16:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6363 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6364 case AMDGPU::S_MUL_F16:
6365 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6366 : AMDGPU::V_MUL_F16_fake16_e64;
6367 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6368 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6369 case AMDGPU::S_FMAC_F16:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6371 : AMDGPU::V_FMAC_F16_fake16_e64;
6372 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6373 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6374 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6375 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6376 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6377 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6378 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6379 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6380 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6381 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6382 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6383 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6384 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6385 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6386 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6387 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6388 case AMDGPU::S_CMP_LT_F16:
6389 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6390 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6391 case AMDGPU::S_CMP_EQ_F16:
6392 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6393 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6394 case AMDGPU::S_CMP_LE_F16:
6395 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6396 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6397 case AMDGPU::S_CMP_GT_F16:
6398 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6399 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6400 case AMDGPU::S_CMP_LG_F16:
6401 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6402 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6403 case AMDGPU::S_CMP_GE_F16:
6404 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6405 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6406 case AMDGPU::S_CMP_O_F16:
6407 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6408 : AMDGPU::V_CMP_O_F16_fake16_e64;
6409 case AMDGPU::S_CMP_U_F16:
6410 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6411 : AMDGPU::V_CMP_U_F16_fake16_e64;
6412 case AMDGPU::S_CMP_NGE_F16:
6413 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6414 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6415 case AMDGPU::S_CMP_NLG_F16:
6416 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6417 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6418 case AMDGPU::S_CMP_NGT_F16:
6419 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6420 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6421 case AMDGPU::S_CMP_NLE_F16:
6422 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6423 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6424 case AMDGPU::S_CMP_NEQ_F16:
6425 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6426 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6427 case AMDGPU::S_CMP_NLT_F16:
6428 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6429 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6430 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6431 case AMDGPU::V_S_EXP_F16_e64:
6432 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6433 : AMDGPU::V_EXP_F16_fake16_e64;
6434 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6435 case AMDGPU::V_S_LOG_F16_e64:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6437 : AMDGPU::V_LOG_F16_fake16_e64;
6438 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6439 case AMDGPU::V_S_RCP_F16_e64:
6440 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6441 : AMDGPU::V_RCP_F16_fake16_e64;
6442 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6443 case AMDGPU::V_S_RSQ_F16_e64:
6444 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6445 : AMDGPU::V_RSQ_F16_fake16_e64;
6446 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6447 case AMDGPU::V_S_SQRT_F16_e64:
6448 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6449 : AMDGPU::V_SQRT_F16_fake16_e64;
6452 "Unexpected scalar opcode without corresponding vector one!");
6501 "Not a whole wave func");
6504 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6505 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6512 unsigned OpNo)
const {
6514 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6515 Desc.operands()[OpNo].RegClass == -1) {
6518 if (Reg.isVirtual()) {
6520 return MRI.getRegClass(Reg);
6522 return RI.getPhysRegBaseClass(Reg);
6525 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6526 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6531 constexpr AMDGPU::OpName OpNames[] = {
6532 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6535 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6536 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6548 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6550 unsigned Size = RI.getRegSizeInBits(*RC);
6551 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6552 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6553 : AMDGPU::V_MOV_B32_e32;
6555 Opcode = AMDGPU::COPY;
6556 else if (RI.isSGPRClass(RC))
6557 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6576 Register Low64 =
MRI.createVirtualRegister(VRC64);
6582 .
addImm(AMDGPU::sub0_sub1)
6584 .
addImm(AMDGPU::sub2_sub3);
6585 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6602 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6606 Register SubReg =
MRI.createVirtualRegister(SubRC);
6608 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6619 if (SubIdx == AMDGPU::sub0)
6621 if (SubIdx == AMDGPU::sub1)
6633void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6649 if (Reg.isPhysical())
6656 RI.getLargestLegalSuperClass(RC,
MRI.getMF());
6659 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6662 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6669 unsigned Opc =
MI.getOpcode();
6682 bool IsAGPR = RI.isAGPR(
MRI, MO.
getReg());
6683 if (IsAGPR && !ST.hasMAIInsts())
6685 if (IsAGPR && (!ST.hasGFX90AInsts() || !
MRI.reservedRegsFrozen()) &&
6689 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6690 const int DataIdx = AMDGPU::getNamedOperandIdx(
6691 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6692 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6693 MI.getOperand(DataIdx).isReg() &&
6694 RI.isAGPR(
MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6696 if ((
int)OpIdx == DataIdx) {
6697 if (VDstIdx != -1 &&
6698 RI.isAGPR(
MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6701 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6702 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6703 RI.isAGPR(
MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6708 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6709 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6713 if (ST.hasFlatScratchHiInB64InstHazard() &&
6720 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6724 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6733 constexpr unsigned NumOps = 3;
6734 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6735 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6736 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6737 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6742 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6745 MO = &
MI.getOperand(SrcIdx);
6752 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6756 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6760 return !OpSel && !OpSelHi;
6765 if (!ST.hasPkF32InvalidOpSel() ||
MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6778 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6783 assert(
MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6791 const unsigned Mods[3] = {
6792 static_cast<unsigned>(
6794 static_cast<unsigned>(
6796 static_cast<unsigned>(
6801 for (
unsigned I = 0;
I != 3; ++
I) {
6815 bool DivergentSGPRs =
false;
6816 for (
unsigned I = 0;
I != 3; ++
I) {
6819 if (!SGPRSrcs.
empty()) {
6822 Srcs[
I]->getSubReg() == Srcs[
First]->getSubReg() &&
6823 "constant bus limit allows only one SGPR source");
6825 OpSel[
I][0] != OpSel[
First][0] || OpSel[
I][1] != OpSel[
First][1];
6830 if (DivergentSGPRs) {
6833 for (
unsigned I :
ArrayRef(SGPRSrcs).drop_front())
6839 unsigned SubIdx = (
Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6841 Op.isReg() ?
MRI.getRegClass(
Op.getReg()) :
nullptr;
6843 : RI.isVGPR(
MRI,
Op.getReg())
6844 ? RI.getVGPRClassForBitWidth(32)
6845 : RI.getSGPRClassForBitWidth(32);
6850 auto LaneMods = [](
unsigned Mods,
bool Hi) ->
unsigned {
6857 auto BuildLane = [&](
Register Dst,
bool Hi) {
6875 BuildLane(
Lo,
false);
6876 BuildLane(
Hi,
true);
6885 MI.eraseFromParent();
6894 int64_t RegClass = getOpRegClassID(OpInfo);
6896 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6898 MO = &
MI.getOperand(OpIdx);
6902 if (
isVALU(
MI,
false) && !IsInlineConst &&
6906 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6907 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6911 if (!LiteralLimit--)
6921 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6929 if (--ConstantBusLimit <= 0)
6941 if (!LiteralLimit--)
6943 if (--ConstantBusLimit <= 0)
6949 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6953 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6955 !
Op.isIdenticalTo(*MO))
6977 bool Is64BitOp = Is64BitFPOp ||
6985 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6994 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
7012 bool IsGFX950Only = ST.hasGFX950Insts();
7013 bool IsGFX940Only = ST.hasGFX940Insts();
7015 if (!IsGFX950Only && !IsGFX940Only)
7033 unsigned Opcode =
MI.getOpcode();
7035 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7036 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7037 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7038 case AMDGPU::V_MQSAD_U32_U8_e64:
7039 case AMDGPU::V_PK_ADD_F16:
7040 case AMDGPU::V_PK_ADD_F32:
7041 case AMDGPU::V_PK_ADD_I16:
7042 case AMDGPU::V_PK_ADD_U16:
7043 case AMDGPU::V_PK_ASHRREV_I16:
7044 case AMDGPU::V_PK_FMA_F16:
7045 case AMDGPU::V_PK_FMA_F32:
7046 case AMDGPU::V_PK_FMAC_F16_e32:
7047 case AMDGPU::V_PK_FMAC_F16_e64:
7048 case AMDGPU::V_PK_LSHLREV_B16:
7049 case AMDGPU::V_PK_LSHRREV_B16:
7050 case AMDGPU::V_PK_MAD_I16:
7051 case AMDGPU::V_PK_MAD_U16:
7052 case AMDGPU::V_PK_MAX_F16:
7053 case AMDGPU::V_PK_MAX_I16:
7054 case AMDGPU::V_PK_MAX_U16:
7055 case AMDGPU::V_PK_MIN_F16:
7056 case AMDGPU::V_PK_MIN_I16:
7057 case AMDGPU::V_PK_MIN_U16:
7058 case AMDGPU::V_PK_MOV_B32:
7059 case AMDGPU::V_PK_MUL_F16:
7060 case AMDGPU::V_PK_MUL_F32:
7061 case AMDGPU::V_PK_MUL_LO_U16:
7062 case AMDGPU::V_PK_SUB_I16:
7063 case AMDGPU::V_PK_SUB_U16:
7064 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7073 unsigned Opc =
MI.getOpcode();
7076 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
7079 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7085 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7086 RI.isSGPRReg(
MRI, Src0.getReg()))
7092 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7094 if (Src0.isReg() && RI.isVGPR(
MRI, Src0.getReg())) {
7095 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7098 Src0.ChangeToRegister(Reg,
false);
7100 if (Src1.isReg() && RI.isVGPR(
MRI, Src1.getReg())) {
7101 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7105 Src1.ChangeToRegister(Reg,
false);
7111 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7112 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7113 if (!RI.isVGPR(
MRI,
MI.getOperand(Src2Idx).getReg()))
7125 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7126 RI.isVGPR(
MRI, Src1.getReg())) {
7127 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7131 Src1.ChangeToRegister(Reg,
false);
7139 if (HasImplicitSGPR || !
MI.isCommutable()) {
7149 if ((!Src1.isImm() && !Src1.isReg()) ||
7156 if (CommutedOpc == -1) {
7161 MI.setDesc(
get(CommutedOpc));
7164 unsigned Src0SubReg = Src0.getSubReg();
7165 bool Src0Kill = Src0.isKill();
7168 Src0.ChangeToImmediate(Src1.getImm());
7169 else if (Src1.isReg()) {
7170 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7171 Src0.setSubReg(Src1.getSubReg());
7175 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7176 Src1.setSubReg(Src0SubReg);
7184 unsigned Opc =
MI.getOpcode();
7187 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7188 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7189 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7192 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7193 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7194 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7195 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7196 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7197 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7202 if (Src1.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src1.getReg()))) {
7203 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7206 Src1.ChangeToRegister(Reg,
false);
7208 if (VOP3Idx[2] != -1) {
7210 if (Src2.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src2.getReg()))) {
7211 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7214 Src2.ChangeToRegister(Reg,
false);
7220 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7221 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7223 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7225 SGPRsUsed.
insert(SGPRReg);
7229 for (
int Idx : VOP3Idx) {
7238 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7250 if (!RI.isSGPRClass(RI.getRegClassForReg(
MRI, MO.
getReg())))
7257 if (ConstantBusLimit > 0) {
7269 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7270 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7271 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7272 !RI.isVGPR(
MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7278 for (
unsigned I = 0;
I < 3; ++
I) {
7291 SRC = RI.getCommonSubClass(SRC, DstRC);
7294 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7296 if (RI.hasAGPRs(VRC)) {
7297 VRC = RI.getEquivalentVGPRClass(VRC);
7298 Register NewSrcReg =
MRI.createVirtualRegister(VRC);
7300 get(TargetOpcode::COPY), NewSrcReg)
7307 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7313 for (
unsigned i = 0; i < SubRegs; ++i) {
7314 Register SGPR =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7316 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7317 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7323 get(AMDGPU::REG_SEQUENCE), DstReg);
7324 for (
unsigned i = 0; i < SubRegs; ++i) {
7326 MIB.
addImm(RI.getSubRegFromChannel(i));
7339 if (SBase && !RI.isSGPRClass(
MRI.getRegClass(SBase->getReg()))) {
7341 SBase->setReg(SGPR);
7344 if (SOff && !RI.isSGPRReg(
MRI, SOff->
getReg())) {
7352 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7353 if (OldSAddrIdx < 0)
7369 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7370 if (NewVAddrIdx < 0)
7373 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7377 if (OldVAddrIdx >= 0) {
7379 VAddrDef =
MRI.getUniqueVRegDef(VAddr.
getReg());
7391 if (OldVAddrIdx == NewVAddrIdx) {
7394 MRI.removeRegOperandFromUseList(&NewVAddr);
7395 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7399 MRI.removeRegOperandFromUseList(&NewVAddr);
7400 MRI.addRegOperandToUseList(&NewVAddr);
7402 assert(OldSAddrIdx == NewVAddrIdx);
7404 if (OldVAddrIdx >= 0) {
7405 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7406 AMDGPU::OpName::vdst_in);
7410 if (NewVDstIn != -1) {
7411 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7417 if (NewVDstIn != -1) {
7418 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7439 if (!SAddr || RI.isSGPRClass(
MRI.getRegClass(SAddr->
getReg())))
7459 unsigned OpSubReg =
Op.getSubReg();
7462 RI.getRegClassForReg(
MRI, OpReg), OpSubReg);
7468 Register DstReg =
MRI.createVirtualRegister(DstRC);
7469 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7470 .
addReg(OpReg, {}, OpSubReg);
7472 Op.setSubReg(AMDGPU::NoSubRegister);
7479 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7482 bool ImpDef = Def->isImplicitDef();
7483 while (!ImpDef && Def && Def->isCopy()) {
7484 if (Def->getOperand(1).getReg().isPhysical())
7486 Def =
MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7487 ImpDef = Def && Def->isImplicitDef();
7489 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7505 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7510 bool UseNewExecInstructions =
7519 if (UseNewExecInstructions) {
7554 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7555 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(),
MRI);
7556 unsigned NumSubRegs =
RegSize / 32;
7557 Register VScalarOp = ScalarOp->getReg();
7560 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7562 if (NumSubRegs == 1) {
7565 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7566 Common != VScalarOpRC) {
7573 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7576 if (UseNewExecInstructions) {
7578 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7581 if (
I == LoopBB.
end())
7586 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7592 CondReg = NewCondReg;
7604 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7605 ScalarOp->setReg(CurReg);
7608 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7609 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7611 ScalarOp->setReg(PhySGPRs[Idx]);
7616 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7617 "Unhandled register size");
7619 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7626 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7627 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7630 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7631 .
addReg(VScalarOp, VScalarOpUndef,
7632 TRI->getSubRegFromChannel(Idx + 1));
7639 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7646 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7648 if (UseNewExecInstructions) {
7650 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7652 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7653 if (
I == LoopBB.
end())
7657 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7659 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7663 CondReg = NewCondReg;
7675 const auto *SScalarOpRC =
7681 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7682 unsigned Channel = 0;
7683 for (
Register Piece : ReadlanePieces) {
7684 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7688 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7689 ScalarOp->setReg(SScalarOp);
7691 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7692 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7694 ScalarOp->setReg(PhySGPRs[Idx]);
7702 if (!UseNewExecInstructions) {
7715 if (UseNewExecInstructions) {
7748 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7749 "Physical SGPRs must be empty or match the number of scalar operands");
7755 if (!Begin.isValid())
7757 if (!
End.isValid()) {
7763 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7772 std::numeric_limits<unsigned>::max()) !=
7790 for (
auto I = Begin;
I != AfterMI;
I++) {
7791 for (
auto &MO :
I->all_uses())
7827 for (
auto &Succ : RemainderBB->
successors()) {
7852static std::tuple<unsigned, unsigned>
7860 TII.buildExtractSubReg(
MI,
MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7861 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7864 Register Zero64 =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7865 Register SRsrcFormatLo =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7866 Register SRsrcFormatHi =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7867 Register NewSRsrc =
MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7868 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7885 .
addImm(AMDGPU::sub0_sub1)
7891 return std::tuple(RsrcPtr, NewSRsrc);
7902 if (ST.useRealTrue16Insts())
7932 if (
MI.getOpcode() == AMDGPU::PHI) {
7934 assert(!RI.isSGPRClass(VRC));
7937 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7939 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7955 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7958 if (RI.hasVGPRs(DstRC)) {
7962 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7964 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7981 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7986 if (DstRC != Src0RC) {
7995 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7997 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8003 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8004 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8005 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8006 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8007 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8008 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8009 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8011 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8024 ? AMDGPU::OpName::rsrc
8025 : AMDGPU::OpName::srsrc;
8027 if (SRsrc && !RI.isSGPRClass(
MRI.getRegClass(SRsrc->
getReg())))
8030 AMDGPU::OpName SampOpName =
8031 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8033 if (SSamp && !RI.isSGPRClass(
MRI.getRegClass(SSamp->
getReg())))
8040 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8042 if (!RI.isSGPRClass(
MRI.getRegClass(Dest->
getReg()))) {
8048 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8050 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8052 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
8056 Src0.ChangeToRegister(Reg,
false);
8062 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8063 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8064 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8065 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8067 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8074 bool isSoffsetLegal =
true;
8076 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
8077 if (SoffsetIdx != -1) {
8080 !RI.isSGPRClass(
MRI.getRegClass(Soffset->
getReg()))) {
8081 isSoffsetLegal =
false;
8085 bool isRsrcLegal =
true;
8087 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8088 if (RsrcIdx != -1) {
8091 isRsrcLegal =
false;
8095 if (isRsrcLegal && isSoffsetLegal)
8119 Register NewVAddrLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8120 Register NewVAddrHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8121 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8123 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8124 Register CondReg0 =
MRI.createVirtualRegister(BoolXExecRC);
8125 Register CondReg1 =
MRI.createVirtualRegister(BoolXExecRC);
8127 unsigned RsrcPtr, NewSRsrc;
8134 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8135 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8141 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8142 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8155 }
else if (!VAddr && ST.hasAddr64()) {
8159 "FIXME: Need to emit flat atomics here");
8161 unsigned RsrcPtr, NewSRsrc;
8164 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8187 MIB.
addImm(CPol->getImm());
8192 MIB.
addImm(TFE->getImm());
8212 MI.removeFromParent();
8217 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8218 .addImm(AMDGPU::sub0)
8219 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8220 .addImm(AMDGPU::sub1);
8223 if (!isSoffsetLegal) {
8234 if (!isSoffsetLegal) {
8243 if (InSet.insert(
MI).second)
8247 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8248 if (RsrcIdx != -1) {
8249 DeferredList.insert(
MI);
8254 return DeferredList.contains(
MI);
8264 if (!ST.useRealTrue16Insts())
8267 unsigned Opcode =
MI.getOpcode();
8270 if (OpIdx >=
MI.getNumExplicitOperands() ||
8271 OpIdx >=
get(Opcode).getNumOperands() ||
8272 get(Opcode).operands()[OpIdx].RegClass == -1)
8276 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8280 if (!RI.isVGPRClass(CurrRC))
8283 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8285 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8287 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8288 Op.setSubReg(AMDGPU::lo16);
8293 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8294 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8296 Register NewDstReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8304 Op.setReg(NewDstReg);
8305 Op.setSubReg(AMDGPU::NoSubRegister);
8310 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8318 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8319 "This only handle waterfall for SI_CALL_ISEL");
8326 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8329 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8334 while (
End !=
MBB.end() &&
End->isCopy() &&
8335 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8345 while (!Worklist.
empty()) {
8351 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8357 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8359 "Deferred MachineInstr are not supposed to re-populate worklist");
8362 for (
auto &Entry : WaterFalls) {
8363 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8365 Entry.second.SGPRs);
8368 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8370 Entry.first->eraseFromParent();
8378 if (SubRegIndices.
size() <= 1) {
8379 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8381 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8388 for (int16_t Indice : SubRegIndices) {
8389 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8391 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8398 get(AMDGPU::REG_SEQUENCE), DstReg);
8399 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8401 MIB.
addImm(RI.getSubRegFromChannel(i));
8411 if (DstReg == AMDGPU::M0) {
8424 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8426 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8427 if (
UseMI->getOperand(i).isReg() &&
8428 UseMI->getOperand(i).getReg() == DstReg) {
8432 V2SCopyInfo.MOs.push_back(MO);
8433 V2SCopyInfo.SGPRs.push_back(DstReg);
8437 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8438 I->getOperand(0).isReg() &&
8439 I->getOperand(0).getReg() == DstReg) {
8442 }
else if (
I->readsRegister(DstReg, &RI)) {
8444 V2SPhyCopiesToErase[&Inst] =
false;
8446 if (
I->findRegisterDefOperand(DstReg, &RI))
8468 case AMDGPU::S_ADD_I32:
8469 case AMDGPU::S_SUB_I32: {
8473 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8481 case AMDGPU::S_MUL_U64:
8482 if (ST.useVMulU64Inst()) {
8483 NewOpcode = AMDGPU::V_MUL_U64_e64;
8487 splitScalarSMulU64(Worklist, Inst, MDT);
8491 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8492 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8495 splitScalarSMulPseudo(Worklist, Inst, MDT);
8499 case AMDGPU::S_AND_B64:
8500 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8504 case AMDGPU::S_OR_B64:
8505 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8509 case AMDGPU::S_XOR_B64:
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8514 case AMDGPU::S_NAND_B64:
8515 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8519 case AMDGPU::S_NOR_B64:
8520 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8524 case AMDGPU::S_XNOR_B64:
8525 if (ST.hasDLInsts())
8526 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8528 splitScalar64BitXnor(Worklist, Inst, MDT);
8532 case AMDGPU::S_ANDN2_B64:
8533 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8537 case AMDGPU::S_ORN2_B64:
8538 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8542 case AMDGPU::S_BREV_B64:
8543 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8547 case AMDGPU::S_NOT_B64:
8548 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8552 case AMDGPU::S_BCNT1_I32_B64:
8553 splitScalar64BitBCNT(Worklist, Inst);
8557 case AMDGPU::S_BFE_I64:
8558 splitScalar64BitBFE(Worklist, Inst);
8562 case AMDGPU::S_FLBIT_I32_B64:
8563 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8566 case AMDGPU::S_FF1_I32_B64:
8567 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8571 case AMDGPU::S_LSHL_B32:
8572 if (ST.hasOnlyRevVALUShifts()) {
8573 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8577 case AMDGPU::S_ASHR_I32:
8578 if (ST.hasOnlyRevVALUShifts()) {
8579 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8583 case AMDGPU::S_LSHR_B32:
8584 if (ST.hasOnlyRevVALUShifts()) {
8585 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8589 case AMDGPU::S_LSHL_B64:
8590 if (ST.hasOnlyRevVALUShifts()) {
8592 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8593 : AMDGPU::V_LSHLREV_B64_e64;
8597 case AMDGPU::S_ASHR_I64:
8598 if (ST.hasOnlyRevVALUShifts()) {
8599 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8603 case AMDGPU::S_LSHR_B64:
8604 if (ST.hasOnlyRevVALUShifts()) {
8605 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8610 case AMDGPU::S_ABS_I32:
8611 lowerScalarAbs(Worklist, Inst);
8615 case AMDGPU::S_ABSDIFF_I32:
8616 lowerScalarAbsDiff(Worklist, Inst);
8620 case AMDGPU::S_CBRANCH_SCC0:
8621 case AMDGPU::S_CBRANCH_SCC1: {
8624 bool IsSCC = CondReg == AMDGPU::SCC;
8633 case AMDGPU::S_BFE_U64:
8634 case AMDGPU::S_BFM_B64:
8637 case AMDGPU::S_PACK_LL_B32_B16:
8638 case AMDGPU::S_PACK_LH_B32_B16:
8639 case AMDGPU::S_PACK_HL_B32_B16:
8640 case AMDGPU::S_PACK_HH_B32_B16:
8641 movePackToVALU(Worklist,
MRI, Inst);
8645 case AMDGPU::S_XNOR_B32:
8646 lowerScalarXnor(Worklist, Inst);
8650 case AMDGPU::S_NAND_B32:
8651 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8655 case AMDGPU::S_NOR_B32:
8656 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8660 case AMDGPU::S_ANDN2_B32:
8661 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8665 case AMDGPU::S_ORN2_B32:
8666 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8674 case AMDGPU::S_ADD_CO_PSEUDO:
8675 case AMDGPU::S_SUB_CO_PSEUDO: {
8676 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8677 ? AMDGPU::V_ADDC_U32_e64
8678 : AMDGPU::V_SUBB_U32_e64;
8679 const auto *CarryRC = RI.getWaveMaskRegClass();
8682 if (!
MRI.constrainRegClass(CarryInReg, CarryRC)) {
8683 Register NewCarryReg =
MRI.createVirtualRegister(CarryRC);
8690 Register DestReg =
MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8701 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8705 case AMDGPU::S_UADDO_PSEUDO:
8706 case AMDGPU::S_USUBO_PSEUDO: {
8712 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8713 ? AMDGPU::V_ADD_CO_U32_e64
8714 : AMDGPU::V_SUB_CO_U32_e64;
8716 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest0.
getReg()));
8717 Register DestReg =
MRI.createVirtualRegister(NewRC);
8725 MRI.replaceRegWith(Dest0.
getReg(), DestReg);
8726 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8730 case AMDGPU::S_LSHL1_ADD_U32:
8731 case AMDGPU::S_LSHL2_ADD_U32:
8732 case AMDGPU::S_LSHL3_ADD_U32:
8733 case AMDGPU::S_LSHL4_ADD_U32: {
8737 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8738 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8739 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8743 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest.
getReg()));
8744 Register DestReg =
MRI.createVirtualRegister(NewRC);
8752 MRI.replaceRegWith(Dest.
getReg(), DestReg);
8753 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8757 case AMDGPU::S_CSELECT_B32:
8758 case AMDGPU::S_CSELECT_B64:
8759 lowerSelect(Worklist, Inst, MDT);
8762 case AMDGPU::S_CMP_EQ_I32:
8763 case AMDGPU::S_CMP_LG_I32:
8764 case AMDGPU::S_CMP_GT_I32:
8765 case AMDGPU::S_CMP_GE_I32:
8766 case AMDGPU::S_CMP_LT_I32:
8767 case AMDGPU::S_CMP_LE_I32:
8768 case AMDGPU::S_CMP_EQ_U32:
8769 case AMDGPU::S_CMP_LG_U32:
8770 case AMDGPU::S_CMP_GT_U32:
8771 case AMDGPU::S_CMP_GE_U32:
8772 case AMDGPU::S_CMP_LT_U32:
8773 case AMDGPU::S_CMP_LE_U32:
8774 case AMDGPU::S_CMP_EQ_U64:
8775 case AMDGPU::S_CMP_LG_U64:
8776 case AMDGPU::S_CMP_LT_F32:
8777 case AMDGPU::S_CMP_EQ_F32:
8778 case AMDGPU::S_CMP_LE_F32:
8779 case AMDGPU::S_CMP_GT_F32:
8780 case AMDGPU::S_CMP_LG_F32:
8781 case AMDGPU::S_CMP_GE_F32:
8782 case AMDGPU::S_CMP_O_F32:
8783 case AMDGPU::S_CMP_U_F32:
8784 case AMDGPU::S_CMP_NGE_F32:
8785 case AMDGPU::S_CMP_NLG_F32:
8786 case AMDGPU::S_CMP_NGT_F32:
8787 case AMDGPU::S_CMP_NLE_F32:
8788 case AMDGPU::S_CMP_NEQ_F32:
8789 case AMDGPU::S_CMP_NLT_F32: {
8790 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8794 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8808 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8812 case AMDGPU::S_CMP_LT_F16:
8813 case AMDGPU::S_CMP_EQ_F16:
8814 case AMDGPU::S_CMP_LE_F16:
8815 case AMDGPU::S_CMP_GT_F16:
8816 case AMDGPU::S_CMP_LG_F16:
8817 case AMDGPU::S_CMP_GE_F16:
8818 case AMDGPU::S_CMP_O_F16:
8819 case AMDGPU::S_CMP_U_F16:
8820 case AMDGPU::S_CMP_NGE_F16:
8821 case AMDGPU::S_CMP_NLG_F16:
8822 case AMDGPU::S_CMP_NGT_F16:
8823 case AMDGPU::S_CMP_NLE_F16:
8824 case AMDGPU::S_CMP_NEQ_F16:
8825 case AMDGPU::S_CMP_NLT_F16: {
8826 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8847 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8851 case AMDGPU::S_CVT_HI_F32_F16: {
8852 Register TmpReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8853 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8854 if (ST.useRealTrue16Insts()) {
8859 .
addReg(TmpReg, {}, AMDGPU::hi16)
8875 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8879 case AMDGPU::S_MINIMUM_F32:
8880 case AMDGPU::S_MAXIMUM_F32: {
8881 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8892 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8896 case AMDGPU::S_MINIMUM_F16:
8897 case AMDGPU::S_MAXIMUM_F16: {
8898 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8899 ? &AMDGPU::VGPR_16RegClass
8900 : &AMDGPU::VGPR_32RegClass);
8911 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8915 case AMDGPU::V_S_EXP_F16_e64:
8916 case AMDGPU::V_S_LOG_F16_e64:
8917 case AMDGPU::V_S_RCP_F16_e64:
8918 case AMDGPU::V_S_RSQ_F16_e64:
8919 case AMDGPU::V_S_SQRT_F16_e64: {
8920 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8921 ? &AMDGPU::VGPR_16RegClass
8922 : &AMDGPU::VGPR_32RegClass);
8933 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8939 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8947 if (NewOpcode == Opcode) {
8954 V2SPhyCopiesToErase);
8962 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8969 addUsersToMoveToVALUWorklist(DstReg,
MRI, Worklist);
8975 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8976 UseMO.setReg(NewDstReg);
8980 MRI.clearKillFlags(NewDstReg);
8982 if (!
MRI.constrainRegClass(NewDstReg, CommonRC))
8995 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8998 MRI.constrainRegClass(NewDstReg, OpRC);
9008 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
9012 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9013 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9018 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9024 MRI.replaceRegWith(DstReg, NewDstReg);
9025 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9027 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9030 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9031 MRI.replaceRegWith(DstReg, NewDstReg);
9032 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9037 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9038 MRI.replaceRegWith(DstReg, NewDstReg);
9040 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9050 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9051 AMDGPU::OpName::src0_modifiers) >= 0)
9055 NewInstr->addOperand(Src);
9058 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9061 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9063 NewInstr.addImm(
Size);
9064 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9068 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9073 "Scalar BFE is only implemented for constant width and offset");
9081 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9082 AMDGPU::OpName::src1_modifiers) >= 0)
9084 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9087 AMDGPU::OpName::src2_modifiers) >= 0)
9089 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9091 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9093 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9095 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9101 NewInstr->addOperand(
Op);
9107 bool DeadSCCDef =
false;
9109 if (
Op.getReg() == AMDGPU::SCC) {
9115 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9119 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9124 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9125 Register DstReg = NewInstr->getOperand(0).getReg();
9130 NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9131 MRI.replaceRegWith(DstReg, NewDstReg);
9139 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9140 VCCDef->setIsDead();
9146 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9150std::pair<bool, MachineBasicBlock *>
9153 if (ST.hasAddNoCarryInsts()) {
9162 Register ResultReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9165 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9167 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9168 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9176 MRI.replaceRegWith(OldDstReg, ResultReg);
9179 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9180 return std::pair(
true, NewBB);
9183 return std::pair(
false,
nullptr);
9200 bool IsSCC = (CondReg == AMDGPU::SCC);
9206 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9207 (
Src1.getImm() == 0)) {
9208 for (MachineOperand &UseMO :
9210 MachineInstr &
UseMI = *UseMO.getParent();
9211 switch (
UseMI.getOpcode()) {
9212 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9213 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9214 case AMDGPU::V_CNDMASK_B16_t16_e32:
9215 case AMDGPU::V_CNDMASK_B16_t16_e64:
9216 case AMDGPU::V_CNDMASK_B32_e32:
9217 case AMDGPU::V_CNDMASK_B32_e64:
9218 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9219 if (UseMO.isImplicit() ||
9221 UseMO.setReg(CondReg);
9235 bool CopyFound =
false;
9236 for (MachineInstr &CandI :
9239 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9241 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9243 .
addReg(CandI.getOperand(1).getReg());
9255 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9264 MachineInstr *NewInst;
9265 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9266 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9281 addUsersToMoveToVALUWorklist(NewDestReg,
MRI, Worklist);
9296 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9298 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9300 MachineInstrBuilder
Sub =
9310 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9327 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9329 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9331 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9335 MachineInstrBuilder Sub2 =
9348 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9362 if (ST.hasDLInsts()) {
9372 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9378 bool Src0IsSGPR =
Src0.isReg() &&
9380 bool Src1IsSGPR =
Src1.isReg() &&
9394 }
else if (Src1IsSGPR) {
9412 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9418 unsigned Opcode)
const {
9442 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9447 unsigned Opcode)
const {
9471 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9486 const MCInstrDesc &InstDesc =
get(Opcode);
9489 &AMDGPU::SGPR_32RegClass;
9492 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9495 AMDGPU::sub0, Src0SubRC);
9500 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9503 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9506 AMDGPU::sub1, Src0SubRC);
9509 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9523 Worklist.
insert(&LoHalf);
9524 Worklist.
insert(&HiHalf);
9530 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9554 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9555 if (RI.isSGPRClass(Src0SubRC))
9556 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9558 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9559 if (RI.isSGPRClass(Src1SubRC))
9560 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9564 MachineOperand Op0L =
9566 MachineOperand Op1L =
9568 MachineOperand Op0H =
9570 MachineOperand Op1H =
9589 MachineInstr *Op1L_Op0H =
9595 MachineInstr *Op1H_Op0L =
9601 MachineInstr *Carry =
9606 MachineInstr *LoHalf =
9616 MachineInstr *HiHalf =
9639 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9663 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9664 if (RI.isSGPRClass(Src0SubRC))
9665 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9667 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9668 if (RI.isSGPRClass(Src1SubRC))
9669 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9673 MachineOperand Op0L =
9675 MachineOperand Op1L =
9679 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9680 ? AMDGPU::V_MUL_HI_U32_e64
9681 : AMDGPU::V_MUL_HI_I32_e64;
9682 MachineInstr *HiHalf =
9685 MachineInstr *LoHalf =
9704 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9720 const MCInstrDesc &InstDesc =
get(Opcode);
9723 &AMDGPU::SGPR_32RegClass;
9726 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9729 &AMDGPU::SGPR_32RegClass;
9732 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9735 AMDGPU::sub0, Src0SubRC);
9737 AMDGPU::sub0, Src1SubRC);
9739 AMDGPU::sub1, Src0SubRC);
9741 AMDGPU::sub1, Src1SubRC);
9746 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9749 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9754 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9767 Worklist.
insert(&LoHalf);
9768 Worklist.
insert(&HiHalf);
9771 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9791 MachineOperand* Op0;
9792 MachineOperand* Op1;
9794 if (
Src0.isReg() && RI.isSGPRReg(
MRI,
Src0.getReg())) {
9827 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9830 &AMDGPU::SGPR_32RegClass;
9836 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9839 AMDGPU::sub0, SrcSubRC);
9841 AMDGPU::sub1, SrcSubRC);
9851 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9870 Offset == 0 &&
"Not implemented");
9893 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9903 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9906 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9912 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9931 const MCInstrDesc &InstDesc =
get(Opcode);
9933 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9936 Src.isReg() ?
MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9938 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9940 MachineOperand SrcRegSub0 =
9942 MachineOperand SrcRegSub1 =
9956 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9960 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9964 addUsersToMoveToVALUWorklist(MidReg4,
MRI, Worklist);
9967void SIInstrInfo::addUsersToMoveToVALUWorklist(
9971 MachineInstr &
UseMI = *MO.getParent();
9975 switch (
UseMI.getOpcode()) {
9978 case AMDGPU::SOFT_WQM:
9979 case AMDGPU::STRICT_WWM:
9980 case AMDGPU::STRICT_WQM:
9981 case AMDGPU::REG_SEQUENCE:
9983 case AMDGPU::INSERT_SUBREG:
9986 OpNo = MO.getOperandNo();
9993 if (!RI.hasVectorRegisters(OpRC))
10010 if (ST.useRealTrue16Insts()) {
10012 if (!
Src0.isReg() || !RI.isVGPR(
MRI,
Src0.getReg())) {
10015 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10018 SrcReg0 =
Src0.getReg();
10021 if (!
Src1.isReg() || !RI.isVGPR(
MRI,
Src1.getReg())) {
10024 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10027 SrcReg1 =
Src1.getReg();
10033 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
10035 case AMDGPU::S_PACK_LL_B32_B16:
10037 .addReg(SrcReg0, {},
10038 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10039 .addImm(AMDGPU::lo16)
10040 .addReg(SrcReg1, {},
10041 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10042 .addImm(AMDGPU::hi16);
10044 case AMDGPU::S_PACK_LH_B32_B16:
10046 .addReg(SrcReg0, {},
10047 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::lo16)
10049 .addReg(SrcReg1, {}, AMDGPU::hi16)
10050 .addImm(AMDGPU::hi16);
10052 case AMDGPU::S_PACK_HL_B32_B16:
10053 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10054 .addImm(AMDGPU::lo16)
10055 .addReg(SrcReg1, {},
10056 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10057 .addImm(AMDGPU::hi16);
10059 case AMDGPU::S_PACK_HH_B32_B16:
10060 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10061 .addImm(AMDGPU::lo16)
10062 .addReg(SrcReg1, {}, AMDGPU::hi16)
10063 .addImm(AMDGPU::hi16);
10071 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10076 case AMDGPU::S_PACK_LL_B32_B16: {
10095 case AMDGPU::S_PACK_LH_B32_B16: {
10105 case AMDGPU::S_PACK_HL_B32_B16: {
10116 case AMDGPU::S_PACK_HH_B32_B16: {
10136 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10145 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10146 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10147 SmallVector<MachineInstr *, 4> CopyToDelete;
10150 for (MachineInstr &
MI :
10154 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10155 if (SCCIdx != -1) {
10158 Register DestReg =
MI.getOperand(0).getReg();
10165 MI.getOperand(SCCIdx).setReg(NewCond);
10171 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10174 for (
auto &Copy : CopyToDelete)
10175 Copy->eraseFromParent();
10183void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10189 for (MachineInstr &
MI :
10192 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10194 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10211 case AMDGPU::REG_SEQUENCE:
10212 case AMDGPU::INSERT_SUBREG:
10214 case AMDGPU::SOFT_WQM:
10215 case AMDGPU::STRICT_WWM:
10216 case AMDGPU::STRICT_WQM: {
10218 if (RI.isAGPRClass(SrcRC)) {
10219 if (RI.isAGPRClass(NewDstRC))
10224 case AMDGPU::REG_SEQUENCE:
10225 case AMDGPU::INSERT_SUBREG:
10226 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10229 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10235 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10238 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10252 int OpIndices[3])
const {
10253 const MCInstrDesc &
Desc =
MI.getDesc();
10271 for (
unsigned i = 0; i < 3; ++i) {
10272 int Idx = OpIndices[i];
10276 const MachineOperand &MO =
MI.getOperand(Idx);
10283 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10284 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10285 if (IsRequiredSGPR)
10291 if (RI.isSGPRClass(RegRC))
10292 UsedSGPRs[i] =
Reg;
10308 if (UsedSGPRs[0]) {
10309 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10310 SGPRReg = UsedSGPRs[0];
10313 if (!SGPRReg && UsedSGPRs[1]) {
10314 if (UsedSGPRs[1] == UsedSGPRs[2])
10315 SGPRReg = UsedSGPRs[1];
10322 AMDGPU::OpName OperandName)
const {
10323 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10326 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10330 return &
MI.getOperand(Idx);
10344 if (ST.isAmdHsaOS()) {
10347 RsrcDataFormat |= (1ULL << 56);
10352 RsrcDataFormat |= (2ULL << 59);
10355 return RsrcDataFormat;
10365 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10370 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10377 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10383 unsigned Opc =
MI.getOpcode();
10389 return get(
Opc).mayLoad() &&
10396 if (!Addr || !Addr->
isFI())
10405 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10407 return MI.getOperand(VDataIdx).getReg();
10417 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10419 return MI.getOperand(DataIdx).getReg();
10440 if (!
MI.mayStore())
10453 unsigned Opc =
MI.getOpcode();
10455 unsigned DescSize =
Desc.getSize();
10460 unsigned Size = DescSize;
10464 if (
MI.isBranch() && ST.hasOffset3fBug())
10475 bool HasLiteral =
false;
10476 unsigned LiteralSize = 4;
10477 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10482 if (ST.has64BitLiterals()) {
10483 switch (OpInfo.OperandType) {
10508 return HasLiteral ? DescSize + LiteralSize : DescSize;
10513 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10517 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10518 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10522 case TargetOpcode::BUNDLE:
10523 return getInstBundleSize(
MI);
10524 case TargetOpcode::INLINEASM:
10525 case TargetOpcode::INLINEASM_BR: {
10527 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10531 if (
MI.isMetaInstruction())
10535 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10538 unsigned LoInstOpcode = D16Info->LoOp;
10540 DescSize =
Desc.getSize();
10544 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10547 DescSize =
Desc.getSize();
10556 if (
MI.isBranch() && ST.hasOffset3fBug())
10557 return InstSizeVerifyMode::NoVerify;
10558 return InstSizeVerifyMode::ExactSize;
10563 static const std::pair<int, const char *> TargetIndices[] = {
10603std::pair<unsigned, unsigned>
10610 static const std::pair<unsigned, const char *> TargetFlags[] = {
10628 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10646 return AMDGPU::WWM_COPY;
10648 return AMDGPU::COPY;
10665 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10669 if (RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg)))
10670 return IsLRSplitInst;
10683 bool IsNullOrVectorRegister =
true;
10687 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg));
10690 return IsNullOrVectorRegister &&
10692 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10693 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10701 if (ST.hasAddNoCarryInsts())
10705 Register UnusedCarry =
MRI.createVirtualRegister(RI.getBoolRC());
10706 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10717 if (ST.hasAddNoCarryInsts())
10721 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10723 : RS.scavengeRegisterBackwards(
10724 *RI.getBoolRC(),
I,
false,
10737 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10738 case AMDGPU::SI_KILL_I1_TERMINATOR:
10747 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10748 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10749 case AMDGPU::SI_KILL_I1_PSEUDO:
10750 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10762 const unsigned OffsetBits =
10764 return (1 << OffsetBits) - 1;
10768 if (!ST.isWave32())
10771 if (
MI.isInlineAsm())
10774 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10777 for (
auto &
Op :
MI.implicit_operands()) {
10778 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10779 Op.setReg(AMDGPU::VCC_LO);
10788 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10792 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10793 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10809 if (
Imm > MaxImm) {
10810 if (
Imm <= MaxImm + 64) {
10812 Overflow =
Imm - MaxImm;
10827 Overflow =
High - Alignment.value();
10831 if (Overflow > 0) {
10839 if (ST.hasRestrictedSOffset())
10844 SOffset = Overflow;
10882 if (!ST.hasFlatInstOffsets())
10886 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10891 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10892 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10903std::pair<int64_t, int64_t>
10906 int64_t RemainderOffset = COffsetVal;
10907 int64_t ImmField = 0;
10912 if (AllowNegative) {
10914 int64_t
D = 1LL << NumBits;
10915 RemainderOffset = (COffsetVal /
D) *
D;
10916 ImmField = COffsetVal - RemainderOffset;
10918 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10920 (ImmField % 4) != 0) {
10922 RemainderOffset += ImmField % 4;
10923 ImmField -= ImmField % 4;
10925 }
else if (COffsetVal >= 0) {
10927 RemainderOffset = COffsetVal - ImmField;
10931 assert(RemainderOffset + ImmField == COffsetVal);
10932 return {ImmField, RemainderOffset};
10937 if (ST.hasNegativeScratchOffsetBug() &&
10945 switch (ST.getGeneration()) {
10979 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10980 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10981 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10982 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10983 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10984 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10985 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10986 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10993#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10994 case OPCODE##_dpp: \
10995 case OPCODE##_e32: \
11009 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11010 case AMDGPU::V_FMA_F16_gfx9_e64:
11011 case AMDGPU::V_INTERP_P2_F16:
11012 case AMDGPU::V_MAD_F16_e64:
11013 case AMDGPU::V_MAD_U16_e64:
11014 case AMDGPU::V_MAD_I16_e64:
11015 case AMDGPU::V_MAD_U16_gfx9_e64:
11016 case AMDGPU::V_MAD_I16_gfx9_e64:
11025 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11033 switch (ST.getGeneration()) {
11046 if (
isMAI(Opcode)) {
11060 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11063 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11070 if (ST.hasGFX90AInsts()) {
11071 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11072 if (ST.hasGFX940Insts())
11074 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11076 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11078 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11084 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11103 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11104 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11105 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11117 switch (
MI.getOpcode()) {
11119 case AMDGPU::REG_SEQUENCE:
11123 case AMDGPU::INSERT_SUBREG:
11124 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11141 if (!
P.Reg.isVirtual())
11145 auto *DefInst =
MRI.getVRegDef(RSR.Reg);
11146 while (
auto *
MI = DefInst) {
11148 switch (
MI->getOpcode()) {
11150 case AMDGPU::V_MOV_B32_e32: {
11151 auto &Op1 =
MI->getOperand(1);
11156 DefInst =
MRI.getVRegDef(RSR.Reg);
11164 DefInst =
MRI.getVRegDef(RSR.Reg);
11177 assert(
MRI.isSSA() &&
"Must be run on SSA");
11179 auto *
TRI =
MRI.getTargetRegisterInfo();
11180 auto *DefBB =
DefMI.getParent();
11184 if (
UseMI.getParent() != DefBB)
11187 const int MaxInstScan = 20;
11191 auto E =
UseMI.getIterator();
11192 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11193 if (
I->isDebugInstr())
11196 if (++NumInst > MaxInstScan)
11199 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11209 assert(
MRI.isSSA() &&
"Must be run on SSA");
11211 auto *
TRI =
MRI.getTargetRegisterInfo();
11212 auto *DefBB =
DefMI.getParent();
11214 const int MaxUseScan = 10;
11217 for (
auto &
Use :
MRI.use_nodbg_operands(VReg)) {
11218 auto &UseInst = *
Use.getParent();
11221 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11224 if (++NumUse > MaxUseScan)
11231 const int MaxInstScan = 20;
11235 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11238 if (
I->isDebugInstr())
11241 if (++NumInst > MaxInstScan)
11254 if (Reg == VReg && --NumUse == 0)
11256 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11265 auto Cur =
MBB.begin();
11266 if (Cur !=
MBB.end())
11268 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11271 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11280 if (InsPt !=
MBB.end() &&
11281 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11282 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11283 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11284 InsPt->definesRegister(Src,
nullptr)) {
11288 .
addReg(Src, {}, SrcSubReg)
11331 if (isFullCopyInstr(
MI)) {
11332 Register DstReg =
MI.getOperand(0).getReg();
11333 Register SrcReg =
MI.getOperand(1).getReg();
11340 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11344 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11355 unsigned *PredCost)
const {
11356 if (
MI.isBundle()) {
11359 unsigned Lat = 0,
Count = 0;
11360 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11362 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11364 return Lat +
Count - 1;
11367 return SchedModel.computeInstrLatency(&
MI);
11371 if (!ST.hasGFX1250VALUBlockingCycles())
11378 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11379 return Entry->GFX1250BlockingCycles;
11387 return *CallAddrOp;
11394 unsigned Opcode =
MI.getOpcode();
11399 LLT DstTy =
MRI.getType(Dst);
11400 LLT SrcTy =
MRI.getType(Src);
11402 unsigned SrcAS = SrcTy.getAddressSpace();
11405 ST.hasGloballyAddressableScratch()
11413 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11414 return HandleAddrSpaceCast(
MI);
11417 auto IID = GI->getIntrinsicID();
11424 case Intrinsic::amdgcn_if:
11425 case Intrinsic::amdgcn_else:
11439 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11440 Opcode == AMDGPU::G_SEXTLOAD) {
11441 if (
MI.memoperands_empty())
11445 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11446 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11454 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11455 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11456 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11462 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11465 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11473 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11474 return Formatter.get();
11482 unsigned opcode =
MI.getOpcode();
11483 if (opcode == AMDGPU::V_READLANE_B32 ||
11484 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11485 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11490 if (
MI.isInlineAsm()) {
11496 if (!RC || !RI.isSGPRClass(RC))
11501 if (isCopyInstr(
MI)) {
11505 RI.getPhysRegBaseClass(srcOp.
getReg());
11513 if (
MI.isPreISelOpcode())
11528 if (
MI.memoperands_empty())
11532 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11533 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11548 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11550 if (!
SrcOp.isReg())
11554 if (!Reg || !
SrcOp.readsReg())
11560 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11587 F,
"ds_ordered_count unsupported for this calling conv"));
11601 Register &SrcReg2, int64_t &CmpMask,
11602 int64_t &CmpValue)
const {
11603 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11606 switch (
MI.getOpcode()) {
11609 case AMDGPU::S_CMP_EQ_U32:
11610 case AMDGPU::S_CMP_EQ_I32:
11611 case AMDGPU::S_CMP_LG_U32:
11612 case AMDGPU::S_CMP_LG_I32:
11613 case AMDGPU::S_CMP_LT_U32:
11614 case AMDGPU::S_CMP_LT_I32:
11615 case AMDGPU::S_CMP_GT_U32:
11616 case AMDGPU::S_CMP_GT_I32:
11617 case AMDGPU::S_CMP_LE_U32:
11618 case AMDGPU::S_CMP_LE_I32:
11619 case AMDGPU::S_CMP_GE_U32:
11620 case AMDGPU::S_CMP_GE_I32:
11621 case AMDGPU::S_CMP_EQ_U64:
11622 case AMDGPU::S_CMP_LG_U64:
11623 SrcReg =
MI.getOperand(0).getReg();
11624 if (
MI.getOperand(1).isReg()) {
11625 if (
MI.getOperand(1).getSubReg())
11627 SrcReg2 =
MI.getOperand(1).getReg();
11629 }
else if (
MI.getOperand(1).isImm()) {
11631 CmpValue =
MI.getOperand(1).getImm();
11637 case AMDGPU::S_CMPK_EQ_U32:
11638 case AMDGPU::S_CMPK_EQ_I32:
11639 case AMDGPU::S_CMPK_LG_U32:
11640 case AMDGPU::S_CMPK_LG_I32:
11641 case AMDGPU::S_CMPK_LT_U32:
11642 case AMDGPU::S_CMPK_LT_I32:
11643 case AMDGPU::S_CMPK_GT_U32:
11644 case AMDGPU::S_CMPK_GT_I32:
11645 case AMDGPU::S_CMPK_LE_U32:
11646 case AMDGPU::S_CMPK_LE_I32:
11647 case AMDGPU::S_CMPK_GE_U32:
11648 case AMDGPU::S_CMPK_GE_I32:
11649 SrcReg =
MI.getOperand(0).getReg();
11651 CmpValue =
MI.getOperand(1).getImm();
11661 if (S->isLiveIn(AMDGPU::SCC))
11670bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11673 bool SCCIsDead =
false;
11676 constexpr unsigned ScanLimit = 12;
11677 unsigned Count = 0;
11680 if (++
Count > ScanLimit)
11682 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11683 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11684 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11685 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11686 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11691 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11704 for (MachineInstr *
MI : InvertInstr) {
11705 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11706 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11708 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11709 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11710 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11711 ? AMDGPU::S_CBRANCH_SCC1
11712 : AMDGPU::S_CBRANCH_SCC0));
11725 bool NeedInversion)
const {
11726 MachineInstr *KillsSCC =
nullptr;
11731 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11733 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11736 if (NeedInversion && !invertSCCUse(SCCRedefine))
11738 if (MachineOperand *SccDef =
11740 SccDef->setIsDead(
false);
11749static std::optional<std::pair<int64_t, int64_t>>
11753 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11755 std::optional<int64_t>
A =
11759 std::optional<int64_t>
B =
11763 if (
Opc == AMDGPU::S_CSELECT_B32) {
11769 return std::pair(*
A, *
B);
11773 unsigned &NewDefOpc) {
11776 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11777 Def.getOpcode() != AMDGPU::S_ADD_U32)
11783 Def.getMF()->getSubtarget().getInstrInfo());
11785 auto Imm1 =
TII->getImmOrMaterializedImm(
MRI, AddSrc1);
11786 auto Imm2 =
TII->getImmOrMaterializedImm(
MRI, AddSrc2);
11787 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11790 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11792 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11795 NewDefOpc = AMDGPU::S_ADD_U32;
11797 NeedInversion = !NeedInversion;
11802 Register SrcReg2, int64_t CmpMask,
11812 CmpValue = *ImmOpt;
11815 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue,
MRI,
11816 this](
bool NeedInversion) ->
bool {
11821 unsigned NewDefOpc = Def->getOpcode();
11828 auto [
A,
B] = *Consts;
11829 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11832 NeedInversion = !NeedInversion;
11844 if (CmpValue != 0 ||
11850 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11853 if (NewDefOpc != Def->getOpcode())
11854 Def->setDesc(
get(NewDefOpc));
11863 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11864 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11870 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11879 auto [
A,
B] = *Consts;
11880 if (
A == 0 ||
B == 0)
11881 optimizeSCC(
Select, Def,
A == 0);
11890 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue,
MRI,
11891 this](int64_t ExpectedValue,
unsigned SrcSize,
11892 bool IsReversible,
bool IsSigned) ->
bool {
11920 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11921 Def->getOpcode() != AMDGPU::S_AND_B64)
11925 const auto isMask = [&Mask, SrcSize,
MRI,
11937 SrcOp = &Def->getOperand(2);
11938 else if (isMask(&Def->getOperand(2)))
11939 SrcOp = &Def->getOperand(1);
11947 if (IsSigned && BitNo == SrcSize - 1)
11950 ExpectedValue <<= BitNo;
11952 bool IsReversedCC =
false;
11953 if (CmpValue != ExpectedValue) {
11956 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11961 Register DefReg = Def->getOperand(0).getReg();
11962 if (IsReversedCC && !
MRI->hasOneNonDBGUse(DefReg))
11965 if (!optimizeSCC(Def, &CmpInstr,
false))
11968 if (!
MRI->use_nodbg_empty(DefReg)) {
11976 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11977 : AMDGPU::S_BITCMP1_B32
11978 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11979 : AMDGPU::S_BITCMP1_B64;
11984 Def->eraseFromParent();
11992 case AMDGPU::S_CMP_EQ_U32:
11993 case AMDGPU::S_CMP_EQ_I32:
11994 case AMDGPU::S_CMPK_EQ_U32:
11995 case AMDGPU::S_CMPK_EQ_I32:
11996 return optimizeCmpAnd(1, 32,
true,
false) ||
11997 optimizeCmpSelect(
true);
11998 case AMDGPU::S_CMP_GE_U32:
11999 case AMDGPU::S_CMPK_GE_U32:
12000 return optimizeCmpAnd(1, 32,
false,
false);
12001 case AMDGPU::S_CMP_GE_I32:
12002 case AMDGPU::S_CMPK_GE_I32:
12003 return optimizeCmpAnd(1, 32,
false,
true);
12004 case AMDGPU::S_CMP_EQ_U64:
12005 return optimizeCmpAnd(1, 64,
true,
false) ||
12006 optimizeCmpSelect(
true);
12007 case AMDGPU::S_CMP_LG_U32:
12008 case AMDGPU::S_CMP_LG_I32:
12009 case AMDGPU::S_CMPK_LG_U32:
12010 case AMDGPU::S_CMPK_LG_I32:
12011 return optimizeCmpAnd(0, 32,
true,
false) ||
12012 optimizeCmpSelect(
false);
12013 case AMDGPU::S_CMP_GT_U32:
12014 case AMDGPU::S_CMPK_GT_U32:
12015 return optimizeCmpAnd(0, 32,
false,
false);
12016 case AMDGPU::S_CMP_GT_I32:
12017 case AMDGPU::S_CMPK_GT_I32:
12018 return optimizeCmpAnd(0, 32,
false,
true);
12019 case AMDGPU::S_CMP_LG_U64:
12020 return optimizeCmpAnd(0, 64,
true,
false) ||
12021 optimizeCmpSelect(
false);
12028 AMDGPU::OpName
OpName)
const {
12029 if (!ST.needsAlignedVGPRs())
12032 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
12044 bool IsAGPR = RI.isAGPR(
MRI, DataReg);
12046 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12049 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12050 : &AMDGPU::VReg_64_Align2RegClass);
12052 .
addReg(DataReg, {},
Op.getSubReg())
12057 Op.setSubReg(AMDGPU::sub0);
12062 if (!SchedModel.hasInstrSchedModel())
12068 unsigned RepeatRate = 0;
12070 PI = SchedModel.getWriteProcResBegin(SCDesc),
12071 PE = SchedModel.getWriteProcResEnd(SCDesc);
12073 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12090 if (ST.hasGFX1250Insts())
12097 unsigned Opcode =
MI.getOpcode();
12103 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12104 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12107 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!")
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...
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)
static bool isReg(const MCInst &MI, unsigned OpNo)
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 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.
LiveInterval - This class represents the liveness of a register, or stack slot.
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)
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.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
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
void decomposePkFMAF32(MachineInstr &MI, MachineRegisterInfo &MRI) const
Decompose a GFX950 v_pk_fma_f32 with invalid op_sel into two independent scalar V_FMA_F32_e64 instruc...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isLegalPkFMAF32OpSel(const MachineInstr &MI) const
Check if MI has legal GFX950 v_pk_fma op_sel.
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
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
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.
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 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
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
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)
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
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.