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() || std::next(
MI.getIterator()) !=
MBB.end()) {
2063 MBB.splitAt(
MI,
false);
2067 MBB.addSuccessor(TrapBB);
2077 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2081 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2087 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2088 .
addUse(DoorbellRegMasked)
2089 .
addImm(ECQueueWaveAbort)
2091 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2092 .
addUse(SetWaveAbortBit);
2095 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2106 return MBB.getNextNode();
2110 switch (
MI.getOpcode()) {
2112 if (
MI.isMetaInstruction())
2117 return MI.getOperand(0).getImm() + 1;
2128 switch (
MI.getOpcode()) {
2130 case AMDGPU::S_MOV_B64_term:
2133 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2136 case AMDGPU::S_MOV_B32_term:
2139 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2142 case AMDGPU::S_XOR_B64_term:
2145 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2148 case AMDGPU::S_XOR_B32_term:
2151 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2153 case AMDGPU::S_OR_B64_term:
2156 MI.setDesc(
get(AMDGPU::S_OR_B64));
2158 case AMDGPU::S_OR_B32_term:
2161 MI.setDesc(
get(AMDGPU::S_OR_B32));
2164 case AMDGPU::S_ANDN2_B64_term:
2167 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2170 case AMDGPU::S_ANDN2_B32_term:
2173 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2176 case AMDGPU::S_AND_B64_term:
2179 MI.setDesc(
get(AMDGPU::S_AND_B64));
2182 case AMDGPU::S_AND_B32_term:
2185 MI.setDesc(
get(AMDGPU::S_AND_B32));
2188 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2191 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2194 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2197 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2200 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2201 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2203 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2204 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2207 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2208 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2211 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2212 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2214 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2218 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2221 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2224 int64_t
Imm =
MI.getOperand(1).getImm();
2226 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2227 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2232 MI.eraseFromParent();
2238 case AMDGPU::V_MOV_B64_PSEUDO: {
2240 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2241 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2249 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2250 MI.setDesc(Mov64Desc);
2254 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2257 if (
SrcOp.isGlobal()) {
2262 unsigned BaseFlags, LoReloc, HiReloc;
2263 std::tie(BaseFlags, LoReloc, HiReloc) =
2270 }
else if (
SrcOp.isImm()) {
2272 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2273 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2297 if (ST.hasPkMovB32() &&
2316 MI.eraseFromParent();
2319 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2323 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2327 if (ST.has64BitLiterals()) {
2328 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2332 if (
SrcOp.isGlobal()) {
2334 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2335 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2338 unsigned BaseFlags, LoReloc, HiReloc;
2339 std::tie(BaseFlags, LoReloc, HiReloc) =
2346 MI.eraseFromParent();
2353 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2358 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2359 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2361 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2362 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2367 MI.eraseFromParent();
2370 case AMDGPU::V_SET_INACTIVE_B32: {
2374 .
add(
MI.getOperand(3))
2375 .
add(
MI.getOperand(4))
2376 .
add(
MI.getOperand(1))
2377 .
add(
MI.getOperand(2))
2378 .
add(
MI.getOperand(5));
2379 MI.eraseFromParent();
2382 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2383 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2396 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2397 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2418 if (RI.hasVGPRs(EltRC)) {
2419 Opc = AMDGPU::V_MOVRELD_B32_e32;
2421 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2422 : AMDGPU::S_MOVRELD_B32;
2427 bool IsUndef =
MI.getOperand(1).isUndef();
2428 unsigned SubReg =
MI.getOperand(3).getImm();
2429 assert(VecReg ==
MI.getOperand(1).getReg());
2434 .
add(
MI.getOperand(2))
2438 const int ImpDefIdx =
2440 const int ImpUseIdx = ImpDefIdx + 1;
2442 MI.eraseFromParent();
2445 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2446 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2459 assert(ST.useVGPRIndexMode());
2461 bool IsUndef =
MI.getOperand(1).isUndef();
2470 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2474 .
add(
MI.getOperand(2))
2478 const int ImpDefIdx =
2480 const int ImpUseIdx = ImpDefIdx + 1;
2487 MI.eraseFromParent();
2490 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2491 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2504 assert(ST.useVGPRIndexMode());
2507 bool IsUndef =
MI.getOperand(1).isUndef();
2511 .
add(
MI.getOperand(2))
2524 MI.eraseFromParent();
2527 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2530 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2531 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2550 if (ST.hasGetPCZeroExtension()) {
2554 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2561 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2571 MI.eraseFromParent();
2574 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2584 Op.setOffset(
Op.getOffset() + 4);
2586 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2590 MI.eraseFromParent();
2593 case AMDGPU::ENTER_STRICT_WWM: {
2599 case AMDGPU::ENTER_STRICT_WQM: {
2606 MI.eraseFromParent();
2609 case AMDGPU::EXIT_STRICT_WWM:
2610 case AMDGPU::EXIT_STRICT_WQM: {
2616 case AMDGPU::SI_RETURN: {
2630 MI.eraseFromParent();
2634 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2635 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2636 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2639 case AMDGPU::S_GETPC_B64_pseudo:
2640 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2641 if (ST.hasGetPCZeroExtension()) {
2643 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2652 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2653 assert(ST.hasBF16PackedInsts());
2654 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2665 case AMDGPU::GET_STACK_BASE:
2668 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2675 Register DestReg =
MI.getOperand(0).getReg();
2685 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2686 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2687 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2690 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2693 MI.getNumExplicitOperands());
2711 case AMDGPU::S_MOV_B64:
2712 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2721 if (UsedLanes.
all())
2726 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2727 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2729 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2730 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2732 if (NeedLo && NeedHi)
2736 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2738 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2747 case AMDGPU::S_LOAD_DWORDX16_IMM:
2748 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2761 for (
auto &CandMO :
I->operands()) {
2762 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2770 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2780 unsigned NewOpcode = -1;
2781 if (SubregSize == 256)
2782 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2783 else if (SubregSize == 128)
2784 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2794 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2799 MI->getOperand(0).setReg(DestReg);
2800 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2804 OffsetMO->
setImm(FinalOffset);
2810 MI->setMemRefs(*MF, NewMMOs);
2823std::pair<MachineInstr*, MachineInstr*>
2825 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2827 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2830 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2831 return std::pair(&
MI,
nullptr);
2842 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2844 if (Dst.isPhysical()) {
2845 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2852 for (
unsigned I = 1;
I <= 2; ++
I) {
2855 if (
SrcOp.isImm()) {
2857 Imm.ashrInPlace(Part * 32);
2858 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2862 if (Src.isPhysical())
2863 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2870 MovDPP.addImm(MO.getImm());
2872 Split[Part] = MovDPP;
2876 if (Dst.isVirtual())
2883 MI.eraseFromParent();
2884 return std::pair(Split[0], Split[1]);
2887std::optional<DestSourcePair>
2889 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2892 return std::nullopt;
2896 AMDGPU::OpName Src0OpName,
2898 AMDGPU::OpName Src1OpName)
const {
2905 "All commutable instructions have both src0 and src1 modifiers");
2907 int Src0ModsVal = Src0Mods->
getImm();
2908 int Src1ModsVal = Src1Mods->
getImm();
2910 Src1Mods->
setImm(Src0ModsVal);
2911 Src0Mods->
setImm(Src1ModsVal);
2920 bool IsKill = RegOp.
isKill();
2922 bool IsUndef = RegOp.
isUndef();
2923 bool IsDebug = RegOp.
isDebug();
2925 if (NonRegOp.
isImm())
2927 else if (NonRegOp.
isFI())
2948 int64_t NonRegVal = NonRegOp1.
getImm();
2951 NonRegOp2.
setImm(NonRegVal);
2958 unsigned OpIdx1)
const {
2963 unsigned Opc =
MI.getOpcode();
2964 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2974 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2977 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2982 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2988 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3010 unsigned Src1Idx)
const {
3011 assert(!NewMI &&
"this should never be used");
3016 unsigned Opc =
MI.getOpcode();
3018 if (CommutedOpcode == -1)
3021 if (Src0Idx > Src1Idx)
3024 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3025 static_cast<int>(Src0Idx) &&
3026 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3027 static_cast<int>(Src1Idx) &&
3028 "inconsistency with findCommutedOpIndices");
3036 if (Src0.isReg() && Src1.isReg()) {
3040 }
else if (Src0.isReg() && !Src1.isReg()) {
3042 }
else if (!Src0.isReg() && Src1.isReg()) {
3044 }
else if (Src0.isImm() && Src1.isImm()) {
3053 Src1, AMDGPU::OpName::src1_modifiers);
3056 AMDGPU::OpName::src1_sel);
3068 unsigned &SrcOpIdx0,
3069 unsigned &SrcOpIdx1)
const {
3077 unsigned &SrcOpIdx0,
3078 unsigned &SrcOpIdx1)
const {
3079 if (!
Desc.isCommutable())
3082 unsigned Opc =
Desc.getOpcode();
3083 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3087 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3091 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3095 int64_t BrOffset)
const {
3112 return MI.getOperand(0).getMBB();
3117 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3118 MI.getOpcode() == AMDGPU::SI_LOOP ||
3119 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3131 "new block should be inserted for expanding unconditional branch");
3134 "restore block should be inserted for restoring clobbered registers");
3142 if (ST.useAddPC64Inst()) {
3144 MCCtx.createTempSymbol(
"offset",
true);
3148 MCCtx.createTempSymbol(
"post_addpc",
true);
3149 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3153 Offset->setVariableValue(OffsetExpr);
3157 assert(RS &&
"RegScavenger required for long branching");
3165 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3166 ST.hasVALUReadSGPRHazard();
3167 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3168 if (FlushSGPRWrites)
3176 ApplyHazardWorkarounds();
3179 MCCtx.createTempSymbol(
"post_getpc",
true);
3183 MCCtx.createTempSymbol(
"offset_lo",
true);
3185 MCCtx.createTempSymbol(
"offset_hi",
true);
3188 .
addReg(PCReg, {}, AMDGPU::sub0)
3192 .
addReg(PCReg, {}, AMDGPU::sub1)
3194 ApplyHazardWorkarounds();
3235 if (LongBranchReservedReg) {
3236 RS->enterBasicBlock(
MBB);
3237 Scav = LongBranchReservedReg;
3239 RS->enterBasicBlockEnd(
MBB);
3240 Scav = RS->scavengeRegisterBackwards(
3245 RS->setRegUsed(Scav);
3253 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3270unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3272 case SIInstrInfo::SCC_TRUE:
3273 return AMDGPU::S_CBRANCH_SCC1;
3274 case SIInstrInfo::SCC_FALSE:
3275 return AMDGPU::S_CBRANCH_SCC0;
3276 case SIInstrInfo::VCCNZ:
3277 return AMDGPU::S_CBRANCH_VCCNZ;
3278 case SIInstrInfo::VCCZ:
3279 return AMDGPU::S_CBRANCH_VCCZ;
3280 case SIInstrInfo::EXECNZ:
3281 return AMDGPU::S_CBRANCH_EXECNZ;
3282 case SIInstrInfo::EXECZ:
3283 return AMDGPU::S_CBRANCH_EXECZ;
3289SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3291 case AMDGPU::S_CBRANCH_SCC0:
3293 case AMDGPU::S_CBRANCH_SCC1:
3295 case AMDGPU::S_CBRANCH_VCCNZ:
3297 case AMDGPU::S_CBRANCH_VCCZ:
3299 case AMDGPU::S_CBRANCH_EXECNZ:
3301 case AMDGPU::S_CBRANCH_EXECZ:
3313 bool AllowModify)
const {
3314 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3316 TBB =
I->getOperand(0).getMBB();
3320 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3321 if (Pred == INVALID_BR)
3326 Cond.push_back(
I->getOperand(1));
3330 if (
I ==
MBB.end()) {
3336 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3338 FBB =
I->getOperand(0).getMBB();
3348 bool AllowModify)
const {
3356 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3357 switch (
I->getOpcode()) {
3358 case AMDGPU::S_MOV_B64_term:
3359 case AMDGPU::S_XOR_B64_term:
3360 case AMDGPU::S_OR_B64_term:
3361 case AMDGPU::S_ANDN2_B64_term:
3362 case AMDGPU::S_AND_B64_term:
3363 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3364 case AMDGPU::S_MOV_B32_term:
3365 case AMDGPU::S_XOR_B32_term:
3366 case AMDGPU::S_OR_B32_term:
3367 case AMDGPU::S_ANDN2_B32_term:
3368 case AMDGPU::S_AND_B32_term:
3369 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3370 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3371 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3374 case AMDGPU::SI_ELSE:
3375 case AMDGPU::SI_KILL_I1_TERMINATOR:
3376 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3393 int *BytesRemoved)
const {
3395 unsigned RemovedSize = 0;
3398 if (
MI.isBranch() ||
MI.isReturn()) {
3400 MI.eraseFromParent();
3406 *BytesRemoved = RemovedSize;
3423 int *BytesAdded)
const {
3424 if (!FBB &&
Cond.empty()) {
3428 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3435 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3447 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3465 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3472 if (
Cond.size() != 2) {
3476 if (
Cond[0].isImm()) {
3497 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3501 std::optional<bool> createTripCountGreaterCondition(
3502 int TC, MachineBasicBlock &
MBB,
3503 SmallVectorImpl<MachineOperand> &CondParam)
override {
3504 CondParam = this->
Cond;
3508 void adjustTripCount(
int TripCountAdjust)
override {}
3510 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3514std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3523 if (
TBB == LoopBB && FBB == LoopBB)
3530 assert((
TBB == LoopBB || FBB == LoopBB) &&
3531 "The Loop must be a single-basic-block loop");
3534 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3535 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3540 if (
MI.isCall() ||
MI.isInlineAsm())
3555 if (CmpI == Instructions.end() || CmpI->isPHI())
3559 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3566 SelectExpansion &Exp)
const {
3576 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3579 return RI.hasVGPRs(RC) && NumInsts <= 6;
3593 if (NumInsts % 2 == 0)
3596 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3597 return RI.isSGPRClass(RC);
3608 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3609 if (Pred == VCCZ || Pred == SCC_FALSE) {
3610 Pred =
static_cast<BranchPredicate
>(-Pred);
3616 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3618 if (DstSize == 32) {
3620 if (Pred == SCC_TRUE) {
3635 if (DstSize == 64 && Pred == SCC_TRUE) {
3645 static const int16_t Sub0_15[] = {
3646 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3647 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3648 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3649 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3652 static const int16_t Sub0_15_64[] = {
3653 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3654 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3655 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3656 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3659 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3661 const int16_t *SubIndices = Sub0_15;
3662 int NElts = DstSize / 32;
3666 if (Pred == SCC_TRUE) {
3668 SelOp = AMDGPU::S_CSELECT_B32;
3669 EltRC = &AMDGPU::SGPR_32RegClass;
3671 SelOp = AMDGPU::S_CSELECT_B64;
3672 EltRC = &AMDGPU::SGPR_64RegClass;
3673 SubIndices = Sub0_15_64;
3679 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3684 for (
int Idx = 0; Idx != NElts; ++Idx) {
3688 unsigned SubIdx = SubIndices[Idx];
3691 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3693 .
addReg(FalseReg, {}, SubIdx)
3694 .addReg(TrueReg, {}, SubIdx);
3697 .
addReg(TrueReg, {}, SubIdx)
3698 .addReg(FalseReg, {}, SubIdx);
3711 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3714 switch (
MI.getOpcode()) {
3715 case AMDGPU::S_ENDPGM:
3716 case AMDGPU::S_ENDPGM_SAVED:
3717 case AMDGPU::S_TRAP:
3718 case AMDGPU::S_GETREG_B32:
3719 case AMDGPU::S_SETREG_B32:
3720 case AMDGPU::S_SETREG_B32_mode:
3721 case AMDGPU::S_SETREG_IMM32_B32:
3722 case AMDGPU::S_SETREG_IMM32_B32_mode:
3723 case AMDGPU::S_SENDMSG:
3724 case AMDGPU::S_SENDMSGHALT:
3725 case AMDGPU::S_SENDMSG_RTN_B32:
3726 case AMDGPU::S_SENDMSG_RTN_B64:
3727 case AMDGPU::S_BARRIER_WAIT:
3728 case AMDGPU::S_BARRIER_SIGNAL_M0:
3729 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3730 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3739 switch (
MI.getOpcode()) {
3740 case AMDGPU::V_MOV_B16_t16_e32:
3741 case AMDGPU::V_MOV_B16_t16_e64:
3742 case AMDGPU::V_MOV_B32_e32:
3743 case AMDGPU::V_MOV_B32_e64:
3744 case AMDGPU::V_MOV_B64_PSEUDO:
3745 case AMDGPU::V_MOV_B64_e32:
3746 case AMDGPU::V_MOV_B64_e64:
3747 case AMDGPU::S_MOV_B32:
3748 case AMDGPU::S_MOV_B64:
3749 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3751 case AMDGPU::WWM_COPY:
3752 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3753 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3754 case AMDGPU::V_ACCVGPR_MOV_B32:
3755 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3756 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3764 switch (
MI.getOpcode()) {
3765 case AMDGPU::V_MOV_B16_t16_e32:
3766 case AMDGPU::V_MOV_B16_t16_e64:
3768 case AMDGPU::V_MOV_B32_e32:
3769 case AMDGPU::V_MOV_B32_e64:
3770 case AMDGPU::V_MOV_B64_PSEUDO:
3771 case AMDGPU::V_MOV_B64_e32:
3772 case AMDGPU::V_MOV_B64_e64:
3773 case AMDGPU::S_MOV_B32:
3774 case AMDGPU::S_MOV_B64:
3775 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3777 case AMDGPU::WWM_COPY:
3778 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3779 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3780 case AMDGPU::V_ACCVGPR_MOV_B32:
3781 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3782 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3790 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3791 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3792 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3795 unsigned Opc =
MI.getOpcode();
3797 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3799 MI.removeOperand(Idx);
3805 MI.setDesc(NewDesc);
3811 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3812 Desc.implicit_defs().size();
3814 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3815 MI.removeOperand(
I);
3819 unsigned SubRegIndex) {
3820 switch (SubRegIndex) {
3821 case AMDGPU::NoSubRegister:
3831 case AMDGPU::sub1_lo16:
3833 case AMDGPU::sub1_hi16:
3836 return std::nullopt;
3844 case AMDGPU::V_MAC_F16_e32:
3845 case AMDGPU::V_MAC_F16_e64:
3846 case AMDGPU::V_MAD_F16_e64:
3847 return AMDGPU::V_MADAK_F16;
3848 case AMDGPU::V_MAC_F32_e32:
3849 case AMDGPU::V_MAC_F32_e64:
3850 case AMDGPU::V_MAD_F32_e64:
3851 return AMDGPU::V_MADAK_F32;
3852 case AMDGPU::V_FMAC_F32_e32:
3853 case AMDGPU::V_FMAC_F32_e64:
3854 case AMDGPU::V_FMA_F32_e64:
3855 return AMDGPU::V_FMAAK_F32;
3856 case AMDGPU::V_FMAC_F16_e32:
3857 case AMDGPU::V_FMAC_F16_e64:
3858 case AMDGPU::V_FMAC_F16_t16_e64:
3859 case AMDGPU::V_FMAC_F16_fake16_e64:
3860 case AMDGPU::V_FMAC_F16_t16_e32:
3861 case AMDGPU::V_FMAC_F16_fake16_e32:
3862 case AMDGPU::V_FMA_F16_e64:
3863 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3864 ? AMDGPU::V_FMAAK_F16_t16
3865 : AMDGPU::V_FMAAK_F16_fake16
3866 : AMDGPU::V_FMAAK_F16;
3867 case AMDGPU::V_FMAC_F64_e32:
3868 case AMDGPU::V_FMAC_F64_e64:
3869 case AMDGPU::V_FMA_F64_e64:
3870 return AMDGPU::V_FMAAK_F64;
3878 case AMDGPU::V_MAC_F16_e32:
3879 case AMDGPU::V_MAC_F16_e64:
3880 case AMDGPU::V_MAD_F16_e64:
3881 return AMDGPU::V_MADMK_F16;
3882 case AMDGPU::V_MAC_F32_e32:
3883 case AMDGPU::V_MAC_F32_e64:
3884 case AMDGPU::V_MAD_F32_e64:
3885 return AMDGPU::V_MADMK_F32;
3886 case AMDGPU::V_FMAC_F32_e32:
3887 case AMDGPU::V_FMAC_F32_e64:
3888 case AMDGPU::V_FMA_F32_e64:
3889 return AMDGPU::V_FMAMK_F32;
3890 case AMDGPU::V_FMAC_F16_e32:
3891 case AMDGPU::V_FMAC_F16_e64:
3892 case AMDGPU::V_FMAC_F16_t16_e64:
3893 case AMDGPU::V_FMAC_F16_fake16_e64:
3894 case AMDGPU::V_FMAC_F16_t16_e32:
3895 case AMDGPU::V_FMAC_F16_fake16_e32:
3896 case AMDGPU::V_FMA_F16_e64:
3897 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3898 ? AMDGPU::V_FMAMK_F16_t16
3899 : AMDGPU::V_FMAMK_F16_fake16
3900 : AMDGPU::V_FMAMK_F16;
3901 case AMDGPU::V_FMAC_F64_e32:
3902 case AMDGPU::V_FMAC_F64_e64:
3903 case AMDGPU::V_FMA_F64_e64:
3904 return AMDGPU::V_FMAMK_F64;
3918 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3921 if (
Opc == AMDGPU::COPY) {
3922 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3929 if (HasMultipleUses) {
3932 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3935 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3943 if (ImmDefSize == 32 &&
3948 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3949 RI.getSubRegIdxSize(UseSubReg) == 16;
3952 if (RI.hasVGPRs(DstRC))
3955 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3961 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3968 for (
unsigned MovOp :
3969 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3970 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3978 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3982 if (MovDstPhysReg) {
3986 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3993 if (MovDstPhysReg) {
3994 if (!MovDstRC->
contains(MovDstPhysReg))
4010 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4018 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4022 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4024 UseMI.getOperand(0).setReg(MovDstPhysReg);
4029 UseMI.setDesc(NewMCID);
4030 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4031 UseMI.addImplicitDefUseOperands(*MF);
4035 if (HasMultipleUses)
4038 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4039 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4040 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4041 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4043 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4044 Opc == AMDGPU::V_FMAC_F64_e64) {
4053 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4064 auto CopyRegOperandToNarrowerRC =
4067 if (!
MI.getOperand(OpNo).isReg())
4071 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4074 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4075 get(AMDGPU::COPY), Tmp)
4077 MI.getOperand(OpNo).setReg(Tmp);
4078 MI.getOperand(OpNo).setIsKill();
4082 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4083 (Src1->isReg() && Src1->getReg() == Reg)) {
4085 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4086 if (!RegSrc->
isReg())
4089 ST.getConstantBusLimit(
Opc) < 2)
4092 if (!Src2->isReg() || RI.isSGPRClass(MRI->
getRegClass(Src2->getReg())))
4104 if (Def && Def->isMoveImmediate() &&
4113 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4119 unsigned SrcSubReg = RegSrc->
getSubReg();
4120 Src0->setReg(SrcReg);
4121 Src0->setSubReg(SrcSubReg);
4122 Src0->setIsKill(RegSrc->
isKill());
4124 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4125 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4126 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4127 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4128 UseMI.untieRegOperand(
4129 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4131 Src1->ChangeToImmediate(*SubRegImm);
4136 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4137 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4141 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4142 UseMI.getOperand(0).getReg())
4144 UseMI.getOperand(0).setReg(Tmp);
4145 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4146 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4151 DefMI.eraseFromParent();
4157 if (Src2->isReg() && Src2->getReg() == Reg) {
4158 if (ST.getConstantBusLimit(
Opc) < 2) {
4161 bool Src0Inlined =
false;
4162 if (Src0->isReg()) {
4167 if (Def && Def->isMoveImmediate() &&
4170 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4172 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4173 RI.isSGPRReg(*MRI, Src0->getReg())) {
4179 if (Src1->isReg() && !Src0Inlined) {
4182 if (Def && Def->isMoveImmediate() &&
4185 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4186 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4199 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4200 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4201 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4202 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4203 UseMI.untieRegOperand(
4204 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4206 const std::optional<int64_t> SubRegImm =
4210 Src2->ChangeToImmediate(*SubRegImm);
4216 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4217 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4221 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4222 UseMI.getOperand(0).getReg())
4224 UseMI.getOperand(0).setReg(Tmp);
4225 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4226 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4235 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4241 DefMI.eraseFromParent();
4253 if (BaseOps1.
size() != BaseOps2.
size())
4255 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4256 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4264 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4265 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4266 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4268 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4271bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4274 int64_t Offset0, Offset1;
4277 bool Offset0IsScalable, Offset1IsScalable;
4291 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4292 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4299 "MIa must load from or modify a memory location");
4301 "MIb must load from or modify a memory location");
4323 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4330 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4340 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4354 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4365 case AMDGPU::V_MAC_F16_e32:
4366 case AMDGPU::V_MAC_F16_e64:
4367 return AMDGPU::V_MAD_F16_e64;
4368 case AMDGPU::V_MAC_F32_e32:
4369 case AMDGPU::V_MAC_F32_e64:
4370 return AMDGPU::V_MAD_F32_e64;
4371 case AMDGPU::V_MAC_LEGACY_F32_e32:
4372 case AMDGPU::V_MAC_LEGACY_F32_e64:
4373 return AMDGPU::V_MAD_LEGACY_F32_e64;
4374 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4375 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4376 return AMDGPU::V_FMA_LEGACY_F32_e64;
4377 case AMDGPU::V_FMAC_F16_e32:
4378 case AMDGPU::V_FMAC_F16_e64:
4379 case AMDGPU::V_FMAC_F16_t16_e64:
4380 case AMDGPU::V_FMAC_F16_fake16_e64:
4381 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4382 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4383 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4384 : AMDGPU::V_FMA_F16_gfx9_e64;
4385 case AMDGPU::V_FMAC_F32_e32:
4386 case AMDGPU::V_FMAC_F32_e64:
4387 return AMDGPU::V_FMA_F32_e64;
4388 case AMDGPU::V_FMAC_F64_e32:
4389 case AMDGPU::V_FMAC_F64_e64:
4390 return AMDGPU::V_FMA_F64_e64;
4409 if (
MI.isBundle()) {
4412 if (
MI.getBundleSize() != 1)
4414 CandidateMI =
MI.getNextNode();
4418 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4422 if (
MI.isBundle()) {
4427 MI.untieRegOperand(MO.getOperandNo());
4434 if (Def.isEarlyClobber() && Def.isReg() &&
4439 auto UpdateDefIndex = [&](
LiveRange &LR) {
4440 auto *S = LR.find(OldIndex);
4441 if (S != LR.end() && S->start == OldIndex) {
4442 assert(S->valno && S->valno->def == OldIndex);
4443 S->start = NewIndex;
4444 S->valno->def = NewIndex;
4448 for (
auto &SR : LI.subranges())
4454 if (U.RemoveMIUse) {
4457 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4461 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4462 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4463 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4464 U.RemoveMIUse->removeOperand(
I);
4467 if (
MI.isBundle()) {
4471 if (MO.isReg() && MO.getReg() == DefReg) {
4472 assert(MO.getSubReg() == 0 &&
4473 "tied sub-registers in bundles currently not supported");
4474 MI.removeOperand(MO.getOperandNo());
4491 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4492 MIOp.setIsUndef(
true);
4493 MIOp.setReg(DummyReg);
4497 if (
MI.isBundle()) {
4501 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4502 MIOp.setIsUndef(
true);
4503 MIOp.setReg(DummyReg);
4516 return MI.isBundle() ? &
MI : NewMI;
4521 ThreeAddressUpdates &U)
const {
4523 unsigned Opc =
MI.getOpcode();
4527 if (NewMFMAOpc != -1) {
4530 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4531 MIB.
add(
MI.getOperand(
I));
4539 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4544 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4545 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4546 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4550 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4551 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4552 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4553 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4554 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4555 bool Src0Literal =
false;
4560 case AMDGPU::V_MAC_F16_e64:
4561 case AMDGPU::V_FMAC_F16_e64:
4562 case AMDGPU::V_FMAC_F16_t16_e64:
4563 case AMDGPU::V_FMAC_F16_fake16_e64:
4564 case AMDGPU::V_MAC_F32_e64:
4565 case AMDGPU::V_MAC_LEGACY_F32_e64:
4566 case AMDGPU::V_FMAC_F32_e64:
4567 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4568 case AMDGPU::V_FMAC_F64_e64:
4570 case AMDGPU::V_MAC_F16_e32:
4571 case AMDGPU::V_FMAC_F16_e32:
4572 case AMDGPU::V_MAC_F32_e32:
4573 case AMDGPU::V_MAC_LEGACY_F32_e32:
4574 case AMDGPU::V_FMAC_F32_e32:
4575 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4576 case AMDGPU::V_FMAC_F64_e32: {
4577 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4578 AMDGPU::OpName::src0);
4579 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4580 if (!
Src0->isReg() && !
Src0->isImm())
4590 MachineInstrBuilder MIB;
4593 const MachineOperand *Src0Mods =
4596 const MachineOperand *Src1Mods =
4599 const MachineOperand *Src2Mods =
4605 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4606 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4608 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4610 MachineInstr *
DefMI =
nullptr;
4612 std::optional<int64_t> ImmOpt;
4647 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4663 if (Src0Literal && !ST.hasVOP3Literal())
4691 switch (
MI.getOpcode()) {
4692 case AMDGPU::S_SET_GPR_IDX_ON:
4693 case AMDGPU::S_SET_GPR_IDX_MODE:
4694 case AMDGPU::S_SET_GPR_IDX_OFF:
4712 if (
MI.isTerminator() ||
MI.isPosition())
4716 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4719 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4725 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4726 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4727 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4728 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4729 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4734 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4735 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4736 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4750 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4755 if (
MI.memoperands_empty())
4760 unsigned AS = Memop->getAddrSpace();
4761 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4762 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4763 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4764 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4779 if (
MI.memoperands_empty())
4788 unsigned AS = Memop->getAddrSpace();
4798 bool TgSplit)
const {
4811 if (
MI.memoperands_empty())
4816 unsigned AS = Memop->getAddrSpace();
4832 unsigned Opcode =
MI.getOpcode();
4847 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4848 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4849 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4850 Opcode == AMDGPU::S_SETHALT)
4853 if (
MI.isCall() ||
MI.isInlineAsm())
4859 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4875 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4876 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4877 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4878 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4886 if (
MI.isMetaInstruction())
4890 if (
MI.isCopyLike()) {
4891 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4895 return MI.readsRegister(AMDGPU::EXEC, &RI);
4906 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4910 switch (
Imm.getBitWidth()) {
4916 ST.hasInv2PiInlineImm());
4919 ST.hasInv2PiInlineImm());
4921 return ST.has16BitInsts() &&
4923 ST.hasInv2PiInlineImm());
4930 APInt IntImm =
Imm.bitcastToAPInt();
4932 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4940 return ST.has16BitInsts() &&
4943 return ST.has16BitInsts() &&
4953 switch (OperandType) {
4963 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5007 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5008 return ST.has16BitInsts() &&
5017 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5018 return ST.has16BitInsts() &&
5070 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5076 return ST.hasVOP3Literal();
5080 int64_t ImmVal)
const {
5082 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5083 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5084 OpNo ==
static_cast<unsigned>(Src1Idx))
5089 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5090 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5091 AMDGPU::OpName::src2))
5094 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5101 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5113 "unexpected imm-like operand kind");
5126 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5146 return Op32 != -1 &&
TII.isVOPC(Op32);
5151 unsigned Depth)
const {
5152 assert(MRI.
isSSA() &&
"isMaskedByExec requires SSA form");
5161 constexpr unsigned MaxDepth = 6;
5162 if (
Depth >= MaxDepth || !Reg.isVirtual())
5168 if (!Def || Def->getParent() !=
MBB)
5176 auto Recurse = [&](
unsigned OpIdx) {
5182 unsigned Opc = Def->getOpcode();
5183 if (
Opc == AMDGPU::COPY && Recurse(1))
5185 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5205 AMDGPU::OpName
OpName)
const {
5207 return Mods && Mods->
getImm();
5220 switch (
MI.getOpcode()) {
5221 default:
return false;
5223 case AMDGPU::V_ADDC_U32_e64:
5224 case AMDGPU::V_SUBB_U32_e64:
5225 case AMDGPU::V_SUBBREV_U32_e64: {
5228 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5233 case AMDGPU::V_MAC_F16_e64:
5234 case AMDGPU::V_MAC_F32_e64:
5235 case AMDGPU::V_MAC_LEGACY_F32_e64:
5236 case AMDGPU::V_FMAC_F16_e64:
5237 case AMDGPU::V_FMAC_F16_t16_e64:
5238 case AMDGPU::V_FMAC_F16_fake16_e64:
5239 case AMDGPU::V_FMAC_F32_e64:
5240 case AMDGPU::V_FMAC_F64_e64:
5241 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5242 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5247 case AMDGPU::V_CNDMASK_B32_e64:
5253 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5266 if (Src0 && Src0->isImm()) {
5269 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5291 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5300 unsigned Op32)
const {
5314 Inst32.
add(
MI.getOperand(
I));
5318 int Idx =
MI.getNumExplicitDefs();
5320 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5325 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5345 if (OldSDst && OldSDst->
isDead()) {
5348 NewVCC->setIsDead();
5357 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5365 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5368 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5369 AMDGPU::SReg_64RegClass.contains(Reg);
5397 switch (MO.getReg()) {
5399 case AMDGPU::VCC_LO:
5400 case AMDGPU::VCC_HI:
5402 case AMDGPU::FLAT_SCR:
5415 switch (
MI.getOpcode()) {
5416 case AMDGPU::V_READLANE_B32:
5417 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5418 case AMDGPU::V_WRITELANE_B32:
5419 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5426 if (
MI.isPreISelOpcode() ||
5427 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5445 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5456 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5457 ErrInfo =
"illegal copy from vector register to SGPR";
5475 if (!MRI.
isSSA() &&
MI.isCopy())
5476 return verifyCopy(
MI, MRI, ErrInfo);
5478 if (SIInstrInfo::isGenericOpcode(Opcode))
5481 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5482 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5483 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5485 if (Src0Idx == -1) {
5487 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5488 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5489 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5490 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5495 if (!
Desc.isVariadic() &&
5496 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5497 ErrInfo =
"Instruction has wrong number of operands.";
5501 if (
MI.isInlineAsm()) {
5514 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5515 ErrInfo =
"inlineasm operand has incorrect register class.";
5523 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5524 ErrInfo =
"missing memory operand from image instruction.";
5529 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5532 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5533 "all fp values to integers.";
5539 switch (OpInfo.OperandType) {
5541 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5542 ErrInfo =
"Illegal immediate value for operand.";
5574 ErrInfo =
"Illegal immediate value for operand.";
5583 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5586 OpInfo.OperandType ==
5588 ErrInfo =
"illegal 64-bit immediate value for operand.";
5595 ErrInfo =
"Expected inline constant for operand.";
5609 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5610 ErrInfo =
"Expected immediate, but got non-immediate";
5619 if (OpInfo.isGenericType())
5627 if (!ST.hasSDWA()) {
5628 ErrInfo =
"SDWA is not supported on this target";
5632 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5633 AMDGPU::OpName::dst_sel}) {
5639 ErrInfo =
"Invalid SDWA selection";
5644 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5646 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5651 if (!ST.hasSDWAScalar()) {
5653 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5654 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5661 "Only reg allowed as operands in SDWA instructions on GFX9+";
5667 if (!ST.hasSDWAOmod()) {
5670 if (OMod !=
nullptr &&
5672 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5677 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5678 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5679 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5680 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5683 unsigned Mods = Src0ModsMO->
getImm();
5686 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5692 if (
isVOPC(BasicOpcode)) {
5693 if (!ST.hasSDWASdst() && DstIdx != -1) {
5696 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5697 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5700 }
else if (!ST.hasSDWAOutModsVOPC()) {
5703 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5704 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5710 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5711 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5718 if (DstUnused && DstUnused->isImm() &&
5721 if (!Dst.isReg() || !Dst.isTied()) {
5722 ErrInfo =
"Dst register should have tied register";
5727 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5730 "Dst register should be tied to implicit use of preserved register";
5734 ErrInfo =
"Dst register should use same physical register as preserved";
5740 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5742 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5743 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5746 if (Src1MO.
isImm()) {
5747 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5753 if (
isImage(Opcode) && !
MI.mayStore()) {
5758 uint64_t DMaskImm = DMask->
getImm();
5765 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5773 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5777 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5778 if (RegCount > DstSize) {
5779 ErrInfo =
"Image instruction returns too many registers for dst "
5789 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5790 unsigned ConstantBusCount = 0;
5791 bool UsesLiteral =
false;
5794 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5798 LiteralVal = &
MI.getOperand(ImmIdx);
5807 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5818 }
else if (!MO.
isFI()) {
5825 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5835 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5836 return !RI.regsOverlap(SGPRUsed, SGPR);
5845 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5846 Opcode != AMDGPU::V_WRITELANE_B32) {
5847 ErrInfo =
"VOP* instruction violates constant bus restriction";
5851 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5852 ErrInfo =
"VOP3 instruction uses literal";
5859 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5860 unsigned SGPRCount = 0;
5863 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5871 if (MO.
getReg() != SGPRUsed)
5876 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5877 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5884 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5885 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5889 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5892 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5902 ErrInfo =
"ABS not allowed in VOP3B instructions";
5914 !Src0.isIdenticalTo(Src1)) {
5915 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5922 if (
Desc.isBranch()) {
5924 ErrInfo =
"invalid branch target for SOPK instruction";
5928 uint64_t
Imm =
Op->getImm();
5931 ErrInfo =
"invalid immediate for SOPK instruction";
5936 ErrInfo =
"invalid immediate for SOPK instruction";
5943 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5944 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5945 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5946 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5947 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5948 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5950 const unsigned StaticNumOps =
5951 Desc.getNumOperands() +
Desc.implicit_uses().size();
5952 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5958 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5959 ErrInfo =
"missing implicit register operands";
5965 if (!Dst->isUse()) {
5966 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5971 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5972 UseOpIdx != StaticNumOps + 1) {
5973 ErrInfo =
"movrel implicit operands should be tied";
5980 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5982 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5983 ErrInfo =
"src0 should be subreg of implicit vector use";
5991 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5992 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5998 if (
MI.mayStore() &&
6003 if (Soff && Soff->
getReg() != AMDGPU::M0) {
6004 ErrInfo =
"scalar stores must use m0 as offset register";
6010 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6012 if (
Offset->getImm() != 0) {
6013 ErrInfo =
"subtarget does not support offsets in flat instructions";
6018 if (
isDS(
MI) && !ST.hasGDS()) {
6020 if (GDSOp && GDSOp->
getImm() != 0) {
6021 ErrInfo =
"GDS is not supported on this subtarget";
6029 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6030 AMDGPU::OpName::vaddr0);
6031 AMDGPU::OpName RSrcOpName =
6032 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6033 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6041 ErrInfo =
"dim is out of range";
6046 if (ST.hasR128A16()) {
6048 IsA16 = R128A16->
getImm() != 0;
6049 }
else if (ST.hasA16()) {
6051 IsA16 = A16->
getImm() != 0;
6054 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6056 unsigned AddrWords =
6059 unsigned VAddrWords;
6061 VAddrWords = RsrcIdx - VAddr0Idx;
6062 if (ST.hasPartialNSAEncoding() &&
6064 unsigned LastVAddrIdx = RsrcIdx - 1;
6065 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6073 if (VAddrWords != AddrWords) {
6075 <<
" but got " << VAddrWords <<
"\n");
6076 ErrInfo =
"bad vaddr size";
6086 unsigned DC = DppCt->
getImm();
6087 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6088 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6089 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6090 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6091 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6092 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6093 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6094 ErrInfo =
"Invalid dpp_ctrl value";
6097 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6098 !ST.hasDPPWavefrontShifts()) {
6099 ErrInfo =
"Invalid dpp_ctrl value: "
6100 "wavefront shifts are not supported on GFX10+";
6103 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6104 !ST.hasDPPBroadcasts()) {
6105 ErrInfo =
"Invalid dpp_ctrl value: "
6106 "broadcasts are not supported on GFX10+";
6109 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6111 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6112 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6113 !ST.hasGFX90AInsts()) {
6114 ErrInfo =
"Invalid dpp_ctrl value: "
6115 "row_newbroadcast/row_share is not supported before "
6119 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6120 ErrInfo =
"Invalid dpp_ctrl value: "
6121 "row_share and row_xmask are not supported before GFX10";
6126 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6128 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6130 ErrInfo =
"Invalid dpp_ctrl value: "
6131 "DP ALU dpp only support row_newbcast";
6138 AMDGPU::OpName DataName =
6139 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6145 if (!ST.hasGFX90AInsts()) {
6146 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6147 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6148 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6149 ErrInfo =
"Invalid register class: "
6150 "agpr loads and stores not supported on this GPU";
6156 if (ST.needsAlignedVGPRs()) {
6157 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6162 if (Reg.isPhysical())
6163 return !(RI.getHWRegIndex(Reg) & 1);
6165 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6166 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6170 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6171 ErrInfo =
"Subtarget requires even aligned vector registers "
6172 "for vaddr operand of image instructions";
6178 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6180 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6181 ErrInfo =
"Invalid register class: "
6182 "v_accvgpr_write with an SGPR is not supported on this GPU";
6187 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6190 ErrInfo =
"pseudo expects only physical SGPRs";
6197 if (!ST.hasScaleOffset()) {
6198 ErrInfo =
"Subtarget does not support offset scaling";
6202 ErrInfo =
"Instruction does not support offset scaling";
6210 for (
unsigned I = 0;
I < 3; ++
I) {
6216 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6217 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6219 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6220 &AMDGPU::SReg_64RegClass) ||
6221 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6222 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6231 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6233 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6235 : AMDGPU::V_MOV_B32_e32;
6245 default:
return AMDGPU::INSTRUCTION_LIST_END;
6246 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6247 case AMDGPU::COPY:
return AMDGPU::COPY;
6248 case AMDGPU::PHI:
return AMDGPU::PHI;
6249 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6250 case AMDGPU::WQM:
return AMDGPU::WQM;
6251 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6252 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6253 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6254 case AMDGPU::S_ADD_I32:
6255 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6256 case AMDGPU::S_ADDC_U32:
6257 return AMDGPU::V_ADDC_U32_e32;
6258 case AMDGPU::S_SUB_I32:
6259 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6262 case AMDGPU::S_ADD_U32:
6263 return AMDGPU::V_ADD_CO_U32_e32;
6264 case AMDGPU::S_SUB_U32:
6265 return AMDGPU::V_SUB_CO_U32_e32;
6266 case AMDGPU::S_ADD_U64_PSEUDO:
6267 return AMDGPU::V_ADD_U64_PSEUDO;
6268 case AMDGPU::S_SUB_U64_PSEUDO:
6269 return AMDGPU::V_SUB_U64_PSEUDO;
6270 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6271 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6272 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6273 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6274 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6275 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6276 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6277 case AMDGPU::S_XNOR_B32:
6278 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6279 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6280 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6281 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6282 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6283 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6284 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6285 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6286 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6287 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6288 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6289 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6290 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6291 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6292 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6293 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6294 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6295 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6296 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6297 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6298 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6299 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6300 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6301 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6302 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6303 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6304 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6305 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6306 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6307 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6308 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6309 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6310 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6311 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6312 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6313 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6314 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6315 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6316 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6317 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6318 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6319 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6320 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6321 case AMDGPU::S_CVT_F32_F16:
6322 case AMDGPU::S_CVT_HI_F32_F16:
6323 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6324 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6325 case AMDGPU::S_CVT_F16_F32:
6326 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6327 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6328 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6329 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6330 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6331 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6332 case AMDGPU::S_CEIL_F16:
6333 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6334 : AMDGPU::V_CEIL_F16_fake16_e64;
6335 case AMDGPU::S_FLOOR_F16:
6336 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6337 : AMDGPU::V_FLOOR_F16_fake16_e64;
6338 case AMDGPU::S_TRUNC_F16:
6339 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6340 : AMDGPU::V_TRUNC_F16_fake16_e64;
6341 case AMDGPU::S_RNDNE_F16:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6343 : AMDGPU::V_RNDNE_F16_fake16_e64;
6344 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6345 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6346 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6347 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6348 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6349 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6350 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6351 case AMDGPU::S_ADD_F16:
6352 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6353 : AMDGPU::V_ADD_F16_fake16_e64;
6354 case AMDGPU::S_SUB_F16:
6355 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6356 : AMDGPU::V_SUB_F16_fake16_e64;
6357 case AMDGPU::S_MIN_F16:
6358 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6359 : AMDGPU::V_MIN_F16_fake16_e64;
6360 case AMDGPU::S_MAX_F16:
6361 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6362 : AMDGPU::V_MAX_F16_fake16_e64;
6363 case AMDGPU::S_MINIMUM_F16:
6364 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6365 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6366 case AMDGPU::S_MAXIMUM_F16:
6367 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6368 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6369 case AMDGPU::S_MUL_F16:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6371 : AMDGPU::V_MUL_F16_fake16_e64;
6372 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6373 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6374 case AMDGPU::S_FMAC_F16:
6375 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6376 : AMDGPU::V_FMAC_F16_fake16_e64;
6377 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6378 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6379 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6380 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6381 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6382 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6383 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6384 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6385 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6386 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6387 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6388 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6389 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6390 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6391 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6392 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6393 case AMDGPU::S_CMP_LT_F16:
6394 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6395 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6396 case AMDGPU::S_CMP_EQ_F16:
6397 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6398 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6399 case AMDGPU::S_CMP_LE_F16:
6400 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6401 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6402 case AMDGPU::S_CMP_GT_F16:
6403 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6404 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6405 case AMDGPU::S_CMP_LG_F16:
6406 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6407 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6408 case AMDGPU::S_CMP_GE_F16:
6409 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6410 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6411 case AMDGPU::S_CMP_O_F16:
6412 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6413 : AMDGPU::V_CMP_O_F16_fake16_e64;
6414 case AMDGPU::S_CMP_U_F16:
6415 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6416 : AMDGPU::V_CMP_U_F16_fake16_e64;
6417 case AMDGPU::S_CMP_NGE_F16:
6418 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6419 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6420 case AMDGPU::S_CMP_NLG_F16:
6421 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6422 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6423 case AMDGPU::S_CMP_NGT_F16:
6424 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6425 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6426 case AMDGPU::S_CMP_NLE_F16:
6427 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6428 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6429 case AMDGPU::S_CMP_NEQ_F16:
6430 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6431 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6432 case AMDGPU::S_CMP_NLT_F16:
6433 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6434 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6435 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6436 case AMDGPU::V_S_EXP_F16_e64:
6437 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6438 : AMDGPU::V_EXP_F16_fake16_e64;
6439 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6440 case AMDGPU::V_S_LOG_F16_e64:
6441 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6442 : AMDGPU::V_LOG_F16_fake16_e64;
6443 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6444 case AMDGPU::V_S_RCP_F16_e64:
6445 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6446 : AMDGPU::V_RCP_F16_fake16_e64;
6447 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6448 case AMDGPU::V_S_RSQ_F16_e64:
6449 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6450 : AMDGPU::V_RSQ_F16_fake16_e64;
6451 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6452 case AMDGPU::V_S_SQRT_F16_e64:
6453 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6454 : AMDGPU::V_SQRT_F16_fake16_e64;
6457 "Unexpected scalar opcode without corresponding vector one!");
6506 "Not a whole wave func");
6509 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6510 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6517 unsigned OpNo)
const {
6519 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6520 Desc.operands()[OpNo].RegClass == -1) {
6523 if (Reg.isVirtual()) {
6527 return RI.getPhysRegBaseClass(Reg);
6530 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6531 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6536 constexpr AMDGPU::OpName OpNames[] = {
6537 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6540 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6541 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6553 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6555 unsigned Size = RI.getRegSizeInBits(*RC);
6556 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6557 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6558 : AMDGPU::V_MOV_B32_e32;
6560 Opcode = AMDGPU::COPY;
6561 else if (RI.isSGPRClass(RC))
6562 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6587 .
addImm(AMDGPU::sub0_sub1)
6589 .
addImm(AMDGPU::sub2_sub3);
6590 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6607 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6613 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6624 if (SubIdx == AMDGPU::sub0)
6626 if (SubIdx == AMDGPU::sub1)
6638void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6654 if (Reg.isPhysical())
6661 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6664 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6667 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6674 unsigned Opc =
MI.getOpcode();
6677 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6687 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6688 if (IsAGPR && !ST.hasMAIInsts())
6694 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6695 const int DataIdx = AMDGPU::getNamedOperandIdx(
6696 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6697 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6698 MI.getOperand(DataIdx).isReg() &&
6699 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6701 if ((
int)OpIdx == DataIdx) {
6702 if (VDstIdx != -1 &&
6703 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6706 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6707 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6708 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6713 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6714 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6715 RI.isSGPRReg(MRI, MO.
getReg()))
6718 if (ST.hasFlatScratchHiInB64InstHazard() &&
6725 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6728 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6729 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6738 constexpr unsigned NumOps = 3;
6739 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6740 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6741 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6742 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6747 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6750 MO = &
MI.getOperand(SrcIdx);
6753 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6757 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6761 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6765 return !OpSel && !OpSelHi;
6770 if (!ST.hasPkF32InvalidOpSel() ||
MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6783 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6788 assert(
MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6796 const unsigned Mods[3] = {
6797 static_cast<unsigned>(
6799 static_cast<unsigned>(
6801 static_cast<unsigned>(
6806 for (
unsigned I = 0;
I != 3; ++
I) {
6820 bool DivergentSGPRs =
false;
6821 for (
unsigned I = 0;
I != 3; ++
I) {
6822 if (!Srcs[
I]->
isReg() || !RI.isSGPRReg(MRI, Srcs[
I]->
getReg()))
6824 if (!SGPRSrcs.
empty()) {
6827 Srcs[
I]->getSubReg() == Srcs[
First]->getSubReg() &&
6828 "constant bus limit allows only one SGPR source");
6830 OpSel[
I][0] != OpSel[
First][0] || OpSel[
I][1] != OpSel[
First][1];
6835 if (DivergentSGPRs) {
6838 for (
unsigned I :
ArrayRef(SGPRSrcs).drop_front())
6844 unsigned SubIdx = (
Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6848 : RI.isVGPR(MRI,
Op.getReg())
6849 ? RI.getVGPRClassForBitWidth(32)
6850 : RI.getSGPRClassForBitWidth(32);
6855 auto LaneMods = [](
unsigned Mods,
bool Hi) ->
unsigned {
6862 auto BuildLane = [&](
Register Dst,
bool Hi) {
6880 BuildLane(
Lo,
false);
6881 BuildLane(
Hi,
true);
6890 MI.eraseFromParent();
6899 int64_t RegClass = getOpRegClassID(OpInfo);
6901 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6903 MO = &
MI.getOperand(OpIdx);
6907 if (
isVALU(
MI,
false) && !IsInlineConst &&
6911 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6912 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6916 if (!LiteralLimit--)
6926 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6934 if (--ConstantBusLimit <= 0)
6946 if (!LiteralLimit--)
6948 if (--ConstantBusLimit <= 0)
6954 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6958 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6960 !
Op.isIdenticalTo(*MO))
6982 bool Is64BitOp = Is64BitFPOp ||
6990 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6999 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
7017 bool IsGFX950Only = ST.hasGFX950Insts();
7018 bool IsGFX940Only = ST.hasGFX940Insts();
7020 if (!IsGFX950Only && !IsGFX940Only)
7038 unsigned Opcode =
MI.getOpcode();
7040 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7041 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7042 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7043 case AMDGPU::V_MQSAD_U32_U8_e64:
7044 case AMDGPU::V_PK_ADD_F16:
7045 case AMDGPU::V_PK_ADD_F32:
7046 case AMDGPU::V_PK_ADD_I16:
7047 case AMDGPU::V_PK_ADD_U16:
7048 case AMDGPU::V_PK_ASHRREV_I16:
7049 case AMDGPU::V_PK_FMA_F16:
7050 case AMDGPU::V_PK_FMA_F32:
7051 case AMDGPU::V_PK_FMAC_F16_e32:
7052 case AMDGPU::V_PK_FMAC_F16_e64:
7053 case AMDGPU::V_PK_LSHLREV_B16:
7054 case AMDGPU::V_PK_LSHRREV_B16:
7055 case AMDGPU::V_PK_MAD_I16:
7056 case AMDGPU::V_PK_MAD_U16:
7057 case AMDGPU::V_PK_MAX_F16:
7058 case AMDGPU::V_PK_MAX_I16:
7059 case AMDGPU::V_PK_MAX_U16:
7060 case AMDGPU::V_PK_MIN_F16:
7061 case AMDGPU::V_PK_MIN_I16:
7062 case AMDGPU::V_PK_MIN_U16:
7063 case AMDGPU::V_PK_MOV_B32:
7064 case AMDGPU::V_PK_MUL_F16:
7065 case AMDGPU::V_PK_MUL_F32:
7066 case AMDGPU::V_PK_MUL_LO_U16:
7067 case AMDGPU::V_PK_SUB_I16:
7068 case AMDGPU::V_PK_SUB_U16:
7069 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7078 unsigned Opc =
MI.getOpcode();
7081 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
7084 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7090 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7091 RI.isSGPRReg(MRI, Src0.getReg()))
7097 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7099 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7103 Src0.ChangeToRegister(Reg,
false);
7105 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7110 Src1.ChangeToRegister(Reg,
false);
7116 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7117 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7118 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
7130 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7131 RI.isVGPR(MRI, Src1.getReg())) {
7136 Src1.ChangeToRegister(Reg,
false);
7144 if (HasImplicitSGPR || !
MI.isCommutable()) {
7154 if ((!Src1.isImm() && !Src1.isReg()) ||
7161 if (CommutedOpc == -1) {
7166 MI.setDesc(
get(CommutedOpc));
7169 unsigned Src0SubReg = Src0.getSubReg();
7170 bool Src0Kill = Src0.isKill();
7173 Src0.ChangeToImmediate(Src1.getImm());
7174 else if (Src1.isReg()) {
7175 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7176 Src0.setSubReg(Src1.getSubReg());
7180 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7181 Src1.setSubReg(Src0SubReg);
7189 unsigned Opc =
MI.getOpcode();
7192 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7193 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7194 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7197 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7200 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7201 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7202 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7203 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7207 if (Src1.isReg() && !RI.isSGPRClass(MRI.
getRegClass(Src1.getReg()))) {
7211 Src1.ChangeToRegister(Reg,
false);
7213 if (VOP3Idx[2] != -1) {
7215 if (Src2.isReg() && !RI.isSGPRClass(MRI.
getRegClass(Src2.getReg()))) {
7219 Src2.ChangeToRegister(Reg,
false);
7225 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7226 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7228 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7230 SGPRsUsed.
insert(SGPRReg);
7234 for (
int Idx : VOP3Idx) {
7243 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7255 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7262 if (ConstantBusLimit > 0) {
7274 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7275 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7276 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7277 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7283 for (
unsigned I = 0;
I < 3; ++
I) {
7296 SRC = RI.getCommonSubClass(SRC, DstRC);
7299 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7301 if (RI.hasAGPRs(VRC)) {
7302 VRC = RI.getEquivalentVGPRClass(VRC);
7305 get(TargetOpcode::COPY), NewSrcReg)
7312 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7318 for (
unsigned i = 0; i < SubRegs; ++i) {
7321 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7322 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7328 get(AMDGPU::REG_SEQUENCE), DstReg);
7329 for (
unsigned i = 0; i < SubRegs; ++i) {
7331 MIB.
addImm(RI.getSubRegFromChannel(i));
7344 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7346 SBase->setReg(SGPR);
7349 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7357 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7358 if (OldSAddrIdx < 0)
7371 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7374 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7375 if (NewVAddrIdx < 0)
7378 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7382 if (OldVAddrIdx >= 0) {
7396 if (OldVAddrIdx == NewVAddrIdx) {
7407 assert(OldSAddrIdx == NewVAddrIdx);
7409 if (OldVAddrIdx >= 0) {
7410 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7411 AMDGPU::OpName::vdst_in);
7415 if (NewVDstIn != -1) {
7416 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7422 if (NewVDstIn != -1) {
7423 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7464 unsigned OpSubReg =
Op.getSubReg();
7467 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7474 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7475 .
addReg(OpReg, {}, OpSubReg);
7477 Op.setSubReg(AMDGPU::NoSubRegister);
7484 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7487 bool ImpDef = Def->isImplicitDef();
7488 while (!ImpDef && Def && Def->isCopy()) {
7489 if (Def->getOperand(1).getReg().isPhysical())
7492 ImpDef = Def && Def->isImplicitDef();
7494 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7510 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7515 bool UseNewExecInstructions =
7524 if (UseNewExecInstructions) {
7559 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7560 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7561 unsigned NumSubRegs =
RegSize / 32;
7562 Register VScalarOp = ScalarOp->getReg();
7565 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7567 if (NumSubRegs == 1) {
7570 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7571 Common != VScalarOpRC) {
7578 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7581 if (UseNewExecInstructions) {
7583 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7586 if (
I == LoopBB.
end())
7591 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7597 CondReg = NewCondReg;
7609 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7610 ScalarOp->setReg(CurReg);
7613 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7614 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7616 ScalarOp->setReg(PhySGPRs[Idx]);
7621 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7622 "Unhandled register size");
7624 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7631 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7632 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7635 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7636 .
addReg(VScalarOp, VScalarOpUndef,
7637 TRI->getSubRegFromChannel(Idx + 1));
7644 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7651 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7653 if (UseNewExecInstructions) {
7655 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7657 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7658 if (
I == LoopBB.
end())
7662 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7664 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7668 CondReg = NewCondReg;
7680 const auto *SScalarOpRC =
7686 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7687 unsigned Channel = 0;
7688 for (
Register Piece : ReadlanePieces) {
7689 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7693 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7694 ScalarOp->setReg(SScalarOp);
7696 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7697 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7699 ScalarOp->setReg(PhySGPRs[Idx]);
7707 if (!UseNewExecInstructions) {
7720 if (UseNewExecInstructions) {
7753 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7754 "Physical SGPRs must be empty or match the number of scalar operands");
7760 if (!Begin.isValid())
7762 if (!
End.isValid()) {
7768 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7777 std::numeric_limits<unsigned>::max()) !=
7795 for (
auto I = Begin;
I != AfterMI;
I++) {
7796 for (
auto &MO :
I->all_uses())
7832 for (
auto &Succ : RemainderBB->
successors()) {
7857static std::tuple<unsigned, unsigned>
7865 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7866 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7873 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7890 .
addImm(AMDGPU::sub0_sub1)
7896 return std::tuple(RsrcPtr, NewSRsrc);
7907 if (ST.useRealTrue16Insts())
7937 if (
MI.getOpcode() == AMDGPU::PHI) {
7939 assert(!RI.isSGPRClass(VRC));
7942 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7944 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7960 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7963 if (RI.hasVGPRs(DstRC)) {
7967 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7969 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7986 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7991 if (DstRC != Src0RC) {
8000 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
8002 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8008 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8009 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8010 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8011 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8012 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8013 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8014 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8016 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8029 ? AMDGPU::OpName::rsrc
8030 : AMDGPU::OpName::srsrc;
8035 AMDGPU::OpName SampOpName =
8036 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8045 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8053 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8057 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
8061 Src0.ChangeToRegister(Reg,
false);
8067 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8068 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8069 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8070 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8072 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
8079 bool isSoffsetLegal =
true;
8081 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
8082 if (SoffsetIdx != -1) {
8086 isSoffsetLegal =
false;
8090 bool isRsrcLegal =
true;
8092 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8093 if (RsrcIdx != -1) {
8095 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
8096 isRsrcLegal =
false;
8100 if (isRsrcLegal && isSoffsetLegal)
8128 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8132 unsigned RsrcPtr, NewSRsrc;
8139 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8140 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8146 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8147 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8160 }
else if (!VAddr && ST.hasAddr64()) {
8164 "FIXME: Need to emit flat atomics here");
8166 unsigned RsrcPtr, NewSRsrc;
8192 MIB.
addImm(CPol->getImm());
8197 MIB.
addImm(TFE->getImm());
8217 MI.removeFromParent();
8222 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8223 .addImm(AMDGPU::sub0)
8224 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8225 .addImm(AMDGPU::sub1);
8228 if (!isSoffsetLegal) {
8239 if (!isSoffsetLegal) {
8248 if (InSet.insert(
MI).second)
8252 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8253 if (RsrcIdx != -1) {
8254 DeferredList.insert(
MI);
8259 return DeferredList.contains(
MI);
8269 if (!ST.useRealTrue16Insts())
8272 unsigned Opcode =
MI.getOpcode();
8275 if (OpIdx >=
MI.getNumExplicitOperands() ||
8276 OpIdx >=
get(Opcode).getNumOperands() ||
8277 get(Opcode).operands()[OpIdx].RegClass == -1)
8281 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8285 if (!RI.isVGPRClass(CurrRC))
8288 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8290 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8292 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8293 Op.setSubReg(AMDGPU::lo16);
8298 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8299 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8309 Op.setReg(NewDstReg);
8310 Op.setSubReg(AMDGPU::NoSubRegister);
8315 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8323 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8324 "This only handle waterfall for SI_CALL_ISEL");
8331 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8334 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8339 while (
End !=
MBB.end() &&
End->isCopy() &&
8340 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8350 while (!Worklist.
empty()) {
8356 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8362 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8364 "Deferred MachineInstr are not supposed to re-populate worklist");
8367 for (
auto &Entry : WaterFalls) {
8368 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8370 Entry.second.SGPRs);
8373 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8375 Entry.first->eraseFromParent();
8383 if (SubRegIndices.
size() <= 1) {
8386 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8393 for (int16_t Indice : SubRegIndices) {
8396 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8403 get(AMDGPU::REG_SEQUENCE), DstReg);
8404 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8406 MIB.
addImm(RI.getSubRegFromChannel(i));
8416 if (DstReg == AMDGPU::M0) {
8429 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8431 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8432 if (
UseMI->getOperand(i).isReg() &&
8433 UseMI->getOperand(i).getReg() == DstReg) {
8437 V2SCopyInfo.MOs.push_back(MO);
8438 V2SCopyInfo.SGPRs.push_back(DstReg);
8442 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8443 I->getOperand(0).isReg() &&
8444 I->getOperand(0).getReg() == DstReg) {
8447 }
else if (
I->readsRegister(DstReg, &RI)) {
8449 V2SPhyCopiesToErase[&Inst] =
false;
8451 if (
I->findRegisterDefOperand(DstReg, &RI))
8473 case AMDGPU::S_ADD_I32:
8474 case AMDGPU::S_SUB_I32: {
8478 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8486 case AMDGPU::S_MUL_U64:
8487 if (ST.useVMulU64Inst()) {
8488 NewOpcode = AMDGPU::V_MUL_U64_e64;
8492 splitScalarSMulU64(Worklist, Inst, MDT);
8496 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8497 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8500 splitScalarSMulPseudo(Worklist, Inst, MDT);
8504 case AMDGPU::S_AND_B64:
8505 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8509 case AMDGPU::S_OR_B64:
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8514 case AMDGPU::S_XOR_B64:
8515 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8519 case AMDGPU::S_NAND_B64:
8520 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8524 case AMDGPU::S_NOR_B64:
8525 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8529 case AMDGPU::S_XNOR_B64:
8530 if (ST.hasDLInsts())
8531 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8533 splitScalar64BitXnor(Worklist, Inst, MDT);
8537 case AMDGPU::S_ANDN2_B64:
8538 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8542 case AMDGPU::S_ORN2_B64:
8543 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8547 case AMDGPU::S_BREV_B64:
8548 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8552 case AMDGPU::S_NOT_B64:
8553 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8557 case AMDGPU::S_BCNT1_I32_B64:
8558 splitScalar64BitBCNT(Worklist, Inst);
8562 case AMDGPU::S_BFE_I64:
8563 splitScalar64BitBFE(Worklist, Inst);
8567 case AMDGPU::S_FLBIT_I32_B64:
8568 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8571 case AMDGPU::S_FF1_I32_B64:
8572 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8576 case AMDGPU::S_LSHL_B32:
8577 if (ST.hasOnlyRevVALUShifts()) {
8578 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8582 case AMDGPU::S_ASHR_I32:
8583 if (ST.hasOnlyRevVALUShifts()) {
8584 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8588 case AMDGPU::S_LSHR_B32:
8589 if (ST.hasOnlyRevVALUShifts()) {
8590 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8594 case AMDGPU::S_LSHL_B64:
8595 if (ST.hasOnlyRevVALUShifts()) {
8597 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8598 : AMDGPU::V_LSHLREV_B64_e64;
8602 case AMDGPU::S_ASHR_I64:
8603 if (ST.hasOnlyRevVALUShifts()) {
8604 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8608 case AMDGPU::S_LSHR_B64:
8609 if (ST.hasOnlyRevVALUShifts()) {
8610 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8615 case AMDGPU::S_ABS_I32:
8616 lowerScalarAbs(Worklist, Inst);
8620 case AMDGPU::S_ABSDIFF_I32:
8621 lowerScalarAbsDiff(Worklist, Inst);
8625 case AMDGPU::S_CBRANCH_SCC0:
8626 case AMDGPU::S_CBRANCH_SCC1: {
8629 bool IsSCC = CondReg == AMDGPU::SCC;
8638 case AMDGPU::S_BFE_U64:
8639 case AMDGPU::S_BFM_B64:
8642 case AMDGPU::S_PACK_LL_B32_B16:
8643 case AMDGPU::S_PACK_LH_B32_B16:
8644 case AMDGPU::S_PACK_HL_B32_B16:
8645 case AMDGPU::S_PACK_HH_B32_B16:
8646 movePackToVALU(Worklist, MRI, Inst);
8650 case AMDGPU::S_XNOR_B32:
8651 lowerScalarXnor(Worklist, Inst);
8655 case AMDGPU::S_NAND_B32:
8656 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8660 case AMDGPU::S_NOR_B32:
8661 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8665 case AMDGPU::S_ANDN2_B32:
8666 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8670 case AMDGPU::S_ORN2_B32:
8671 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8679 case AMDGPU::S_ADD_CO_PSEUDO:
8680 case AMDGPU::S_SUB_CO_PSEUDO: {
8681 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8682 ? AMDGPU::V_ADDC_U32_e64
8683 : AMDGPU::V_SUBB_U32_e64;
8684 const auto *CarryRC = RI.getWaveMaskRegClass();
8706 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8710 case AMDGPU::S_UADDO_PSEUDO:
8711 case AMDGPU::S_USUBO_PSEUDO: {
8717 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8718 ? AMDGPU::V_ADD_CO_U32_e64
8719 : AMDGPU::V_SUB_CO_U32_e64;
8731 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8735 case AMDGPU::S_LSHL1_ADD_U32:
8736 case AMDGPU::S_LSHL2_ADD_U32:
8737 case AMDGPU::S_LSHL3_ADD_U32:
8738 case AMDGPU::S_LSHL4_ADD_U32: {
8742 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8743 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8744 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8758 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8762 case AMDGPU::S_CSELECT_B32:
8763 case AMDGPU::S_CSELECT_B64:
8764 lowerSelect(Worklist, Inst, MDT);
8767 case AMDGPU::S_CMP_EQ_I32:
8768 case AMDGPU::S_CMP_LG_I32:
8769 case AMDGPU::S_CMP_GT_I32:
8770 case AMDGPU::S_CMP_GE_I32:
8771 case AMDGPU::S_CMP_LT_I32:
8772 case AMDGPU::S_CMP_LE_I32:
8773 case AMDGPU::S_CMP_EQ_U32:
8774 case AMDGPU::S_CMP_LG_U32:
8775 case AMDGPU::S_CMP_GT_U32:
8776 case AMDGPU::S_CMP_GE_U32:
8777 case AMDGPU::S_CMP_LT_U32:
8778 case AMDGPU::S_CMP_LE_U32:
8779 case AMDGPU::S_CMP_EQ_U64:
8780 case AMDGPU::S_CMP_LG_U64:
8781 case AMDGPU::S_CMP_LT_F32:
8782 case AMDGPU::S_CMP_EQ_F32:
8783 case AMDGPU::S_CMP_LE_F32:
8784 case AMDGPU::S_CMP_GT_F32:
8785 case AMDGPU::S_CMP_LG_F32:
8786 case AMDGPU::S_CMP_GE_F32:
8787 case AMDGPU::S_CMP_O_F32:
8788 case AMDGPU::S_CMP_U_F32:
8789 case AMDGPU::S_CMP_NGE_F32:
8790 case AMDGPU::S_CMP_NLG_F32:
8791 case AMDGPU::S_CMP_NGT_F32:
8792 case AMDGPU::S_CMP_NLE_F32:
8793 case AMDGPU::S_CMP_NEQ_F32:
8794 case AMDGPU::S_CMP_NLT_F32: {
8799 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8813 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8817 case AMDGPU::S_CMP_LT_F16:
8818 case AMDGPU::S_CMP_EQ_F16:
8819 case AMDGPU::S_CMP_LE_F16:
8820 case AMDGPU::S_CMP_GT_F16:
8821 case AMDGPU::S_CMP_LG_F16:
8822 case AMDGPU::S_CMP_GE_F16:
8823 case AMDGPU::S_CMP_O_F16:
8824 case AMDGPU::S_CMP_U_F16:
8825 case AMDGPU::S_CMP_NGE_F16:
8826 case AMDGPU::S_CMP_NLG_F16:
8827 case AMDGPU::S_CMP_NGT_F16:
8828 case AMDGPU::S_CMP_NLE_F16:
8829 case AMDGPU::S_CMP_NEQ_F16:
8830 case AMDGPU::S_CMP_NLT_F16: {
8852 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8856 case AMDGPU::S_CVT_HI_F32_F16: {
8859 if (ST.useRealTrue16Insts()) {
8864 .
addReg(TmpReg, {}, AMDGPU::hi16)
8880 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8884 case AMDGPU::S_MINIMUM_F32:
8885 case AMDGPU::S_MAXIMUM_F32: {
8897 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8901 case AMDGPU::S_MINIMUM_F16:
8902 case AMDGPU::S_MAXIMUM_F16: {
8904 ? &AMDGPU::VGPR_16RegClass
8905 : &AMDGPU::VGPR_32RegClass);
8916 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8920 case AMDGPU::V_S_EXP_F16_e64:
8921 case AMDGPU::V_S_LOG_F16_e64:
8922 case AMDGPU::V_S_RCP_F16_e64:
8923 case AMDGPU::V_S_RSQ_F16_e64:
8924 case AMDGPU::V_S_SQRT_F16_e64: {
8926 ? &AMDGPU::VGPR_16RegClass
8927 : &AMDGPU::VGPR_32RegClass);
8938 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8944 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8952 if (NewOpcode == Opcode) {
8959 V2SPhyCopiesToErase);
8967 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8974 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8980 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8981 UseMO.setReg(NewDstReg);
9000 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
9013 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
9017 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9023 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9030 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9032 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9037 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9045 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9055 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9056 AMDGPU::OpName::src0_modifiers) >= 0)
9060 NewInstr->addOperand(Src);
9063 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9066 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9068 NewInstr.addImm(
Size);
9069 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9073 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9078 "Scalar BFE is only implemented for constant width and offset");
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9087 AMDGPU::OpName::src1_modifiers) >= 0)
9089 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9091 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9092 AMDGPU::OpName::src2_modifiers) >= 0)
9094 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9096 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9098 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9100 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9106 NewInstr->addOperand(
Op);
9112 bool DeadSCCDef =
false;
9114 if (
Op.getReg() == AMDGPU::SCC) {
9120 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9124 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9129 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9130 Register DstReg = NewInstr->getOperand(0).getReg();
9144 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9145 VCCDef->setIsDead();
9151 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9155std::pair<bool, MachineBasicBlock *>
9158 if (ST.hasAddNoCarryInsts()) {
9170 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9172 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9173 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9184 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9185 return std::pair(
true, NewBB);
9188 return std::pair(
false,
nullptr);
9205 bool IsSCC = (CondReg == AMDGPU::SCC);
9211 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9212 (
Src1.getImm() == 0)) {
9213 for (MachineOperand &UseMO :
9215 MachineInstr &
UseMI = *UseMO.getParent();
9216 switch (
UseMI.getOpcode()) {
9217 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9218 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9219 case AMDGPU::V_CNDMASK_B16_t16_e32:
9220 case AMDGPU::V_CNDMASK_B16_t16_e64:
9221 case AMDGPU::V_CNDMASK_B32_e32:
9222 case AMDGPU::V_CNDMASK_B32_e64:
9223 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9224 if (UseMO.isImplicit() ||
9226 UseMO.setReg(CondReg);
9240 bool CopyFound =
false;
9241 for (MachineInstr &CandI :
9244 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9246 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9248 .
addReg(CandI.getOperand(1).getReg());
9260 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9269 MachineInstr *NewInst;
9270 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9271 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9286 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9301 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9303 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9305 MachineInstrBuilder
Sub =
9315 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9332 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9334 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9336 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9340 MachineInstrBuilder Sub2 =
9353 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9367 if (ST.hasDLInsts()) {
9377 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9383 bool Src0IsSGPR =
Src0.isReg() &&
9385 bool Src1IsSGPR =
Src1.isReg() &&
9399 }
else if (Src1IsSGPR) {
9417 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9423 unsigned Opcode)
const {
9447 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9452 unsigned Opcode)
const {
9476 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9491 const MCInstrDesc &InstDesc =
get(Opcode);
9494 &AMDGPU::SGPR_32RegClass;
9497 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9500 AMDGPU::sub0, Src0SubRC);
9505 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9508 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9511 AMDGPU::sub1, Src0SubRC);
9514 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9528 Worklist.
insert(&LoHalf);
9529 Worklist.
insert(&HiHalf);
9535 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9559 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9560 if (RI.isSGPRClass(Src0SubRC))
9561 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9563 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9564 if (RI.isSGPRClass(Src1SubRC))
9565 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9569 MachineOperand Op0L =
9571 MachineOperand Op1L =
9573 MachineOperand Op0H =
9575 MachineOperand Op1H =
9594 MachineInstr *Op1L_Op0H =
9600 MachineInstr *Op1H_Op0L =
9606 MachineInstr *Carry =
9611 MachineInstr *LoHalf =
9621 MachineInstr *HiHalf =
9644 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9668 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9669 if (RI.isSGPRClass(Src0SubRC))
9670 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9672 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9673 if (RI.isSGPRClass(Src1SubRC))
9674 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9678 MachineOperand Op0L =
9680 MachineOperand Op1L =
9684 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9685 ? AMDGPU::V_MUL_HI_U32_e64
9686 : AMDGPU::V_MUL_HI_I32_e64;
9687 MachineInstr *HiHalf =
9690 MachineInstr *LoHalf =
9709 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9725 const MCInstrDesc &InstDesc =
get(Opcode);
9728 &AMDGPU::SGPR_32RegClass;
9731 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9734 &AMDGPU::SGPR_32RegClass;
9737 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9740 AMDGPU::sub0, Src0SubRC);
9742 AMDGPU::sub0, Src1SubRC);
9744 AMDGPU::sub1, Src0SubRC);
9746 AMDGPU::sub1, Src1SubRC);
9751 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9754 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9759 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9772 Worklist.
insert(&LoHalf);
9773 Worklist.
insert(&HiHalf);
9776 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9796 MachineOperand* Op0;
9797 MachineOperand* Op1;
9799 if (
Src0.isReg() && RI.isSGPRReg(MRI,
Src0.getReg())) {
9832 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9835 &AMDGPU::SGPR_32RegClass;
9841 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9844 AMDGPU::sub0, SrcSubRC);
9846 AMDGPU::sub1, SrcSubRC);
9856 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9875 Offset == 0 &&
"Not implemented");
9898 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9908 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9911 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9917 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9936 const MCInstrDesc &InstDesc =
get(Opcode);
9938 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9941 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9943 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9945 MachineOperand SrcRegSub0 =
9947 MachineOperand SrcRegSub1 =
9961 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9965 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9969 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9972void SIInstrInfo::addUsersToMoveToVALUWorklist(
9976 MachineInstr &
UseMI = *MO.getParent();
9980 switch (
UseMI.getOpcode()) {
9983 case AMDGPU::SOFT_WQM:
9984 case AMDGPU::STRICT_WWM:
9985 case AMDGPU::STRICT_WQM:
9986 case AMDGPU::REG_SEQUENCE:
9988 case AMDGPU::INSERT_SUBREG:
9991 OpNo = MO.getOperandNo();
9998 if (!RI.hasVectorRegisters(OpRC))
10015 if (ST.useRealTrue16Insts()) {
10017 if (!
Src0.isReg() || !RI.isVGPR(MRI,
Src0.getReg())) {
10020 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10023 SrcReg0 =
Src0.getReg();
10026 if (!
Src1.isReg() || !RI.isVGPR(MRI,
Src1.getReg())) {
10029 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10032 SrcReg1 =
Src1.getReg();
10038 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
10040 case AMDGPU::S_PACK_LL_B32_B16:
10042 .addReg(SrcReg0, {},
10043 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10044 .addImm(AMDGPU::lo16)
10045 .addReg(SrcReg1, {},
10046 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10047 .addImm(AMDGPU::hi16);
10049 case AMDGPU::S_PACK_LH_B32_B16:
10051 .addReg(SrcReg0, {},
10052 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10053 .addImm(AMDGPU::lo16)
10054 .addReg(SrcReg1, {}, AMDGPU::hi16)
10055 .addImm(AMDGPU::hi16);
10057 case AMDGPU::S_PACK_HL_B32_B16:
10058 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10059 .addImm(AMDGPU::lo16)
10060 .addReg(SrcReg1, {},
10061 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10062 .addImm(AMDGPU::hi16);
10064 case AMDGPU::S_PACK_HH_B32_B16:
10065 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10066 .addImm(AMDGPU::lo16)
10067 .addReg(SrcReg1, {}, AMDGPU::hi16)
10068 .addImm(AMDGPU::hi16);
10076 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10081 case AMDGPU::S_PACK_LL_B32_B16: {
10100 case AMDGPU::S_PACK_LH_B32_B16: {
10110 case AMDGPU::S_PACK_HL_B32_B16: {
10121 case AMDGPU::S_PACK_HH_B32_B16: {
10141 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10150 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10151 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10152 SmallVector<MachineInstr *, 4> CopyToDelete;
10155 for (MachineInstr &
MI :
10159 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10160 if (SCCIdx != -1) {
10163 Register DestReg =
MI.getOperand(0).getReg();
10170 MI.getOperand(SCCIdx).setReg(NewCond);
10176 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10179 for (
auto &Copy : CopyToDelete)
10180 Copy->eraseFromParent();
10188void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10194 for (MachineInstr &
MI :
10197 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10199 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10216 case AMDGPU::REG_SEQUENCE:
10217 case AMDGPU::INSERT_SUBREG:
10219 case AMDGPU::SOFT_WQM:
10220 case AMDGPU::STRICT_WWM:
10221 case AMDGPU::STRICT_WQM: {
10223 if (RI.isAGPRClass(SrcRC)) {
10224 if (RI.isAGPRClass(NewDstRC))
10229 case AMDGPU::REG_SEQUENCE:
10230 case AMDGPU::INSERT_SUBREG:
10231 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10234 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10240 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10243 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10257 int OpIndices[3])
const {
10258 const MCInstrDesc &
Desc =
MI.getDesc();
10276 for (
unsigned i = 0; i < 3; ++i) {
10277 int Idx = OpIndices[i];
10281 const MachineOperand &MO =
MI.getOperand(Idx);
10288 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10289 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10290 if (IsRequiredSGPR)
10296 if (RI.isSGPRClass(RegRC))
10297 UsedSGPRs[i] =
Reg;
10313 if (UsedSGPRs[0]) {
10314 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10315 SGPRReg = UsedSGPRs[0];
10318 if (!SGPRReg && UsedSGPRs[1]) {
10319 if (UsedSGPRs[1] == UsedSGPRs[2])
10320 SGPRReg = UsedSGPRs[1];
10327 AMDGPU::OpName OperandName)
const {
10328 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10331 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10335 return &
MI.getOperand(Idx);
10349 if (ST.isAmdHsaOS()) {
10352 RsrcDataFormat |= (1ULL << 56);
10357 RsrcDataFormat |= (2ULL << 59);
10360 return RsrcDataFormat;
10370 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10375 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10382 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10388 unsigned Opc =
MI.getOpcode();
10394 return get(
Opc).mayLoad() &&
10401 if (!Addr || !Addr->
isFI())
10410 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10412 return MI.getOperand(VDataIdx).getReg();
10422 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10424 return MI.getOperand(DataIdx).getReg();
10445 if (!
MI.mayStore())
10458 unsigned Opc =
MI.getOpcode();
10460 unsigned DescSize =
Desc.getSize();
10465 unsigned Size = DescSize;
10469 if (
MI.isBranch() && ST.hasOffset3fBug())
10480 bool HasLiteral =
false;
10481 unsigned LiteralSize = 4;
10482 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10487 if (ST.has64BitLiterals()) {
10488 switch (OpInfo.OperandType) {
10513 return HasLiteral ? DescSize + LiteralSize : DescSize;
10518 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10522 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10523 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10527 case TargetOpcode::BUNDLE:
10528 return getInstBundleSize(
MI);
10529 case TargetOpcode::INLINEASM:
10530 case TargetOpcode::INLINEASM_BR: {
10532 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10536 if (
MI.isMetaInstruction())
10540 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10543 unsigned LoInstOpcode = D16Info->LoOp;
10545 DescSize =
Desc.getSize();
10549 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10552 DescSize =
Desc.getSize();
10561 if (
MI.isBranch() && ST.hasOffset3fBug())
10562 return InstSizeVerifyMode::NoVerify;
10563 return InstSizeVerifyMode::ExactSize;
10568 static const std::pair<int, const char *> TargetIndices[] = {
10608std::pair<unsigned, unsigned>
10615 static const std::pair<unsigned, const char *> TargetFlags[] = {
10633 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10649 return AMDGPU::WWM_COPY;
10651 return AMDGPU::COPY;
10668 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10672 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10673 return IsLRSplitInst;
10686 bool IsNullOrVectorRegister =
true;
10690 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10693 return IsNullOrVectorRegister &&
10695 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10696 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10704 if (ST.hasAddNoCarryInsts())
10720 if (ST.hasAddNoCarryInsts())
10724 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10726 : RS.scavengeRegisterBackwards(
10727 *RI.getBoolRC(),
I,
false,
10740 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10741 case AMDGPU::SI_KILL_I1_TERMINATOR:
10750 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10751 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10752 case AMDGPU::SI_KILL_I1_PSEUDO:
10753 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10765 const unsigned OffsetBits =
10767 return (1 << OffsetBits) - 1;
10771 if (!ST.isWave32())
10774 if (
MI.isInlineAsm())
10777 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10780 for (
auto &
Op :
MI.implicit_operands()) {
10781 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10782 Op.setReg(AMDGPU::VCC_LO);
10791 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10795 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10796 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10812 if (
Imm > MaxImm) {
10813 if (
Imm <= MaxImm + 64) {
10815 Overflow =
Imm - MaxImm;
10830 Overflow =
High - Alignment.value();
10834 if (Overflow > 0) {
10842 if (ST.hasRestrictedSOffset())
10847 SOffset = Overflow;
10885 if (!ST.hasFlatInstOffsets())
10889 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10894 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10895 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10906std::pair<int64_t, int64_t>
10909 int64_t RemainderOffset = COffsetVal;
10910 int64_t ImmField = 0;
10915 if (AllowNegative) {
10917 int64_t
D = 1LL << NumBits;
10918 RemainderOffset = (COffsetVal /
D) *
D;
10919 ImmField = COffsetVal - RemainderOffset;
10921 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10923 (ImmField % 4) != 0) {
10925 RemainderOffset += ImmField % 4;
10926 ImmField -= ImmField % 4;
10928 }
else if (COffsetVal >= 0) {
10930 RemainderOffset = COffsetVal - ImmField;
10934 assert(RemainderOffset + ImmField == COffsetVal);
10935 return {ImmField, RemainderOffset};
10940 if (ST.hasNegativeScratchOffsetBug() &&
10948 switch (ST.getGeneration()) {
10982 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10983 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10984 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10985 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10986 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10987 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10988 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10989 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10996#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10997 case OPCODE##_dpp: \
10998 case OPCODE##_e32: \
11012 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11013 case AMDGPU::V_FMA_F16_gfx9_e64:
11014 case AMDGPU::V_INTERP_P2_F16:
11015 case AMDGPU::V_MAD_F16_e64:
11016 case AMDGPU::V_MAD_U16_e64:
11017 case AMDGPU::V_MAD_I16_e64:
11026 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11034 switch (ST.getGeneration()) {
11047 if (
isMAI(Opcode)) {
11061 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11064 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11071 if (ST.hasGFX90AInsts()) {
11072 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11073 if (ST.hasGFX940Insts())
11075 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11077 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11079 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11085 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11104 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11105 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11106 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11118 switch (
MI.getOpcode()) {
11120 case AMDGPU::REG_SEQUENCE:
11124 case AMDGPU::INSERT_SUBREG:
11125 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11142 if (!
P.Reg.isVirtual())
11147 while (
auto *
MI = DefInst) {
11149 switch (
MI->getOpcode()) {
11151 case AMDGPU::V_MOV_B32_e32: {
11152 auto &Op1 =
MI->getOperand(1);
11181 auto *DefBB =
DefMI.getParent();
11185 if (
UseMI.getParent() != DefBB)
11188 const int MaxInstScan = 20;
11192 auto E =
UseMI.getIterator();
11193 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11194 if (
I->isDebugInstr())
11197 if (++NumInst > MaxInstScan)
11200 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11213 auto *DefBB =
DefMI.getParent();
11215 const int MaxUseScan = 10;
11219 auto &UseInst = *
Use.getParent();
11222 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11225 if (++NumUse > MaxUseScan)
11232 const int MaxInstScan = 20;
11236 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11239 if (
I->isDebugInstr())
11242 if (++NumInst > MaxInstScan)
11255 if (Reg == VReg && --NumUse == 0)
11257 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11266 auto Cur =
MBB.begin();
11267 if (Cur !=
MBB.end())
11269 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11272 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11281 if (InsPt !=
MBB.end() &&
11282 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11283 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11284 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11285 InsPt->definesRegister(Src,
nullptr)) {
11289 .
addReg(Src, {}, SrcSubReg)
11332 if (isFullCopyInstr(
MI)) {
11333 Register DstReg =
MI.getOperand(0).getReg();
11334 Register SrcReg =
MI.getOperand(1).getReg();
11356 unsigned *PredCost)
const {
11357 if (
MI.isBundle()) {
11360 unsigned Lat = 0,
Count = 0;
11361 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11363 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11365 return Lat +
Count - 1;
11368 return SchedModel.computeInstrLatency(&
MI);
11372 if (!ST.hasGFX1250VALUBlockingCycles())
11379 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11380 return Entry->GFX1250BlockingCycles;
11388 return *CallAddrOp;
11395 unsigned Opcode =
MI.getOpcode();
11397 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11403 unsigned SrcAS = SrcTy.getAddressSpace();
11406 ST.hasGloballyAddressableScratch()
11414 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11415 return HandleAddrSpaceCast(
MI);
11418 auto IID = GI->getIntrinsicID();
11425 case Intrinsic::amdgcn_if:
11426 case Intrinsic::amdgcn_else:
11440 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11441 Opcode == AMDGPU::G_SEXTLOAD) {
11442 if (
MI.memoperands_empty())
11446 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11447 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11455 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11456 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11457 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11463 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11466 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11474 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11475 return Formatter.get();
11483 unsigned opcode =
MI.getOpcode();
11484 if (opcode == AMDGPU::V_READLANE_B32 ||
11485 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11486 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11491 if (
MI.isInlineAsm()) {
11497 if (!RC || !RI.isSGPRClass(RC))
11502 if (isCopyInstr(
MI)) {
11506 RI.getPhysRegBaseClass(srcOp.
getReg());
11514 if (
MI.isPreISelOpcode())
11529 if (
MI.memoperands_empty())
11533 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11534 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11549 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11551 if (!
SrcOp.isReg())
11555 if (!Reg || !
SrcOp.readsReg())
11561 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11588 F,
"ds_ordered_count unsupported for this calling conv"));
11602 Register &SrcReg2, int64_t &CmpMask,
11603 int64_t &CmpValue)
const {
11604 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11607 switch (
MI.getOpcode()) {
11610 case AMDGPU::S_CMP_EQ_U32:
11611 case AMDGPU::S_CMP_EQ_I32:
11612 case AMDGPU::S_CMP_LG_U32:
11613 case AMDGPU::S_CMP_LG_I32:
11614 case AMDGPU::S_CMP_LT_U32:
11615 case AMDGPU::S_CMP_LT_I32:
11616 case AMDGPU::S_CMP_GT_U32:
11617 case AMDGPU::S_CMP_GT_I32:
11618 case AMDGPU::S_CMP_LE_U32:
11619 case AMDGPU::S_CMP_LE_I32:
11620 case AMDGPU::S_CMP_GE_U32:
11621 case AMDGPU::S_CMP_GE_I32:
11622 case AMDGPU::S_CMP_EQ_U64:
11623 case AMDGPU::S_CMP_LG_U64:
11624 SrcReg =
MI.getOperand(0).getReg();
11625 if (
MI.getOperand(1).isReg()) {
11626 if (
MI.getOperand(1).getSubReg())
11628 SrcReg2 =
MI.getOperand(1).getReg();
11630 }
else if (
MI.getOperand(1).isImm()) {
11632 CmpValue =
MI.getOperand(1).getImm();
11638 case AMDGPU::S_CMPK_EQ_U32:
11639 case AMDGPU::S_CMPK_EQ_I32:
11640 case AMDGPU::S_CMPK_LG_U32:
11641 case AMDGPU::S_CMPK_LG_I32:
11642 case AMDGPU::S_CMPK_LT_U32:
11643 case AMDGPU::S_CMPK_LT_I32:
11644 case AMDGPU::S_CMPK_GT_U32:
11645 case AMDGPU::S_CMPK_GT_I32:
11646 case AMDGPU::S_CMPK_LE_U32:
11647 case AMDGPU::S_CMPK_LE_I32:
11648 case AMDGPU::S_CMPK_GE_U32:
11649 case AMDGPU::S_CMPK_GE_I32:
11650 SrcReg =
MI.getOperand(0).getReg();
11652 CmpValue =
MI.getOperand(1).getImm();
11662 if (S->isLiveIn(AMDGPU::SCC))
11671bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11674 bool SCCIsDead =
false;
11677 constexpr unsigned ScanLimit = 12;
11678 unsigned Count = 0;
11681 if (++
Count > ScanLimit)
11683 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11684 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11685 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11686 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11687 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11692 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11705 for (MachineInstr *
MI : InvertInstr) {
11706 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11707 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11709 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11710 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11711 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11712 ? AMDGPU::S_CBRANCH_SCC1
11713 : AMDGPU::S_CBRANCH_SCC0));
11726 bool NeedInversion)
const {
11727 MachineInstr *KillsSCC =
nullptr;
11732 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11734 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11737 if (NeedInversion && !invertSCCUse(SCCRedefine))
11739 if (MachineOperand *SccDef =
11741 SccDef->setIsDead(
false);
11750static std::optional<std::pair<int64_t, int64_t>>
11754 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11756 std::optional<int64_t>
A =
11760 std::optional<int64_t>
B =
11764 if (
Opc == AMDGPU::S_CSELECT_B32) {
11770 return std::pair(*
A, *
B);
11774 unsigned &NewDefOpc) {
11777 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11778 Def.getOpcode() != AMDGPU::S_ADD_U32)
11784 Def.getMF()->getSubtarget().getInstrInfo());
11786 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11787 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11788 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11791 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11793 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11796 NewDefOpc = AMDGPU::S_ADD_U32;
11798 NeedInversion = !NeedInversion;
11803 Register SrcReg2, int64_t CmpMask,
11813 CmpValue = *ImmOpt;
11816 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11817 this](
bool NeedInversion) ->
bool {
11822 unsigned NewDefOpc = Def->getOpcode();
11829 auto [
A,
B] = *Consts;
11830 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11833 NeedInversion = !NeedInversion;
11845 if (CmpValue != 0 ||
11851 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11854 if (NewDefOpc != Def->getOpcode())
11855 Def->setDesc(
get(NewDefOpc));
11864 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11871 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11880 auto [
A,
B] = *Consts;
11881 if (
A == 0 ||
B == 0)
11882 optimizeSCC(
Select, Def,
A == 0);
11891 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11892 this](int64_t ExpectedValue,
unsigned SrcSize,
11893 bool IsReversible,
bool IsSigned) ->
bool {
11921 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11922 Def->getOpcode() != AMDGPU::S_AND_B64)
11926 const auto isMask = [&Mask, SrcSize, MRI,
11938 SrcOp = &Def->getOperand(2);
11939 else if (isMask(&Def->getOperand(2)))
11940 SrcOp = &Def->getOperand(1);
11948 if (IsSigned && BitNo == SrcSize - 1)
11951 ExpectedValue <<= BitNo;
11953 bool IsReversedCC =
false;
11954 if (CmpValue != ExpectedValue) {
11957 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11962 Register DefReg = Def->getOperand(0).getReg();
11963 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11966 if (!optimizeSCC(Def, &CmpInstr,
false))
11969 if (!MRI->use_nodbg_empty(DefReg)) {
11977 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11978 : AMDGPU::S_BITCMP1_B32
11979 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11980 : AMDGPU::S_BITCMP1_B64;
11985 Def->eraseFromParent();
11993 case AMDGPU::S_CMP_EQ_U32:
11994 case AMDGPU::S_CMP_EQ_I32:
11995 case AMDGPU::S_CMPK_EQ_U32:
11996 case AMDGPU::S_CMPK_EQ_I32:
11997 return optimizeCmpAnd(1, 32,
true,
false) ||
11998 optimizeCmpSelect(
true);
11999 case AMDGPU::S_CMP_GE_U32:
12000 case AMDGPU::S_CMPK_GE_U32:
12001 return optimizeCmpAnd(1, 32,
false,
false);
12002 case AMDGPU::S_CMP_GE_I32:
12003 case AMDGPU::S_CMPK_GE_I32:
12004 return optimizeCmpAnd(1, 32,
false,
true);
12005 case AMDGPU::S_CMP_EQ_U64:
12006 return optimizeCmpAnd(1, 64,
true,
false) ||
12007 optimizeCmpSelect(
true);
12008 case AMDGPU::S_CMP_LG_U32:
12009 case AMDGPU::S_CMP_LG_I32:
12010 case AMDGPU::S_CMPK_LG_U32:
12011 case AMDGPU::S_CMPK_LG_I32:
12012 return optimizeCmpAnd(0, 32,
true,
false) ||
12013 optimizeCmpSelect(
false);
12014 case AMDGPU::S_CMP_GT_U32:
12015 case AMDGPU::S_CMPK_GT_U32:
12016 return optimizeCmpAnd(0, 32,
false,
false);
12017 case AMDGPU::S_CMP_GT_I32:
12018 case AMDGPU::S_CMPK_GT_I32:
12019 return optimizeCmpAnd(0, 32,
false,
true);
12020 case AMDGPU::S_CMP_LG_U64:
12021 return optimizeCmpAnd(0, 64,
true,
false) ||
12022 optimizeCmpSelect(
false);
12029 AMDGPU::OpName
OpName)
const {
12030 if (!ST.needsAlignedVGPRs())
12033 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
12045 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12047 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12051 : &AMDGPU::VReg_64_Align2RegClass);
12053 .
addReg(DataReg, {},
Op.getSubReg())
12058 Op.setSubReg(AMDGPU::sub0);
12063 if (!SchedModel.hasInstrSchedModel())
12069 unsigned RepeatRate = 0;
12071 PI = SchedModel.getWriteProcResBegin(SCDesc),
12072 PE = SchedModel.getWriteProcResEnd(SCDesc);
12074 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12091 if (ST.hasGFX1250Insts())
12098 unsigned Opcode =
MI.getOpcode();
12104 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12105 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12108 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.
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.