33#include "llvm/IR/IntrinsicsAMDGPU.h"
41#define DEBUG_TYPE "si-instr-info"
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
57#include "AMDGPUGenSearchableTables.inc"
65 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
68 "amdgpu-fix-16-bit-physreg-copies",
69 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
85 unsigned N =
Node->getNumOperands();
86 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
98 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
99 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
101 if (Op0Idx == -1 && Op1Idx == -1)
105 if ((Op0Idx == -1 && Op1Idx != -1) ||
106 (Op1Idx == -1 && Op0Idx != -1))
127 return !
MI.memoperands_empty() &&
129 return MMO->isLoad() && MMO->isInvariant();
138static std::tuple<unsigned, unsigned, unsigned>
146 unsigned LoReloc, HiReloc;
176 return {BaseFlags, LoReloc, HiReloc};
194 if (!
MI.hasImplicitDef() &&
195 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
196 !
MI.mayRaiseFPException())
205 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
220 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
221 MI.hasUnmodeledSideEffects())
226 if (
MI.isInlineAsm())
230 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
245 if (Reg.isPhysical()) {
250 if (!
MRI.isConstantPhysReg(Reg))
261 if (MO.isDef() && Reg != DefReg)
271 case AMDGPU::V_SUBREV_U16_e32:
272 case AMDGPU::V_SUBREV_U16_e64:
274 case AMDGPU::V_SUBREV_U32_e32:
275 case AMDGPU::V_SUBREV_U32_e64:
277 case AMDGPU::V_SUBREV_CO_U32_e32:
278 case AMDGPU::V_SUBREV_CO_U32_e64:
280 case AMDGPU::V_SUBBREV_U32_e32:
281 case AMDGPU::V_SUBBREV_U32_e64:
284 case AMDGPU::V_ASHRREV_I16_e32:
285 case AMDGPU::V_ASHRREV_I16_e64:
286 case AMDGPU::V_ASHRREV_I32_e32:
287 case AMDGPU::V_ASHRREV_I32_e64:
288 case AMDGPU::V_ASHRREV_I64_e64:
289 case AMDGPU::V_LSHLREV_B16_e32:
290 case AMDGPU::V_LSHLREV_B16_e64:
291 case AMDGPU::V_LSHLREV_B32_e32:
292 case AMDGPU::V_LSHLREV_B32_e64:
293 case AMDGPU::V_LSHLREV_B64_e64:
294 case AMDGPU::V_LSHRREV_B16_e32:
295 case AMDGPU::V_LSHRREV_B16_e64:
296 case AMDGPU::V_LSHRREV_B32_e32:
297 case AMDGPU::V_LSHRREV_B32_e64:
298 case AMDGPU::V_LSHRREV_B64_e64:
299 return !ST.hasGFX11Insts();
306bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
310 if (
MI.isConvergent())
338 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
343 for (
auto Op :
MI.uses()) {
344 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
345 RI.isSGPRClass(
MRI.getRegClass(
Op.getReg()))) {
358 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
378 int64_t &Offset1)
const {
386 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
390 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
406 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
407 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
408 if (Offset0Idx == -1 || Offset1Idx == -1)
415 Offset0Idx -=
get(Opc0).NumDefs;
416 Offset1Idx -=
get(Opc1).NumDefs;
446 if (!Load0Offset || !Load1Offset)
463 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
464 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
466 if (OffIdx0 == -1 || OffIdx1 == -1)
472 OffIdx0 -=
get(Opc0).NumDefs;
473 OffIdx1 -=
get(Opc1).NumDefs;
492 case AMDGPU::DS_READ2ST64_B32:
493 case AMDGPU::DS_READ2ST64_B64:
494 case AMDGPU::DS_WRITE2ST64_B32:
495 case AMDGPU::DS_WRITE2ST64_B64:
509 OffsetIsScalable =
false;
526 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
528 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
529 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
542 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
543 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
544 if (Offset0 + 1 != Offset1)
555 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
556 EltSize = RI.getRegSizeInBits(*
getOpRegClass(LdSt, Data0Idx)) / 8;
563 Offset = EltSize * Offset0;
565 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
566 if (DataOpIdx == -1) {
567 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
569 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
585 if (BaseOp && !BaseOp->
isFI())
593 if (SOffset->
isReg())
599 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
601 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
610 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
611 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
613 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
614 if (VAddr0Idx >= 0) {
616 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
623 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
638 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
655 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
657 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
674 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
682 if (MO1->getAddrSpace() != MO2->getAddrSpace())
685 const auto *Base1 = MO1->getValue();
686 const auto *Base2 = MO2->getValue();
687 if (!Base1 || !Base2)
695 return Base1 == Base2;
706 *BaseOps2.
front()->getParent(), BaseOps2);
710 int64_t Offset1,
bool OffsetIsScalable1,
712 int64_t Offset2,
bool OffsetIsScalable2,
713 unsigned ClusterSize,
714 unsigned NumBytes)
const {
724 if (!BaseOps1.
empty()) {
726 MaxMemoryClusterDWords =
744 const unsigned LoadSize = NumBytes / ClusterSize;
745 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
746 return NumDWords <= MaxMemoryClusterDWords;
760 int64_t Offset0, int64_t Offset1,
761 unsigned NumLoads)
const {
762 assert(Offset1 > Offset0 &&
763 "Second offset should be larger than first offset!");
768 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
775 const char *
Msg =
"illegal VGPR to SGPR copy") {
794 assert((
TII.getSubtarget().hasMAIInsts() &&
795 !
TII.getSubtarget().hasGFX90AInsts()) &&
796 "Expected GFX908 subtarget.");
799 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
800 "Source register of the copy should be either an SGPR or an AGPR.");
803 "Destination register of the copy should be an AGPR.");
812 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
815 if (!Def->modifiesRegister(SrcReg, &RI))
818 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
819 Def->getOperand(0).getReg() != SrcReg)
826 bool SafeToPropagate =
true;
829 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
830 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
831 SafeToPropagate =
false;
833 if (!SafeToPropagate)
836 for (
auto I = Def;
I !=
MI; ++
I)
837 I->clearRegisterKills(DefOp.
getReg(), &RI);
845 if (ImpUseSuperReg) {
846 Builder.addReg(ImpUseSuperReg,
854 RS.enterBasicBlockEnd(
MBB);
855 RS.backward(std::next(
MI));
864 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
867 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
868 "VGPR used for an intermediate copy should have been reserved.");
873 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
883 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
884 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
885 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
892 if (ImpUseSuperReg) {
893 UseBuilder.
addReg(ImpUseSuperReg,
910 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
911 int16_t SubIdx = BaseIndices[Idx];
912 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
913 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
914 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
915 unsigned Opcode = AMDGPU::S_MOV_B32;
918 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
919 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
920 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
924 DestSubReg = RI.getSubReg(DestReg, SubIdx);
925 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
926 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
927 Opcode = AMDGPU::S_MOV_B64;
942 assert(FirstMI && LastMI);
947 LastMI->addRegisterKilled(SrcReg, &RI);
953 Register SrcReg,
bool KillSrc,
bool RenamableDest,
954 bool RenamableSrc)
const {
956 unsigned Size = RI.getRegSizeInBits(*RC);
958 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
964 if (((
Size == 16) != (SrcSize == 16))) {
966 assert(ST.useRealTrue16Insts());
968 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
971 if (DestReg == SrcReg) {
977 RC = RI.getPhysRegBaseClass(DestReg);
978 Size = RI.getRegSizeInBits(*RC);
979 SrcRC = RI.getPhysRegBaseClass(SrcReg);
980 SrcSize = RI.getRegSizeInBits(*SrcRC);
984 if (RC == &AMDGPU::VGPR_32RegClass) {
986 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
987 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
988 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
989 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
995 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
996 RC == &AMDGPU::SReg_32RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
1004 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC_LO) {
1023 if (RC == &AMDGPU::SReg_64RegClass) {
1024 if (SrcReg == AMDGPU::SCC) {
1031 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1032 if (DestReg == AMDGPU::VCC) {
1050 if (DestReg == AMDGPU::SCC) {
1053 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1057 assert(ST.hasScalarCompareEq64());
1071 if (RC == &AMDGPU::AGPR_32RegClass) {
1072 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1073 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1079 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1088 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1095 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1096 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1098 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1099 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1100 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1101 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1104 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1105 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1118 if (IsAGPRDst || IsAGPRSrc) {
1119 if (!DstLow || !SrcLow) {
1121 "Cannot use hi16 subreg with an AGPR!");
1128 if (ST.useRealTrue16Insts()) {
1134 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1135 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1147 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1148 if (!DstLow || !SrcLow) {
1150 "Cannot use hi16 subreg on VI!");
1176 unsigned SrcOp = 1) {
1180 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1184 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1185 if (ST.hasVMovB64Inst() &&
1186 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1191 if (ST.hasPkMovB32() &&
1192 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1208 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1209 if (RI.isSGPRClass(RC)) {
1210 if (!RI.isSGPRClass(SrcRC)) {
1214 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1220 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1221 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1222 if (RI.isAGPRClass(RC)) {
1223 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1224 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1225 else if (RI.hasVGPRs(SrcRC) ||
1226 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1227 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1229 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1230 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1231 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1232 }
else if (RI.isVGPRClass(RC)) {
1233 if (ST.hasVMovB64Inst())
1234 WideOpcode = AMDGPU::V_MOV_B64_e32;
1235 else if (ST.hasPkMovB32())
1236 WideOpcode = AMDGPU::V_PK_MOV_B32;
1240 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1242 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1249 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1250 const bool CanKillSuperReg = KillSrc && !Overlap;
1257 std::unique_ptr<RegScavenger> RS;
1258 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1259 RS = std::make_unique<RegScavenger>();
1263 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1264 unsigned NumRegs = 1;
1265 unsigned ThisOpcode = Opcode;
1267 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1269 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1270 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1274 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1275 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1276 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1278 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1279 WideSrcRC->contains(WideSrc)) {
1280 SubIdx = WideSubIdx;
1282 ThisOpcode = WideOpcode;
1286 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1287 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1288 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1291 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1293 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1296 *RS, Overlap, ImpUseSuper);
1297 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1338 int64_t &ImmVal)
const {
1339 switch (
MI.getOpcode()) {
1340 case AMDGPU::V_MOV_B32_e32:
1341 case AMDGPU::S_MOV_B32:
1342 case AMDGPU::S_MOVK_I32:
1343 case AMDGPU::S_MOV_B64:
1344 case AMDGPU::V_MOV_B64_e32:
1345 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1346 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1347 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1348 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::V_MOV_B64_PSEUDO:
1350 case AMDGPU::V_MOV_B16_t16_e32: {
1353 ImmVal = Src0.getImm();
1354 return MI.getOperand(0).getReg() == Reg;
1359 case AMDGPU::V_MOV_B16_t16_e64: {
1361 if (Src0.isImm() && !
MI.getOperand(1).getImm()) {
1362 ImmVal = Src0.getImm();
1363 return MI.getOperand(0).getReg() == Reg;
1368 case AMDGPU::S_BREV_B32:
1369 case AMDGPU::V_BFREV_B32_e32:
1370 case AMDGPU::V_BFREV_B32_e64: {
1374 return MI.getOperand(0).getReg() == Reg;
1379 case AMDGPU::S_NOT_B32:
1380 case AMDGPU::V_NOT_B32_e32:
1381 case AMDGPU::V_NOT_B32_e64: {
1384 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.getImm()));
1385 return MI.getOperand(0).getReg() == Reg;
1395std::optional<int64_t>
1405 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1406 return std::nullopt;
1408 if (Def && Def->isMoveImmediate()) {
1410 if (ImmSrc.
isImm()) {
1417 return std::nullopt;
1420std::optional<int64_t>
1429 if (RI.isAGPRClass(DstRC))
1430 return AMDGPU::COPY;
1431 if (RI.getRegSizeInBits(*DstRC) == 16) {
1434 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1436 if (RI.getRegSizeInBits(*DstRC) == 32)
1437 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1438 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1439 return AMDGPU::S_MOV_B64;
1440 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1441 return AMDGPU::V_MOV_B64_PSEUDO;
1442 return AMDGPU::COPY;
1447 bool IsIndirectSrc)
const {
1448 if (IsIndirectSrc) {
1450 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1452 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1454 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1456 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1458 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1460 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1462 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1464 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1466 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1468 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1470 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1472 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1474 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1475 if (VecSize <= 1024)
1476 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1482 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1484 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1486 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1488 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1490 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1492 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1494 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1496 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1498 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1500 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1502 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1504 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1506 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1507 if (VecSize <= 1024)
1508 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1515 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1517 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1519 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1521 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1523 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1525 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1527 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1529 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1531 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1533 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1535 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1537 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1539 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1540 if (VecSize <= 1024)
1541 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1548 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1550 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1552 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1564 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1573 if (VecSize <= 1024)
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1581 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1583 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1585 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1587 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1588 if (VecSize <= 1024)
1589 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1596 bool IsSGPR)
const {
1608 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1621 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1622 : AMDGPU::SI_SPILL_S128_SAVE;
1624 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1625 : AMDGPU::SI_SPILL_S160_SAVE;
1627 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1628 : AMDGPU::SI_SPILL_S192_SAVE;
1630 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1631 : AMDGPU::SI_SPILL_S224_SAVE;
1633 return AMDGPU::SI_SPILL_S256_SAVE;
1635 return AMDGPU::SI_SPILL_S288_SAVE;
1637 return AMDGPU::SI_SPILL_S320_SAVE;
1639 return AMDGPU::SI_SPILL_S352_SAVE;
1641 return AMDGPU::SI_SPILL_S384_SAVE;
1643 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1644 : AMDGPU::SI_SPILL_S512_SAVE;
1646 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1647 : AMDGPU::SI_SPILL_S1024_SAVE;
1656 return AMDGPU::SI_SPILL_V16_SAVE;
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1662 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V128_SAVE;
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V160_SAVE;
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V192_SAVE;
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V224_SAVE;
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V256_SAVE;
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V288_SAVE;
1682 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1683 : AMDGPU::SI_SPILL_V320_SAVE;
1685 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1686 : AMDGPU::SI_SPILL_V352_SAVE;
1688 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1689 : AMDGPU::SI_SPILL_V384_SAVE;
1691 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1692 : AMDGPU::SI_SPILL_V512_SAVE;
1694 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1695 : AMDGPU::SI_SPILL_V1024_SAVE;
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV32_SAVE;
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV64_SAVE;
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV96_SAVE;
1713 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1714 : AMDGPU::SI_SPILL_AV128_SAVE;
1716 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1717 : AMDGPU::SI_SPILL_AV160_SAVE;
1719 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1720 : AMDGPU::SI_SPILL_AV192_SAVE;
1722 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1723 : AMDGPU::SI_SPILL_AV224_SAVE;
1725 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1726 : AMDGPU::SI_SPILL_AV256_SAVE;
1728 return AMDGPU::SI_SPILL_AV288_SAVE;
1730 return AMDGPU::SI_SPILL_AV320_SAVE;
1732 return AMDGPU::SI_SPILL_AV352_SAVE;
1734 return AMDGPU::SI_SPILL_AV384_SAVE;
1736 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1737 : AMDGPU::SI_SPILL_AV512_SAVE;
1739 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1740 : AMDGPU::SI_SPILL_AV1024_SAVE;
1747 bool IsVectorSuperClass) {
1752 if (IsVectorSuperClass)
1753 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1755 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1761 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1768 if (ST.hasMAIInsts())
1774void SIInstrInfo::storeRegToStackSlotImpl(
1787 FrameInfo.getObjectAlign(FrameIndex));
1788 unsigned SpillSize = RI.getSpillSize(*RC);
1794 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1795 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1796 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1805 if (SrcReg.
isVirtual() && SpillSize == 4) {
1806 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1819 SpillSize, *MFI, NeedsCFI);
1834 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1843 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1850 return AMDGPU::SI_SPILL_S32_RESTORE;
1852 return AMDGPU::SI_SPILL_S64_RESTORE;
1854 return AMDGPU::SI_SPILL_S96_RESTORE;
1856 return AMDGPU::SI_SPILL_S128_RESTORE;
1858 return AMDGPU::SI_SPILL_S160_RESTORE;
1860 return AMDGPU::SI_SPILL_S192_RESTORE;
1862 return AMDGPU::SI_SPILL_S224_RESTORE;
1864 return AMDGPU::SI_SPILL_S256_RESTORE;
1866 return AMDGPU::SI_SPILL_S288_RESTORE;
1868 return AMDGPU::SI_SPILL_S320_RESTORE;
1870 return AMDGPU::SI_SPILL_S352_RESTORE;
1872 return AMDGPU::SI_SPILL_S384_RESTORE;
1874 return AMDGPU::SI_SPILL_S512_RESTORE;
1876 return AMDGPU::SI_SPILL_S1024_RESTORE;
1885 return AMDGPU::SI_SPILL_V16_RESTORE;
1887 return AMDGPU::SI_SPILL_V32_RESTORE;
1889 return AMDGPU::SI_SPILL_V64_RESTORE;
1891 return AMDGPU::SI_SPILL_V96_RESTORE;
1893 return AMDGPU::SI_SPILL_V128_RESTORE;
1895 return AMDGPU::SI_SPILL_V160_RESTORE;
1897 return AMDGPU::SI_SPILL_V192_RESTORE;
1899 return AMDGPU::SI_SPILL_V224_RESTORE;
1901 return AMDGPU::SI_SPILL_V256_RESTORE;
1903 return AMDGPU::SI_SPILL_V288_RESTORE;
1905 return AMDGPU::SI_SPILL_V320_RESTORE;
1907 return AMDGPU::SI_SPILL_V352_RESTORE;
1909 return AMDGPU::SI_SPILL_V384_RESTORE;
1911 return AMDGPU::SI_SPILL_V512_RESTORE;
1913 return AMDGPU::SI_SPILL_V1024_RESTORE;
1922 return AMDGPU::SI_SPILL_AV32_RESTORE;
1924 return AMDGPU::SI_SPILL_AV64_RESTORE;
1926 return AMDGPU::SI_SPILL_AV96_RESTORE;
1928 return AMDGPU::SI_SPILL_AV128_RESTORE;
1930 return AMDGPU::SI_SPILL_AV160_RESTORE;
1932 return AMDGPU::SI_SPILL_AV192_RESTORE;
1934 return AMDGPU::SI_SPILL_AV224_RESTORE;
1936 return AMDGPU::SI_SPILL_AV256_RESTORE;
1938 return AMDGPU::SI_SPILL_AV288_RESTORE;
1940 return AMDGPU::SI_SPILL_AV320_RESTORE;
1942 return AMDGPU::SI_SPILL_AV352_RESTORE;
1944 return AMDGPU::SI_SPILL_AV384_RESTORE;
1946 return AMDGPU::SI_SPILL_AV512_RESTORE;
1948 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1955 bool IsVectorSuperClass) {
1960 if (IsVectorSuperClass)
1961 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1963 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1969 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1976 if (ST.hasMAIInsts())
1979 assert(!RI.isAGPRClass(RC));
1993 unsigned SpillSize = RI.getSpillSize(*RC);
2000 FrameInfo.getObjectAlign(FrameIndex));
2002 if (RI.isSGPRClass(RC)) {
2005 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
2006 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2007 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
2012 if (DestReg.
isVirtual() && SpillSize == 4) {
2014 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2041 unsigned Quantity)
const {
2043 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2044 while (Quantity > 0) {
2045 unsigned Arg = std::min(Quantity, MaxSNopCount);
2056 constexpr unsigned DoorbellIDMask = 0x3ff;
2057 constexpr unsigned ECQueueWaveAbort = 0x400;
2062 if (!
MBB.succ_empty() ||
2064 false) !=
MBB.end()) {
2065 MBB.splitAt(
MI,
false);
2069 MBB.addSuccessor(TrapBB);
2075 Register DoorbellReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2079 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2082 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2083 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2088 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2089 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2090 .
addUse(DoorbellRegMasked)
2091 .
addImm(ECQueueWaveAbort)
2093 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2094 .
addUse(SetWaveAbortBit);
2097 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2108 return MBB.getNextNode();
2112 switch (
MI.getOpcode()) {
2114 if (
MI.isMetaInstruction())
2119 return MI.getOperand(0).getImm() + 1;
2130 switch (
MI.getOpcode()) {
2132 case AMDGPU::S_MOV_B64_term:
2135 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2138 case AMDGPU::S_MOV_B32_term:
2141 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2144 case AMDGPU::S_XOR_B64_term:
2147 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2150 case AMDGPU::S_XOR_B32_term:
2153 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2155 case AMDGPU::S_OR_B64_term:
2158 MI.setDesc(
get(AMDGPU::S_OR_B64));
2160 case AMDGPU::S_OR_B32_term:
2163 MI.setDesc(
get(AMDGPU::S_OR_B32));
2166 case AMDGPU::S_ANDN2_B64_term:
2169 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2172 case AMDGPU::S_ANDN2_B32_term:
2175 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2178 case AMDGPU::S_AND_B64_term:
2181 MI.setDesc(
get(AMDGPU::S_AND_B64));
2184 case AMDGPU::S_AND_B32_term:
2187 MI.setDesc(
get(AMDGPU::S_AND_B32));
2190 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2193 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2196 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2199 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2202 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2203 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2205 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2206 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2209 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2210 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2213 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2214 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2216 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2220 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2223 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2226 int64_t
Imm =
MI.getOperand(1).getImm();
2228 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2229 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2234 MI.eraseFromParent();
2240 case AMDGPU::V_MOV_B64_PSEUDO: {
2242 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2243 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2251 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2252 MI.setDesc(Mov64Desc);
2256 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2259 if (
SrcOp.isGlobal()) {
2264 unsigned BaseFlags, LoReloc, HiReloc;
2265 std::tie(BaseFlags, LoReloc, HiReloc) =
2272 }
else if (
SrcOp.isImm()) {
2274 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2275 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2299 if (ST.hasPkMovB32() &&
2318 MI.eraseFromParent();
2321 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2325 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2329 if (ST.has64BitLiterals()) {
2330 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2334 if (
SrcOp.isGlobal()) {
2336 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2337 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2340 unsigned BaseFlags, LoReloc, HiReloc;
2341 std::tie(BaseFlags, LoReloc, HiReloc) =
2348 MI.eraseFromParent();
2355 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2360 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2361 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2363 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2364 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2369 MI.eraseFromParent();
2372 case AMDGPU::V_SET_INACTIVE_B32: {
2376 .
add(
MI.getOperand(3))
2377 .
add(
MI.getOperand(4))
2378 .
add(
MI.getOperand(1))
2379 .
add(
MI.getOperand(2))
2380 .
add(
MI.getOperand(5));
2381 MI.eraseFromParent();
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2420 if (RI.hasVGPRs(EltRC)) {
2421 Opc = AMDGPU::V_MOVRELD_B32_e32;
2423 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2424 : AMDGPU::S_MOVRELD_B32;
2429 bool IsUndef =
MI.getOperand(1).isUndef();
2430 unsigned SubReg =
MI.getOperand(3).getImm();
2431 assert(VecReg ==
MI.getOperand(1).getReg());
2436 .
add(
MI.getOperand(2))
2440 const int ImpDefIdx =
2442 const int ImpUseIdx = ImpDefIdx + 1;
2444 MI.eraseFromParent();
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2461 assert(ST.useVGPRIndexMode());
2463 bool IsUndef =
MI.getOperand(1).isUndef();
2472 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2476 .
add(
MI.getOperand(2))
2480 const int ImpDefIdx =
2482 const int ImpUseIdx = ImpDefIdx + 1;
2489 MI.eraseFromParent();
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2506 assert(ST.useVGPRIndexMode());
2509 bool IsUndef =
MI.getOperand(1).isUndef();
2513 .
add(
MI.getOperand(2))
2526 MI.eraseFromParent();
2529 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2532 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2533 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2552 if (ST.hasGetPCZeroExtension()) {
2556 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2563 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2573 MI.eraseFromParent();
2576 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2586 Op.setOffset(
Op.getOffset() + 4);
2588 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2592 MI.eraseFromParent();
2595 case AMDGPU::ENTER_STRICT_WWM: {
2601 case AMDGPU::ENTER_STRICT_WQM: {
2608 MI.eraseFromParent();
2611 case AMDGPU::EXIT_STRICT_WWM:
2612 case AMDGPU::EXIT_STRICT_WQM: {
2618 case AMDGPU::SI_RETURN: {
2632 MI.eraseFromParent();
2636 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2637 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2638 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2641 case AMDGPU::S_GETPC_B64_pseudo:
2642 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2643 if (ST.hasGetPCZeroExtension()) {
2645 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2654 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2655 assert(ST.hasBF16PackedInsts());
2656 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2667 case AMDGPU::GET_STACK_BASE:
2670 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2677 Register DestReg =
MI.getOperand(0).getReg();
2687 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2688 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2689 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2692 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2695 MI.getNumExplicitOperands());
2713 case AMDGPU::S_MOV_B64:
2714 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2723 if (UsedLanes.
all())
2728 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2729 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2731 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2732 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2734 if (NeedLo && NeedHi)
2738 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2740 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2749 case AMDGPU::S_LOAD_DWORDX16_IMM:
2750 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2751 if (SubIdx != 0 || UsedLanes.
all())
2762 assert(
MRI.use_nodbg_empty(DestReg) &&
"DestReg should have no users yet.");
2769 UseMO !=
I->findRegisterUseOperand(RegToFind,
nullptr) ||
2770 UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2776 unsigned NewOpcode = -1;
2777 if (SubregSize == 256)
2778 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2779 else if (SubregSize == 128)
2780 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2787 MRI.setRegClass(DestReg, NewRC);
2790 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2795 MI->getOperand(0).setReg(DestReg);
2796 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2800 OffsetMO->
setImm(FinalOffset);
2806 MI->setMemRefs(*MF, NewMMOs);
2819std::pair<MachineInstr*, MachineInstr*>
2821 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2823 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2826 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2827 return std::pair(&
MI,
nullptr);
2838 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2840 if (Dst.isPhysical()) {
2841 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2844 auto Tmp =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2848 for (
unsigned I = 1;
I <= 2; ++
I) {
2851 if (
SrcOp.isImm()) {
2853 Imm.ashrInPlace(Part * 32);
2854 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2858 if (Src.isPhysical())
2859 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2866 MovDPP.addImm(MO.getImm());
2868 Split[Part] = MovDPP;
2872 if (Dst.isVirtual())
2879 MI.eraseFromParent();
2880 return std::pair(Split[0], Split[1]);
2883std::optional<DestSourcePair>
2885 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2888 return std::nullopt;
2892 AMDGPU::OpName Src0OpName,
2894 AMDGPU::OpName Src1OpName)
const {
2901 "All commutable instructions have both src0 and src1 modifiers");
2903 int Src0ModsVal = Src0Mods->
getImm();
2904 int Src1ModsVal = Src1Mods->
getImm();
2906 Src1Mods->
setImm(Src0ModsVal);
2907 Src0Mods->
setImm(Src1ModsVal);
2916 bool IsKill = RegOp.
isKill();
2918 bool IsUndef = RegOp.
isUndef();
2919 bool IsDebug = RegOp.
isDebug();
2921 if (NonRegOp.
isImm())
2923 else if (NonRegOp.
isFI())
2944 int64_t NonRegVal = NonRegOp1.
getImm();
2947 NonRegOp2.
setImm(NonRegVal);
2957 bool CheckSwappedSrc =
false) {
2958 unsigned Opc =
MI.getOpcode();
2959 if (!
TII.getSubtarget().hasPkF32InvalidOpSel() ||
2960 (
Opc != AMDGPU::V_PK_ADD_F32 &&
Opc != AMDGPU::V_PK_MUL_F32 &&
2961 Opc != AMDGPU::V_PK_FMA_F32))
2964 auto Mods = [&](AMDGPU::OpName Name) {
2966 return Op ?
static_cast<unsigned>(
Op->getImm()) : 0u;
2968 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2969 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2970 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2972 if (CheckSwappedSrc)
2975 if (
Opc == AMDGPU::V_PK_FMA_F32)
2981 unsigned OpIdx1)
const {
2986 unsigned Opc =
MI.getOpcode();
2987 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2988 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2992 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2993 ((
int)OpIdx0 == Src1Idx && (
int)OpIdx1 == Src0Idx);
3005 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
3008 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
3013 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
3019 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3041 unsigned Src1Idx)
const {
3042 assert(!NewMI &&
"this should never be used");
3047 unsigned Opc =
MI.getOpcode();
3049 if (CommutedOpcode == -1)
3052 if (Src0Idx > Src1Idx)
3055 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3056 static_cast<int>(Src0Idx) &&
3057 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3058 static_cast<int>(Src1Idx) &&
3059 "inconsistency with findCommutedOpIndices");
3067 if (Src0.isReg() && Src1.isReg()) {
3071 }
else if (Src0.isReg() && !Src1.isReg()) {
3073 }
else if (!Src0.isReg() && Src1.isReg()) {
3075 }
else if (Src0.isImm() && Src1.isImm()) {
3084 Src1, AMDGPU::OpName::src1_modifiers);
3087 AMDGPU::OpName::src1_sel);
3099 unsigned &SrcOpIdx0,
3100 unsigned &SrcOpIdx1)
const {
3108 unsigned &SrcOpIdx0,
3109 unsigned &SrcOpIdx1)
const {
3110 if (!
Desc.isCommutable())
3113 unsigned Opc =
Desc.getOpcode();
3114 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3118 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3122 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3126 int64_t BrOffset)
const {
3143 return MI.getOperand(0).getMBB();
3148 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3149 MI.getOpcode() == AMDGPU::SI_LOOP ||
3150 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3162 "new block should be inserted for expanding unconditional branch");
3165 "restore block should be inserted for restoring clobbered registers");
3173 if (ST.useAddPCI64Inst()) {
3175 MCCtx.createTempSymbol(
"offset",
true);
3179 MCCtx.createTempSymbol(
"post_addpc",
true);
3180 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3184 Offset->setVariableValue(OffsetExpr);
3188 assert(RS &&
"RegScavenger required for long branching");
3192 Register PCReg =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3196 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3197 ST.hasVALUReadSGPRHazard();
3198 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3199 if (FlushSGPRWrites)
3207 ApplyHazardWorkarounds();
3210 MCCtx.createTempSymbol(
"post_getpc",
true);
3214 MCCtx.createTempSymbol(
"offset_lo",
true);
3216 MCCtx.createTempSymbol(
"offset_hi",
true);
3219 .
addReg(PCReg, {}, AMDGPU::sub0)
3223 .
addReg(PCReg, {}, AMDGPU::sub1)
3225 ApplyHazardWorkarounds();
3266 if (LongBranchReservedReg) {
3267 RS->enterBasicBlock(
MBB);
3268 Scav = LongBranchReservedReg;
3270 RS->enterBasicBlockEnd(
MBB);
3271 Scav = RS->scavengeRegisterBackwards(
3276 RS->setRegUsed(Scav);
3277 MRI.replaceRegWith(PCReg, Scav);
3278 MRI.clearVirtRegs();
3284 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3285 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3286 MRI.clearVirtRegs();
3301unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3303 case SIInstrInfo::SCC_TRUE:
3304 return AMDGPU::S_CBRANCH_SCC1;
3305 case SIInstrInfo::SCC_FALSE:
3306 return AMDGPU::S_CBRANCH_SCC0;
3307 case SIInstrInfo::VCCNZ:
3308 return AMDGPU::S_CBRANCH_VCCNZ;
3309 case SIInstrInfo::VCCZ:
3310 return AMDGPU::S_CBRANCH_VCCZ;
3311 case SIInstrInfo::EXECNZ:
3312 return AMDGPU::S_CBRANCH_EXECNZ;
3313 case SIInstrInfo::EXECZ:
3314 return AMDGPU::S_CBRANCH_EXECZ;
3320SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3322 case AMDGPU::S_CBRANCH_SCC0:
3324 case AMDGPU::S_CBRANCH_SCC1:
3326 case AMDGPU::S_CBRANCH_VCCNZ:
3328 case AMDGPU::S_CBRANCH_VCCZ:
3330 case AMDGPU::S_CBRANCH_EXECNZ:
3332 case AMDGPU::S_CBRANCH_EXECZ:
3344 bool AllowModify)
const {
3345 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3347 TBB =
I->getOperand(0).getMBB();
3351 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3352 if (Pred == INVALID_BR)
3357 Cond.push_back(
I->getOperand(1));
3361 if (
I ==
MBB.end()) {
3367 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3369 FBB =
I->getOperand(0).getMBB();
3379 bool AllowModify)
const {
3387 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3388 switch (
I->getOpcode()) {
3389 case AMDGPU::S_MOV_B64_term:
3390 case AMDGPU::S_XOR_B64_term:
3391 case AMDGPU::S_OR_B64_term:
3392 case AMDGPU::S_ANDN2_B64_term:
3393 case AMDGPU::S_AND_B64_term:
3394 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3395 case AMDGPU::S_MOV_B32_term:
3396 case AMDGPU::S_XOR_B32_term:
3397 case AMDGPU::S_OR_B32_term:
3398 case AMDGPU::S_ANDN2_B32_term:
3399 case AMDGPU::S_AND_B32_term:
3400 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3401 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3402 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3405 case AMDGPU::SI_ELSE:
3406 case AMDGPU::SI_KILL_I1_TERMINATOR:
3407 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3424 int *BytesRemoved)
const {
3426 unsigned RemovedSize = 0;
3429 if (
MI.isBranch() ||
MI.isReturn()) {
3431 MI.eraseFromParent();
3437 *BytesRemoved = RemovedSize;
3454 int *BytesAdded)
const {
3455 if (!FBB &&
Cond.empty()) {
3459 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3466 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3478 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3496 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3503 if (
Cond.size() != 2) {
3507 if (
Cond[0].isImm()) {
3528 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3532 std::optional<bool> createTripCountGreaterCondition(
3533 int TC, MachineBasicBlock &
MBB,
3534 SmallVectorImpl<MachineOperand> &CondParam)
override {
3535 CondParam = this->
Cond;
3539 void adjustTripCount(
int TripCountAdjust)
override {}
3541 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3545std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3554 if (
TBB == LoopBB && FBB == LoopBB)
3561 assert((
TBB == LoopBB || FBB == LoopBB) &&
3562 "The Loop must be a single-basic-block loop");
3565 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3566 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3571 if (
MI.isCall() ||
MI.isInlineAsm())
3586 if (CmpI == Instructions.end() || CmpI->isPHI())
3590 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3597 SelectExpansion &Exp)
const {
3603 if (
MRI.getRegClass(FalseReg) != RC)
3607 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3610 return RI.hasVGPRs(RC) && NumInsts <= 6;
3618 if (
MRI.getRegClass(FalseReg) != RC)
3624 if (NumInsts % 2 == 0)
3627 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3628 return RI.isSGPRClass(RC);
3639 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3640 if (Pred == VCCZ || Pred == SCC_FALSE) {
3641 Pred =
static_cast<BranchPredicate
>(-Pred);
3647 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3649 if (DstSize == 32) {
3651 if (Pred == SCC_TRUE) {
3666 if (DstSize == 64 && Pred == SCC_TRUE) {
3676 static const int16_t Sub0_15[] = {
3677 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3678 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3679 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3680 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3683 static const int16_t Sub0_15_64[] = {
3684 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3685 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3686 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3687 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3690 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3692 const int16_t *SubIndices = Sub0_15;
3693 int NElts = DstSize / 32;
3697 if (Pred == SCC_TRUE) {
3699 SelOp = AMDGPU::S_CSELECT_B32;
3700 EltRC = &AMDGPU::SGPR_32RegClass;
3702 SelOp = AMDGPU::S_CSELECT_B64;
3703 EltRC = &AMDGPU::SGPR_64RegClass;
3704 SubIndices = Sub0_15_64;
3710 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3715 for (
int Idx = 0; Idx != NElts; ++Idx) {
3716 Register DstElt =
MRI.createVirtualRegister(EltRC);
3719 unsigned SubIdx = SubIndices[Idx];
3722 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3724 .
addReg(FalseReg, {}, SubIdx)
3725 .addReg(TrueReg, {}, SubIdx);
3728 .
addReg(TrueReg, {}, SubIdx)
3729 .addReg(FalseReg, {}, SubIdx);
3742 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3745 switch (
MI.getOpcode()) {
3746 case AMDGPU::S_ENDPGM:
3747 case AMDGPU::S_ENDPGM_SAVED:
3748 case AMDGPU::S_TRAP:
3749 case AMDGPU::S_GETREG_B32:
3750 case AMDGPU::S_SETREG_B32:
3751 case AMDGPU::S_SETREG_B32_mode:
3752 case AMDGPU::S_SETREG_IMM32_B32:
3753 case AMDGPU::S_SETREG_IMM32_B32_mode:
3754 case AMDGPU::S_SENDMSG:
3755 case AMDGPU::S_SENDMSGHALT:
3756 case AMDGPU::S_SENDMSG_RTN_B32:
3757 case AMDGPU::S_SENDMSG_RTN_B64:
3758 case AMDGPU::S_BARRIER_WAIT:
3759 case AMDGPU::S_BARRIER_SIGNAL_M0:
3760 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3761 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3762 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3770 switch (
MI.getOpcode()) {
3771 case AMDGPU::V_MOV_B16_t16_e32:
3772 case AMDGPU::V_MOV_B16_t16_e64:
3773 case AMDGPU::V_MOV_B32_e32:
3774 case AMDGPU::V_MOV_B32_e64:
3775 case AMDGPU::V_MOV_B64_PSEUDO:
3776 case AMDGPU::V_MOV_B64_e32:
3777 case AMDGPU::V_MOV_B64_e64:
3778 case AMDGPU::S_MOV_B32:
3779 case AMDGPU::S_MOV_B64:
3780 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3782 case AMDGPU::WWM_COPY:
3783 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3784 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3785 case AMDGPU::V_ACCVGPR_MOV_B32:
3786 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3787 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3795 switch (
MI.getOpcode()) {
3796 case AMDGPU::V_MOV_B16_t16_e32:
3797 case AMDGPU::V_MOV_B16_t16_e64:
3799 case AMDGPU::V_MOV_B32_e32:
3800 case AMDGPU::V_MOV_B32_e64:
3801 case AMDGPU::V_MOV_B64_PSEUDO:
3802 case AMDGPU::V_MOV_B64_e32:
3803 case AMDGPU::V_MOV_B64_e64:
3804 case AMDGPU::S_MOV_B32:
3805 case AMDGPU::S_MOV_B64:
3806 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3808 case AMDGPU::WWM_COPY:
3809 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3810 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3811 case AMDGPU::V_ACCVGPR_MOV_B32:
3812 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3813 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3821 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3822 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3823 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3826 unsigned Opc =
MI.getOpcode();
3828 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3830 MI.removeOperand(Idx);
3836 MI.setDesc(NewDesc);
3842 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3843 Desc.implicit_defs().size();
3845 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3846 MI.removeOperand(
I);
3850 unsigned SubRegIndex) {
3851 switch (SubRegIndex) {
3852 case AMDGPU::NoSubRegister:
3862 case AMDGPU::sub1_lo16:
3864 case AMDGPU::sub1_hi16:
3867 return std::nullopt;
3875 case AMDGPU::V_MAC_F16_e32:
3876 case AMDGPU::V_MAC_F16_e64:
3877 case AMDGPU::V_MAD_F16_e64:
3878 return AMDGPU::V_MADAK_F16;
3879 case AMDGPU::V_MAC_F32_e32:
3880 case AMDGPU::V_MAC_F32_e64:
3881 case AMDGPU::V_MAD_F32_e64:
3882 return AMDGPU::V_MADAK_F32;
3883 case AMDGPU::V_FMAC_F32_e32:
3884 case AMDGPU::V_FMAC_F32_e64:
3885 case AMDGPU::V_FMA_F32_e64:
3886 return AMDGPU::V_FMAAK_F32;
3887 case AMDGPU::V_FMAC_F16_e32:
3888 case AMDGPU::V_FMAC_F16_e64:
3889 case AMDGPU::V_FMAC_F16_t16_e64:
3890 case AMDGPU::V_FMAC_F16_fake16_e64:
3891 case AMDGPU::V_FMAC_F16_t16_e32:
3892 case AMDGPU::V_FMAC_F16_fake16_e32:
3893 case AMDGPU::V_FMA_F16_e64:
3894 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3895 ? AMDGPU::V_FMAAK_F16_t16
3896 : AMDGPU::V_FMAAK_F16_fake16
3897 : AMDGPU::V_FMAAK_F16;
3898 case AMDGPU::V_FMAC_F64_e32:
3899 case AMDGPU::V_FMAC_F64_e64:
3900 case AMDGPU::V_FMA_F64_e64:
3901 return AMDGPU::V_FMAAK_F64;
3909 case AMDGPU::V_MAC_F16_e32:
3910 case AMDGPU::V_MAC_F16_e64:
3911 case AMDGPU::V_MAD_F16_e64:
3912 return AMDGPU::V_MADMK_F16;
3913 case AMDGPU::V_MAC_F32_e32:
3914 case AMDGPU::V_MAC_F32_e64:
3915 case AMDGPU::V_MAD_F32_e64:
3916 return AMDGPU::V_MADMK_F32;
3917 case AMDGPU::V_FMAC_F32_e32:
3918 case AMDGPU::V_FMAC_F32_e64:
3919 case AMDGPU::V_FMA_F32_e64:
3920 return AMDGPU::V_FMAMK_F32;
3921 case AMDGPU::V_FMAC_F16_e32:
3922 case AMDGPU::V_FMAC_F16_e64:
3923 case AMDGPU::V_FMAC_F16_t16_e64:
3924 case AMDGPU::V_FMAC_F16_fake16_e64:
3925 case AMDGPU::V_FMAC_F16_t16_e32:
3926 case AMDGPU::V_FMAC_F16_fake16_e32:
3927 case AMDGPU::V_FMA_F16_e64:
3928 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3929 ? AMDGPU::V_FMAMK_F16_t16
3930 : AMDGPU::V_FMAMK_F16_fake16
3931 : AMDGPU::V_FMAMK_F16;
3932 case AMDGPU::V_FMAC_F64_e32:
3933 case AMDGPU::V_FMAC_F64_e64:
3934 case AMDGPU::V_FMA_F64_e64:
3935 return AMDGPU::V_FMAMK_F64;
3947 const bool HasMultipleUses = !
MRI->hasOneNonDBGUse(Reg);
3949 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3952 if (
Opc == AMDGPU::COPY) {
3953 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3960 if (HasMultipleUses) {
3963 unsigned ImmDefSize = RI.getRegSizeInBits(*
MRI->getRegClass(Reg));
3966 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3974 if (ImmDefSize == 32 &&
3979 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3980 RI.getSubRegIdxSize(UseSubReg) == 16;
3983 if (RI.hasVGPRs(DstRC))
3986 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3992 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3999 for (
unsigned MovOp :
4000 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4001 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4009 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4013 if (MovDstPhysReg) {
4017 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4024 if (MovDstPhysReg) {
4025 if (!MovDstRC->
contains(MovDstPhysReg))
4027 }
else if (!
MRI->constrainRegClass(DstReg, MovDstRC)) {
4041 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4049 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4053 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4055 UseMI.getOperand(0).setReg(MovDstPhysReg);
4060 UseMI.setDesc(NewMCID);
4061 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4062 UseMI.addImplicitDefUseOperands(*MF);
4066 if (HasMultipleUses)
4069 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4070 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4071 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4072 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4073 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4074 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4075 Opc == AMDGPU::V_FMAC_F64_e64) {
4084 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4095 auto CopyRegOperandToNarrowerRC =
4098 if (!
MI.getOperand(OpNo).isReg())
4102 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4105 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4106 get(AMDGPU::COPY), Tmp)
4108 MI.getOperand(OpNo).setReg(Tmp);
4112 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4113 (Src1->isReg() && Src1->getReg() == Reg)) {
4115 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4116 if (!RegSrc->
isReg())
4118 if (RI.isSGPRClass(
MRI->getRegClass(RegSrc->
getReg())) &&
4119 ST.getConstantBusLimit(
Opc) < 2)
4122 if (!Src2->isReg() || RI.isSGPRClass(
MRI->getRegClass(Src2->getReg())))
4134 if (Def && Def->isMoveImmediate() &&
4143 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4149 unsigned SrcSubReg = RegSrc->
getSubReg();
4150 Src0->setReg(SrcReg);
4151 Src0->setSubReg(SrcSubReg);
4152 Src0->setIsKill(RegSrc->
isKill());
4154 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4155 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4156 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4157 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4158 UseMI.untieRegOperand(
4159 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4161 Src1->ChangeToImmediate(*SubRegImm);
4166 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4167 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4171 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4172 UseMI.getOperand(0).getReg())
4174 UseMI.getOperand(0).setReg(Tmp);
4175 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4176 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4179 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4181 DefMI.eraseFromParent();
4187 if (Src2->isReg() && Src2->getReg() == Reg) {
4188 if (ST.getConstantBusLimit(
Opc) < 2) {
4191 bool Src0Inlined =
false;
4192 if (Src0->isReg()) {
4197 if (Def && Def->isMoveImmediate() &&
4199 MRI->hasOneNonDBGUse(Src0->getReg())) {
4200 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4202 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4203 RI.isSGPRReg(*
MRI, Src0->getReg())) {
4209 if (Src1->isReg() && !Src0Inlined) {
4212 if (Def && Def->isMoveImmediate() &&
4214 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(
UseMI))
4215 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4216 else if (RI.isSGPRReg(*
MRI, Src1->getReg()))
4229 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4230 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4231 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4232 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4233 UseMI.untieRegOperand(
4234 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4236 const std::optional<int64_t> SubRegImm =
4240 Src2->ChangeToImmediate(*SubRegImm);
4246 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4247 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4251 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4252 UseMI.getOperand(0).getReg())
4254 UseMI.getOperand(0).setReg(Tmp);
4255 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4256 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4265 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4269 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4271 DefMI.eraseFromParent();
4283 if (BaseOps1.
size() != BaseOps2.
size())
4285 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4286 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4294 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4295 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4296 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4298 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4301bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4304 int64_t Offset0, Offset1;
4307 bool Offset0IsScalable, Offset1IsScalable;
4321 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4322 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4329 "MIa must load from or modify a memory location");
4331 "MIb must load from or modify a memory location");
4353 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4360 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4370 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4384 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4395 case AMDGPU::V_MAC_F16_e32:
4396 case AMDGPU::V_MAC_F16_e64:
4397 return AMDGPU::V_MAD_F16_e64;
4398 case AMDGPU::V_MAC_F32_e32:
4399 case AMDGPU::V_MAC_F32_e64:
4400 return AMDGPU::V_MAD_F32_e64;
4401 case AMDGPU::V_MAC_LEGACY_F32_e32:
4402 case AMDGPU::V_MAC_LEGACY_F32_e64:
4403 return AMDGPU::V_MAD_LEGACY_F32_e64;
4404 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4405 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4406 return AMDGPU::V_FMA_LEGACY_F32_e64;
4407 case AMDGPU::V_FMAC_F16_e32:
4408 case AMDGPU::V_FMAC_F16_e64:
4409 case AMDGPU::V_FMAC_F16_t16_e64:
4410 case AMDGPU::V_FMAC_F16_fake16_e64:
4411 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4412 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4413 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4414 : AMDGPU::V_FMA_F16_gfx9_e64;
4415 case AMDGPU::V_FMAC_F32_e32:
4416 case AMDGPU::V_FMAC_F32_e64:
4417 return AMDGPU::V_FMA_F32_e64;
4418 case AMDGPU::V_FMAC_F64_e32:
4419 case AMDGPU::V_FMAC_F64_e64:
4420 return AMDGPU::V_FMA_F64_e64;
4439 if (
MI.isBundle()) {
4442 if (
MI.getBundleSize() != 1)
4444 CandidateMI =
MI.getNextNode();
4448 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4452 if (
MI.isBundle()) {
4457 MI.untieRegOperand(MO.getOperandNo());
4464 if (Def.isEarlyClobber() && Def.isReg() &&
4469 auto UpdateDefIndex = [&](
LiveRange &LR) {
4470 auto *S = LR.find(OldIndex);
4471 if (S != LR.end() && S->start == OldIndex) {
4472 assert(S->valno && S->valno->def == OldIndex);
4473 S->start = NewIndex;
4474 S->valno->def = NewIndex;
4478 for (
auto &SR : LI.subranges())
4484 if (U.RemoveMIUse) {
4487 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4489 if (
MRI.hasOneNonDBGUse(DefReg)) {
4491 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4492 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4493 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4494 U.RemoveMIUse->removeOperand(
I);
4497 if (
MI.isBundle()) {
4501 if (MO.isReg() && MO.getReg() == DefReg) {
4502 assert(MO.getSubReg() == 0 &&
4503 "tied sub-registers in bundles currently not supported");
4504 MI.removeOperand(MO.getOperandNo());
4519 Register DummyReg =
MRI.cloneVirtualRegister(DefReg);
4521 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4522 MIOp.setIsUndef(
true);
4523 MIOp.setReg(DummyReg);
4527 if (
MI.isBundle()) {
4531 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4532 MIOp.setIsUndef(
true);
4533 MIOp.setReg(DummyReg);
4546 return MI.isBundle() ? &
MI : NewMI;
4551 ThreeAddressUpdates &U)
const {
4553 unsigned Opc =
MI.getOpcode();
4557 if (NewMFMAOpc != -1) {
4560 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4561 MIB.
add(
MI.getOperand(
I));
4569 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4574 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4575 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4576 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4580 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4581 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4582 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4583 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4584 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4585 bool Src0Literal =
false;
4590 case AMDGPU::V_MAC_F16_e64:
4591 case AMDGPU::V_FMAC_F16_e64:
4592 case AMDGPU::V_FMAC_F16_t16_e64:
4593 case AMDGPU::V_FMAC_F16_fake16_e64:
4594 case AMDGPU::V_MAC_F32_e64:
4595 case AMDGPU::V_MAC_LEGACY_F32_e64:
4596 case AMDGPU::V_FMAC_F32_e64:
4597 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4598 case AMDGPU::V_FMAC_F64_e64:
4600 case AMDGPU::V_MAC_F16_e32:
4601 case AMDGPU::V_FMAC_F16_e32:
4602 case AMDGPU::V_MAC_F32_e32:
4603 case AMDGPU::V_MAC_LEGACY_F32_e32:
4604 case AMDGPU::V_FMAC_F32_e32:
4605 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4606 case AMDGPU::V_FMAC_F64_e32: {
4607 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4608 AMDGPU::OpName::src0);
4609 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4610 if (!
Src0->isReg() && !
Src0->isImm())
4620 MachineInstrBuilder MIB;
4623 const MachineOperand *Src0Mods =
4626 const MachineOperand *Src1Mods =
4629 const MachineOperand *Src2Mods =
4635 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4636 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4638 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4640 MachineInstr *
DefMI =
nullptr;
4642 std::optional<int64_t> ImmOpt;
4677 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4693 if (Src0Literal && !ST.hasVOP3Literal())
4721 switch (
MI.getOpcode()) {
4722 case AMDGPU::S_SET_GPR_IDX_ON:
4723 case AMDGPU::S_SET_GPR_IDX_MODE:
4724 case AMDGPU::S_SET_GPR_IDX_OFF:
4742 if (
MI.isTerminator() ||
MI.isPosition())
4746 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4749 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4755 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4756 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4757 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4758 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4759 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4764 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4765 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4766 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4780 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4785 if (
MI.memoperands_empty())
4790 unsigned AS = Memop->getAddrSpace();
4791 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4792 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4793 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4794 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4809 if (
MI.memoperands_empty())
4818 unsigned AS = Memop->getAddrSpace();
4828 bool TgSplit)
const {
4841 if (
MI.memoperands_empty())
4846 unsigned AS = Memop->getAddrSpace();
4862 unsigned Opcode =
MI.getOpcode();
4877 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4878 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4879 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4880 Opcode == AMDGPU::S_SETHALT)
4883 if (
MI.isCall() ||
MI.isInlineAsm())
4889 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4905 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4906 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4907 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4908 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4916 if (
MI.isMetaInstruction())
4920 if (
MI.isCopyLike()) {
4921 if (!RI.isSGPRReg(
MRI,
MI.getOperand(0).getReg()))
4925 return MI.readsRegister(AMDGPU::EXEC, &RI);
4936 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4940 switch (
Imm.getBitWidth()) {
4946 ST.hasInv2PiInlineImm());
4949 ST.hasInv2PiInlineImm());
4951 return ST.has16BitInsts() &&
4953 ST.hasInv2PiInlineImm());
4960 APInt IntImm =
Imm.bitcastToAPInt();
4962 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4970 return ST.has16BitInsts() &&
4973 return ST.has16BitInsts() &&
4983 switch (OperandType) {
4993 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5037 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5038 return ST.has16BitInsts() &&
5047 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5048 return ST.has16BitInsts() &&
5100 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5106 return ST.hasVOP3Literal();
5110 int64_t ImmVal)
const {
5112 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5113 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5114 OpNo ==
static_cast<unsigned>(Src1Idx))
5119 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5120 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5121 AMDGPU::OpName::src2))
5124 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5131 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5143 "unexpected imm-like operand kind");
5156 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5176 return Op32 != -1 &&
TII.isVOPC(Op32);
5181 unsigned Depth)
const {
5182 assert(
MRI.isSSA() &&
"isMaskedByExec requires SSA form");
5191 constexpr unsigned MaxDepth = 6;
5192 if (
Depth >= MaxDepth || !Reg.isVirtual())
5198 if (!Def || Def->getParent() !=
MBB)
5206 auto Recurse = [&](
unsigned OpIdx) {
5212 unsigned Opc = Def->getOpcode();
5213 if (
Opc == AMDGPU::COPY && Recurse(1))
5215 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5235 AMDGPU::OpName
OpName)
const {
5237 return Mods && Mods->
getImm();
5250 switch (
MI.getOpcode()) {
5251 default:
return false;
5253 case AMDGPU::V_ADDC_U32_e64:
5254 case AMDGPU::V_SUBB_U32_e64:
5255 case AMDGPU::V_SUBBREV_U32_e64: {
5258 if (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()))
5263 case AMDGPU::V_MAC_F16_e64:
5264 case AMDGPU::V_MAC_F32_e64:
5265 case AMDGPU::V_MAC_LEGACY_F32_e64:
5266 case AMDGPU::V_FMAC_F16_e64:
5267 case AMDGPU::V_FMAC_F16_t16_e64:
5268 case AMDGPU::V_FMAC_F16_fake16_e64:
5269 case AMDGPU::V_FMAC_F32_e64:
5270 case AMDGPU::V_FMAC_F64_e64:
5271 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5272 if (!Src2->isReg() || !RI.isVGPR(
MRI, Src2->getReg()) ||
5277 case AMDGPU::V_CNDMASK_B32_e64:
5283 if (Src1 && (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()) ||
5296 if (Src0 && Src0->isImm()) {
5299 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5321 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5330 unsigned Op32)
const {
5344 Inst32.
add(
MI.getOperand(
I));
5348 int Idx =
MI.getNumExplicitDefs();
5350 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5355 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5375 if (OldSDst && OldSDst->
isDead()) {
5378 NewVCC->setIsDead();
5387 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5395 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5398 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5399 AMDGPU::SReg_64RegClass.contains(Reg);
5405 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5417 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5427 switch (MO.getReg()) {
5429 case AMDGPU::VCC_LO:
5430 case AMDGPU::VCC_HI:
5432 case AMDGPU::FLAT_SCR:
5445 switch (
MI.getOpcode()) {
5446 case AMDGPU::V_READLANE_B32:
5447 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5448 case AMDGPU::V_WRITELANE_B32:
5449 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5456 if (
MI.isPreISelOpcode() ||
5457 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5475 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5486 if (RI.isVectorRegister(
MRI, SrcReg) && RI.isSGPRReg(
MRI, DstReg)) {
5487 ErrInfo =
"illegal copy from vector register to SGPR";
5505 if (!
MRI.isSSA() &&
MI.isCopy())
5506 return verifyCopy(
MI,
MRI, ErrInfo);
5508 if (SIInstrInfo::isGenericOpcode(Opcode))
5511 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5512 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5513 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5515 if (Src0Idx == -1) {
5517 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5518 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5519 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5520 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5525 if (!
Desc.isVariadic() &&
5526 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5527 ErrInfo =
"Instruction has wrong number of operands.";
5531 if (
MI.isInlineAsm()) {
5544 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5545 ErrInfo =
"inlineasm operand has incorrect register class.";
5553 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5554 ErrInfo =
"missing memory operand from image instruction.";
5559 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5562 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5563 "all fp values to integers.";
5569 switch (OpInfo.OperandType) {
5571 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5572 ErrInfo =
"Illegal immediate value for operand.";
5604 ErrInfo =
"Illegal immediate value for operand.";
5613 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5616 OpInfo.OperandType ==
5618 ErrInfo =
"illegal 64-bit immediate value for operand.";
5625 ErrInfo =
"Expected inline constant for operand.";
5639 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5640 ErrInfo =
"Expected immediate, but got non-immediate";
5649 if (OpInfo.isGenericType())
5657 if (!ST.hasSDWA()) {
5658 ErrInfo =
"SDWA is not supported on this target";
5662 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5663 AMDGPU::OpName::dst_sel}) {
5669 ErrInfo =
"Invalid SDWA selection";
5674 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5676 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5681 if (!ST.hasSDWAScalar()) {
5683 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(
MRI, MO.
getReg()))) {
5684 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5691 "Only reg allowed as operands in SDWA instructions on GFX9+";
5697 if (!ST.hasSDWAOmod()) {
5700 if (OMod !=
nullptr &&
5702 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5707 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5708 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5709 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5710 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5713 unsigned Mods = Src0ModsMO->
getImm();
5716 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5722 if (
isVOPC(BasicOpcode)) {
5723 if (!ST.hasSDWASdst() && DstIdx != -1) {
5726 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5727 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5730 }
else if (!ST.hasSDWAOutModsVOPC()) {
5733 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5734 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5740 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5741 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5748 if (DstUnused && DstUnused->isImm() &&
5751 if (!Dst.isReg() || !Dst.isTied()) {
5752 ErrInfo =
"Dst register should have tied register";
5757 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5760 "Dst register should be tied to implicit use of preserved register";
5764 ErrInfo =
"Dst register should use same physical register as preserved";
5770 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5773 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5776 if (Src1MO.
isImm()) {
5777 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5783 if (
isImage(Opcode) && !
MI.mayStore()) {
5788 uint64_t DMaskImm = DMask->
getImm();
5795 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5803 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5807 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5808 if (RegCount > DstSize) {
5809 ErrInfo =
"Image instruction returns too many registers for dst "
5819 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5820 unsigned ConstantBusCount = 0;
5821 bool UsesLiteral =
false;
5824 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5828 LiteralVal = &
MI.getOperand(ImmIdx);
5837 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5848 }
else if (!MO.
isFI()) {
5855 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5865 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5866 return !RI.regsOverlap(SGPRUsed, SGPR);
5875 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5876 Opcode != AMDGPU::V_WRITELANE_B32) {
5877 ErrInfo =
"VOP* instruction violates constant bus restriction";
5881 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5882 ErrInfo =
"VOP3 instruction uses literal";
5889 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5890 unsigned SGPRCount = 0;
5893 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5901 if (MO.
getReg() != SGPRUsed)
5906 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5907 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5914 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5915 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5919 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5922 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5932 ErrInfo =
"ABS not allowed in VOP3B instructions";
5944 !Src0.isIdenticalTo(Src1)) {
5945 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5952 if (
Desc.isBranch()) {
5954 ErrInfo =
"invalid branch target for SOPK instruction";
5958 uint64_t
Imm =
Op->getImm();
5961 ErrInfo =
"invalid immediate for SOPK instruction";
5966 ErrInfo =
"invalid immediate for SOPK instruction";
5973 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5974 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5975 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5976 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5977 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5978 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5980 const unsigned StaticNumOps =
5981 Desc.getNumOperands() +
Desc.implicit_uses().size();
5982 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5988 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5989 ErrInfo =
"missing implicit register operands";
5995 if (!Dst->isUse()) {
5996 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
6001 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6002 UseOpIdx != StaticNumOps + 1) {
6003 ErrInfo =
"movrel implicit operands should be tied";
6010 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6012 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6013 ErrInfo =
"src0 should be subreg of implicit vector use";
6021 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6022 ErrInfo =
"VALU instruction does not implicitly read exec mask";
6028 if (
MI.mayStore() &&
6033 if (Soff && Soff->
getReg() != AMDGPU::M0) {
6034 ErrInfo =
"scalar stores must use m0 as offset register";
6040 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6042 if (
Offset->getImm() != 0) {
6043 ErrInfo =
"subtarget does not support offsets in flat instructions";
6048 if (
isDS(
MI) && !ST.hasGDS()) {
6050 if (GDSOp && GDSOp->
getImm() != 0) {
6051 ErrInfo =
"GDS is not supported on this subtarget";
6059 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6060 AMDGPU::OpName::vaddr0);
6061 AMDGPU::OpName RSrcOpName =
6062 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6063 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6071 ErrInfo =
"dim is out of range";
6076 if (ST.hasR128A16()) {
6078 IsA16 = R128A16->
getImm() != 0;
6079 }
else if (ST.hasA16()) {
6081 IsA16 = A16->
getImm() != 0;
6084 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6086 unsigned AddrWords =
6089 unsigned VAddrWords;
6091 VAddrWords = RsrcIdx - VAddr0Idx;
6092 if (ST.hasPartialNSAEncoding() &&
6094 unsigned LastVAddrIdx = RsrcIdx - 1;
6095 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6103 if (VAddrWords != AddrWords) {
6105 <<
" but got " << VAddrWords <<
"\n");
6106 ErrInfo =
"bad vaddr size";
6116 unsigned DC = DppCt->
getImm();
6117 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6118 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6119 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6120 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6121 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6122 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6123 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6124 ErrInfo =
"Invalid dpp_ctrl value";
6127 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6128 !ST.hasDPPWavefrontShifts()) {
6129 ErrInfo =
"Invalid dpp_ctrl value: "
6130 "wavefront shifts are not supported on GFX10+";
6133 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6134 !ST.hasDPPBroadcasts()) {
6135 ErrInfo =
"Invalid dpp_ctrl value: "
6136 "broadcasts are not supported on GFX10+";
6139 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6141 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6142 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6143 !ST.hasGFX90AInsts()) {
6144 ErrInfo =
"Invalid dpp_ctrl value: "
6145 "row_newbroadcast/row_share is not supported before "
6149 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6150 ErrInfo =
"Invalid dpp_ctrl value: "
6151 "row_share and row_xmask are not supported before GFX10";
6156 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6158 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6160 ErrInfo =
"Invalid dpp_ctrl value: "
6161 "DP ALU dpp only support row_newbcast";
6168 AMDGPU::OpName DataName =
6169 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6175 if (!ST.hasGFX90AInsts()) {
6176 if ((Dst && RI.isAGPR(
MRI, Dst->getReg())) ||
6178 (Data2 && RI.isAGPR(
MRI, Data2->
getReg()))) {
6179 ErrInfo =
"Invalid register class: "
6180 "agpr loads and stores not supported on this GPU";
6186 if (ST.needsAlignedVGPRs()) {
6187 const auto isAlignedReg = [&
MI, &
MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6192 if (Reg.isPhysical())
6193 return !(RI.getHWRegIndex(Reg) & 1);
6195 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6196 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6200 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6201 ErrInfo =
"Subtarget requires even aligned vector registers "
6202 "for vaddr operand of image instructions";
6208 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6210 if (Src->isReg() && RI.isSGPRReg(
MRI, Src->getReg())) {
6211 ErrInfo =
"Invalid register class: "
6212 "v_accvgpr_write with an SGPR is not supported on this GPU";
6217 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6220 ErrInfo =
"pseudo expects only physical SGPRs";
6227 if (!ST.hasScaleOffset()) {
6228 ErrInfo =
"Subtarget does not support offset scaling";
6232 ErrInfo =
"Instruction does not support offset scaling";
6240 for (
unsigned I = 0;
I < 3; ++
I) {
6246 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6247 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6249 if ((Dst && RI.getRegClassForReg(
MRI, Dst->getReg()) ==
6250 &AMDGPU::SReg_64RegClass) ||
6251 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6252 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6259 ErrInfo =
"GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6267 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6269 return MI.getOperand(1).isReg() || RI.isAGPR(
MRI,
MI.getOperand(0).getReg())
6271 : AMDGPU::V_MOV_B32_e32;
6281 default:
return AMDGPU::INSTRUCTION_LIST_END;
6282 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6283 case AMDGPU::COPY:
return AMDGPU::COPY;
6284 case AMDGPU::PHI:
return AMDGPU::PHI;
6285 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6286 case AMDGPU::WQM:
return AMDGPU::WQM;
6287 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6288 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6289 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6290 case AMDGPU::S_ADD_I32:
6291 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6292 case AMDGPU::S_ADDC_U32:
6293 return AMDGPU::V_ADDC_U32_e32;
6294 case AMDGPU::S_SUB_I32:
6295 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6298 case AMDGPU::S_ADD_U32:
6299 return AMDGPU::V_ADD_CO_U32_e32;
6300 case AMDGPU::S_SUB_U32:
6301 return AMDGPU::V_SUB_CO_U32_e32;
6302 case AMDGPU::S_ADD_U64_PSEUDO:
6303 return AMDGPU::V_ADD_U64_PSEUDO;
6304 case AMDGPU::S_SUB_U64_PSEUDO:
6305 return AMDGPU::V_SUB_U64_PSEUDO;
6306 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6307 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6308 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6309 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6310 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6311 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6312 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6313 case AMDGPU::S_XNOR_B32:
6314 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6315 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6316 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6317 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6318 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6319 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6320 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6321 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6322 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6323 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6324 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6325 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6326 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6327 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6328 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6329 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6330 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6331 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6332 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6333 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6334 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6335 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6336 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6337 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6338 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6339 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6340 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6341 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6342 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6343 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6344 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6345 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6346 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6347 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6348 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6349 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6350 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6351 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6352 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6353 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6354 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6355 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6356 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6357 case AMDGPU::S_CVT_F32_F16:
6358 case AMDGPU::S_CVT_HI_F32_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6360 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6361 case AMDGPU::S_CVT_F16_F32:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6363 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6364 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6365 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6366 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6367 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6368 case AMDGPU::S_CEIL_F16:
6369 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6370 : AMDGPU::V_CEIL_F16_fake16_e64;
6371 case AMDGPU::S_FLOOR_F16:
6372 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6373 : AMDGPU::V_FLOOR_F16_fake16_e64;
6374 case AMDGPU::S_TRUNC_F16:
6375 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6376 : AMDGPU::V_TRUNC_F16_fake16_e64;
6377 case AMDGPU::S_RNDNE_F16:
6378 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6379 : AMDGPU::V_RNDNE_F16_fake16_e64;
6380 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6381 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6382 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6383 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6384 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6385 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6386 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6387 case AMDGPU::S_ADD_F16:
6388 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6389 : AMDGPU::V_ADD_F16_fake16_e64;
6390 case AMDGPU::S_SUB_F16:
6391 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6392 : AMDGPU::V_SUB_F16_fake16_e64;
6393 case AMDGPU::S_MIN_F16:
6394 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6395 : AMDGPU::V_MIN_F16_fake16_e64;
6396 case AMDGPU::S_MAX_F16:
6397 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6398 : AMDGPU::V_MAX_F16_fake16_e64;
6399 case AMDGPU::S_MINIMUM_F16:
6400 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6401 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6402 case AMDGPU::S_MAXIMUM_F16:
6403 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6404 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6405 case AMDGPU::S_MUL_F16:
6406 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6407 : AMDGPU::V_MUL_F16_fake16_e64;
6408 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6409 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6410 case AMDGPU::S_FMAC_F16:
6411 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6412 : AMDGPU::V_FMAC_F16_fake16_e64;
6413 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6414 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6415 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6416 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6417 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6418 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6419 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6420 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6421 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6422 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6423 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6424 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6425 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6426 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6427 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6428 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6429 case AMDGPU::S_CMP_LT_F16:
6430 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6431 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6432 case AMDGPU::S_CMP_EQ_F16:
6433 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6434 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6435 case AMDGPU::S_CMP_LE_F16:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6437 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6438 case AMDGPU::S_CMP_GT_F16:
6439 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6440 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6441 case AMDGPU::S_CMP_LG_F16:
6442 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6443 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6444 case AMDGPU::S_CMP_GE_F16:
6445 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6446 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6447 case AMDGPU::S_CMP_O_F16:
6448 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6449 : AMDGPU::V_CMP_O_F16_fake16_e64;
6450 case AMDGPU::S_CMP_U_F16:
6451 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6452 : AMDGPU::V_CMP_U_F16_fake16_e64;
6453 case AMDGPU::S_CMP_NGE_F16:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6455 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6456 case AMDGPU::S_CMP_NLG_F16:
6457 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6458 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6459 case AMDGPU::S_CMP_NGT_F16:
6460 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6461 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6462 case AMDGPU::S_CMP_NLE_F16:
6463 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6464 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6465 case AMDGPU::S_CMP_NEQ_F16:
6466 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6467 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6468 case AMDGPU::S_CMP_NLT_F16:
6469 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6470 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6471 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6472 case AMDGPU::V_S_EXP_F16_e64:
6473 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6474 : AMDGPU::V_EXP_F16_fake16_e64;
6475 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6476 case AMDGPU::V_S_LOG_F16_e64:
6477 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6478 : AMDGPU::V_LOG_F16_fake16_e64;
6479 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6480 case AMDGPU::V_S_RCP_F16_e64:
6481 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6482 : AMDGPU::V_RCP_F16_fake16_e64;
6483 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6484 case AMDGPU::V_S_RSQ_F16_e64:
6485 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6486 : AMDGPU::V_RSQ_F16_fake16_e64;
6487 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6488 case AMDGPU::V_S_SQRT_F16_e64:
6489 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6490 : AMDGPU::V_SQRT_F16_fake16_e64;
6493 "Unexpected scalar opcode without corresponding vector one!");
6542 "Not a whole wave func");
6545 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6546 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6553 unsigned OpNo)
const {
6555 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6556 Desc.operands()[OpNo].RegClass == -1) {
6559 if (Reg.isVirtual()) {
6561 return MRI.getRegClass(Reg);
6563 return RI.getPhysRegBaseClass(Reg);
6566 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6567 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6572 constexpr AMDGPU::OpName OpNames[] = {
6573 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6576 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6577 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6589 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6591 unsigned Size = RI.getRegSizeInBits(*RC);
6592 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6593 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6594 : AMDGPU::V_MOV_B32_e32;
6596 Opcode = AMDGPU::COPY;
6597 else if (RI.isSGPRClass(RC))
6598 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6617 Register Low64 =
MRI.createVirtualRegister(VRC64);
6623 .
addImm(AMDGPU::sub0_sub1)
6625 .
addImm(AMDGPU::sub2_sub3);
6626 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6643 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6647 Register SubReg =
MRI.createVirtualRegister(SubRC);
6649 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6660 if (SubIdx == AMDGPU::sub0)
6662 if (SubIdx == AMDGPU::sub1)
6674void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6690 if (Reg.isPhysical())
6697 RI.getLargestLegalSuperClass(RC,
MRI.getMF());
6700 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6703 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6710 unsigned Opc =
MI.getOpcode();
6723 bool IsAGPR = RI.isAGPR(
MRI, MO.
getReg());
6724 if (IsAGPR && !ST.hasMAIInsts())
6726 if (IsAGPR && (!ST.hasGFX90AInsts() || !
MRI.reservedRegsFrozen()) &&
6730 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6731 const int DataIdx = AMDGPU::getNamedOperandIdx(
6732 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6733 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6734 MI.getOperand(DataIdx).isReg() &&
6735 RI.isAGPR(
MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6737 if ((
int)OpIdx == DataIdx) {
6738 if (VDstIdx != -1 &&
6739 RI.isAGPR(
MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6742 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6743 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6744 RI.isAGPR(
MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6749 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6750 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6754 if (ST.hasFlatScratchHiInB64InstHazard() &&
6761 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6765 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6774 constexpr unsigned NumOps = 3;
6775 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6776 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6777 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6778 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6783 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6786 MO = &
MI.getOperand(SrcIdx);
6793 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6797 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6801 return !OpSel && !OpSelHi;
6810 int64_t RegClass = getOpRegClassID(OpInfo);
6812 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6814 MO = &
MI.getOperand(OpIdx);
6818 if (
isVALU(
MI,
false) && !IsInlineConst &&
6822 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6823 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6827 if (!LiteralLimit--)
6837 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6845 if (--ConstantBusLimit <= 0)
6857 if (!LiteralLimit--)
6859 if (--ConstantBusLimit <= 0)
6865 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6869 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6871 !
Op.isIdenticalTo(*MO))
6893 bool Is64BitOp = Is64BitFPOp ||
6901 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6910 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6928 bool IsGFX950Only = ST.hasGFX950Insts();
6929 bool IsGFX940Only = ST.hasGFX940Insts();
6931 if (!IsGFX950Only && !IsGFX940Only)
6949 unsigned Opcode =
MI.getOpcode();
6951 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6952 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6953 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6954 case AMDGPU::V_MQSAD_U32_U8_e64:
6955 case AMDGPU::V_PK_ADD_F16:
6956 case AMDGPU::V_PK_ADD_F32:
6957 case AMDGPU::V_PK_ADD_I16:
6958 case AMDGPU::V_PK_ADD_U16:
6959 case AMDGPU::V_PK_ASHRREV_I16:
6960 case AMDGPU::V_PK_FMA_F16:
6961 case AMDGPU::V_PK_FMA_F32:
6962 case AMDGPU::V_PK_FMAC_F16_e32:
6963 case AMDGPU::V_PK_FMAC_F16_e64:
6964 case AMDGPU::V_PK_LSHLREV_B16:
6965 case AMDGPU::V_PK_LSHRREV_B16:
6966 case AMDGPU::V_PK_MAD_I16:
6967 case AMDGPU::V_PK_MAD_U16:
6968 case AMDGPU::V_PK_MAX_F16:
6969 case AMDGPU::V_PK_MAX_I16:
6970 case AMDGPU::V_PK_MAX_U16:
6971 case AMDGPU::V_PK_MIN_F16:
6972 case AMDGPU::V_PK_MIN_I16:
6973 case AMDGPU::V_PK_MIN_U16:
6974 case AMDGPU::V_PK_MOV_B32:
6975 case AMDGPU::V_PK_MUL_F16:
6976 case AMDGPU::V_PK_MUL_F32:
6977 case AMDGPU::V_PK_MUL_LO_U16:
6978 case AMDGPU::V_PK_SUB_I16:
6979 case AMDGPU::V_PK_SUB_U16:
6980 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6989 unsigned Opc =
MI.getOpcode();
6992 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6995 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7001 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7002 RI.isSGPRReg(
MRI, Src0.getReg()))
7008 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7010 if (Src0.isReg() && RI.isVGPR(
MRI, Src0.getReg())) {
7011 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7014 Src0.ChangeToRegister(Reg,
false);
7016 if (Src1.isReg() && RI.isVGPR(
MRI, Src1.getReg())) {
7017 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7021 Src1.ChangeToRegister(Reg,
false);
7027 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7028 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7029 if (!RI.isVGPR(
MRI,
MI.getOperand(Src2Idx).getReg()))
7041 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7042 RI.isVGPR(
MRI, Src1.getReg())) {
7043 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7047 Src1.ChangeToRegister(Reg,
false);
7055 if (HasImplicitSGPR || !
MI.isCommutable()) {
7065 if ((!Src1.isImm() && !Src1.isReg()) ||
7072 if (CommutedOpc == -1) {
7077 MI.setDesc(
get(CommutedOpc));
7080 unsigned Src0SubReg = Src0.getSubReg();
7081 bool Src0Kill = Src0.isKill();
7084 Src0.ChangeToImmediate(Src1.getImm());
7085 else if (Src1.isReg()) {
7086 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7087 Src0.setSubReg(Src1.getSubReg());
7091 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7092 Src1.setSubReg(Src0SubReg);
7100 unsigned Opc =
MI.getOpcode();
7103 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7104 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7105 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7108 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7109 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7110 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7111 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7112 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7113 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7114 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7118 if (Src1.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src1.getReg()))) {
7119 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7122 Src1.ChangeToRegister(Reg,
false);
7124 if (VOP3Idx[2] != -1) {
7126 if (Src2.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src2.getReg()))) {
7127 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7130 Src2.ChangeToRegister(Reg,
false);
7136 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7137 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7139 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7141 SGPRsUsed.
insert(SGPRReg);
7145 for (
int Idx : VOP3Idx) {
7154 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7166 if (!RI.isSGPRClass(RI.getRegClassForReg(
MRI, MO.
getReg())))
7173 if (ConstantBusLimit > 0) {
7185 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7186 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7187 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7188 !RI.isVGPR(
MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7194 for (
unsigned I = 0;
I < 3; ++
I) {
7207 SRC = RI.getCommonSubClass(SRC, DstRC);
7210 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7212 if (RI.hasAGPRs(VRC)) {
7213 VRC = RI.getEquivalentVGPRClass(VRC);
7214 Register NewSrcReg =
MRI.createVirtualRegister(VRC);
7216 get(TargetOpcode::COPY), NewSrcReg)
7223 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7229 for (
unsigned i = 0; i < SubRegs; ++i) {
7230 Register SGPR =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7232 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7233 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7239 get(AMDGPU::REG_SEQUENCE), DstReg);
7240 for (
unsigned i = 0; i < SubRegs; ++i) {
7242 MIB.
addImm(RI.getSubRegFromChannel(i));
7255 if (SBase && !RI.isSGPRClass(
MRI.getRegClass(SBase->getReg()))) {
7257 SBase->setReg(SGPR);
7260 if (SOff && !RI.isSGPRReg(
MRI, SOff->
getReg())) {
7268 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7269 if (OldSAddrIdx < 0)
7285 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7286 if (NewVAddrIdx < 0)
7289 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7293 if (OldVAddrIdx >= 0) {
7295 VAddrDef =
MRI.getUniqueVRegDef(VAddr.
getReg());
7307 if (OldVAddrIdx == NewVAddrIdx) {
7310 MRI.removeRegOperandFromUseList(&NewVAddr);
7311 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7315 MRI.removeRegOperandFromUseList(&NewVAddr);
7316 MRI.addRegOperandToUseList(&NewVAddr);
7318 assert(OldSAddrIdx == NewVAddrIdx);
7320 if (OldVAddrIdx >= 0) {
7321 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7322 AMDGPU::OpName::vdst_in);
7326 if (NewVDstIn != -1) {
7327 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7333 if (NewVDstIn != -1) {
7334 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7355 if (!SAddr || RI.isSGPRClass(
MRI.getRegClass(SAddr->
getReg())))
7375 unsigned OpSubReg =
Op.getSubReg();
7378 RI.getRegClassForReg(
MRI, OpReg), OpSubReg);
7384 Register DstReg =
MRI.createVirtualRegister(DstRC);
7385 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7386 .
addReg(OpReg, {}, OpSubReg);
7388 Op.setSubReg(AMDGPU::NoSubRegister);
7395 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7398 bool ImpDef = Def->isImplicitDef();
7399 while (!ImpDef && Def && Def->isCopy()) {
7400 if (Def->getOperand(1).getReg().isPhysical())
7402 Def =
MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7403 ImpDef = Def && Def->isImplicitDef();
7405 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7421 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7426 bool UseNewExecInstructions =
7435 if (UseNewExecInstructions) {
7470 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7471 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(),
MRI);
7472 unsigned NumSubRegs =
RegSize / 32;
7473 Register VScalarOp = ScalarOp->getReg();
7476 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7478 if (NumSubRegs == 1) {
7481 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7482 Common != VScalarOpRC) {
7489 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7492 if (UseNewExecInstructions) {
7494 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7497 if (
I == LoopBB.
end())
7502 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7508 CondReg = NewCondReg;
7520 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7521 ScalarOp->setReg(CurReg);
7524 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7525 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7527 ScalarOp->setReg(PhySGPRs[Idx]);
7532 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7533 "Unhandled register size");
7535 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7542 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7543 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7546 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7547 .
addReg(VScalarOp, VScalarOpUndef,
7548 TRI->getSubRegFromChannel(Idx + 1));
7555 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7562 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7564 if (UseNewExecInstructions) {
7566 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7568 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7569 if (
I == LoopBB.
end())
7573 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7575 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7579 CondReg = NewCondReg;
7591 const auto *SScalarOpRC =
7597 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7598 unsigned Channel = 0;
7599 for (
Register Piece : ReadlanePieces) {
7600 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7604 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7605 ScalarOp->setReg(SScalarOp);
7607 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7608 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7610 ScalarOp->setReg(PhySGPRs[Idx]);
7618 if (!UseNewExecInstructions) {
7631 if (UseNewExecInstructions) {
7664 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7665 "Physical SGPRs must be empty or match the number of scalar operands");
7671 if (!Begin.isValid())
7673 if (!
End.isValid()) {
7679 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7688 std::numeric_limits<unsigned>::max()) !=
7706 for (
auto I = Begin;
I != AfterMI;
I++) {
7707 for (
auto &MO :
I->all_uses())
7743 for (
auto &Succ : RemainderBB->
successors()) {
7768static std::tuple<unsigned, unsigned>
7776 TII.buildExtractSubReg(
MI,
MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7777 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7780 Register Zero64 =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7781 Register SRsrcFormatLo =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7782 Register SRsrcFormatHi =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7783 Register NewSRsrc =
MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7784 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7801 .
addImm(AMDGPU::sub0_sub1)
7807 return std::tuple(RsrcPtr, NewSRsrc);
7818 if (ST.useRealTrue16Insts())
7848 if (
MI.getOpcode() == AMDGPU::PHI) {
7850 assert(!RI.isSGPRClass(VRC));
7853 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7855 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7871 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7874 if (RI.hasVGPRs(DstRC)) {
7878 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7880 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7897 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7902 if (DstRC != Src0RC) {
7911 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7913 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
7919 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7920 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7921 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7922 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7923 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7924 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7925 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7927 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
7940 ? AMDGPU::OpName::rsrc
7941 : AMDGPU::OpName::srsrc;
7943 if (SRsrc && !RI.isSGPRClass(
MRI.getRegClass(SRsrc->
getReg())))
7946 AMDGPU::OpName SampOpName =
7947 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7949 if (SSamp && !RI.isSGPRClass(
MRI.getRegClass(SSamp->
getReg())))
7956 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7958 if (!RI.isSGPRClass(
MRI.getRegClass(Dest->
getReg()))) {
7964 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7966 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7968 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7972 Src0.ChangeToRegister(Reg,
false);
7978 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7979 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7980 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7981 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7983 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
7990 bool isSoffsetLegal =
true;
7992 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7993 if (SoffsetIdx != -1) {
7996 !RI.isSGPRClass(
MRI.getRegClass(Soffset->
getReg()))) {
7997 isSoffsetLegal =
false;
8001 bool isRsrcLegal =
true;
8003 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8004 if (RsrcIdx != -1) {
8007 isRsrcLegal =
false;
8011 if (isRsrcLegal && isSoffsetLegal)
8035 Register NewVAddrLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8036 Register NewVAddrHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8037 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8039 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8040 Register CondReg0 =
MRI.createVirtualRegister(BoolXExecRC);
8041 Register CondReg1 =
MRI.createVirtualRegister(BoolXExecRC);
8043 unsigned RsrcPtr, NewSRsrc;
8050 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8051 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8057 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8058 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8071 }
else if (!VAddr && ST.hasAddr64()) {
8075 "FIXME: Need to emit flat atomics here");
8077 unsigned RsrcPtr, NewSRsrc;
8080 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8103 MIB.
addImm(CPol->getImm());
8108 MIB.
addImm(TFE->getImm());
8128 MI.removeFromParent();
8133 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8134 .addImm(AMDGPU::sub0)
8135 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8136 .addImm(AMDGPU::sub1);
8139 if (!isSoffsetLegal) {
8150 if (!isSoffsetLegal) {
8159 if (InSet.insert(
MI).second)
8163 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8164 if (RsrcIdx != -1) {
8165 DeferredList.insert(
MI);
8170 return DeferredList.contains(
MI);
8180 if (!ST.useRealTrue16Insts())
8183 unsigned Opcode =
MI.getOpcode();
8186 if (OpIdx >=
MI.getNumExplicitOperands() ||
8187 OpIdx >=
get(Opcode).getNumOperands() ||
8188 get(Opcode).operands()[OpIdx].RegClass == -1)
8192 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8196 if (!RI.isVGPRClass(CurrRC))
8199 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8201 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8203 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8204 Op.setSubReg(AMDGPU::lo16);
8209 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8210 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8212 Register NewDstReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8220 Op.setReg(NewDstReg);
8221 Op.setSubReg(AMDGPU::NoSubRegister);
8226 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8234 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8235 "This only handle waterfall for SI_CALL_ISEL");
8242 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8245 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8250 while (
End !=
MBB.end() &&
End->isCopy() &&
8251 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8261 while (!Worklist.
empty()) {
8267 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8273 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8275 "Deferred MachineInstr are not supposed to re-populate worklist");
8278 for (
auto &Entry : WaterFalls) {
8279 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8281 Entry.second.SGPRs);
8284 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8286 Entry.first->eraseFromParent();
8294 if (SubRegIndices.
size() <= 1) {
8295 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8297 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8304 for (int16_t Indice : SubRegIndices) {
8305 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8307 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8314 get(AMDGPU::REG_SEQUENCE), DstReg);
8315 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8317 MIB.
addImm(RI.getSubRegFromChannel(i));
8327 if (DstReg == AMDGPU::M0) {
8340 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8342 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8343 if (
UseMI->getOperand(i).isReg() &&
8344 UseMI->getOperand(i).getReg() == DstReg) {
8348 V2SCopyInfo.MOs.push_back(MO);
8349 V2SCopyInfo.SGPRs.push_back(DstReg);
8353 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8354 I->getOperand(0).isReg() &&
8355 I->getOperand(0).getReg() == DstReg) {
8358 }
else if (
I->readsRegister(DstReg, &RI)) {
8360 V2SPhyCopiesToErase[&Inst] =
false;
8362 if (
I->findRegisterDefOperand(DstReg, &RI))
8384 case AMDGPU::S_ADD_I32:
8385 case AMDGPU::S_SUB_I32: {
8389 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8397 case AMDGPU::S_MUL_U64:
8398 if (ST.useVMulU64Inst()) {
8399 NewOpcode = AMDGPU::V_MUL_U64_e64;
8403 splitScalarSMulU64(Worklist, Inst, MDT);
8407 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8408 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8411 splitScalarSMulPseudo(Worklist, Inst, MDT);
8415 case AMDGPU::S_AND_B64:
8416 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8420 case AMDGPU::S_OR_B64:
8421 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8425 case AMDGPU::S_XOR_B64:
8426 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8430 case AMDGPU::S_NAND_B64:
8431 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8435 case AMDGPU::S_NOR_B64:
8436 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8440 case AMDGPU::S_XNOR_B64:
8441 if (ST.hasDLInsts())
8442 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8444 splitScalar64BitXnor(Worklist, Inst, MDT);
8448 case AMDGPU::S_ANDN2_B64:
8449 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8453 case AMDGPU::S_ORN2_B64:
8454 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8458 case AMDGPU::S_BREV_B64:
8459 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8463 case AMDGPU::S_NOT_B64:
8464 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8468 case AMDGPU::S_BCNT1_I32_B64:
8469 splitScalar64BitBCNT(Worklist, Inst);
8473 case AMDGPU::S_BFE_I64:
8474 splitScalar64BitBFE(Worklist, Inst);
8478 case AMDGPU::S_FLBIT_I32_B64:
8479 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8482 case AMDGPU::S_FF1_I32_B64:
8483 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8487 case AMDGPU::S_LSHL_B32:
8488 if (ST.hasOnlyRevVALUShifts()) {
8489 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8493 case AMDGPU::S_ASHR_I32:
8494 if (ST.hasOnlyRevVALUShifts()) {
8495 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8499 case AMDGPU::S_LSHR_B32:
8500 if (ST.hasOnlyRevVALUShifts()) {
8501 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8505 case AMDGPU::S_LSHL_B64:
8506 if (ST.hasOnlyRevVALUShifts()) {
8508 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8509 : AMDGPU::V_LSHLREV_B64_e64;
8513 case AMDGPU::S_ASHR_I64:
8514 if (ST.hasOnlyRevVALUShifts()) {
8515 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8519 case AMDGPU::S_LSHR_B64:
8520 if (ST.hasOnlyRevVALUShifts()) {
8521 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8526 case AMDGPU::S_ABS_I32:
8527 lowerScalarAbs(Worklist, Inst);
8531 case AMDGPU::S_ABSDIFF_I32:
8532 lowerScalarAbsDiff(Worklist, Inst);
8536 case AMDGPU::S_CBRANCH_SCC0:
8537 case AMDGPU::S_CBRANCH_SCC1: {
8540 bool IsSCC = CondReg == AMDGPU::SCC;
8549 case AMDGPU::S_BFE_U64:
8550 case AMDGPU::S_BFM_B64:
8553 case AMDGPU::S_PACK_LL_B32_B16:
8554 case AMDGPU::S_PACK_LH_B32_B16:
8555 case AMDGPU::S_PACK_HL_B32_B16:
8556 case AMDGPU::S_PACK_HH_B32_B16:
8557 movePackToVALU(Worklist,
MRI, Inst);
8561 case AMDGPU::S_XNOR_B32:
8562 lowerScalarXnor(Worklist, Inst);
8566 case AMDGPU::S_NAND_B32:
8567 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8571 case AMDGPU::S_NOR_B32:
8572 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8576 case AMDGPU::S_ANDN2_B32:
8577 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8581 case AMDGPU::S_ORN2_B32:
8582 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8590 case AMDGPU::S_ADD_CO_PSEUDO:
8591 case AMDGPU::S_SUB_CO_PSEUDO: {
8592 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8593 ? AMDGPU::V_ADDC_U32_e64
8594 : AMDGPU::V_SUBB_U32_e64;
8595 const auto *CarryRC = RI.getWaveMaskRegClass();
8598 if (!
MRI.constrainRegClass(CarryInReg, CarryRC)) {
8599 Register NewCarryReg =
MRI.createVirtualRegister(CarryRC);
8606 Register DestReg =
MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8617 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8621 case AMDGPU::S_UADDO_PSEUDO:
8622 case AMDGPU::S_USUBO_PSEUDO: {
8628 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8629 ? AMDGPU::V_ADD_CO_U32_e64
8630 : AMDGPU::V_SUB_CO_U32_e64;
8632 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest0.
getReg()));
8633 Register DestReg =
MRI.createVirtualRegister(NewRC);
8641 MRI.replaceRegWith(Dest0.
getReg(), DestReg);
8642 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8646 case AMDGPU::S_LSHL1_ADD_U32:
8647 case AMDGPU::S_LSHL2_ADD_U32:
8648 case AMDGPU::S_LSHL3_ADD_U32:
8649 case AMDGPU::S_LSHL4_ADD_U32: {
8653 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8654 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8655 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8659 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest.
getReg()));
8660 Register DestReg =
MRI.createVirtualRegister(NewRC);
8668 MRI.replaceRegWith(Dest.
getReg(), DestReg);
8669 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8673 case AMDGPU::S_CSELECT_B32:
8674 case AMDGPU::S_CSELECT_B64:
8675 lowerSelect(Worklist, Inst, MDT);
8678 case AMDGPU::S_CMP_EQ_I32:
8679 case AMDGPU::S_CMP_LG_I32:
8680 case AMDGPU::S_CMP_GT_I32:
8681 case AMDGPU::S_CMP_GE_I32:
8682 case AMDGPU::S_CMP_LT_I32:
8683 case AMDGPU::S_CMP_LE_I32:
8684 case AMDGPU::S_CMP_EQ_U32:
8685 case AMDGPU::S_CMP_LG_U32:
8686 case AMDGPU::S_CMP_GT_U32:
8687 case AMDGPU::S_CMP_GE_U32:
8688 case AMDGPU::S_CMP_LT_U32:
8689 case AMDGPU::S_CMP_LE_U32:
8690 case AMDGPU::S_CMP_EQ_U64:
8691 case AMDGPU::S_CMP_LG_U64:
8692 case AMDGPU::S_CMP_LT_F32:
8693 case AMDGPU::S_CMP_EQ_F32:
8694 case AMDGPU::S_CMP_LE_F32:
8695 case AMDGPU::S_CMP_GT_F32:
8696 case AMDGPU::S_CMP_LG_F32:
8697 case AMDGPU::S_CMP_GE_F32:
8698 case AMDGPU::S_CMP_O_F32:
8699 case AMDGPU::S_CMP_U_F32:
8700 case AMDGPU::S_CMP_NGE_F32:
8701 case AMDGPU::S_CMP_NLG_F32:
8702 case AMDGPU::S_CMP_NGT_F32:
8703 case AMDGPU::S_CMP_NLE_F32:
8704 case AMDGPU::S_CMP_NEQ_F32:
8705 case AMDGPU::S_CMP_NLT_F32: {
8706 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8710 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8724 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8728 case AMDGPU::S_CMP_LT_F16:
8729 case AMDGPU::S_CMP_EQ_F16:
8730 case AMDGPU::S_CMP_LE_F16:
8731 case AMDGPU::S_CMP_GT_F16:
8732 case AMDGPU::S_CMP_LG_F16:
8733 case AMDGPU::S_CMP_GE_F16:
8734 case AMDGPU::S_CMP_O_F16:
8735 case AMDGPU::S_CMP_U_F16:
8736 case AMDGPU::S_CMP_NGE_F16:
8737 case AMDGPU::S_CMP_NLG_F16:
8738 case AMDGPU::S_CMP_NGT_F16:
8739 case AMDGPU::S_CMP_NLE_F16:
8740 case AMDGPU::S_CMP_NEQ_F16:
8741 case AMDGPU::S_CMP_NLT_F16: {
8742 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8763 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8767 case AMDGPU::S_CVT_HI_F32_F16: {
8768 Register TmpReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8769 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8770 if (ST.useRealTrue16Insts()) {
8775 .
addReg(TmpReg, {}, AMDGPU::hi16)
8791 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8795 case AMDGPU::S_MINIMUM_F32:
8796 case AMDGPU::S_MAXIMUM_F32: {
8797 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8808 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8812 case AMDGPU::S_MINIMUM_F16:
8813 case AMDGPU::S_MAXIMUM_F16: {
8814 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8815 ? &AMDGPU::VGPR_16RegClass
8816 : &AMDGPU::VGPR_32RegClass);
8827 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8831 case AMDGPU::V_S_EXP_F16_e64:
8832 case AMDGPU::V_S_LOG_F16_e64:
8833 case AMDGPU::V_S_RCP_F16_e64:
8834 case AMDGPU::V_S_RSQ_F16_e64:
8835 case AMDGPU::V_S_SQRT_F16_e64: {
8836 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8837 ? &AMDGPU::VGPR_16RegClass
8838 : &AMDGPU::VGPR_32RegClass);
8849 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8855 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8863 if (NewOpcode == Opcode) {
8870 V2SPhyCopiesToErase);
8878 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8885 addUsersToMoveToVALUWorklist(DstReg,
MRI, Worklist);
8891 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8892 UseMO.setReg(NewDstReg);
8896 MRI.clearKillFlags(NewDstReg);
8898 if (!
MRI.constrainRegClass(NewDstReg, CommonRC))
8911 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8914 MRI.constrainRegClass(NewDstReg, OpRC);
8924 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8928 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8929 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
8934 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8940 MRI.replaceRegWith(DstReg, NewDstReg);
8941 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
8943 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8946 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
8947 MRI.replaceRegWith(DstReg, NewDstReg);
8948 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
8953 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
8954 MRI.replaceRegWith(DstReg, NewDstReg);
8956 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
8966 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8967 AMDGPU::OpName::src0_modifiers) >= 0)
8971 NewInstr->addOperand(Src);
8974 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8977 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8979 NewInstr.addImm(
Size);
8980 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8984 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8989 "Scalar BFE is only implemented for constant width and offset");
8997 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8998 AMDGPU::OpName::src1_modifiers) >= 0)
9000 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9002 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9003 AMDGPU::OpName::src2_modifiers) >= 0)
9005 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9007 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9009 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9011 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9017 NewInstr->addOperand(
Op);
9023 bool DeadSCCDef =
false;
9025 if (
Op.getReg() == AMDGPU::SCC) {
9031 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9035 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9040 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9041 Register DstReg = NewInstr->getOperand(0).getReg();
9046 NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9047 MRI.replaceRegWith(DstReg, NewDstReg);
9055 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9056 VCCDef->setIsDead();
9062 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9066std::pair<bool, MachineBasicBlock *>
9069 if (ST.hasAddNoCarryInsts()) {
9078 Register ResultReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9081 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9083 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9084 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9092 MRI.replaceRegWith(OldDstReg, ResultReg);
9095 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9096 return std::pair(
true, NewBB);
9099 return std::pair(
false,
nullptr);
9116 bool IsSCC = (CondReg == AMDGPU::SCC);
9122 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9123 (
Src1.getImm() == 0)) {
9124 for (MachineOperand &UseMO :
9126 MachineInstr &
UseMI = *UseMO.getParent();
9127 switch (
UseMI.getOpcode()) {
9128 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9129 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9130 case AMDGPU::V_CNDMASK_B16_t16_e32:
9131 case AMDGPU::V_CNDMASK_B16_t16_e64:
9132 case AMDGPU::V_CNDMASK_B32_e32:
9133 case AMDGPU::V_CNDMASK_B32_e64:
9134 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9135 if (UseMO.isImplicit() ||
9137 UseMO.setReg(CondReg);
9151 bool CopyFound =
false;
9152 for (MachineInstr &CandI :
9155 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9157 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9159 .
addReg(CandI.getOperand(1).getReg());
9171 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9180 MachineInstr *NewInst;
9181 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9182 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9197 addUsersToMoveToVALUWorklist(NewDestReg,
MRI, Worklist);
9212 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9214 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9216 MachineInstrBuilder
Sub =
9226 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9243 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9245 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9247 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9251 MachineInstrBuilder Sub2 =
9264 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9278 if (ST.hasDLInsts()) {
9288 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9294 bool Src0IsSGPR =
Src0.isReg() &&
9296 bool Src1IsSGPR =
Src1.isReg() &&
9310 }
else if (Src1IsSGPR) {
9328 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9334 unsigned Opcode)
const {
9358 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9363 unsigned Opcode)
const {
9387 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9402 const MCInstrDesc &InstDesc =
get(Opcode);
9405 &AMDGPU::SGPR_32RegClass;
9408 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9411 AMDGPU::sub0, Src0SubRC);
9416 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9419 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9422 AMDGPU::sub1, Src0SubRC);
9425 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9439 Worklist.
insert(&LoHalf);
9440 Worklist.
insert(&HiHalf);
9446 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9470 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9471 if (RI.isSGPRClass(Src0SubRC))
9472 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9474 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9475 if (RI.isSGPRClass(Src1SubRC))
9476 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9480 MachineOperand Op0L =
9482 MachineOperand Op1L =
9484 MachineOperand Op0H =
9486 MachineOperand Op1H =
9505 MachineInstr *Op1L_Op0H =
9511 MachineInstr *Op1H_Op0L =
9517 MachineInstr *Carry =
9522 MachineInstr *LoHalf =
9532 MachineInstr *HiHalf =
9555 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9579 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9580 if (RI.isSGPRClass(Src0SubRC))
9581 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9583 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9584 if (RI.isSGPRClass(Src1SubRC))
9585 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9589 MachineOperand Op0L =
9591 MachineOperand Op1L =
9595 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9596 ? AMDGPU::V_MUL_HI_U32_e64
9597 : AMDGPU::V_MUL_HI_I32_e64;
9598 MachineInstr *HiHalf =
9601 MachineInstr *LoHalf =
9620 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9636 const MCInstrDesc &InstDesc =
get(Opcode);
9639 &AMDGPU::SGPR_32RegClass;
9642 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9645 &AMDGPU::SGPR_32RegClass;
9648 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9651 AMDGPU::sub0, Src0SubRC);
9653 AMDGPU::sub0, Src1SubRC);
9655 AMDGPU::sub1, Src0SubRC);
9657 AMDGPU::sub1, Src1SubRC);
9662 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9665 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9670 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9683 Worklist.
insert(&LoHalf);
9684 Worklist.
insert(&HiHalf);
9687 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9707 MachineOperand* Op0;
9708 MachineOperand* Op1;
9710 if (
Src0.isReg() && RI.isSGPRReg(
MRI,
Src0.getReg())) {
9743 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9746 &AMDGPU::SGPR_32RegClass;
9752 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9755 AMDGPU::sub0, SrcSubRC);
9757 AMDGPU::sub1, SrcSubRC);
9767 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9786 Offset == 0 &&
"Not implemented");
9809 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9819 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9822 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9828 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9847 const MCInstrDesc &InstDesc =
get(Opcode);
9849 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9852 Src.isReg() ?
MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9854 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9856 MachineOperand SrcRegSub0 =
9858 MachineOperand SrcRegSub1 =
9872 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9876 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9880 addUsersToMoveToVALUWorklist(MidReg4,
MRI, Worklist);
9883void SIInstrInfo::addUsersToMoveToVALUWorklist(
9887 MachineInstr &
UseMI = *MO.getParent();
9891 switch (
UseMI.getOpcode()) {
9894 case AMDGPU::SOFT_WQM:
9895 case AMDGPU::STRICT_WWM:
9896 case AMDGPU::STRICT_WQM:
9897 case AMDGPU::REG_SEQUENCE:
9899 case AMDGPU::INSERT_SUBREG:
9902 OpNo = MO.getOperandNo();
9909 if (!RI.hasVectorRegisters(OpRC))
9926 if (ST.useRealTrue16Insts()) {
9928 if (!
Src0.isReg() || !RI.isVGPR(
MRI,
Src0.getReg())) {
9931 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9934 SrcReg0 =
Src0.getReg();
9937 if (!
Src1.isReg() || !RI.isVGPR(
MRI,
Src1.getReg())) {
9940 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9943 SrcReg1 =
Src1.getReg();
9949 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9951 case AMDGPU::S_PACK_LL_B32_B16:
9953 .addReg(SrcReg0, {},
9954 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9955 .addImm(AMDGPU::lo16)
9956 .addReg(SrcReg1, {},
9957 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9958 .addImm(AMDGPU::hi16);
9960 case AMDGPU::S_PACK_LH_B32_B16:
9962 .addReg(SrcReg0, {},
9963 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9964 .addImm(AMDGPU::lo16)
9965 .addReg(SrcReg1, {}, AMDGPU::hi16)
9966 .addImm(AMDGPU::hi16);
9968 case AMDGPU::S_PACK_HL_B32_B16:
9969 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9970 .addImm(AMDGPU::lo16)
9971 .addReg(SrcReg1, {},
9972 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9973 .addImm(AMDGPU::hi16);
9975 case AMDGPU::S_PACK_HH_B32_B16:
9976 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9977 .addImm(AMDGPU::lo16)
9978 .addReg(SrcReg1, {}, AMDGPU::hi16)
9979 .addImm(AMDGPU::hi16);
9987 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9992 case AMDGPU::S_PACK_LL_B32_B16: {
10011 case AMDGPU::S_PACK_LH_B32_B16: {
10021 case AMDGPU::S_PACK_HL_B32_B16: {
10032 case AMDGPU::S_PACK_HH_B32_B16: {
10052 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10061 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10062 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10063 SmallVector<MachineInstr *, 4> CopyToDelete;
10066 for (MachineInstr &
MI :
10070 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10071 if (SCCIdx != -1) {
10074 Register DestReg =
MI.getOperand(0).getReg();
10081 MI.getOperand(SCCIdx).setReg(NewCond);
10087 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10090 for (
auto &Copy : CopyToDelete)
10091 Copy->eraseFromParent();
10099void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10105 for (MachineInstr &
MI :
10108 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10110 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10127 case AMDGPU::REG_SEQUENCE:
10128 case AMDGPU::INSERT_SUBREG:
10130 case AMDGPU::SOFT_WQM:
10131 case AMDGPU::STRICT_WWM:
10132 case AMDGPU::STRICT_WQM: {
10134 if (RI.isAGPRClass(SrcRC)) {
10135 if (RI.isAGPRClass(NewDstRC))
10140 case AMDGPU::REG_SEQUENCE:
10141 case AMDGPU::INSERT_SUBREG:
10142 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10145 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10151 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10154 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10168 int OpIndices[3])
const {
10169 const MCInstrDesc &
Desc =
MI.getDesc();
10187 for (
unsigned i = 0; i < 3; ++i) {
10188 int Idx = OpIndices[i];
10192 const MachineOperand &MO =
MI.getOperand(Idx);
10199 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10200 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10201 if (IsRequiredSGPR)
10207 if (RI.isSGPRClass(RegRC))
10208 UsedSGPRs[i] =
Reg;
10224 if (UsedSGPRs[0]) {
10225 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10226 SGPRReg = UsedSGPRs[0];
10229 if (!SGPRReg && UsedSGPRs[1]) {
10230 if (UsedSGPRs[1] == UsedSGPRs[2])
10231 SGPRReg = UsedSGPRs[1];
10238 AMDGPU::OpName OperandName)
const {
10239 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10242 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10246 return &
MI.getOperand(Idx);
10260 if (ST.isAmdHsaOS()) {
10263 RsrcDataFormat |= (1ULL << 56);
10268 RsrcDataFormat |= (2ULL << 59);
10271 return RsrcDataFormat;
10281 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10286 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10293 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10299 unsigned Opc =
MI.getOpcode();
10305 return get(
Opc).mayLoad() &&
10312 if (!Addr || !Addr->
isFI())
10321 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10323 return MI.getOperand(VDataIdx).getReg();
10333 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10335 return MI.getOperand(DataIdx).getReg();
10356 if (!
MI.mayStore())
10369 unsigned Opc =
MI.getOpcode();
10371 unsigned DescSize =
Desc.getSize();
10376 unsigned Size = DescSize;
10380 if (
MI.isBranch() && ST.hasOffset3fBug())
10391 bool HasLiteral =
false;
10392 unsigned LiteralSize = 4;
10393 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10398 if (ST.has64BitLiterals()) {
10399 switch (OpInfo.OperandType) {
10424 return HasLiteral ? DescSize + LiteralSize : DescSize;
10429 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10433 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10434 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10438 case TargetOpcode::BUNDLE:
10439 return getInstBundleSize(
MI);
10440 case TargetOpcode::INLINEASM:
10441 case TargetOpcode::INLINEASM_BR: {
10443 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10447 if (
MI.isMetaInstruction())
10451 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10454 unsigned LoInstOpcode = D16Info->LoOp;
10456 DescSize =
Desc.getSize();
10460 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10463 DescSize =
Desc.getSize();
10472 if (
MI.isBranch() && ST.hasOffset3fBug())
10473 return InstSizeVerifyMode::NoVerify;
10474 return InstSizeVerifyMode::ExactSize;
10479 static const std::pair<int, const char *> TargetIndices[] = {
10519std::pair<unsigned, unsigned>
10526 static const std::pair<unsigned, const char *> TargetFlags[] = {
10544 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10562 return AMDGPU::WWM_COPY;
10564 return AMDGPU::COPY;
10581 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10585 if (RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg)))
10586 return IsLRSplitInst;
10599 bool IsNullOrVectorRegister =
true;
10603 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg));
10606 return IsNullOrVectorRegister &&
10608 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10609 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10617 if (ST.hasAddNoCarryInsts())
10621 Register UnusedCarry =
MRI.createVirtualRegister(RI.getBoolRC());
10622 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10633 if (ST.hasAddNoCarryInsts())
10637 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10639 : RS.scavengeRegisterBackwards(
10640 *RI.getBoolRC(),
I,
false,
10653 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10654 case AMDGPU::SI_KILL_I1_TERMINATOR:
10663 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10664 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10665 case AMDGPU::SI_KILL_I1_PSEUDO:
10666 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10678 const unsigned OffsetBits =
10680 return (1 << OffsetBits) - 1;
10684 if (!ST.isWave32())
10687 if (
MI.isInlineAsm())
10690 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10693 for (
auto &
Op :
MI.implicit_operands()) {
10694 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10695 Op.setReg(AMDGPU::VCC_LO);
10704 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10708 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10709 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10725 if (
Imm > MaxImm) {
10726 if (
Imm <= MaxImm + 64) {
10728 Overflow =
Imm - MaxImm;
10743 Overflow =
High - Alignment.value();
10747 if (Overflow > 0) {
10755 if (ST.hasRestrictedSOffset())
10760 SOffset = Overflow;
10798 if (!ST.hasFlatInstOffsets())
10802 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10807 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10808 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10819std::pair<int64_t, int64_t>
10822 int64_t RemainderOffset = COffsetVal;
10823 int64_t ImmField = 0;
10828 if (AllowNegative) {
10830 int64_t
D = 1LL << NumBits;
10831 RemainderOffset = (COffsetVal /
D) *
D;
10832 ImmField = COffsetVal - RemainderOffset;
10834 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10836 (ImmField % 4) != 0) {
10838 RemainderOffset += ImmField % 4;
10839 ImmField -= ImmField % 4;
10841 }
else if (COffsetVal >= 0) {
10843 RemainderOffset = COffsetVal - ImmField;
10847 assert(RemainderOffset + ImmField == COffsetVal);
10848 return {ImmField, RemainderOffset};
10853 if (ST.hasNegativeScratchOffsetBug() &&
10861 switch (ST.getGeneration()) {
10895 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10896 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10897 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10898 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10899 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10900 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10901 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10902 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10909#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10910 case OPCODE##_dpp: \
10911 case OPCODE##_e32: \
10925 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10926 case AMDGPU::V_FMA_F16_gfx9_e64:
10927 case AMDGPU::V_INTERP_P2_F16:
10928 case AMDGPU::V_MAD_F16_e64:
10929 case AMDGPU::V_MAD_U16_e64:
10930 case AMDGPU::V_MAD_I16_e64:
10931 case AMDGPU::V_MAD_U16_gfx9_e64:
10932 case AMDGPU::V_MAD_I16_gfx9_e64:
10941 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10949 switch (ST.getGeneration()) {
10962 if (
isMAI(Opcode)) {
10976 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10979 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10986 if (ST.hasGFX90AInsts()) {
10987 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10988 if (ST.hasGFX940Insts())
10990 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10992 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10994 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11000 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11019 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11020 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11021 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11033 switch (
MI.getOpcode()) {
11035 case AMDGPU::REG_SEQUENCE:
11039 case AMDGPU::INSERT_SUBREG:
11040 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11057 if (!
P.Reg.isVirtual())
11061 auto *DefInst =
MRI.getVRegDef(RSR.Reg);
11062 while (
auto *
MI = DefInst) {
11064 switch (
MI->getOpcode()) {
11066 case AMDGPU::V_MOV_B32_e32: {
11067 auto &Op1 =
MI->getOperand(1);
11072 DefInst =
MRI.getVRegDef(RSR.Reg);
11080 DefInst =
MRI.getVRegDef(RSR.Reg);
11093 assert(
MRI.isSSA() &&
"Must be run on SSA");
11095 auto *
TRI =
MRI.getTargetRegisterInfo();
11096 auto *DefBB =
DefMI.getParent();
11100 if (
UseMI.getParent() != DefBB)
11103 const int MaxInstScan = 20;
11107 auto E =
UseMI.getIterator();
11108 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11109 if (
I->isDebugInstr())
11112 if (++NumInst > MaxInstScan)
11115 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11125 assert(
MRI.isSSA() &&
"Must be run on SSA");
11127 auto *
TRI =
MRI.getTargetRegisterInfo();
11128 auto *DefBB =
DefMI.getParent();
11130 const int MaxUseScan = 10;
11133 for (
auto &
Use :
MRI.use_nodbg_operands(VReg)) {
11134 auto &UseInst = *
Use.getParent();
11137 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11140 if (++NumUse > MaxUseScan)
11147 const int MaxInstScan = 20;
11151 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11154 if (
I->isDebugInstr())
11157 if (++NumInst > MaxInstScan)
11170 if (Reg == VReg && --NumUse == 0)
11172 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11181 auto Cur =
MBB.begin();
11182 if (Cur !=
MBB.end())
11184 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11187 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11196 if (InsPt !=
MBB.end() &&
11197 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11198 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11199 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11200 InsPt->definesRegister(Src,
nullptr)) {
11204 .
addReg(Src, {}, SrcSubReg)
11247 if (isFullCopyInstr(
MI)) {
11248 Register DstReg =
MI.getOperand(0).getReg();
11249 Register SrcReg =
MI.getOperand(1).getReg();
11256 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11260 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11271 unsigned *PredCost)
const {
11272 if (
MI.isBundle()) {
11275 unsigned Lat = 0,
Count = 0;
11276 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11278 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11280 return Lat +
Count - 1;
11283 return SchedModel.computeInstrLatency(&
MI);
11287 if (!ST.hasGFX1250VALUBlockingCycles())
11294 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11295 return Entry->GFX1250BlockingCycles;
11303 return *CallAddrOp;
11310 unsigned Opcode =
MI.getOpcode();
11315 LLT DstTy =
MRI.getType(Dst);
11316 LLT SrcTy =
MRI.getType(Src);
11318 unsigned SrcAS = SrcTy.getAddressSpace();
11321 ST.hasGloballyAddressableScratch()
11329 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11330 return HandleAddrSpaceCast(
MI);
11333 auto IID = GI->getIntrinsicID();
11340 case Intrinsic::amdgcn_if:
11341 case Intrinsic::amdgcn_else:
11355 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11356 Opcode == AMDGPU::G_SEXTLOAD) {
11357 if (
MI.memoperands_empty())
11361 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11362 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11370 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11371 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11372 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11378 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11381 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11389 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11390 return Formatter.get();
11398 unsigned opcode =
MI.getOpcode();
11399 if (opcode == AMDGPU::V_READLANE_B32 ||
11400 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11401 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11406 if (
MI.isInlineAsm()) {
11412 if (!RC || !RI.isSGPRClass(RC))
11417 if (isCopyInstr(
MI)) {
11421 RI.getPhysRegBaseClass(srcOp.
getReg());
11429 if (
MI.isPreISelOpcode())
11444 if (
MI.memoperands_empty())
11448 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11449 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11464 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11466 if (!
SrcOp.isReg())
11470 if (!Reg || !
SrcOp.readsReg())
11476 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11503 F,
"ds_ordered_count unsupported for this calling conv"));
11517 Register &SrcReg2, int64_t &CmpMask,
11518 int64_t &CmpValue)
const {
11519 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11522 switch (
MI.getOpcode()) {
11525 case AMDGPU::S_CMP_EQ_U32:
11526 case AMDGPU::S_CMP_EQ_I32:
11527 case AMDGPU::S_CMP_LG_U32:
11528 case AMDGPU::S_CMP_LG_I32:
11529 case AMDGPU::S_CMP_LT_U32:
11530 case AMDGPU::S_CMP_LT_I32:
11531 case AMDGPU::S_CMP_GT_U32:
11532 case AMDGPU::S_CMP_GT_I32:
11533 case AMDGPU::S_CMP_LE_U32:
11534 case AMDGPU::S_CMP_LE_I32:
11535 case AMDGPU::S_CMP_GE_U32:
11536 case AMDGPU::S_CMP_GE_I32:
11537 case AMDGPU::S_CMP_EQ_U64:
11538 case AMDGPU::S_CMP_LG_U64:
11539 SrcReg =
MI.getOperand(0).getReg();
11540 if (
MI.getOperand(1).isReg()) {
11541 if (
MI.getOperand(1).getSubReg())
11543 SrcReg2 =
MI.getOperand(1).getReg();
11545 }
else if (
MI.getOperand(1).isImm()) {
11547 CmpValue =
MI.getOperand(1).getImm();
11553 case AMDGPU::S_CMPK_EQ_U32:
11554 case AMDGPU::S_CMPK_EQ_I32:
11555 case AMDGPU::S_CMPK_LG_U32:
11556 case AMDGPU::S_CMPK_LG_I32:
11557 case AMDGPU::S_CMPK_LT_U32:
11558 case AMDGPU::S_CMPK_LT_I32:
11559 case AMDGPU::S_CMPK_GT_U32:
11560 case AMDGPU::S_CMPK_GT_I32:
11561 case AMDGPU::S_CMPK_LE_U32:
11562 case AMDGPU::S_CMPK_LE_I32:
11563 case AMDGPU::S_CMPK_GE_U32:
11564 case AMDGPU::S_CMPK_GE_I32:
11565 SrcReg =
MI.getOperand(0).getReg();
11567 CmpValue =
MI.getOperand(1).getImm();
11577 if (S->isLiveIn(AMDGPU::SCC))
11586bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11589 bool SCCIsDead =
false;
11592 constexpr unsigned ScanLimit = 12;
11593 unsigned Count = 0;
11596 if (++
Count > ScanLimit)
11598 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11599 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11600 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11601 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11602 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11607 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11620 for (MachineInstr *
MI : InvertInstr) {
11621 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11622 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11624 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11625 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11626 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11627 ? AMDGPU::S_CBRANCH_SCC1
11628 : AMDGPU::S_CBRANCH_SCC0));
11641 bool NeedInversion)
const {
11642 MachineInstr *KillsSCC =
nullptr;
11647 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11649 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11652 if (NeedInversion && !invertSCCUse(SCCRedefine))
11654 if (MachineOperand *SccDef =
11656 SccDef->setIsDead(
false);
11665static std::optional<std::pair<int64_t, int64_t>>
11669 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11671 std::optional<int64_t>
A =
11675 std::optional<int64_t>
B =
11679 if (
Opc == AMDGPU::S_CSELECT_B32) {
11685 return std::pair(*
A, *
B);
11689 unsigned &NewDefOpc) {
11692 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11693 Def.getOpcode() != AMDGPU::S_ADD_U32)
11699 Def.getMF()->getSubtarget().getInstrInfo());
11701 auto Imm1 =
TII->getImmOrMaterializedImm(
MRI, AddSrc1);
11702 auto Imm2 =
TII->getImmOrMaterializedImm(
MRI, AddSrc2);
11703 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11706 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11708 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11711 NewDefOpc = AMDGPU::S_ADD_U32;
11713 NeedInversion = !NeedInversion;
11718 Register SrcReg2, int64_t CmpMask,
11728 CmpValue = *ImmOpt;
11731 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue,
MRI,
11732 this](
bool NeedInversion) ->
bool {
11737 unsigned NewDefOpc = Def->getOpcode();
11744 auto [
A,
B] = *Consts;
11745 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11748 NeedInversion = !NeedInversion;
11760 if (CmpValue != 0 ||
11766 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11769 if (NewDefOpc != Def->getOpcode())
11770 Def->setDesc(
get(NewDefOpc));
11779 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11780 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11786 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11795 auto [
A,
B] = *Consts;
11796 if (
A == 0 ||
B == 0)
11797 optimizeSCC(
Select, Def,
A == 0);
11806 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue,
MRI,
11807 this](int64_t ExpectedValue,
unsigned SrcSize,
11808 bool IsReversible,
bool IsSigned) ->
bool {
11836 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11837 Def->getOpcode() != AMDGPU::S_AND_B64)
11841 const auto isMask = [&Mask, SrcSize,
MRI,
11853 SrcOp = &Def->getOperand(2);
11854 else if (isMask(&Def->getOperand(2)))
11855 SrcOp = &Def->getOperand(1);
11863 if (IsSigned && BitNo == SrcSize - 1)
11866 ExpectedValue <<= BitNo;
11868 bool IsReversedCC =
false;
11869 if (CmpValue != ExpectedValue) {
11872 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11877 Register DefReg = Def->getOperand(0).getReg();
11878 if (IsReversedCC && !
MRI->hasOneNonDBGUse(DefReg))
11881 if (!optimizeSCC(Def, &CmpInstr,
false))
11884 if (!
MRI->use_nodbg_empty(DefReg)) {
11892 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11893 : AMDGPU::S_BITCMP1_B32
11894 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11895 : AMDGPU::S_BITCMP1_B64;
11900 Def->eraseFromParent();
11908 case AMDGPU::S_CMP_EQ_U32:
11909 case AMDGPU::S_CMP_EQ_I32:
11910 case AMDGPU::S_CMPK_EQ_U32:
11911 case AMDGPU::S_CMPK_EQ_I32:
11912 return optimizeCmpAnd(1, 32,
true,
false) ||
11913 optimizeCmpSelect(
true);
11914 case AMDGPU::S_CMP_GE_U32:
11915 case AMDGPU::S_CMPK_GE_U32:
11916 return optimizeCmpAnd(1, 32,
false,
false);
11917 case AMDGPU::S_CMP_GE_I32:
11918 case AMDGPU::S_CMPK_GE_I32:
11919 return optimizeCmpAnd(1, 32,
false,
true);
11920 case AMDGPU::S_CMP_EQ_U64:
11921 return optimizeCmpAnd(1, 64,
true,
false) ||
11922 optimizeCmpSelect(
true);
11923 case AMDGPU::S_CMP_LG_U32:
11924 case AMDGPU::S_CMP_LG_I32:
11925 case AMDGPU::S_CMPK_LG_U32:
11926 case AMDGPU::S_CMPK_LG_I32:
11927 return optimizeCmpAnd(0, 32,
true,
false) ||
11928 optimizeCmpSelect(
false);
11929 case AMDGPU::S_CMP_GT_U32:
11930 case AMDGPU::S_CMPK_GT_U32:
11931 return optimizeCmpAnd(0, 32,
false,
false);
11932 case AMDGPU::S_CMP_GT_I32:
11933 case AMDGPU::S_CMPK_GT_I32:
11934 return optimizeCmpAnd(0, 32,
false,
true);
11935 case AMDGPU::S_CMP_LG_U64:
11936 return optimizeCmpAnd(0, 64,
true,
false) ||
11937 optimizeCmpSelect(
false);
11944 AMDGPU::OpName
OpName)
const {
11945 if (!ST.needsAlignedVGPRs())
11948 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11960 bool IsAGPR = RI.isAGPR(
MRI, DataReg);
11962 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11965 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11966 : &AMDGPU::VReg_64_Align2RegClass);
11968 .
addReg(DataReg, {},
Op.getSubReg())
11973 Op.setSubReg(AMDGPU::sub0);
11978 if (!SchedModel.hasInstrSchedModel())
11984 unsigned RepeatRate = 0;
11986 PI = SchedModel.getWriteProcResBegin(SCDesc),
11987 PE = SchedModel.getWriteProcResEnd(SCDesc);
11989 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12006 if (ST.hasGFX1250Insts())
12013 unsigned Opcode =
MI.getOpcode();
12019 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12020 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12023 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)
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const unsigned AndN2WrExecOpc
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned MovTermOpc
const unsigned OrSaveExecOpc
const unsigned AndSaveExecOpc
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
This class is the base class for the comparison instructions.
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void setVariableValue(const MCExpr *Value)
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
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
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_IMM_NOINLINE_FP16
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
static const MachineMemOperand::Flags MOCFSB1
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
@ End
Run the machine verifier once, at the end of the pipeline.
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
@ AlwaysUniform
The result value is always uniform.
@ NeverUniform
The result value can never be assumed to be uniform.
@ Default
The result value is uniform if and only if all operands are uniform.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
uint8_t GFX1250BlockingCycles
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr bool all() const
Summarize the scheduling resources required for an instruction of a particular scheduling class.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
MachineInstr * top() const
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.