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()) {
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() &&
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) {
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) {
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);
2079 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2083 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
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: {
2763 for (
auto &CandMO :
I->operands()) {
2764 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2772 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2776 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2782 unsigned NewOpcode = -1;
2783 if (SubregSize == 256)
2784 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2785 else if (SubregSize == 128)
2786 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2796 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2801 MI->getOperand(0).setReg(DestReg);
2802 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2806 OffsetMO->
setImm(FinalOffset);
2812 MI->setMemRefs(*MF, NewMMOs);
2825std::pair<MachineInstr*, MachineInstr*>
2827 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2829 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2832 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2833 return std::pair(&
MI,
nullptr);
2844 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2846 if (Dst.isPhysical()) {
2847 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2854 for (
unsigned I = 1;
I <= 2; ++
I) {
2857 if (
SrcOp.isImm()) {
2859 Imm.ashrInPlace(Part * 32);
2860 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2864 if (Src.isPhysical())
2865 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2872 MovDPP.addImm(MO.getImm());
2874 Split[Part] = MovDPP;
2878 if (Dst.isVirtual())
2885 MI.eraseFromParent();
2886 return std::pair(Split[0], Split[1]);
2889std::optional<DestSourcePair>
2891 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2894 return std::nullopt;
2898 AMDGPU::OpName Src0OpName,
2900 AMDGPU::OpName Src1OpName)
const {
2907 "All commutable instructions have both src0 and src1 modifiers");
2909 int Src0ModsVal = Src0Mods->
getImm();
2910 int Src1ModsVal = Src1Mods->
getImm();
2912 Src1Mods->
setImm(Src0ModsVal);
2913 Src0Mods->
setImm(Src1ModsVal);
2922 bool IsKill = RegOp.
isKill();
2924 bool IsUndef = RegOp.
isUndef();
2925 bool IsDebug = RegOp.
isDebug();
2927 if (NonRegOp.
isImm())
2929 else if (NonRegOp.
isFI())
2950 int64_t NonRegVal = NonRegOp1.
getImm();
2953 NonRegOp2.
setImm(NonRegVal);
2960 unsigned OpIdx1)
const {
2965 unsigned Opc =
MI.getOpcode();
2966 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2976 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2979 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2984 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2990 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3012 unsigned Src1Idx)
const {
3013 assert(!NewMI &&
"this should never be used");
3018 unsigned Opc =
MI.getOpcode();
3020 if (CommutedOpcode == -1)
3023 if (Src0Idx > Src1Idx)
3026 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3027 static_cast<int>(Src0Idx) &&
3028 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3029 static_cast<int>(Src1Idx) &&
3030 "inconsistency with findCommutedOpIndices");
3038 if (Src0.isReg() && Src1.isReg()) {
3042 }
else if (Src0.isReg() && !Src1.isReg()) {
3044 }
else if (!Src0.isReg() && Src1.isReg()) {
3046 }
else if (Src0.isImm() && Src1.isImm()) {
3055 Src1, AMDGPU::OpName::src1_modifiers);
3058 AMDGPU::OpName::src1_sel);
3070 unsigned &SrcOpIdx0,
3071 unsigned &SrcOpIdx1)
const {
3079 unsigned &SrcOpIdx0,
3080 unsigned &SrcOpIdx1)
const {
3081 if (!
Desc.isCommutable())
3084 unsigned Opc =
Desc.getOpcode();
3085 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3089 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3093 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3097 int64_t BrOffset)
const {
3114 return MI.getOperand(0).getMBB();
3119 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3120 MI.getOpcode() == AMDGPU::SI_LOOP ||
3121 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3133 "new block should be inserted for expanding unconditional branch");
3136 "restore block should be inserted for restoring clobbered registers");
3144 if (ST.useAddPC64Inst()) {
3146 MCCtx.createTempSymbol(
"offset",
true);
3150 MCCtx.createTempSymbol(
"post_addpc",
true);
3151 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3155 Offset->setVariableValue(OffsetExpr);
3159 assert(RS &&
"RegScavenger required for long branching");
3167 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3168 ST.hasVALUReadSGPRHazard();
3169 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3170 if (FlushSGPRWrites)
3178 ApplyHazardWorkarounds();
3181 MCCtx.createTempSymbol(
"post_getpc",
true);
3185 MCCtx.createTempSymbol(
"offset_lo",
true);
3187 MCCtx.createTempSymbol(
"offset_hi",
true);
3190 .
addReg(PCReg, {}, AMDGPU::sub0)
3194 .
addReg(PCReg, {}, AMDGPU::sub1)
3196 ApplyHazardWorkarounds();
3237 if (LongBranchReservedReg) {
3238 RS->enterBasicBlock(
MBB);
3239 Scav = LongBranchReservedReg;
3241 RS->enterBasicBlockEnd(
MBB);
3242 Scav = RS->scavengeRegisterBackwards(
3247 RS->setRegUsed(Scav);
3255 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3272unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3274 case SIInstrInfo::SCC_TRUE:
3275 return AMDGPU::S_CBRANCH_SCC1;
3276 case SIInstrInfo::SCC_FALSE:
3277 return AMDGPU::S_CBRANCH_SCC0;
3278 case SIInstrInfo::VCCNZ:
3279 return AMDGPU::S_CBRANCH_VCCNZ;
3280 case SIInstrInfo::VCCZ:
3281 return AMDGPU::S_CBRANCH_VCCZ;
3282 case SIInstrInfo::EXECNZ:
3283 return AMDGPU::S_CBRANCH_EXECNZ;
3284 case SIInstrInfo::EXECZ:
3285 return AMDGPU::S_CBRANCH_EXECZ;
3291SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3293 case AMDGPU::S_CBRANCH_SCC0:
3295 case AMDGPU::S_CBRANCH_SCC1:
3297 case AMDGPU::S_CBRANCH_VCCNZ:
3299 case AMDGPU::S_CBRANCH_VCCZ:
3301 case AMDGPU::S_CBRANCH_EXECNZ:
3303 case AMDGPU::S_CBRANCH_EXECZ:
3315 bool AllowModify)
const {
3316 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3318 TBB =
I->getOperand(0).getMBB();
3322 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3323 if (Pred == INVALID_BR)
3328 Cond.push_back(
I->getOperand(1));
3332 if (
I ==
MBB.end()) {
3338 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3340 FBB =
I->getOperand(0).getMBB();
3350 bool AllowModify)
const {
3358 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3359 switch (
I->getOpcode()) {
3360 case AMDGPU::S_MOV_B64_term:
3361 case AMDGPU::S_XOR_B64_term:
3362 case AMDGPU::S_OR_B64_term:
3363 case AMDGPU::S_ANDN2_B64_term:
3364 case AMDGPU::S_AND_B64_term:
3365 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3366 case AMDGPU::S_MOV_B32_term:
3367 case AMDGPU::S_XOR_B32_term:
3368 case AMDGPU::S_OR_B32_term:
3369 case AMDGPU::S_ANDN2_B32_term:
3370 case AMDGPU::S_AND_B32_term:
3371 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3372 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3373 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3376 case AMDGPU::SI_ELSE:
3377 case AMDGPU::SI_KILL_I1_TERMINATOR:
3378 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3395 int *BytesRemoved)
const {
3397 unsigned RemovedSize = 0;
3400 if (
MI.isBranch() ||
MI.isReturn()) {
3402 MI.eraseFromParent();
3408 *BytesRemoved = RemovedSize;
3425 int *BytesAdded)
const {
3426 if (!FBB &&
Cond.empty()) {
3430 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3437 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3449 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3467 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3474 if (
Cond.size() != 2) {
3478 if (
Cond[0].isImm()) {
3499 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3503 std::optional<bool> createTripCountGreaterCondition(
3504 int TC, MachineBasicBlock &
MBB,
3505 SmallVectorImpl<MachineOperand> &CondParam)
override {
3506 CondParam = this->
Cond;
3510 void adjustTripCount(
int TripCountAdjust)
override {}
3512 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3516std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3525 if (
TBB == LoopBB && FBB == LoopBB)
3532 assert((
TBB == LoopBB || FBB == LoopBB) &&
3533 "The Loop must be a single-basic-block loop");
3536 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3537 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3542 if (
MI.isCall() ||
MI.isInlineAsm())
3557 if (CmpI == Instructions.end() || CmpI->isPHI())
3561 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3568 SelectExpansion &Exp)
const {
3578 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3581 return RI.hasVGPRs(RC) && NumInsts <= 6;
3595 if (NumInsts % 2 == 0)
3598 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3599 return RI.isSGPRClass(RC);
3610 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3611 if (Pred == VCCZ || Pred == SCC_FALSE) {
3612 Pred =
static_cast<BranchPredicate
>(-Pred);
3618 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3620 if (DstSize == 32) {
3622 if (Pred == SCC_TRUE) {
3637 if (DstSize == 64 && Pred == SCC_TRUE) {
3647 static const int16_t Sub0_15[] = {
3648 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3649 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3650 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3651 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3654 static const int16_t Sub0_15_64[] = {
3655 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3656 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3657 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3658 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3661 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3663 const int16_t *SubIndices = Sub0_15;
3664 int NElts = DstSize / 32;
3668 if (Pred == SCC_TRUE) {
3670 SelOp = AMDGPU::S_CSELECT_B32;
3671 EltRC = &AMDGPU::SGPR_32RegClass;
3673 SelOp = AMDGPU::S_CSELECT_B64;
3674 EltRC = &AMDGPU::SGPR_64RegClass;
3675 SubIndices = Sub0_15_64;
3681 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3686 for (
int Idx = 0; Idx != NElts; ++Idx) {
3690 unsigned SubIdx = SubIndices[Idx];
3693 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3695 .
addReg(FalseReg, {}, SubIdx)
3696 .addReg(TrueReg, {}, SubIdx);
3699 .
addReg(TrueReg, {}, SubIdx)
3700 .addReg(FalseReg, {}, SubIdx);
3713 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3716 switch (
MI.getOpcode()) {
3717 case AMDGPU::S_ENDPGM:
3718 case AMDGPU::S_ENDPGM_SAVED:
3719 case AMDGPU::S_TRAP:
3720 case AMDGPU::S_GETREG_B32:
3721 case AMDGPU::S_SETREG_B32:
3722 case AMDGPU::S_SETREG_B32_mode:
3723 case AMDGPU::S_SETREG_IMM32_B32:
3724 case AMDGPU::S_SETREG_IMM32_B32_mode:
3725 case AMDGPU::S_SENDMSG:
3726 case AMDGPU::S_SENDMSGHALT:
3727 case AMDGPU::S_SENDMSG_RTN_B32:
3728 case AMDGPU::S_SENDMSG_RTN_B64:
3729 case AMDGPU::S_BARRIER_WAIT:
3730 case AMDGPU::S_BARRIER_SIGNAL_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3732 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3733 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3741 switch (
MI.getOpcode()) {
3742 case AMDGPU::V_MOV_B16_t16_e32:
3743 case AMDGPU::V_MOV_B16_t16_e64:
3744 case AMDGPU::V_MOV_B32_e32:
3745 case AMDGPU::V_MOV_B32_e64:
3746 case AMDGPU::V_MOV_B64_PSEUDO:
3747 case AMDGPU::V_MOV_B64_e32:
3748 case AMDGPU::V_MOV_B64_e64:
3749 case AMDGPU::S_MOV_B32:
3750 case AMDGPU::S_MOV_B64:
3751 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3753 case AMDGPU::WWM_COPY:
3754 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3755 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3756 case AMDGPU::V_ACCVGPR_MOV_B32:
3757 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3758 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3766 switch (
MI.getOpcode()) {
3767 case AMDGPU::V_MOV_B16_t16_e32:
3768 case AMDGPU::V_MOV_B16_t16_e64:
3770 case AMDGPU::V_MOV_B32_e32:
3771 case AMDGPU::V_MOV_B32_e64:
3772 case AMDGPU::V_MOV_B64_PSEUDO:
3773 case AMDGPU::V_MOV_B64_e32:
3774 case AMDGPU::V_MOV_B64_e64:
3775 case AMDGPU::S_MOV_B32:
3776 case AMDGPU::S_MOV_B64:
3777 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3779 case AMDGPU::WWM_COPY:
3780 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3781 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3782 case AMDGPU::V_ACCVGPR_MOV_B32:
3783 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3784 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3792 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3793 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3794 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3797 unsigned Opc =
MI.getOpcode();
3799 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3801 MI.removeOperand(Idx);
3807 MI.setDesc(NewDesc);
3813 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3814 Desc.implicit_defs().size();
3816 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3817 MI.removeOperand(
I);
3821 unsigned SubRegIndex) {
3822 switch (SubRegIndex) {
3823 case AMDGPU::NoSubRegister:
3833 case AMDGPU::sub1_lo16:
3835 case AMDGPU::sub1_hi16:
3838 return std::nullopt;
3846 case AMDGPU::V_MAC_F16_e32:
3847 case AMDGPU::V_MAC_F16_e64:
3848 case AMDGPU::V_MAD_F16_e64:
3849 return AMDGPU::V_MADAK_F16;
3850 case AMDGPU::V_MAC_F32_e32:
3851 case AMDGPU::V_MAC_F32_e64:
3852 case AMDGPU::V_MAD_F32_e64:
3853 return AMDGPU::V_MADAK_F32;
3854 case AMDGPU::V_FMAC_F32_e32:
3855 case AMDGPU::V_FMAC_F32_e64:
3856 case AMDGPU::V_FMA_F32_e64:
3857 return AMDGPU::V_FMAAK_F32;
3858 case AMDGPU::V_FMAC_F16_e32:
3859 case AMDGPU::V_FMAC_F16_e64:
3860 case AMDGPU::V_FMAC_F16_t16_e64:
3861 case AMDGPU::V_FMAC_F16_fake16_e64:
3862 case AMDGPU::V_FMAC_F16_t16_e32:
3863 case AMDGPU::V_FMAC_F16_fake16_e32:
3864 case AMDGPU::V_FMA_F16_e64:
3865 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3866 ? AMDGPU::V_FMAAK_F16_t16
3867 : AMDGPU::V_FMAAK_F16_fake16
3868 : AMDGPU::V_FMAAK_F16;
3869 case AMDGPU::V_FMAC_F64_e32:
3870 case AMDGPU::V_FMAC_F64_e64:
3871 case AMDGPU::V_FMA_F64_e64:
3872 return AMDGPU::V_FMAAK_F64;
3880 case AMDGPU::V_MAC_F16_e32:
3881 case AMDGPU::V_MAC_F16_e64:
3882 case AMDGPU::V_MAD_F16_e64:
3883 return AMDGPU::V_MADMK_F16;
3884 case AMDGPU::V_MAC_F32_e32:
3885 case AMDGPU::V_MAC_F32_e64:
3886 case AMDGPU::V_MAD_F32_e64:
3887 return AMDGPU::V_MADMK_F32;
3888 case AMDGPU::V_FMAC_F32_e32:
3889 case AMDGPU::V_FMAC_F32_e64:
3890 case AMDGPU::V_FMA_F32_e64:
3891 return AMDGPU::V_FMAMK_F32;
3892 case AMDGPU::V_FMAC_F16_e32:
3893 case AMDGPU::V_FMAC_F16_e64:
3894 case AMDGPU::V_FMAC_F16_t16_e64:
3895 case AMDGPU::V_FMAC_F16_fake16_e64:
3896 case AMDGPU::V_FMAC_F16_t16_e32:
3897 case AMDGPU::V_FMAC_F16_fake16_e32:
3898 case AMDGPU::V_FMA_F16_e64:
3899 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3900 ? AMDGPU::V_FMAMK_F16_t16
3901 : AMDGPU::V_FMAMK_F16_fake16
3902 : AMDGPU::V_FMAMK_F16;
3903 case AMDGPU::V_FMAC_F64_e32:
3904 case AMDGPU::V_FMAC_F64_e64:
3905 case AMDGPU::V_FMA_F64_e64:
3906 return AMDGPU::V_FMAMK_F64;
3920 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3923 if (
Opc == AMDGPU::COPY) {
3924 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3931 if (HasMultipleUses) {
3934 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3937 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3945 if (ImmDefSize == 32 &&
3950 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3951 RI.getSubRegIdxSize(UseSubReg) == 16;
3954 if (RI.hasVGPRs(DstRC))
3957 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3963 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3970 for (
unsigned MovOp :
3971 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3972 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3980 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3984 if (MovDstPhysReg) {
3988 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3995 if (MovDstPhysReg) {
3996 if (!MovDstRC->
contains(MovDstPhysReg))
4012 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4020 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4024 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4026 UseMI.getOperand(0).setReg(MovDstPhysReg);
4031 UseMI.setDesc(NewMCID);
4032 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4033 UseMI.addImplicitDefUseOperands(*MF);
4037 if (HasMultipleUses)
4040 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4041 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4043 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4044 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4045 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4046 Opc == AMDGPU::V_FMAC_F64_e64) {
4055 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4066 auto CopyRegOperandToNarrowerRC =
4069 if (!
MI.getOperand(OpNo).isReg())
4073 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4076 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4077 get(AMDGPU::COPY), Tmp)
4079 MI.getOperand(OpNo).setReg(Tmp);
4083 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4084 (Src1->isReg() && Src1->getReg() == Reg)) {
4086 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4087 if (!RegSrc->
isReg())
4090 ST.getConstantBusLimit(
Opc) < 2)
4093 if (!Src2->isReg() || RI.isSGPRClass(MRI->
getRegClass(Src2->getReg())))
4105 if (Def && Def->isMoveImmediate() &&
4114 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4120 unsigned SrcSubReg = RegSrc->
getSubReg();
4121 Src0->setReg(SrcReg);
4122 Src0->setSubReg(SrcSubReg);
4123 Src0->setIsKill(RegSrc->
isKill());
4125 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4126 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4127 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4128 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4129 UseMI.untieRegOperand(
4130 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4132 Src1->ChangeToImmediate(*SubRegImm);
4137 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4138 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4142 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4143 UseMI.getOperand(0).getReg())
4145 UseMI.getOperand(0).setReg(Tmp);
4146 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4147 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4152 DefMI.eraseFromParent();
4158 if (Src2->isReg() && Src2->getReg() == Reg) {
4159 if (ST.getConstantBusLimit(
Opc) < 2) {
4162 bool Src0Inlined =
false;
4163 if (Src0->isReg()) {
4168 if (Def && Def->isMoveImmediate() &&
4171 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4173 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4174 RI.isSGPRReg(*MRI, Src0->getReg())) {
4180 if (Src1->isReg() && !Src0Inlined) {
4183 if (Def && Def->isMoveImmediate() &&
4186 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4187 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4200 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4201 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4202 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4203 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4204 UseMI.untieRegOperand(
4205 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4207 const std::optional<int64_t> SubRegImm =
4211 Src2->ChangeToImmediate(*SubRegImm);
4217 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4218 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4222 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4223 UseMI.getOperand(0).getReg())
4225 UseMI.getOperand(0).setReg(Tmp);
4226 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4227 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4236 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4242 DefMI.eraseFromParent();
4254 if (BaseOps1.
size() != BaseOps2.
size())
4256 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4257 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4265 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4266 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4267 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4269 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4272bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4275 int64_t Offset0, Offset1;
4278 bool Offset0IsScalable, Offset1IsScalable;
4292 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4293 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4300 "MIa must load from or modify a memory location");
4302 "MIb must load from or modify a memory location");
4324 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4331 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4341 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4355 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4366 case AMDGPU::V_MAC_F16_e32:
4367 case AMDGPU::V_MAC_F16_e64:
4368 return AMDGPU::V_MAD_F16_e64;
4369 case AMDGPU::V_MAC_F32_e32:
4370 case AMDGPU::V_MAC_F32_e64:
4371 return AMDGPU::V_MAD_F32_e64;
4372 case AMDGPU::V_MAC_LEGACY_F32_e32:
4373 case AMDGPU::V_MAC_LEGACY_F32_e64:
4374 return AMDGPU::V_MAD_LEGACY_F32_e64;
4375 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4376 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4377 return AMDGPU::V_FMA_LEGACY_F32_e64;
4378 case AMDGPU::V_FMAC_F16_e32:
4379 case AMDGPU::V_FMAC_F16_e64:
4380 case AMDGPU::V_FMAC_F16_t16_e64:
4381 case AMDGPU::V_FMAC_F16_fake16_e64:
4382 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4383 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4384 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4385 : AMDGPU::V_FMA_F16_gfx9_e64;
4386 case AMDGPU::V_FMAC_F32_e32:
4387 case AMDGPU::V_FMAC_F32_e64:
4388 return AMDGPU::V_FMA_F32_e64;
4389 case AMDGPU::V_FMAC_F64_e32:
4390 case AMDGPU::V_FMAC_F64_e64:
4391 return AMDGPU::V_FMA_F64_e64;
4410 if (
MI.isBundle()) {
4413 if (
MI.getBundleSize() != 1)
4415 CandidateMI =
MI.getNextNode();
4419 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4423 if (
MI.isBundle()) {
4428 MI.untieRegOperand(MO.getOperandNo());
4435 if (Def.isEarlyClobber() && Def.isReg() &&
4440 auto UpdateDefIndex = [&](
LiveRange &LR) {
4441 auto *S = LR.find(OldIndex);
4442 if (S != LR.end() && S->start == OldIndex) {
4443 assert(S->valno && S->valno->def == OldIndex);
4444 S->start = NewIndex;
4445 S->valno->def = NewIndex;
4449 for (
auto &SR : LI.subranges())
4455 if (U.RemoveMIUse) {
4458 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4462 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4463 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4464 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4465 U.RemoveMIUse->removeOperand(
I);
4468 if (
MI.isBundle()) {
4472 if (MO.isReg() && MO.getReg() == DefReg) {
4473 assert(MO.getSubReg() == 0 &&
4474 "tied sub-registers in bundles currently not supported");
4475 MI.removeOperand(MO.getOperandNo());
4492 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4493 MIOp.setIsUndef(
true);
4494 MIOp.setReg(DummyReg);
4498 if (
MI.isBundle()) {
4502 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4503 MIOp.setIsUndef(
true);
4504 MIOp.setReg(DummyReg);
4517 return MI.isBundle() ? &
MI : NewMI;
4522 ThreeAddressUpdates &U)
const {
4524 unsigned Opc =
MI.getOpcode();
4528 if (NewMFMAOpc != -1) {
4531 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4532 MIB.
add(
MI.getOperand(
I));
4540 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4545 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4546 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4547 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4551 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4552 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4553 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4554 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4555 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4556 bool Src0Literal =
false;
4561 case AMDGPU::V_MAC_F16_e64:
4562 case AMDGPU::V_FMAC_F16_e64:
4563 case AMDGPU::V_FMAC_F16_t16_e64:
4564 case AMDGPU::V_FMAC_F16_fake16_e64:
4565 case AMDGPU::V_MAC_F32_e64:
4566 case AMDGPU::V_MAC_LEGACY_F32_e64:
4567 case AMDGPU::V_FMAC_F32_e64:
4568 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4569 case AMDGPU::V_FMAC_F64_e64:
4571 case AMDGPU::V_MAC_F16_e32:
4572 case AMDGPU::V_FMAC_F16_e32:
4573 case AMDGPU::V_MAC_F32_e32:
4574 case AMDGPU::V_MAC_LEGACY_F32_e32:
4575 case AMDGPU::V_FMAC_F32_e32:
4576 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4577 case AMDGPU::V_FMAC_F64_e32: {
4578 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4579 AMDGPU::OpName::src0);
4580 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4581 if (!
Src0->isReg() && !
Src0->isImm())
4591 MachineInstrBuilder MIB;
4594 const MachineOperand *Src0Mods =
4597 const MachineOperand *Src1Mods =
4600 const MachineOperand *Src2Mods =
4606 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4607 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4609 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4611 MachineInstr *
DefMI =
nullptr;
4613 std::optional<int64_t> ImmOpt;
4648 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4664 if (Src0Literal && !ST.hasVOP3Literal())
4692 switch (
MI.getOpcode()) {
4693 case AMDGPU::S_SET_GPR_IDX_ON:
4694 case AMDGPU::S_SET_GPR_IDX_MODE:
4695 case AMDGPU::S_SET_GPR_IDX_OFF:
4713 if (
MI.isTerminator() ||
MI.isPosition())
4717 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4720 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4726 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4727 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4728 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4729 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4730 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4735 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4736 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4737 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4751 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4756 if (
MI.memoperands_empty())
4761 unsigned AS = Memop->getAddrSpace();
4762 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4763 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4764 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4765 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4780 if (
MI.memoperands_empty())
4789 unsigned AS = Memop->getAddrSpace();
4799 bool TgSplit)
const {
4812 if (
MI.memoperands_empty())
4817 unsigned AS = Memop->getAddrSpace();
4833 unsigned Opcode =
MI.getOpcode();
4848 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4849 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4850 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4851 Opcode == AMDGPU::S_SETHALT)
4854 if (
MI.isCall() ||
MI.isInlineAsm())
4860 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4876 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4877 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4878 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4879 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4887 if (
MI.isMetaInstruction())
4891 if (
MI.isCopyLike()) {
4892 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4896 return MI.readsRegister(AMDGPU::EXEC, &RI);
4907 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4911 switch (
Imm.getBitWidth()) {
4917 ST.hasInv2PiInlineImm());
4920 ST.hasInv2PiInlineImm());
4922 return ST.has16BitInsts() &&
4924 ST.hasInv2PiInlineImm());
4931 APInt IntImm =
Imm.bitcastToAPInt();
4933 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4941 return ST.has16BitInsts() &&
4944 return ST.has16BitInsts() &&
4954 switch (OperandType) {
4964 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5008 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5009 return ST.has16BitInsts() &&
5018 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5019 return ST.has16BitInsts() &&
5071 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5077 return ST.hasVOP3Literal();
5081 int64_t ImmVal)
const {
5083 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5084 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5085 OpNo ==
static_cast<unsigned>(Src1Idx))
5090 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5091 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5092 AMDGPU::OpName::src2))
5095 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5102 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5114 "unexpected imm-like operand kind");
5127 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5147 return Op32 != -1 &&
TII.isVOPC(Op32);
5152 unsigned Depth)
const {
5153 assert(MRI.
isSSA() &&
"isMaskedByExec requires SSA form");
5162 constexpr unsigned MaxDepth = 6;
5163 if (
Depth >= MaxDepth || !Reg.isVirtual())
5169 if (!Def || Def->getParent() !=
MBB)
5177 auto Recurse = [&](
unsigned OpIdx) {
5183 unsigned Opc = Def->getOpcode();
5184 if (
Opc == AMDGPU::COPY && Recurse(1))
5186 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5206 AMDGPU::OpName
OpName)
const {
5208 return Mods && Mods->
getImm();
5221 switch (
MI.getOpcode()) {
5222 default:
return false;
5224 case AMDGPU::V_ADDC_U32_e64:
5225 case AMDGPU::V_SUBB_U32_e64:
5226 case AMDGPU::V_SUBBREV_U32_e64: {
5229 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5234 case AMDGPU::V_MAC_F16_e64:
5235 case AMDGPU::V_MAC_F32_e64:
5236 case AMDGPU::V_MAC_LEGACY_F32_e64:
5237 case AMDGPU::V_FMAC_F16_e64:
5238 case AMDGPU::V_FMAC_F16_t16_e64:
5239 case AMDGPU::V_FMAC_F16_fake16_e64:
5240 case AMDGPU::V_FMAC_F32_e64:
5241 case AMDGPU::V_FMAC_F64_e64:
5242 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5243 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5248 case AMDGPU::V_CNDMASK_B32_e64:
5254 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5267 if (Src0 && Src0->isImm()) {
5270 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5292 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5301 unsigned Op32)
const {
5315 Inst32.
add(
MI.getOperand(
I));
5319 int Idx =
MI.getNumExplicitDefs();
5321 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5326 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5346 if (OldSDst && OldSDst->
isDead()) {
5349 NewVCC->setIsDead();
5358 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5366 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5369 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5370 AMDGPU::SReg_64RegClass.contains(Reg);
5398 switch (MO.getReg()) {
5400 case AMDGPU::VCC_LO:
5401 case AMDGPU::VCC_HI:
5403 case AMDGPU::FLAT_SCR:
5416 switch (
MI.getOpcode()) {
5417 case AMDGPU::V_READLANE_B32:
5418 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5419 case AMDGPU::V_WRITELANE_B32:
5420 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5427 if (
MI.isPreISelOpcode() ||
5428 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5446 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5457 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5458 ErrInfo =
"illegal copy from vector register to SGPR";
5476 if (!MRI.
isSSA() &&
MI.isCopy())
5477 return verifyCopy(
MI, MRI, ErrInfo);
5479 if (SIInstrInfo::isGenericOpcode(Opcode))
5482 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5483 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5484 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5486 if (Src0Idx == -1) {
5488 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5489 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5490 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5491 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5496 if (!
Desc.isVariadic() &&
5497 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5498 ErrInfo =
"Instruction has wrong number of operands.";
5502 if (
MI.isInlineAsm()) {
5515 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5516 ErrInfo =
"inlineasm operand has incorrect register class.";
5524 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5525 ErrInfo =
"missing memory operand from image instruction.";
5530 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5533 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5534 "all fp values to integers.";
5540 switch (OpInfo.OperandType) {
5542 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5543 ErrInfo =
"Illegal immediate value for operand.";
5575 ErrInfo =
"Illegal immediate value for operand.";
5584 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5587 OpInfo.OperandType ==
5589 ErrInfo =
"illegal 64-bit immediate value for operand.";
5596 ErrInfo =
"Expected inline constant for operand.";
5610 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5611 ErrInfo =
"Expected immediate, but got non-immediate";
5620 if (OpInfo.isGenericType())
5628 if (!ST.hasSDWA()) {
5629 ErrInfo =
"SDWA is not supported on this target";
5633 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5634 AMDGPU::OpName::dst_sel}) {
5640 ErrInfo =
"Invalid SDWA selection";
5645 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5647 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5652 if (!ST.hasSDWAScalar()) {
5654 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5655 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5662 "Only reg allowed as operands in SDWA instructions on GFX9+";
5668 if (!ST.hasSDWAOmod()) {
5671 if (OMod !=
nullptr &&
5673 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5678 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5679 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5680 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5681 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5684 unsigned Mods = Src0ModsMO->
getImm();
5687 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5693 if (
isVOPC(BasicOpcode)) {
5694 if (!ST.hasSDWASdst() && DstIdx != -1) {
5697 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5698 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5701 }
else if (!ST.hasSDWAOutModsVOPC()) {
5704 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5705 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5711 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5712 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5719 if (DstUnused && DstUnused->isImm() &&
5722 if (!Dst.isReg() || !Dst.isTied()) {
5723 ErrInfo =
"Dst register should have tied register";
5728 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5731 "Dst register should be tied to implicit use of preserved register";
5735 ErrInfo =
"Dst register should use same physical register as preserved";
5741 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5743 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5744 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5747 if (Src1MO.
isImm()) {
5748 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5754 if (
isImage(Opcode) && !
MI.mayStore()) {
5759 uint64_t DMaskImm = DMask->
getImm();
5766 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5774 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5778 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5779 if (RegCount > DstSize) {
5780 ErrInfo =
"Image instruction returns too many registers for dst "
5790 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5791 unsigned ConstantBusCount = 0;
5792 bool UsesLiteral =
false;
5795 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5799 LiteralVal = &
MI.getOperand(ImmIdx);
5808 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5819 }
else if (!MO.
isFI()) {
5826 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5836 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5837 return !RI.regsOverlap(SGPRUsed, SGPR);
5846 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5847 Opcode != AMDGPU::V_WRITELANE_B32) {
5848 ErrInfo =
"VOP* instruction violates constant bus restriction";
5852 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5853 ErrInfo =
"VOP3 instruction uses literal";
5860 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5861 unsigned SGPRCount = 0;
5864 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5872 if (MO.
getReg() != SGPRUsed)
5877 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5878 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5885 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5886 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5890 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5893 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5903 ErrInfo =
"ABS not allowed in VOP3B instructions";
5915 !Src0.isIdenticalTo(Src1)) {
5916 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5923 if (
Desc.isBranch()) {
5925 ErrInfo =
"invalid branch target for SOPK instruction";
5929 uint64_t
Imm =
Op->getImm();
5932 ErrInfo =
"invalid immediate for SOPK instruction";
5937 ErrInfo =
"invalid immediate for SOPK instruction";
5944 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5945 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5946 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5947 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5948 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5949 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5951 const unsigned StaticNumOps =
5952 Desc.getNumOperands() +
Desc.implicit_uses().size();
5953 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5959 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5960 ErrInfo =
"missing implicit register operands";
5966 if (!Dst->isUse()) {
5967 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5972 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5973 UseOpIdx != StaticNumOps + 1) {
5974 ErrInfo =
"movrel implicit operands should be tied";
5981 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5983 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5984 ErrInfo =
"src0 should be subreg of implicit vector use";
5992 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5993 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5999 if (
MI.mayStore() &&
6004 if (Soff && Soff->
getReg() != AMDGPU::M0) {
6005 ErrInfo =
"scalar stores must use m0 as offset register";
6011 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6013 if (
Offset->getImm() != 0) {
6014 ErrInfo =
"subtarget does not support offsets in flat instructions";
6019 if (
isDS(
MI) && !ST.hasGDS()) {
6021 if (GDSOp && GDSOp->
getImm() != 0) {
6022 ErrInfo =
"GDS is not supported on this subtarget";
6030 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6031 AMDGPU::OpName::vaddr0);
6032 AMDGPU::OpName RSrcOpName =
6033 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6034 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6042 ErrInfo =
"dim is out of range";
6047 if (ST.hasR128A16()) {
6049 IsA16 = R128A16->
getImm() != 0;
6050 }
else if (ST.hasA16()) {
6052 IsA16 = A16->
getImm() != 0;
6055 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6057 unsigned AddrWords =
6060 unsigned VAddrWords;
6062 VAddrWords = RsrcIdx - VAddr0Idx;
6063 if (ST.hasPartialNSAEncoding() &&
6065 unsigned LastVAddrIdx = RsrcIdx - 1;
6066 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6074 if (VAddrWords != AddrWords) {
6076 <<
" but got " << VAddrWords <<
"\n");
6077 ErrInfo =
"bad vaddr size";
6087 unsigned DC = DppCt->
getImm();
6088 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6089 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6090 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6091 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6092 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6093 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6094 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6095 ErrInfo =
"Invalid dpp_ctrl value";
6098 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6099 !ST.hasDPPWavefrontShifts()) {
6100 ErrInfo =
"Invalid dpp_ctrl value: "
6101 "wavefront shifts are not supported on GFX10+";
6104 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6105 !ST.hasDPPBroadcasts()) {
6106 ErrInfo =
"Invalid dpp_ctrl value: "
6107 "broadcasts are not supported on GFX10+";
6110 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6112 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6113 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6114 !ST.hasGFX90AInsts()) {
6115 ErrInfo =
"Invalid dpp_ctrl value: "
6116 "row_newbroadcast/row_share is not supported before "
6120 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6121 ErrInfo =
"Invalid dpp_ctrl value: "
6122 "row_share and row_xmask are not supported before GFX10";
6127 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6129 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6131 ErrInfo =
"Invalid dpp_ctrl value: "
6132 "DP ALU dpp only support row_newbcast";
6139 AMDGPU::OpName DataName =
6140 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6146 if (!ST.hasGFX90AInsts()) {
6147 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6148 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6149 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6150 ErrInfo =
"Invalid register class: "
6151 "agpr loads and stores not supported on this GPU";
6157 if (ST.needsAlignedVGPRs()) {
6158 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6163 if (Reg.isPhysical())
6164 return !(RI.getHWRegIndex(Reg) & 1);
6166 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6167 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6171 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6172 ErrInfo =
"Subtarget requires even aligned vector registers "
6173 "for vaddr operand of image instructions";
6179 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6181 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6182 ErrInfo =
"Invalid register class: "
6183 "v_accvgpr_write with an SGPR is not supported on this GPU";
6188 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6191 ErrInfo =
"pseudo expects only physical SGPRs";
6198 if (!ST.hasScaleOffset()) {
6199 ErrInfo =
"Subtarget does not support offset scaling";
6203 ErrInfo =
"Instruction does not support offset scaling";
6211 for (
unsigned I = 0;
I < 3; ++
I) {
6217 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6218 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6220 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6221 &AMDGPU::SReg_64RegClass) ||
6222 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6223 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6232 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6234 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6236 : AMDGPU::V_MOV_B32_e32;
6246 default:
return AMDGPU::INSTRUCTION_LIST_END;
6247 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6248 case AMDGPU::COPY:
return AMDGPU::COPY;
6249 case AMDGPU::PHI:
return AMDGPU::PHI;
6250 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6251 case AMDGPU::WQM:
return AMDGPU::WQM;
6252 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6253 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6254 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6255 case AMDGPU::S_ADD_I32:
6256 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6257 case AMDGPU::S_ADDC_U32:
6258 return AMDGPU::V_ADDC_U32_e32;
6259 case AMDGPU::S_SUB_I32:
6260 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6263 case AMDGPU::S_ADD_U32:
6264 return AMDGPU::V_ADD_CO_U32_e32;
6265 case AMDGPU::S_SUB_U32:
6266 return AMDGPU::V_SUB_CO_U32_e32;
6267 case AMDGPU::S_ADD_U64_PSEUDO:
6268 return AMDGPU::V_ADD_U64_PSEUDO;
6269 case AMDGPU::S_SUB_U64_PSEUDO:
6270 return AMDGPU::V_SUB_U64_PSEUDO;
6271 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6272 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6273 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6274 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6275 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6276 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6277 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6278 case AMDGPU::S_XNOR_B32:
6279 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6280 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6281 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6282 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6283 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6284 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6285 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6286 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6287 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6288 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6289 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6290 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6291 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6292 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6293 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6294 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6295 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6296 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6297 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6298 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6299 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6300 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6301 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6302 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6303 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6304 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6305 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6306 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6307 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6308 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6309 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6310 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6311 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6312 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6313 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6314 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6315 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6316 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6317 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6318 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6319 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6320 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6321 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6322 case AMDGPU::S_CVT_F32_F16:
6323 case AMDGPU::S_CVT_HI_F32_F16:
6324 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6325 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6326 case AMDGPU::S_CVT_F16_F32:
6327 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6328 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6329 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6330 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6331 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6332 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6333 case AMDGPU::S_CEIL_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6335 : AMDGPU::V_CEIL_F16_fake16_e64;
6336 case AMDGPU::S_FLOOR_F16:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6338 : AMDGPU::V_FLOOR_F16_fake16_e64;
6339 case AMDGPU::S_TRUNC_F16:
6340 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6341 : AMDGPU::V_TRUNC_F16_fake16_e64;
6342 case AMDGPU::S_RNDNE_F16:
6343 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6344 : AMDGPU::V_RNDNE_F16_fake16_e64;
6345 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6346 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6347 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6348 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6349 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6350 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6351 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6352 case AMDGPU::S_ADD_F16:
6353 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6354 : AMDGPU::V_ADD_F16_fake16_e64;
6355 case AMDGPU::S_SUB_F16:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6357 : AMDGPU::V_SUB_F16_fake16_e64;
6358 case AMDGPU::S_MIN_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6360 : AMDGPU::V_MIN_F16_fake16_e64;
6361 case AMDGPU::S_MAX_F16:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6363 : AMDGPU::V_MAX_F16_fake16_e64;
6364 case AMDGPU::S_MINIMUM_F16:
6365 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6366 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6367 case AMDGPU::S_MAXIMUM_F16:
6368 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6369 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6370 case AMDGPU::S_MUL_F16:
6371 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6372 : AMDGPU::V_MUL_F16_fake16_e64;
6373 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6374 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6375 case AMDGPU::S_FMAC_F16:
6376 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6377 : AMDGPU::V_FMAC_F16_fake16_e64;
6378 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6379 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6380 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6381 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6382 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6383 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6384 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6385 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6386 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6387 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6388 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6389 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6390 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6391 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6392 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6393 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6394 case AMDGPU::S_CMP_LT_F16:
6395 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6396 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6397 case AMDGPU::S_CMP_EQ_F16:
6398 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6399 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6400 case AMDGPU::S_CMP_LE_F16:
6401 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6402 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6403 case AMDGPU::S_CMP_GT_F16:
6404 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6405 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6406 case AMDGPU::S_CMP_LG_F16:
6407 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6408 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6409 case AMDGPU::S_CMP_GE_F16:
6410 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6411 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6412 case AMDGPU::S_CMP_O_F16:
6413 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6414 : AMDGPU::V_CMP_O_F16_fake16_e64;
6415 case AMDGPU::S_CMP_U_F16:
6416 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6417 : AMDGPU::V_CMP_U_F16_fake16_e64;
6418 case AMDGPU::S_CMP_NGE_F16:
6419 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6420 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6421 case AMDGPU::S_CMP_NLG_F16:
6422 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6423 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6424 case AMDGPU::S_CMP_NGT_F16:
6425 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6426 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6427 case AMDGPU::S_CMP_NLE_F16:
6428 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6429 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6430 case AMDGPU::S_CMP_NEQ_F16:
6431 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6432 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6433 case AMDGPU::S_CMP_NLT_F16:
6434 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6435 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6436 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6437 case AMDGPU::V_S_EXP_F16_e64:
6438 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6439 : AMDGPU::V_EXP_F16_fake16_e64;
6440 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6441 case AMDGPU::V_S_LOG_F16_e64:
6442 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6443 : AMDGPU::V_LOG_F16_fake16_e64;
6444 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6445 case AMDGPU::V_S_RCP_F16_e64:
6446 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6447 : AMDGPU::V_RCP_F16_fake16_e64;
6448 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6449 case AMDGPU::V_S_RSQ_F16_e64:
6450 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6451 : AMDGPU::V_RSQ_F16_fake16_e64;
6452 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6453 case AMDGPU::V_S_SQRT_F16_e64:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6455 : AMDGPU::V_SQRT_F16_fake16_e64;
6458 "Unexpected scalar opcode without corresponding vector one!");
6507 "Not a whole wave func");
6510 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6511 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6518 unsigned OpNo)
const {
6520 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6521 Desc.operands()[OpNo].RegClass == -1) {
6524 if (Reg.isVirtual()) {
6528 return RI.getPhysRegBaseClass(Reg);
6531 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6532 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6537 constexpr AMDGPU::OpName OpNames[] = {
6538 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6541 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6542 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6554 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6556 unsigned Size = RI.getRegSizeInBits(*RC);
6557 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6558 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6559 : AMDGPU::V_MOV_B32_e32;
6561 Opcode = AMDGPU::COPY;
6562 else if (RI.isSGPRClass(RC))
6563 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6588 .
addImm(AMDGPU::sub0_sub1)
6590 .
addImm(AMDGPU::sub2_sub3);
6591 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6608 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6614 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6625 if (SubIdx == AMDGPU::sub0)
6627 if (SubIdx == AMDGPU::sub1)
6639void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6655 if (Reg.isPhysical())
6662 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6665 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6668 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6675 unsigned Opc =
MI.getOpcode();
6678 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6688 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6689 if (IsAGPR && !ST.hasMAIInsts())
6695 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6696 const int DataIdx = AMDGPU::getNamedOperandIdx(
6697 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6698 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6699 MI.getOperand(DataIdx).isReg() &&
6700 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6702 if ((
int)OpIdx == DataIdx) {
6703 if (VDstIdx != -1 &&
6704 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6707 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6708 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6709 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6714 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6715 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6716 RI.isSGPRReg(MRI, MO.
getReg()))
6719 if (ST.hasFlatScratchHiInB64InstHazard() &&
6726 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6729 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6730 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6739 constexpr unsigned NumOps = 3;
6740 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6741 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6742 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6743 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6748 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6751 MO = &
MI.getOperand(SrcIdx);
6754 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6758 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6762 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6766 return !OpSel && !OpSelHi;
6771 if (!ST.hasPkF32InvalidOpSel() ||
MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6784 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6789 assert(
MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6797 const unsigned Mods[3] = {
6798 static_cast<unsigned>(
6800 static_cast<unsigned>(
6802 static_cast<unsigned>(
6807 for (
unsigned I = 0;
I != 3; ++
I) {
6821 bool DivergentSGPRs =
false;
6822 for (
unsigned I = 0;
I != 3; ++
I) {
6823 if (!Srcs[
I]->
isReg() || !RI.isSGPRReg(MRI, Srcs[
I]->
getReg()))
6825 if (!SGPRSrcs.
empty()) {
6828 Srcs[
I]->getSubReg() == Srcs[
First]->getSubReg() &&
6829 "constant bus limit allows only one SGPR source");
6831 OpSel[
I][0] != OpSel[
First][0] || OpSel[
I][1] != OpSel[
First][1];
6836 if (DivergentSGPRs) {
6839 for (
unsigned I :
ArrayRef(SGPRSrcs).drop_front())
6845 unsigned SubIdx = (
Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6849 : RI.isVGPR(MRI,
Op.getReg())
6850 ? RI.getVGPRClassForBitWidth(32)
6851 : RI.getSGPRClassForBitWidth(32);
6856 auto LaneMods = [](
unsigned Mods,
bool Hi) ->
unsigned {
6863 auto BuildLane = [&](
Register Dst,
bool Hi) {
6881 BuildLane(
Lo,
false);
6882 BuildLane(
Hi,
true);
6891 MI.eraseFromParent();
6900 int64_t RegClass = getOpRegClassID(OpInfo);
6902 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6904 MO = &
MI.getOperand(OpIdx);
6908 if (
isVALU(
MI,
false) && !IsInlineConst &&
6912 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6913 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6917 if (!LiteralLimit--)
6927 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6935 if (--ConstantBusLimit <= 0)
6947 if (!LiteralLimit--)
6949 if (--ConstantBusLimit <= 0)
6955 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6959 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6961 !
Op.isIdenticalTo(*MO))
6983 bool Is64BitOp = Is64BitFPOp ||
6991 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
7000 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
7018 bool IsGFX950Only = ST.hasGFX950Insts();
7019 bool IsGFX940Only = ST.hasGFX940Insts();
7021 if (!IsGFX950Only && !IsGFX940Only)
7039 unsigned Opcode =
MI.getOpcode();
7041 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7042 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7043 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7044 case AMDGPU::V_MQSAD_U32_U8_e64:
7045 case AMDGPU::V_PK_ADD_F16:
7046 case AMDGPU::V_PK_ADD_F32:
7047 case AMDGPU::V_PK_ADD_I16:
7048 case AMDGPU::V_PK_ADD_U16:
7049 case AMDGPU::V_PK_ASHRREV_I16:
7050 case AMDGPU::V_PK_FMA_F16:
7051 case AMDGPU::V_PK_FMA_F32:
7052 case AMDGPU::V_PK_FMAC_F16_e32:
7053 case AMDGPU::V_PK_FMAC_F16_e64:
7054 case AMDGPU::V_PK_LSHLREV_B16:
7055 case AMDGPU::V_PK_LSHRREV_B16:
7056 case AMDGPU::V_PK_MAD_I16:
7057 case AMDGPU::V_PK_MAD_U16:
7058 case AMDGPU::V_PK_MAX_F16:
7059 case AMDGPU::V_PK_MAX_I16:
7060 case AMDGPU::V_PK_MAX_U16:
7061 case AMDGPU::V_PK_MIN_F16:
7062 case AMDGPU::V_PK_MIN_I16:
7063 case AMDGPU::V_PK_MIN_U16:
7064 case AMDGPU::V_PK_MOV_B32:
7065 case AMDGPU::V_PK_MUL_F16:
7066 case AMDGPU::V_PK_MUL_F32:
7067 case AMDGPU::V_PK_MUL_LO_U16:
7068 case AMDGPU::V_PK_SUB_I16:
7069 case AMDGPU::V_PK_SUB_U16:
7070 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7079 unsigned Opc =
MI.getOpcode();
7082 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
7085 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7091 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7092 RI.isSGPRReg(MRI, Src0.getReg()))
7098 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7100 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7104 Src0.ChangeToRegister(Reg,
false);
7106 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7111 Src1.ChangeToRegister(Reg,
false);
7117 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7118 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7119 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
7131 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7132 RI.isVGPR(MRI, Src1.getReg())) {
7137 Src1.ChangeToRegister(Reg,
false);
7145 if (HasImplicitSGPR || !
MI.isCommutable()) {
7155 if ((!Src1.isImm() && !Src1.isReg()) ||
7162 if (CommutedOpc == -1) {
7167 MI.setDesc(
get(CommutedOpc));
7170 unsigned Src0SubReg = Src0.getSubReg();
7171 bool Src0Kill = Src0.isKill();
7174 Src0.ChangeToImmediate(Src1.getImm());
7175 else if (Src1.isReg()) {
7176 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7177 Src0.setSubReg(Src1.getSubReg());
7181 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7182 Src1.setSubReg(Src0SubReg);
7190 unsigned Opc =
MI.getOpcode();
7193 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7194 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7195 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7198 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7200 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7201 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7202 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7203 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7204 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7208 if (Src1.isReg() && !RI.isSGPRClass(MRI.
getRegClass(Src1.getReg()))) {
7212 Src1.ChangeToRegister(Reg,
false);
7214 if (VOP3Idx[2] != -1) {
7216 if (Src2.isReg() && !RI.isSGPRClass(MRI.
getRegClass(Src2.getReg()))) {
7220 Src2.ChangeToRegister(Reg,
false);
7226 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7227 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7229 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7231 SGPRsUsed.
insert(SGPRReg);
7235 for (
int Idx : VOP3Idx) {
7244 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7256 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7263 if (ConstantBusLimit > 0) {
7275 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7276 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7277 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7278 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7284 for (
unsigned I = 0;
I < 3; ++
I) {
7297 SRC = RI.getCommonSubClass(SRC, DstRC);
7300 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7302 if (RI.hasAGPRs(VRC)) {
7303 VRC = RI.getEquivalentVGPRClass(VRC);
7306 get(TargetOpcode::COPY), NewSrcReg)
7313 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7319 for (
unsigned i = 0; i < SubRegs; ++i) {
7322 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7323 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7329 get(AMDGPU::REG_SEQUENCE), DstReg);
7330 for (
unsigned i = 0; i < SubRegs; ++i) {
7332 MIB.
addImm(RI.getSubRegFromChannel(i));
7345 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7347 SBase->setReg(SGPR);
7350 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7358 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7359 if (OldSAddrIdx < 0)
7372 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7375 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7376 if (NewVAddrIdx < 0)
7379 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7383 if (OldVAddrIdx >= 0) {
7397 if (OldVAddrIdx == NewVAddrIdx) {
7408 assert(OldSAddrIdx == NewVAddrIdx);
7410 if (OldVAddrIdx >= 0) {
7411 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7412 AMDGPU::OpName::vdst_in);
7416 if (NewVDstIn != -1) {
7417 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7423 if (NewVDstIn != -1) {
7424 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7465 unsigned OpSubReg =
Op.getSubReg();
7468 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7475 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7476 .
addReg(OpReg, {}, OpSubReg);
7478 Op.setSubReg(AMDGPU::NoSubRegister);
7485 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7488 bool ImpDef = Def->isImplicitDef();
7489 while (!ImpDef && Def && Def->isCopy()) {
7490 if (Def->getOperand(1).getReg().isPhysical())
7493 ImpDef = Def && Def->isImplicitDef();
7495 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7511 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7516 bool UseNewExecInstructions =
7525 if (UseNewExecInstructions) {
7560 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7561 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7562 unsigned NumSubRegs =
RegSize / 32;
7563 Register VScalarOp = ScalarOp->getReg();
7566 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7568 if (NumSubRegs == 1) {
7571 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7572 Common != VScalarOpRC) {
7579 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7582 if (UseNewExecInstructions) {
7584 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7587 if (
I == LoopBB.
end())
7592 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7598 CondReg = NewCondReg;
7610 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7611 ScalarOp->setReg(CurReg);
7614 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7615 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7617 ScalarOp->setReg(PhySGPRs[Idx]);
7622 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7623 "Unhandled register size");
7625 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7632 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7633 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7636 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7637 .
addReg(VScalarOp, VScalarOpUndef,
7638 TRI->getSubRegFromChannel(Idx + 1));
7645 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7652 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7654 if (UseNewExecInstructions) {
7656 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7658 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7659 if (
I == LoopBB.
end())
7663 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7665 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7669 CondReg = NewCondReg;
7681 const auto *SScalarOpRC =
7687 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7688 unsigned Channel = 0;
7689 for (
Register Piece : ReadlanePieces) {
7690 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7694 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7695 ScalarOp->setReg(SScalarOp);
7697 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7698 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7700 ScalarOp->setReg(PhySGPRs[Idx]);
7708 if (!UseNewExecInstructions) {
7721 if (UseNewExecInstructions) {
7754 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7755 "Physical SGPRs must be empty or match the number of scalar operands");
7761 if (!Begin.isValid())
7763 if (!
End.isValid()) {
7769 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7778 std::numeric_limits<unsigned>::max()) !=
7796 for (
auto I = Begin;
I != AfterMI;
I++) {
7797 for (
auto &MO :
I->all_uses())
7833 for (
auto &Succ : RemainderBB->
successors()) {
7858static std::tuple<unsigned, unsigned>
7866 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7867 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7874 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7891 .
addImm(AMDGPU::sub0_sub1)
7897 return std::tuple(RsrcPtr, NewSRsrc);
7908 if (ST.useRealTrue16Insts())
7938 if (
MI.getOpcode() == AMDGPU::PHI) {
7940 assert(!RI.isSGPRClass(VRC));
7943 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7945 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7961 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7964 if (RI.hasVGPRs(DstRC)) {
7968 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7970 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7987 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7992 if (DstRC != Src0RC) {
8001 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
8003 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8009 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8010 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8011 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8012 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8013 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8014 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8015 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8017 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8030 ? AMDGPU::OpName::rsrc
8031 : AMDGPU::OpName::srsrc;
8036 AMDGPU::OpName SampOpName =
8037 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8046 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8054 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8058 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
8062 Src0.ChangeToRegister(Reg,
false);
8068 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8069 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8070 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8071 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8073 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8080 bool isSoffsetLegal =
true;
8082 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
8083 if (SoffsetIdx != -1) {
8087 isSoffsetLegal =
false;
8091 bool isRsrcLegal =
true;
8093 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8094 if (RsrcIdx != -1) {
8096 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
8097 isRsrcLegal =
false;
8101 if (isRsrcLegal && isSoffsetLegal)
8129 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8133 unsigned RsrcPtr, NewSRsrc;
8140 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8141 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8147 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8148 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8161 }
else if (!VAddr && ST.hasAddr64()) {
8165 "FIXME: Need to emit flat atomics here");
8167 unsigned RsrcPtr, NewSRsrc;
8193 MIB.
addImm(CPol->getImm());
8198 MIB.
addImm(TFE->getImm());
8218 MI.removeFromParent();
8223 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8224 .addImm(AMDGPU::sub0)
8225 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8226 .addImm(AMDGPU::sub1);
8229 if (!isSoffsetLegal) {
8240 if (!isSoffsetLegal) {
8249 if (InSet.insert(
MI).second)
8253 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8254 if (RsrcIdx != -1) {
8255 DeferredList.insert(
MI);
8260 return DeferredList.contains(
MI);
8270 if (!ST.useRealTrue16Insts())
8273 unsigned Opcode =
MI.getOpcode();
8276 if (OpIdx >=
MI.getNumExplicitOperands() ||
8277 OpIdx >=
get(Opcode).getNumOperands() ||
8278 get(Opcode).operands()[OpIdx].RegClass == -1)
8282 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8286 if (!RI.isVGPRClass(CurrRC))
8289 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8291 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8293 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8294 Op.setSubReg(AMDGPU::lo16);
8299 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8300 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8310 Op.setReg(NewDstReg);
8311 Op.setSubReg(AMDGPU::NoSubRegister);
8316 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8324 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8325 "This only handle waterfall for SI_CALL_ISEL");
8332 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8335 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8340 while (
End !=
MBB.end() &&
End->isCopy() &&
8341 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8351 while (!Worklist.
empty()) {
8357 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8363 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8365 "Deferred MachineInstr are not supposed to re-populate worklist");
8368 for (
auto &Entry : WaterFalls) {
8369 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8371 Entry.second.SGPRs);
8374 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8376 Entry.first->eraseFromParent();
8384 if (SubRegIndices.
size() <= 1) {
8387 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8394 for (int16_t Indice : SubRegIndices) {
8397 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8404 get(AMDGPU::REG_SEQUENCE), DstReg);
8405 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8407 MIB.
addImm(RI.getSubRegFromChannel(i));
8417 if (DstReg == AMDGPU::M0) {
8430 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8432 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8433 if (
UseMI->getOperand(i).isReg() &&
8434 UseMI->getOperand(i).getReg() == DstReg) {
8438 V2SCopyInfo.MOs.push_back(MO);
8439 V2SCopyInfo.SGPRs.push_back(DstReg);
8443 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8444 I->getOperand(0).isReg() &&
8445 I->getOperand(0).getReg() == DstReg) {
8448 }
else if (
I->readsRegister(DstReg, &RI)) {
8450 V2SPhyCopiesToErase[&Inst] =
false;
8452 if (
I->findRegisterDefOperand(DstReg, &RI))
8474 case AMDGPU::S_ADD_I32:
8475 case AMDGPU::S_SUB_I32: {
8479 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8487 case AMDGPU::S_MUL_U64:
8488 if (ST.useVMulU64Inst()) {
8489 NewOpcode = AMDGPU::V_MUL_U64_e64;
8493 splitScalarSMulU64(Worklist, Inst, MDT);
8497 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8498 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8501 splitScalarSMulPseudo(Worklist, Inst, MDT);
8505 case AMDGPU::S_AND_B64:
8506 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8510 case AMDGPU::S_OR_B64:
8511 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8515 case AMDGPU::S_XOR_B64:
8516 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8520 case AMDGPU::S_NAND_B64:
8521 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8525 case AMDGPU::S_NOR_B64:
8526 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8530 case AMDGPU::S_XNOR_B64:
8531 if (ST.hasDLInsts())
8532 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8534 splitScalar64BitXnor(Worklist, Inst, MDT);
8538 case AMDGPU::S_ANDN2_B64:
8539 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8543 case AMDGPU::S_ORN2_B64:
8544 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8548 case AMDGPU::S_BREV_B64:
8549 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8553 case AMDGPU::S_NOT_B64:
8554 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8558 case AMDGPU::S_BCNT1_I32_B64:
8559 splitScalar64BitBCNT(Worklist, Inst);
8563 case AMDGPU::S_BFE_I64:
8564 splitScalar64BitBFE(Worklist, Inst);
8568 case AMDGPU::S_FLBIT_I32_B64:
8569 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8572 case AMDGPU::S_FF1_I32_B64:
8573 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8577 case AMDGPU::S_LSHL_B32:
8578 if (ST.hasOnlyRevVALUShifts()) {
8579 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8583 case AMDGPU::S_ASHR_I32:
8584 if (ST.hasOnlyRevVALUShifts()) {
8585 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8589 case AMDGPU::S_LSHR_B32:
8590 if (ST.hasOnlyRevVALUShifts()) {
8591 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8595 case AMDGPU::S_LSHL_B64:
8596 if (ST.hasOnlyRevVALUShifts()) {
8598 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8599 : AMDGPU::V_LSHLREV_B64_e64;
8603 case AMDGPU::S_ASHR_I64:
8604 if (ST.hasOnlyRevVALUShifts()) {
8605 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8609 case AMDGPU::S_LSHR_B64:
8610 if (ST.hasOnlyRevVALUShifts()) {
8611 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8616 case AMDGPU::S_ABS_I32:
8617 lowerScalarAbs(Worklist, Inst);
8621 case AMDGPU::S_ABSDIFF_I32:
8622 lowerScalarAbsDiff(Worklist, Inst);
8626 case AMDGPU::S_CBRANCH_SCC0:
8627 case AMDGPU::S_CBRANCH_SCC1: {
8630 bool IsSCC = CondReg == AMDGPU::SCC;
8639 case AMDGPU::S_BFE_U64:
8640 case AMDGPU::S_BFM_B64:
8643 case AMDGPU::S_PACK_LL_B32_B16:
8644 case AMDGPU::S_PACK_LH_B32_B16:
8645 case AMDGPU::S_PACK_HL_B32_B16:
8646 case AMDGPU::S_PACK_HH_B32_B16:
8647 movePackToVALU(Worklist, MRI, Inst);
8651 case AMDGPU::S_XNOR_B32:
8652 lowerScalarXnor(Worklist, Inst);
8656 case AMDGPU::S_NAND_B32:
8657 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8661 case AMDGPU::S_NOR_B32:
8662 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8666 case AMDGPU::S_ANDN2_B32:
8667 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8671 case AMDGPU::S_ORN2_B32:
8672 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8680 case AMDGPU::S_ADD_CO_PSEUDO:
8681 case AMDGPU::S_SUB_CO_PSEUDO: {
8682 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8683 ? AMDGPU::V_ADDC_U32_e64
8684 : AMDGPU::V_SUBB_U32_e64;
8685 const auto *CarryRC = RI.getWaveMaskRegClass();
8707 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8711 case AMDGPU::S_UADDO_PSEUDO:
8712 case AMDGPU::S_USUBO_PSEUDO: {
8718 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8719 ? AMDGPU::V_ADD_CO_U32_e64
8720 : AMDGPU::V_SUB_CO_U32_e64;
8732 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8736 case AMDGPU::S_LSHL1_ADD_U32:
8737 case AMDGPU::S_LSHL2_ADD_U32:
8738 case AMDGPU::S_LSHL3_ADD_U32:
8739 case AMDGPU::S_LSHL4_ADD_U32: {
8743 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8744 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8745 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8759 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8763 case AMDGPU::S_CSELECT_B32:
8764 case AMDGPU::S_CSELECT_B64:
8765 lowerSelect(Worklist, Inst, MDT);
8768 case AMDGPU::S_CMP_EQ_I32:
8769 case AMDGPU::S_CMP_LG_I32:
8770 case AMDGPU::S_CMP_GT_I32:
8771 case AMDGPU::S_CMP_GE_I32:
8772 case AMDGPU::S_CMP_LT_I32:
8773 case AMDGPU::S_CMP_LE_I32:
8774 case AMDGPU::S_CMP_EQ_U32:
8775 case AMDGPU::S_CMP_LG_U32:
8776 case AMDGPU::S_CMP_GT_U32:
8777 case AMDGPU::S_CMP_GE_U32:
8778 case AMDGPU::S_CMP_LT_U32:
8779 case AMDGPU::S_CMP_LE_U32:
8780 case AMDGPU::S_CMP_EQ_U64:
8781 case AMDGPU::S_CMP_LG_U64:
8782 case AMDGPU::S_CMP_LT_F32:
8783 case AMDGPU::S_CMP_EQ_F32:
8784 case AMDGPU::S_CMP_LE_F32:
8785 case AMDGPU::S_CMP_GT_F32:
8786 case AMDGPU::S_CMP_LG_F32:
8787 case AMDGPU::S_CMP_GE_F32:
8788 case AMDGPU::S_CMP_O_F32:
8789 case AMDGPU::S_CMP_U_F32:
8790 case AMDGPU::S_CMP_NGE_F32:
8791 case AMDGPU::S_CMP_NLG_F32:
8792 case AMDGPU::S_CMP_NGT_F32:
8793 case AMDGPU::S_CMP_NLE_F32:
8794 case AMDGPU::S_CMP_NEQ_F32:
8795 case AMDGPU::S_CMP_NLT_F32: {
8800 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8814 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8818 case AMDGPU::S_CMP_LT_F16:
8819 case AMDGPU::S_CMP_EQ_F16:
8820 case AMDGPU::S_CMP_LE_F16:
8821 case AMDGPU::S_CMP_GT_F16:
8822 case AMDGPU::S_CMP_LG_F16:
8823 case AMDGPU::S_CMP_GE_F16:
8824 case AMDGPU::S_CMP_O_F16:
8825 case AMDGPU::S_CMP_U_F16:
8826 case AMDGPU::S_CMP_NGE_F16:
8827 case AMDGPU::S_CMP_NLG_F16:
8828 case AMDGPU::S_CMP_NGT_F16:
8829 case AMDGPU::S_CMP_NLE_F16:
8830 case AMDGPU::S_CMP_NEQ_F16:
8831 case AMDGPU::S_CMP_NLT_F16: {
8853 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8857 case AMDGPU::S_CVT_HI_F32_F16: {
8860 if (ST.useRealTrue16Insts()) {
8865 .
addReg(TmpReg, {}, AMDGPU::hi16)
8881 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8885 case AMDGPU::S_MINIMUM_F32:
8886 case AMDGPU::S_MAXIMUM_F32: {
8898 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8902 case AMDGPU::S_MINIMUM_F16:
8903 case AMDGPU::S_MAXIMUM_F16: {
8905 ? &AMDGPU::VGPR_16RegClass
8906 : &AMDGPU::VGPR_32RegClass);
8917 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8921 case AMDGPU::V_S_EXP_F16_e64:
8922 case AMDGPU::V_S_LOG_F16_e64:
8923 case AMDGPU::V_S_RCP_F16_e64:
8924 case AMDGPU::V_S_RSQ_F16_e64:
8925 case AMDGPU::V_S_SQRT_F16_e64: {
8927 ? &AMDGPU::VGPR_16RegClass
8928 : &AMDGPU::VGPR_32RegClass);
8939 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8945 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8953 if (NewOpcode == Opcode) {
8960 V2SPhyCopiesToErase);
8968 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8975 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8981 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8982 UseMO.setReg(NewDstReg);
9001 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
9014 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
9018 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9024 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9031 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9033 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9038 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9046 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9056 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9057 AMDGPU::OpName::src0_modifiers) >= 0)
9061 NewInstr->addOperand(Src);
9064 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9067 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9069 NewInstr.addImm(
Size);
9070 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9074 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9079 "Scalar BFE is only implemented for constant width and offset");
9087 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9088 AMDGPU::OpName::src1_modifiers) >= 0)
9090 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9092 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9093 AMDGPU::OpName::src2_modifiers) >= 0)
9095 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9097 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9099 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9101 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9107 NewInstr->addOperand(
Op);
9113 bool DeadSCCDef =
false;
9115 if (
Op.getReg() == AMDGPU::SCC) {
9121 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9125 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9130 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9131 Register DstReg = NewInstr->getOperand(0).getReg();
9145 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9146 VCCDef->setIsDead();
9152 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9156std::pair<bool, MachineBasicBlock *>
9159 if (ST.hasAddNoCarryInsts()) {
9171 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9173 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9174 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9185 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9186 return std::pair(
true, NewBB);
9189 return std::pair(
false,
nullptr);
9206 bool IsSCC = (CondReg == AMDGPU::SCC);
9212 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9213 (
Src1.getImm() == 0)) {
9214 for (MachineOperand &UseMO :
9216 MachineInstr &
UseMI = *UseMO.getParent();
9217 switch (
UseMI.getOpcode()) {
9218 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9219 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9220 case AMDGPU::V_CNDMASK_B16_t16_e32:
9221 case AMDGPU::V_CNDMASK_B16_t16_e64:
9222 case AMDGPU::V_CNDMASK_B32_e32:
9223 case AMDGPU::V_CNDMASK_B32_e64:
9224 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9225 if (UseMO.isImplicit() ||
9227 UseMO.setReg(CondReg);
9241 bool CopyFound =
false;
9242 for (MachineInstr &CandI :
9245 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9247 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9249 .
addReg(CandI.getOperand(1).getReg());
9261 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9270 MachineInstr *NewInst;
9271 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9272 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9287 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9302 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9304 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9306 MachineInstrBuilder
Sub =
9316 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9333 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9335 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9337 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9341 MachineInstrBuilder Sub2 =
9354 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9368 if (ST.hasDLInsts()) {
9378 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9384 bool Src0IsSGPR =
Src0.isReg() &&
9386 bool Src1IsSGPR =
Src1.isReg() &&
9400 }
else if (Src1IsSGPR) {
9418 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9424 unsigned Opcode)
const {
9448 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9453 unsigned Opcode)
const {
9477 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9492 const MCInstrDesc &InstDesc =
get(Opcode);
9495 &AMDGPU::SGPR_32RegClass;
9498 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9501 AMDGPU::sub0, Src0SubRC);
9506 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9509 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9512 AMDGPU::sub1, Src0SubRC);
9515 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9529 Worklist.
insert(&LoHalf);
9530 Worklist.
insert(&HiHalf);
9536 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9560 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9561 if (RI.isSGPRClass(Src0SubRC))
9562 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9564 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9565 if (RI.isSGPRClass(Src1SubRC))
9566 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9570 MachineOperand Op0L =
9572 MachineOperand Op1L =
9574 MachineOperand Op0H =
9576 MachineOperand Op1H =
9595 MachineInstr *Op1L_Op0H =
9601 MachineInstr *Op1H_Op0L =
9607 MachineInstr *Carry =
9612 MachineInstr *LoHalf =
9622 MachineInstr *HiHalf =
9645 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9669 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9670 if (RI.isSGPRClass(Src0SubRC))
9671 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9673 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9674 if (RI.isSGPRClass(Src1SubRC))
9675 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9679 MachineOperand Op0L =
9681 MachineOperand Op1L =
9685 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9686 ? AMDGPU::V_MUL_HI_U32_e64
9687 : AMDGPU::V_MUL_HI_I32_e64;
9688 MachineInstr *HiHalf =
9691 MachineInstr *LoHalf =
9710 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9726 const MCInstrDesc &InstDesc =
get(Opcode);
9729 &AMDGPU::SGPR_32RegClass;
9732 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9735 &AMDGPU::SGPR_32RegClass;
9738 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9741 AMDGPU::sub0, Src0SubRC);
9743 AMDGPU::sub0, Src1SubRC);
9745 AMDGPU::sub1, Src0SubRC);
9747 AMDGPU::sub1, Src1SubRC);
9752 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9755 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9760 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9773 Worklist.
insert(&LoHalf);
9774 Worklist.
insert(&HiHalf);
9777 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9797 MachineOperand* Op0;
9798 MachineOperand* Op1;
9800 if (
Src0.isReg() && RI.isSGPRReg(MRI,
Src0.getReg())) {
9833 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9836 &AMDGPU::SGPR_32RegClass;
9842 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9845 AMDGPU::sub0, SrcSubRC);
9847 AMDGPU::sub1, SrcSubRC);
9857 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9876 Offset == 0 &&
"Not implemented");
9899 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9909 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9912 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9918 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9937 const MCInstrDesc &InstDesc =
get(Opcode);
9939 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9942 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9944 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9946 MachineOperand SrcRegSub0 =
9948 MachineOperand SrcRegSub1 =
9962 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9966 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9970 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9973void SIInstrInfo::addUsersToMoveToVALUWorklist(
9977 MachineInstr &
UseMI = *MO.getParent();
9981 switch (
UseMI.getOpcode()) {
9984 case AMDGPU::SOFT_WQM:
9985 case AMDGPU::STRICT_WWM:
9986 case AMDGPU::STRICT_WQM:
9987 case AMDGPU::REG_SEQUENCE:
9989 case AMDGPU::INSERT_SUBREG:
9992 OpNo = MO.getOperandNo();
9999 if (!RI.hasVectorRegisters(OpRC))
10016 if (ST.useRealTrue16Insts()) {
10018 if (!
Src0.isReg() || !RI.isVGPR(MRI,
Src0.getReg())) {
10021 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10024 SrcReg0 =
Src0.getReg();
10027 if (!
Src1.isReg() || !RI.isVGPR(MRI,
Src1.getReg())) {
10030 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10033 SrcReg1 =
Src1.getReg();
10039 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
10041 case AMDGPU::S_PACK_LL_B32_B16:
10043 .addReg(SrcReg0, {},
10044 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10045 .addImm(AMDGPU::lo16)
10046 .addReg(SrcReg1, {},
10047 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::hi16);
10050 case AMDGPU::S_PACK_LH_B32_B16:
10052 .addReg(SrcReg0, {},
10053 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10054 .addImm(AMDGPU::lo16)
10055 .addReg(SrcReg1, {}, AMDGPU::hi16)
10056 .addImm(AMDGPU::hi16);
10058 case AMDGPU::S_PACK_HL_B32_B16:
10059 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10060 .addImm(AMDGPU::lo16)
10061 .addReg(SrcReg1, {},
10062 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10063 .addImm(AMDGPU::hi16);
10065 case AMDGPU::S_PACK_HH_B32_B16:
10066 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10067 .addImm(AMDGPU::lo16)
10068 .addReg(SrcReg1, {}, AMDGPU::hi16)
10069 .addImm(AMDGPU::hi16);
10077 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10082 case AMDGPU::S_PACK_LL_B32_B16: {
10101 case AMDGPU::S_PACK_LH_B32_B16: {
10111 case AMDGPU::S_PACK_HL_B32_B16: {
10122 case AMDGPU::S_PACK_HH_B32_B16: {
10142 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10151 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10152 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10153 SmallVector<MachineInstr *, 4> CopyToDelete;
10156 for (MachineInstr &
MI :
10160 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10161 if (SCCIdx != -1) {
10164 Register DestReg =
MI.getOperand(0).getReg();
10171 MI.getOperand(SCCIdx).setReg(NewCond);
10177 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10180 for (
auto &Copy : CopyToDelete)
10181 Copy->eraseFromParent();
10189void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10195 for (MachineInstr &
MI :
10198 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10200 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10217 case AMDGPU::REG_SEQUENCE:
10218 case AMDGPU::INSERT_SUBREG:
10220 case AMDGPU::SOFT_WQM:
10221 case AMDGPU::STRICT_WWM:
10222 case AMDGPU::STRICT_WQM: {
10224 if (RI.isAGPRClass(SrcRC)) {
10225 if (RI.isAGPRClass(NewDstRC))
10230 case AMDGPU::REG_SEQUENCE:
10231 case AMDGPU::INSERT_SUBREG:
10232 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10235 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10241 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10244 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10258 int OpIndices[3])
const {
10259 const MCInstrDesc &
Desc =
MI.getDesc();
10277 for (
unsigned i = 0; i < 3; ++i) {
10278 int Idx = OpIndices[i];
10282 const MachineOperand &MO =
MI.getOperand(Idx);
10289 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10290 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10291 if (IsRequiredSGPR)
10297 if (RI.isSGPRClass(RegRC))
10298 UsedSGPRs[i] =
Reg;
10314 if (UsedSGPRs[0]) {
10315 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10316 SGPRReg = UsedSGPRs[0];
10319 if (!SGPRReg && UsedSGPRs[1]) {
10320 if (UsedSGPRs[1] == UsedSGPRs[2])
10321 SGPRReg = UsedSGPRs[1];
10328 AMDGPU::OpName OperandName)
const {
10329 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10332 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10336 return &
MI.getOperand(Idx);
10350 if (ST.isAmdHsaOS()) {
10353 RsrcDataFormat |= (1ULL << 56);
10358 RsrcDataFormat |= (2ULL << 59);
10361 return RsrcDataFormat;
10371 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10376 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10383 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10389 unsigned Opc =
MI.getOpcode();
10395 return get(
Opc).mayLoad() &&
10402 if (!Addr || !Addr->
isFI())
10411 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10413 return MI.getOperand(VDataIdx).getReg();
10423 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10425 return MI.getOperand(DataIdx).getReg();
10446 if (!
MI.mayStore())
10459 unsigned Opc =
MI.getOpcode();
10461 unsigned DescSize =
Desc.getSize();
10466 unsigned Size = DescSize;
10470 if (
MI.isBranch() && ST.hasOffset3fBug())
10481 bool HasLiteral =
false;
10482 unsigned LiteralSize = 4;
10483 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10488 if (ST.has64BitLiterals()) {
10489 switch (OpInfo.OperandType) {
10514 return HasLiteral ? DescSize + LiteralSize : DescSize;
10519 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10523 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10524 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10528 case TargetOpcode::BUNDLE:
10529 return getInstBundleSize(
MI);
10530 case TargetOpcode::INLINEASM:
10531 case TargetOpcode::INLINEASM_BR: {
10533 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10537 if (
MI.isMetaInstruction())
10541 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10544 unsigned LoInstOpcode = D16Info->LoOp;
10546 DescSize =
Desc.getSize();
10550 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10553 DescSize =
Desc.getSize();
10562 if (
MI.isBranch() && ST.hasOffset3fBug())
10563 return InstSizeVerifyMode::NoVerify;
10564 return InstSizeVerifyMode::ExactSize;
10569 static const std::pair<int, const char *> TargetIndices[] = {
10609std::pair<unsigned, unsigned>
10616 static const std::pair<unsigned, const char *> TargetFlags[] = {
10634 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10650 return AMDGPU::WWM_COPY;
10652 return AMDGPU::COPY;
10669 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10673 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10674 return IsLRSplitInst;
10687 bool IsNullOrVectorRegister =
true;
10691 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10694 return IsNullOrVectorRegister &&
10696 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10697 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10705 if (ST.hasAddNoCarryInsts())
10721 if (ST.hasAddNoCarryInsts())
10725 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10727 : RS.scavengeRegisterBackwards(
10728 *RI.getBoolRC(),
I,
false,
10741 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10742 case AMDGPU::SI_KILL_I1_TERMINATOR:
10751 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10752 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10753 case AMDGPU::SI_KILL_I1_PSEUDO:
10754 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10766 const unsigned OffsetBits =
10768 return (1 << OffsetBits) - 1;
10772 if (!ST.isWave32())
10775 if (
MI.isInlineAsm())
10778 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10781 for (
auto &
Op :
MI.implicit_operands()) {
10782 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10783 Op.setReg(AMDGPU::VCC_LO);
10792 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10796 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10797 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10813 if (
Imm > MaxImm) {
10814 if (
Imm <= MaxImm + 64) {
10816 Overflow =
Imm - MaxImm;
10831 Overflow =
High - Alignment.value();
10835 if (Overflow > 0) {
10843 if (ST.hasRestrictedSOffset())
10848 SOffset = Overflow;
10886 if (!ST.hasFlatInstOffsets())
10890 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10895 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10896 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10907std::pair<int64_t, int64_t>
10910 int64_t RemainderOffset = COffsetVal;
10911 int64_t ImmField = 0;
10916 if (AllowNegative) {
10918 int64_t
D = 1LL << NumBits;
10919 RemainderOffset = (COffsetVal /
D) *
D;
10920 ImmField = COffsetVal - RemainderOffset;
10922 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10924 (ImmField % 4) != 0) {
10926 RemainderOffset += ImmField % 4;
10927 ImmField -= ImmField % 4;
10929 }
else if (COffsetVal >= 0) {
10931 RemainderOffset = COffsetVal - ImmField;
10935 assert(RemainderOffset + ImmField == COffsetVal);
10936 return {ImmField, RemainderOffset};
10941 if (ST.hasNegativeScratchOffsetBug() &&
10949 switch (ST.getGeneration()) {
10983 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10984 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10985 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10986 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10987 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10988 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10989 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10990 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10997#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10998 case OPCODE##_dpp: \
10999 case OPCODE##_e32: \
11013 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11014 case AMDGPU::V_FMA_F16_gfx9_e64:
11015 case AMDGPU::V_INTERP_P2_F16:
11016 case AMDGPU::V_MAD_F16_e64:
11017 case AMDGPU::V_MAD_U16_e64:
11018 case AMDGPU::V_MAD_I16_e64:
11027 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11035 switch (ST.getGeneration()) {
11048 if (
isMAI(Opcode)) {
11062 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11065 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11072 if (ST.hasGFX90AInsts()) {
11073 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11074 if (ST.hasGFX940Insts())
11076 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11078 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11080 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11086 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11105 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11106 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11107 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11119 switch (
MI.getOpcode()) {
11121 case AMDGPU::REG_SEQUENCE:
11125 case AMDGPU::INSERT_SUBREG:
11126 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11143 if (!
P.Reg.isVirtual())
11148 while (
auto *
MI = DefInst) {
11150 switch (
MI->getOpcode()) {
11152 case AMDGPU::V_MOV_B32_e32: {
11153 auto &Op1 =
MI->getOperand(1);
11182 auto *DefBB =
DefMI.getParent();
11186 if (
UseMI.getParent() != DefBB)
11189 const int MaxInstScan = 20;
11193 auto E =
UseMI.getIterator();
11194 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11195 if (
I->isDebugInstr())
11198 if (++NumInst > MaxInstScan)
11201 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11214 auto *DefBB =
DefMI.getParent();
11216 const int MaxUseScan = 10;
11220 auto &UseInst = *
Use.getParent();
11223 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11226 if (++NumUse > MaxUseScan)
11233 const int MaxInstScan = 20;
11237 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11240 if (
I->isDebugInstr())
11243 if (++NumInst > MaxInstScan)
11256 if (Reg == VReg && --NumUse == 0)
11258 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11267 auto Cur =
MBB.begin();
11268 if (Cur !=
MBB.end())
11270 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11273 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11282 if (InsPt !=
MBB.end() &&
11283 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11284 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11285 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11286 InsPt->definesRegister(Src,
nullptr)) {
11290 .
addReg(Src, {}, SrcSubReg)
11333 if (isFullCopyInstr(
MI)) {
11334 Register DstReg =
MI.getOperand(0).getReg();
11335 Register SrcReg =
MI.getOperand(1).getReg();
11357 unsigned *PredCost)
const {
11358 if (
MI.isBundle()) {
11361 unsigned Lat = 0,
Count = 0;
11362 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11364 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11366 return Lat +
Count - 1;
11369 return SchedModel.computeInstrLatency(&
MI);
11373 if (!ST.hasGFX1250VALUBlockingCycles())
11380 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11381 return Entry->GFX1250BlockingCycles;
11389 return *CallAddrOp;
11396 unsigned Opcode =
MI.getOpcode();
11398 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11404 unsigned SrcAS = SrcTy.getAddressSpace();
11407 ST.hasGloballyAddressableScratch()
11415 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11416 return HandleAddrSpaceCast(
MI);
11419 auto IID = GI->getIntrinsicID();
11426 case Intrinsic::amdgcn_if:
11427 case Intrinsic::amdgcn_else:
11441 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11442 Opcode == AMDGPU::G_SEXTLOAD) {
11443 if (
MI.memoperands_empty())
11447 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11448 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11456 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11457 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11458 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11464 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11467 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11475 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11476 return Formatter.get();
11484 unsigned opcode =
MI.getOpcode();
11485 if (opcode == AMDGPU::V_READLANE_B32 ||
11486 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11487 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11492 if (
MI.isInlineAsm()) {
11498 if (!RC || !RI.isSGPRClass(RC))
11503 if (isCopyInstr(
MI)) {
11507 RI.getPhysRegBaseClass(srcOp.
getReg());
11515 if (
MI.isPreISelOpcode())
11530 if (
MI.memoperands_empty())
11534 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11535 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11550 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11552 if (!
SrcOp.isReg())
11556 if (!Reg || !
SrcOp.readsReg())
11562 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11589 F,
"ds_ordered_count unsupported for this calling conv"));
11603 Register &SrcReg2, int64_t &CmpMask,
11604 int64_t &CmpValue)
const {
11605 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11608 switch (
MI.getOpcode()) {
11611 case AMDGPU::S_CMP_EQ_U32:
11612 case AMDGPU::S_CMP_EQ_I32:
11613 case AMDGPU::S_CMP_LG_U32:
11614 case AMDGPU::S_CMP_LG_I32:
11615 case AMDGPU::S_CMP_LT_U32:
11616 case AMDGPU::S_CMP_LT_I32:
11617 case AMDGPU::S_CMP_GT_U32:
11618 case AMDGPU::S_CMP_GT_I32:
11619 case AMDGPU::S_CMP_LE_U32:
11620 case AMDGPU::S_CMP_LE_I32:
11621 case AMDGPU::S_CMP_GE_U32:
11622 case AMDGPU::S_CMP_GE_I32:
11623 case AMDGPU::S_CMP_EQ_U64:
11624 case AMDGPU::S_CMP_LG_U64:
11625 SrcReg =
MI.getOperand(0).getReg();
11626 if (
MI.getOperand(1).isReg()) {
11627 if (
MI.getOperand(1).getSubReg())
11629 SrcReg2 =
MI.getOperand(1).getReg();
11631 }
else if (
MI.getOperand(1).isImm()) {
11633 CmpValue =
MI.getOperand(1).getImm();
11639 case AMDGPU::S_CMPK_EQ_U32:
11640 case AMDGPU::S_CMPK_EQ_I32:
11641 case AMDGPU::S_CMPK_LG_U32:
11642 case AMDGPU::S_CMPK_LG_I32:
11643 case AMDGPU::S_CMPK_LT_U32:
11644 case AMDGPU::S_CMPK_LT_I32:
11645 case AMDGPU::S_CMPK_GT_U32:
11646 case AMDGPU::S_CMPK_GT_I32:
11647 case AMDGPU::S_CMPK_LE_U32:
11648 case AMDGPU::S_CMPK_LE_I32:
11649 case AMDGPU::S_CMPK_GE_U32:
11650 case AMDGPU::S_CMPK_GE_I32:
11651 SrcReg =
MI.getOperand(0).getReg();
11653 CmpValue =
MI.getOperand(1).getImm();
11663 if (S->isLiveIn(AMDGPU::SCC))
11672bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11675 bool SCCIsDead =
false;
11678 constexpr unsigned ScanLimit = 12;
11679 unsigned Count = 0;
11682 if (++
Count > ScanLimit)
11684 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11685 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11686 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11687 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11688 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11693 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11706 for (MachineInstr *
MI : InvertInstr) {
11707 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11708 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11710 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11711 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11712 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11713 ? AMDGPU::S_CBRANCH_SCC1
11714 : AMDGPU::S_CBRANCH_SCC0));
11727 bool NeedInversion)
const {
11728 MachineInstr *KillsSCC =
nullptr;
11733 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11735 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11738 if (NeedInversion && !invertSCCUse(SCCRedefine))
11740 if (MachineOperand *SccDef =
11742 SccDef->setIsDead(
false);
11751static std::optional<std::pair<int64_t, int64_t>>
11755 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11757 std::optional<int64_t>
A =
11761 std::optional<int64_t>
B =
11765 if (
Opc == AMDGPU::S_CSELECT_B32) {
11771 return std::pair(*
A, *
B);
11775 unsigned &NewDefOpc) {
11778 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11779 Def.getOpcode() != AMDGPU::S_ADD_U32)
11785 Def.getMF()->getSubtarget().getInstrInfo());
11787 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11788 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11789 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11792 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11794 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11797 NewDefOpc = AMDGPU::S_ADD_U32;
11799 NeedInversion = !NeedInversion;
11804 Register SrcReg2, int64_t CmpMask,
11814 CmpValue = *ImmOpt;
11817 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11818 this](
bool NeedInversion) ->
bool {
11823 unsigned NewDefOpc = Def->getOpcode();
11830 auto [
A,
B] = *Consts;
11831 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11834 NeedInversion = !NeedInversion;
11846 if (CmpValue != 0 ||
11852 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11855 if (NewDefOpc != Def->getOpcode())
11856 Def->setDesc(
get(NewDefOpc));
11865 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11872 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11881 auto [
A,
B] = *Consts;
11882 if (
A == 0 ||
B == 0)
11883 optimizeSCC(
Select, Def,
A == 0);
11892 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11893 this](int64_t ExpectedValue,
unsigned SrcSize,
11894 bool IsReversible,
bool IsSigned) ->
bool {
11922 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11923 Def->getOpcode() != AMDGPU::S_AND_B64)
11927 const auto isMask = [&Mask, SrcSize, MRI,
11939 SrcOp = &Def->getOperand(2);
11940 else if (isMask(&Def->getOperand(2)))
11941 SrcOp = &Def->getOperand(1);
11949 if (IsSigned && BitNo == SrcSize - 1)
11952 ExpectedValue <<= BitNo;
11954 bool IsReversedCC =
false;
11955 if (CmpValue != ExpectedValue) {
11958 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11963 Register DefReg = Def->getOperand(0).getReg();
11964 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11967 if (!optimizeSCC(Def, &CmpInstr,
false))
11970 if (!MRI->use_nodbg_empty(DefReg)) {
11978 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11979 : AMDGPU::S_BITCMP1_B32
11980 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11981 : AMDGPU::S_BITCMP1_B64;
11986 Def->eraseFromParent();
11994 case AMDGPU::S_CMP_EQ_U32:
11995 case AMDGPU::S_CMP_EQ_I32:
11996 case AMDGPU::S_CMPK_EQ_U32:
11997 case AMDGPU::S_CMPK_EQ_I32:
11998 return optimizeCmpAnd(1, 32,
true,
false) ||
11999 optimizeCmpSelect(
true);
12000 case AMDGPU::S_CMP_GE_U32:
12001 case AMDGPU::S_CMPK_GE_U32:
12002 return optimizeCmpAnd(1, 32,
false,
false);
12003 case AMDGPU::S_CMP_GE_I32:
12004 case AMDGPU::S_CMPK_GE_I32:
12005 return optimizeCmpAnd(1, 32,
false,
true);
12006 case AMDGPU::S_CMP_EQ_U64:
12007 return optimizeCmpAnd(1, 64,
true,
false) ||
12008 optimizeCmpSelect(
true);
12009 case AMDGPU::S_CMP_LG_U32:
12010 case AMDGPU::S_CMP_LG_I32:
12011 case AMDGPU::S_CMPK_LG_U32:
12012 case AMDGPU::S_CMPK_LG_I32:
12013 return optimizeCmpAnd(0, 32,
true,
false) ||
12014 optimizeCmpSelect(
false);
12015 case AMDGPU::S_CMP_GT_U32:
12016 case AMDGPU::S_CMPK_GT_U32:
12017 return optimizeCmpAnd(0, 32,
false,
false);
12018 case AMDGPU::S_CMP_GT_I32:
12019 case AMDGPU::S_CMPK_GT_I32:
12020 return optimizeCmpAnd(0, 32,
false,
true);
12021 case AMDGPU::S_CMP_LG_U64:
12022 return optimizeCmpAnd(0, 64,
true,
false) ||
12023 optimizeCmpSelect(
false);
12030 AMDGPU::OpName
OpName)
const {
12031 if (!ST.needsAlignedVGPRs())
12034 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
12046 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12048 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12052 : &AMDGPU::VReg_64_Align2RegClass);
12054 .
addReg(DataReg, {},
Op.getSubReg())
12059 Op.setSubReg(AMDGPU::sub0);
12064 if (!SchedModel.hasInstrSchedModel())
12070 unsigned RepeatRate = 0;
12072 PI = SchedModel.getWriteProcResBegin(SCDesc),
12073 PE = SchedModel.getWriteProcResEnd(SCDesc);
12075 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12092 if (ST.hasGFX1250Insts())
12099 unsigned Opcode =
MI.getOpcode();
12105 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12106 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12109 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
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
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...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
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 void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
const MachineFunction & getMF() const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
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 removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
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)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
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.
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...
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.
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.