34#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_D16ImageDimIntrinsics_IMPL
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#include "AMDGPUGenSearchableTables.inc"
58 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
61 "amdgpu-fix-16-bit-physreg-copies",
62 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
78 unsigned N =
Node->getNumOperands();
79 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
91 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
92 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
94 if (Op0Idx == -1 && Op1Idx == -1)
98 if ((Op0Idx == -1 && Op1Idx != -1) ||
99 (Op1Idx == -1 && Op0Idx != -1))
120 return !
MI.memoperands_empty() &&
122 return MMO->isLoad() && MMO->isInvariant();
144 if (!
MI.hasImplicitDef() &&
145 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
146 !
MI.mayRaiseFPException())
154bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
158 if (
MI.isConvergent())
186 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
191 for (
auto Op :
MI.uses()) {
192 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
198 if (FromCycle ==
nullptr)
204 while (FromCycle && !FromCycle->
contains(ToCycle)) {
224 int64_t &Offset1)
const {
232 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
236 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
252 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
253 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
254 if (Offset0Idx == -1 || Offset1Idx == -1)
261 Offset0Idx -=
get(Opc0).NumDefs;
262 Offset1Idx -=
get(Opc1).NumDefs;
292 if (!Load0Offset || !Load1Offset)
309 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
310 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
312 if (OffIdx0 == -1 || OffIdx1 == -1)
318 OffIdx0 -=
get(Opc0).NumDefs;
319 OffIdx1 -=
get(Opc1).NumDefs;
338 case AMDGPU::DS_READ2ST64_B32:
339 case AMDGPU::DS_READ2ST64_B64:
340 case AMDGPU::DS_WRITE2ST64_B32:
341 case AMDGPU::DS_WRITE2ST64_B64:
356 OffsetIsScalable =
false;
373 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
375 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
376 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
389 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
390 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
391 if (Offset0 + 1 != Offset1)
402 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
410 Offset = EltSize * Offset0;
412 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
413 if (DataOpIdx == -1) {
414 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
416 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
432 if (BaseOp && !BaseOp->
isFI())
440 if (SOffset->
isReg())
446 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
448 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
457 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
458 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
460 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
461 if (VAddr0Idx >= 0) {
463 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
470 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
485 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
502 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
504 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
521 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
529 if (MO1->getAddrSpace() != MO2->getAddrSpace())
532 const auto *Base1 = MO1->getValue();
533 const auto *Base2 = MO2->getValue();
534 if (!Base1 || !Base2)
542 return Base1 == Base2;
546 int64_t Offset1,
bool OffsetIsScalable1,
548 int64_t Offset2,
bool OffsetIsScalable2,
549 unsigned ClusterSize,
550 unsigned NumBytes)
const {
563 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
582 const unsigned LoadSize = NumBytes / ClusterSize;
583 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
584 return NumDWords <= MaxMemoryClusterDWords;
598 int64_t Offset0, int64_t Offset1,
599 unsigned NumLoads)
const {
600 assert(Offset1 > Offset0 &&
601 "Second offset should be larger than first offset!");
606 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
613 const char *
Msg =
"illegal VGPR to SGPR copy") {
632 assert((
TII.getSubtarget().hasMAIInsts() &&
633 !
TII.getSubtarget().hasGFX90AInsts()) &&
634 "Expected GFX908 subtarget.");
637 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
638 "Source register of the copy should be either an SGPR or an AGPR.");
641 "Destination register of the copy should be an AGPR.");
650 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
653 if (!Def->modifiesRegister(SrcReg, &RI))
656 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
657 Def->getOperand(0).getReg() != SrcReg)
664 bool SafeToPropagate =
true;
667 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
668 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
669 SafeToPropagate =
false;
671 if (!SafeToPropagate)
674 for (
auto I = Def;
I !=
MI; ++
I)
675 I->clearRegisterKills(DefOp.
getReg(), &RI);
683 if (ImpUseSuperReg) {
684 Builder.addReg(ImpUseSuperReg,
692 RS.enterBasicBlockEnd(
MBB);
693 RS.backward(std::next(
MI));
702 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
705 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
706 "VGPR used for an intermediate copy should have been reserved.");
711 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
721 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
722 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
723 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
730 if (ImpUseSuperReg) {
731 UseBuilder.
addReg(ImpUseSuperReg,
748 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
749 int16_t SubIdx = BaseIndices[Idx];
750 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
751 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
752 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
753 unsigned Opcode = AMDGPU::S_MOV_B32;
756 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
757 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
758 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
762 DestSubReg = RI.getSubReg(DestReg, SubIdx);
763 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
764 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
765 Opcode = AMDGPU::S_MOV_B64;
780 assert(FirstMI && LastMI);
785 LastMI->addRegisterKilled(SrcReg, &RI);
791 Register SrcReg,
bool KillSrc,
bool RenamableDest,
792 bool RenamableSrc)
const {
794 unsigned Size = RI.getRegSizeInBits(*RC);
796 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
802 if (((
Size == 16) != (SrcSize == 16))) {
804 assert(ST.useRealTrue16Insts());
806 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
809 if (DestReg == SrcReg) {
815 RC = RI.getPhysRegBaseClass(DestReg);
816 Size = RI.getRegSizeInBits(*RC);
817 SrcRC = RI.getPhysRegBaseClass(SrcReg);
818 SrcSize = RI.getRegSizeInBits(*SrcRC);
822 if (RC == &AMDGPU::VGPR_32RegClass) {
824 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
825 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
826 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
827 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
833 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
834 RC == &AMDGPU::SReg_32RegClass) {
835 if (SrcReg == AMDGPU::SCC) {
842 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
843 if (DestReg == AMDGPU::VCC_LO) {
861 if (RC == &AMDGPU::SReg_64RegClass) {
862 if (SrcReg == AMDGPU::SCC) {
869 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
870 if (DestReg == AMDGPU::VCC) {
888 if (DestReg == AMDGPU::SCC) {
891 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
895 assert(ST.hasScalarCompareEq64());
909 if (RC == &AMDGPU::AGPR_32RegClass) {
910 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
911 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
917 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
926 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
933 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
934 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
936 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
937 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
938 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
939 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
942 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
943 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
956 if (IsAGPRDst || IsAGPRSrc) {
957 if (!DstLow || !SrcLow) {
959 "Cannot use hi16 subreg with an AGPR!");
966 if (ST.useRealTrue16Insts()) {
972 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
973 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
985 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
986 if (!DstLow || !SrcLow) {
988 "Cannot use hi16 subreg on VI!");
1011 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1012 if (ST.hasVMovB64Inst()) {
1017 if (ST.hasPkMovB32()) {
1033 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1034 if (RI.isSGPRClass(RC)) {
1035 if (!RI.isSGPRClass(SrcRC)) {
1039 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1045 unsigned EltSize = 4;
1046 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1047 if (RI.isAGPRClass(RC)) {
1048 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1049 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1050 else if (RI.hasVGPRs(SrcRC) ||
1051 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1052 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1054 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1055 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1056 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1057 }
else if ((
Size % 64 == 0) && RI.hasVGPRs(RC) &&
1058 (RI.isProperlyAlignedRC(*RC) &&
1059 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1061 if (ST.hasVMovB64Inst()) {
1062 Opcode = AMDGPU::V_MOV_B64_e32;
1064 }
else if (ST.hasPkMovB32()) {
1065 Opcode = AMDGPU::V_PK_MOV_B32;
1075 std::unique_ptr<RegScavenger> RS;
1076 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1077 RS = std::make_unique<RegScavenger>();
1083 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1084 const bool CanKillSuperReg = KillSrc && !Overlap;
1086 for (
unsigned Idx = 0; Idx < SubIndices.
size(); ++Idx) {
1089 SubIdx = SubIndices[Idx];
1091 SubIdx = SubIndices[SubIndices.
size() - Idx - 1];
1092 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1093 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1094 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1096 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size() - 1;
1098 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1101 *RS, Overlap, ImpUseSuper);
1102 }
else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1143 int64_t &ImmVal)
const {
1144 switch (
MI.getOpcode()) {
1145 case AMDGPU::V_MOV_B32_e32:
1146 case AMDGPU::S_MOV_B32:
1147 case AMDGPU::S_MOVK_I32:
1148 case AMDGPU::S_MOV_B64:
1149 case AMDGPU::V_MOV_B64_e32:
1150 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1151 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1152 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1153 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1154 case AMDGPU::V_MOV_B64_PSEUDO:
1155 case AMDGPU::V_MOV_B16_t16_e32: {
1159 return MI.getOperand(0).getReg() == Reg;
1164 case AMDGPU::V_MOV_B16_t16_e64: {
1166 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1168 return MI.getOperand(0).getReg() == Reg;
1173 case AMDGPU::S_BREV_B32:
1174 case AMDGPU::V_BFREV_B32_e32:
1175 case AMDGPU::V_BFREV_B32_e64: {
1179 return MI.getOperand(0).getReg() == Reg;
1184 case AMDGPU::S_NOT_B32:
1185 case AMDGPU::V_NOT_B32_e32:
1186 case AMDGPU::V_NOT_B32_e64: {
1189 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1190 return MI.getOperand(0).getReg() == Reg;
1200std::optional<int64_t>
1205 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1206 return std::nullopt;
1209 if (Def && Def->isMoveImmediate()) {
1215 return std::nullopt;
1220 if (RI.isAGPRClass(DstRC))
1221 return AMDGPU::COPY;
1222 if (RI.getRegSizeInBits(*DstRC) == 16) {
1225 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1227 if (RI.getRegSizeInBits(*DstRC) == 32)
1228 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1229 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1230 return AMDGPU::S_MOV_B64;
1231 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1232 return AMDGPU::V_MOV_B64_PSEUDO;
1233 return AMDGPU::COPY;
1238 bool IsIndirectSrc)
const {
1239 if (IsIndirectSrc) {
1241 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1243 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1245 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1247 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1249 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1251 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1253 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1255 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1257 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1259 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1261 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1263 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1265 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1266 if (VecSize <= 1024)
1267 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1273 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1275 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1277 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1279 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1281 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1283 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1285 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1287 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1289 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1291 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1293 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1295 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1297 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1298 if (VecSize <= 1024)
1299 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1306 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1308 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1310 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1312 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1314 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1316 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1318 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1320 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1322 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1324 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1326 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1328 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1330 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1331 if (VecSize <= 1024)
1332 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1339 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1341 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1343 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1345 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1347 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1349 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1351 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1353 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1355 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1357 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1359 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1361 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1363 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1364 if (VecSize <= 1024)
1365 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1372 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1374 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1376 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1378 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1379 if (VecSize <= 1024)
1380 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1387 bool IsSGPR)
const {
1399 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1406 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1408 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1410 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1412 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1413 : AMDGPU::SI_SPILL_S128_SAVE;
1415 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1416 : AMDGPU::SI_SPILL_S160_SAVE;
1418 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1419 : AMDGPU::SI_SPILL_S192_SAVE;
1421 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1422 : AMDGPU::SI_SPILL_S224_SAVE;
1424 return AMDGPU::SI_SPILL_S256_SAVE;
1426 return AMDGPU::SI_SPILL_S288_SAVE;
1428 return AMDGPU::SI_SPILL_S320_SAVE;
1430 return AMDGPU::SI_SPILL_S352_SAVE;
1432 return AMDGPU::SI_SPILL_S384_SAVE;
1434 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1435 : AMDGPU::SI_SPILL_S512_SAVE;
1437 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1438 : AMDGPU::SI_SPILL_S1024_SAVE;
1447 return AMDGPU::SI_SPILL_V16_SAVE;
1449 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1451 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1453 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1455 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1456 : AMDGPU::SI_SPILL_V128_SAVE;
1458 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1459 : AMDGPU::SI_SPILL_V160_SAVE;
1461 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1462 : AMDGPU::SI_SPILL_V192_SAVE;
1464 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1465 : AMDGPU::SI_SPILL_V224_SAVE;
1467 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1468 : AMDGPU::SI_SPILL_V256_SAVE;
1470 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1471 : AMDGPU::SI_SPILL_V288_SAVE;
1473 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1474 : AMDGPU::SI_SPILL_V320_SAVE;
1476 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1477 : AMDGPU::SI_SPILL_V352_SAVE;
1479 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1480 : AMDGPU::SI_SPILL_V384_SAVE;
1482 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1483 : AMDGPU::SI_SPILL_V512_SAVE;
1485 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1486 : AMDGPU::SI_SPILL_V1024_SAVE;
1495 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1496 : AMDGPU::SI_SPILL_AV32_SAVE;
1498 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1499 : AMDGPU::SI_SPILL_AV64_SAVE;
1501 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1502 : AMDGPU::SI_SPILL_AV96_SAVE;
1504 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1505 : AMDGPU::SI_SPILL_AV128_SAVE;
1507 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1508 : AMDGPU::SI_SPILL_AV160_SAVE;
1510 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1511 : AMDGPU::SI_SPILL_AV192_SAVE;
1513 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1514 : AMDGPU::SI_SPILL_AV224_SAVE;
1516 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1517 : AMDGPU::SI_SPILL_AV256_SAVE;
1519 return AMDGPU::SI_SPILL_AV288_SAVE;
1521 return AMDGPU::SI_SPILL_AV320_SAVE;
1523 return AMDGPU::SI_SPILL_AV352_SAVE;
1525 return AMDGPU::SI_SPILL_AV384_SAVE;
1527 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1528 : AMDGPU::SI_SPILL_AV512_SAVE;
1530 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1531 : AMDGPU::SI_SPILL_AV1024_SAVE;
1538 bool IsVectorSuperClass) {
1543 if (IsVectorSuperClass)
1544 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1546 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1552 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1559 if (ST.hasMAIInsts())
1565void SIInstrInfo::storeRegToStackSlotImpl(
1578 FrameInfo.getObjectAlign(FrameIndex));
1579 unsigned SpillSize = RI.getSpillSize(*RC);
1585 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1586 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1587 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1596 if (SrcReg.
isVirtual() && SpillSize == 4) {
1610 SpillSize, *MFI, NeedsCFI);
1625 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1634 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1641 return AMDGPU::SI_SPILL_S32_RESTORE;
1643 return AMDGPU::SI_SPILL_S64_RESTORE;
1645 return AMDGPU::SI_SPILL_S96_RESTORE;
1647 return AMDGPU::SI_SPILL_S128_RESTORE;
1649 return AMDGPU::SI_SPILL_S160_RESTORE;
1651 return AMDGPU::SI_SPILL_S192_RESTORE;
1653 return AMDGPU::SI_SPILL_S224_RESTORE;
1655 return AMDGPU::SI_SPILL_S256_RESTORE;
1657 return AMDGPU::SI_SPILL_S288_RESTORE;
1659 return AMDGPU::SI_SPILL_S320_RESTORE;
1661 return AMDGPU::SI_SPILL_S352_RESTORE;
1663 return AMDGPU::SI_SPILL_S384_RESTORE;
1665 return AMDGPU::SI_SPILL_S512_RESTORE;
1667 return AMDGPU::SI_SPILL_S1024_RESTORE;
1676 return AMDGPU::SI_SPILL_V16_RESTORE;
1678 return AMDGPU::SI_SPILL_V32_RESTORE;
1680 return AMDGPU::SI_SPILL_V64_RESTORE;
1682 return AMDGPU::SI_SPILL_V96_RESTORE;
1684 return AMDGPU::SI_SPILL_V128_RESTORE;
1686 return AMDGPU::SI_SPILL_V160_RESTORE;
1688 return AMDGPU::SI_SPILL_V192_RESTORE;
1690 return AMDGPU::SI_SPILL_V224_RESTORE;
1692 return AMDGPU::SI_SPILL_V256_RESTORE;
1694 return AMDGPU::SI_SPILL_V288_RESTORE;
1696 return AMDGPU::SI_SPILL_V320_RESTORE;
1698 return AMDGPU::SI_SPILL_V352_RESTORE;
1700 return AMDGPU::SI_SPILL_V384_RESTORE;
1702 return AMDGPU::SI_SPILL_V512_RESTORE;
1704 return AMDGPU::SI_SPILL_V1024_RESTORE;
1713 return AMDGPU::SI_SPILL_AV32_RESTORE;
1715 return AMDGPU::SI_SPILL_AV64_RESTORE;
1717 return AMDGPU::SI_SPILL_AV96_RESTORE;
1719 return AMDGPU::SI_SPILL_AV128_RESTORE;
1721 return AMDGPU::SI_SPILL_AV160_RESTORE;
1723 return AMDGPU::SI_SPILL_AV192_RESTORE;
1725 return AMDGPU::SI_SPILL_AV224_RESTORE;
1727 return AMDGPU::SI_SPILL_AV256_RESTORE;
1729 return AMDGPU::SI_SPILL_AV288_RESTORE;
1731 return AMDGPU::SI_SPILL_AV320_RESTORE;
1733 return AMDGPU::SI_SPILL_AV352_RESTORE;
1735 return AMDGPU::SI_SPILL_AV384_RESTORE;
1737 return AMDGPU::SI_SPILL_AV512_RESTORE;
1739 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1746 bool IsVectorSuperClass) {
1751 if (IsVectorSuperClass)
1752 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1754 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1760 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1767 if (ST.hasMAIInsts())
1770 assert(!RI.isAGPRClass(RC));
1784 unsigned SpillSize = RI.getSpillSize(*RC);
1791 FrameInfo.getObjectAlign(FrameIndex));
1793 if (RI.isSGPRClass(RC)) {
1796 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1797 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1798 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1803 if (DestReg.
isVirtual() && SpillSize == 4) {
1832 unsigned Quantity)
const {
1834 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1835 while (Quantity > 0) {
1836 unsigned Arg = std::min(Quantity, MaxSNopCount);
1847 constexpr unsigned DoorbellIDMask = 0x3ff;
1848 constexpr unsigned ECQueueWaveAbort = 0x400;
1853 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1854 MBB.splitAt(
MI,
false);
1858 MBB.addSuccessor(TrapBB);
1868 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1872 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1877 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1878 .
addUse(DoorbellRegMasked)
1879 .
addImm(ECQueueWaveAbort);
1880 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1881 .
addUse(SetWaveAbortBit);
1884 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1895 return MBB.getNextNode();
1899 switch (
MI.getOpcode()) {
1901 if (
MI.isMetaInstruction())
1906 return MI.getOperand(0).getImm() + 1;
1916 switch (
MI.getOpcode()) {
1918 case AMDGPU::S_MOV_B64_term:
1921 MI.setDesc(
get(AMDGPU::S_MOV_B64));
1924 case AMDGPU::S_MOV_B32_term:
1927 MI.setDesc(
get(AMDGPU::S_MOV_B32));
1930 case AMDGPU::S_XOR_B64_term:
1933 MI.setDesc(
get(AMDGPU::S_XOR_B64));
1936 case AMDGPU::S_XOR_B32_term:
1939 MI.setDesc(
get(AMDGPU::S_XOR_B32));
1941 case AMDGPU::S_OR_B64_term:
1944 MI.setDesc(
get(AMDGPU::S_OR_B64));
1946 case AMDGPU::S_OR_B32_term:
1949 MI.setDesc(
get(AMDGPU::S_OR_B32));
1952 case AMDGPU::S_ANDN2_B64_term:
1955 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
1958 case AMDGPU::S_ANDN2_B32_term:
1961 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
1964 case AMDGPU::S_AND_B64_term:
1967 MI.setDesc(
get(AMDGPU::S_AND_B64));
1970 case AMDGPU::S_AND_B32_term:
1973 MI.setDesc(
get(AMDGPU::S_AND_B32));
1976 case AMDGPU::S_AND_SAVEEXEC_B64_term:
1979 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
1982 case AMDGPU::S_AND_SAVEEXEC_B32_term:
1985 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
1988 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
1989 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
1991 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
1992 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
1995 case AMDGPU::SI_SPILL_S32_TO_VGPR:
1996 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
1999 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2000 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2002 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2006 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2009 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2012 int64_t Imm =
MI.getOperand(1).getImm();
2014 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2015 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2020 MI.eraseFromParent();
2026 case AMDGPU::V_MOV_B64_PSEUDO: {
2028 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2029 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2037 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2038 MI.setDesc(Mov64Desc);
2043 if (
SrcOp.isImm()) {
2045 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2046 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2070 if (ST.hasPkMovB32() &&
2089 MI.eraseFromParent();
2092 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2096 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2100 if (ST.has64BitLiterals()) {
2101 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2107 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2112 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2113 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2115 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2116 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2121 MI.eraseFromParent();
2124 case AMDGPU::V_SET_INACTIVE_B32: {
2128 .
add(
MI.getOperand(3))
2129 .
add(
MI.getOperand(4))
2130 .
add(
MI.getOperand(1))
2131 .
add(
MI.getOperand(2))
2132 .
add(
MI.getOperand(5));
2133 MI.eraseFromParent();
2136 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2137 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2138 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2139 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2140 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2141 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2142 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2143 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2144 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2145 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2146 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2147 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2148 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2149 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2150 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2151 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2152 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2153 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2154 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2155 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2156 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2157 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2158 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2159 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2160 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2161 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2162 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2163 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2164 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2165 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2166 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2167 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2168 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2172 if (RI.hasVGPRs(EltRC)) {
2173 Opc = AMDGPU::V_MOVRELD_B32_e32;
2175 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2176 : AMDGPU::S_MOVRELD_B32;
2181 bool IsUndef =
MI.getOperand(1).isUndef();
2182 unsigned SubReg =
MI.getOperand(3).getImm();
2183 assert(VecReg ==
MI.getOperand(1).getReg());
2188 .
add(
MI.getOperand(2))
2192 const int ImpDefIdx =
2194 const int ImpUseIdx = ImpDefIdx + 1;
2196 MI.eraseFromParent();
2199 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2200 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2201 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2202 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2203 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2204 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2205 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2206 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2207 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2208 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2209 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2210 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2211 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2212 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2213 assert(ST.useVGPRIndexMode());
2215 bool IsUndef =
MI.getOperand(1).isUndef();
2224 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2228 .
add(
MI.getOperand(2))
2232 const int ImpDefIdx =
2234 const int ImpUseIdx = ImpDefIdx + 1;
2241 MI.eraseFromParent();
2244 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2245 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2246 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2247 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2248 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2249 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2250 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2251 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2252 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2253 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2254 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2255 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2256 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2257 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2258 assert(ST.useVGPRIndexMode());
2261 bool IsUndef =
MI.getOperand(1).isUndef();
2265 .
add(
MI.getOperand(2))
2278 MI.eraseFromParent();
2281 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2284 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2285 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2304 if (ST.hasGetPCZeroExtension()) {
2308 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2315 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2325 MI.eraseFromParent();
2328 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2338 Op.setOffset(
Op.getOffset() + 4);
2340 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2344 MI.eraseFromParent();
2347 case AMDGPU::ENTER_STRICT_WWM: {
2353 case AMDGPU::ENTER_STRICT_WQM: {
2360 MI.eraseFromParent();
2363 case AMDGPU::EXIT_STRICT_WWM:
2364 case AMDGPU::EXIT_STRICT_WQM: {
2370 case AMDGPU::SI_RETURN: {
2384 MI.eraseFromParent();
2388 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2389 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2390 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2393 case AMDGPU::S_GETPC_B64_pseudo:
2394 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2395 if (ST.hasGetPCZeroExtension()) {
2397 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2406 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2407 assert(ST.hasBF16PackedInsts());
2408 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2419 case AMDGPU::GET_STACK_BASE:
2422 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2429 Register DestReg =
MI.getOperand(0).getReg();
2439 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2440 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2441 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2444 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2447 MI.getNumExplicitOperands());
2465 case AMDGPU::S_MOV_B64:
2466 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2475 if (UsedLanes.
all())
2480 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2481 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2483 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2484 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2486 if (NeedLo && NeedHi)
2490 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2492 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2501 case AMDGPU::S_LOAD_DWORDX16_IMM:
2502 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2515 for (
auto &CandMO :
I->operands()) {
2516 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2524 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2528 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2534 unsigned NewOpcode = -1;
2535 if (SubregSize == 256)
2536 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2537 else if (SubregSize == 128)
2538 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2548 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2553 MI->getOperand(0).setReg(DestReg);
2554 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2558 OffsetMO->
setImm(FinalOffset);
2564 MI->setMemRefs(*MF, NewMMOs);
2577std::pair<MachineInstr*, MachineInstr*>
2579 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2581 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2584 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2585 return std::pair(&
MI,
nullptr);
2596 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2598 if (Dst.isPhysical()) {
2599 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2606 for (
unsigned I = 1;
I <= 2; ++
I) {
2609 if (
SrcOp.isImm()) {
2611 Imm.ashrInPlace(Part * 32);
2612 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2616 if (Src.isPhysical())
2617 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2624 MovDPP.addImm(MO.getImm());
2626 Split[Part] = MovDPP;
2630 if (Dst.isVirtual())
2637 MI.eraseFromParent();
2638 return std::pair(Split[0], Split[1]);
2641std::optional<DestSourcePair>
2643 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2646 return std::nullopt;
2650 AMDGPU::OpName Src0OpName,
2652 AMDGPU::OpName Src1OpName)
const {
2659 "All commutable instructions have both src0 and src1 modifiers");
2661 int Src0ModsVal = Src0Mods->
getImm();
2662 int Src1ModsVal = Src1Mods->
getImm();
2664 Src1Mods->
setImm(Src0ModsVal);
2665 Src0Mods->
setImm(Src1ModsVal);
2674 bool IsKill = RegOp.
isKill();
2676 bool IsUndef = RegOp.
isUndef();
2677 bool IsDebug = RegOp.
isDebug();
2679 if (NonRegOp.
isImm())
2681 else if (NonRegOp.
isFI())
2702 int64_t NonRegVal = NonRegOp1.
getImm();
2705 NonRegOp2.
setImm(NonRegVal);
2712 unsigned OpIdx1)
const {
2717 unsigned Opc =
MI.getOpcode();
2718 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2728 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2731 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2736 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2742 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2757 unsigned Src1Idx)
const {
2758 assert(!NewMI &&
"this should never be used");
2760 unsigned Opc =
MI.getOpcode();
2762 if (CommutedOpcode == -1)
2765 if (Src0Idx > Src1Idx)
2768 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2769 static_cast<int>(Src0Idx) &&
2770 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2771 static_cast<int>(Src1Idx) &&
2772 "inconsistency with findCommutedOpIndices");
2797 Src1, AMDGPU::OpName::src1_modifiers);
2800 AMDGPU::OpName::src1_sel);
2812 unsigned &SrcOpIdx0,
2813 unsigned &SrcOpIdx1)
const {
2818 unsigned &SrcOpIdx0,
2819 unsigned &SrcOpIdx1)
const {
2820 if (!
Desc.isCommutable())
2823 unsigned Opc =
Desc.getOpcode();
2824 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2828 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2832 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2836 int64_t BrOffset)
const {
2853 return MI.getOperand(0).getMBB();
2858 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
2859 MI.getOpcode() == AMDGPU::SI_LOOP)
2871 "new block should be inserted for expanding unconditional branch");
2874 "restore block should be inserted for restoring clobbered registers");
2882 if (ST.useAddPC64Inst()) {
2884 MCCtx.createTempSymbol(
"offset",
true);
2888 MCCtx.createTempSymbol(
"post_addpc",
true);
2889 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
2893 Offset->setVariableValue(OffsetExpr);
2897 assert(RS &&
"RegScavenger required for long branching");
2905 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
2906 ST.hasVALUReadSGPRHazard();
2907 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
2908 if (FlushSGPRWrites)
2916 ApplyHazardWorkarounds();
2919 MCCtx.createTempSymbol(
"post_getpc",
true);
2923 MCCtx.createTempSymbol(
"offset_lo",
true);
2925 MCCtx.createTempSymbol(
"offset_hi",
true);
2928 .
addReg(PCReg, {}, AMDGPU::sub0)
2932 .
addReg(PCReg, {}, AMDGPU::sub1)
2934 ApplyHazardWorkarounds();
2975 if (LongBranchReservedReg) {
2976 RS->enterBasicBlock(
MBB);
2977 Scav = LongBranchReservedReg;
2979 RS->enterBasicBlockEnd(
MBB);
2980 Scav = RS->scavengeRegisterBackwards(
2985 RS->setRegUsed(Scav);
2993 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3010unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3012 case SIInstrInfo::SCC_TRUE:
3013 return AMDGPU::S_CBRANCH_SCC1;
3014 case SIInstrInfo::SCC_FALSE:
3015 return AMDGPU::S_CBRANCH_SCC0;
3016 case SIInstrInfo::VCCNZ:
3017 return AMDGPU::S_CBRANCH_VCCNZ;
3018 case SIInstrInfo::VCCZ:
3019 return AMDGPU::S_CBRANCH_VCCZ;
3020 case SIInstrInfo::EXECNZ:
3021 return AMDGPU::S_CBRANCH_EXECNZ;
3022 case SIInstrInfo::EXECZ:
3023 return AMDGPU::S_CBRANCH_EXECZ;
3029SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3031 case AMDGPU::S_CBRANCH_SCC0:
3033 case AMDGPU::S_CBRANCH_SCC1:
3035 case AMDGPU::S_CBRANCH_VCCNZ:
3037 case AMDGPU::S_CBRANCH_VCCZ:
3039 case AMDGPU::S_CBRANCH_EXECNZ:
3041 case AMDGPU::S_CBRANCH_EXECZ:
3053 bool AllowModify)
const {
3054 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3056 TBB =
I->getOperand(0).getMBB();
3060 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3061 if (Pred == INVALID_BR)
3066 Cond.push_back(
I->getOperand(1));
3070 if (
I ==
MBB.end()) {
3076 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3078 FBB =
I->getOperand(0).getMBB();
3088 bool AllowModify)
const {
3096 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3097 switch (
I->getOpcode()) {
3098 case AMDGPU::S_MOV_B64_term:
3099 case AMDGPU::S_XOR_B64_term:
3100 case AMDGPU::S_OR_B64_term:
3101 case AMDGPU::S_ANDN2_B64_term:
3102 case AMDGPU::S_AND_B64_term:
3103 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3104 case AMDGPU::S_MOV_B32_term:
3105 case AMDGPU::S_XOR_B32_term:
3106 case AMDGPU::S_OR_B32_term:
3107 case AMDGPU::S_ANDN2_B32_term:
3108 case AMDGPU::S_AND_B32_term:
3109 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3110 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3111 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3114 case AMDGPU::SI_ELSE:
3115 case AMDGPU::SI_KILL_I1_TERMINATOR:
3116 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3133 int *BytesRemoved)
const {
3135 unsigned RemovedSize = 0;
3138 if (
MI.isBranch() ||
MI.isReturn()) {
3140 MI.eraseFromParent();
3146 *BytesRemoved = RemovedSize;
3163 int *BytesAdded)
const {
3164 if (!FBB &&
Cond.empty()) {
3168 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3175 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3187 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3205 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3212 if (
Cond.size() != 2) {
3216 if (
Cond[0].isImm()) {
3227 Register FalseReg,
int &CondCycles,
3228 int &TrueCycles,
int &FalseCycles)
const {
3238 CondCycles = TrueCycles = FalseCycles = NumInsts;
3241 return RI.hasVGPRs(RC) && NumInsts <= 6;
3255 if (NumInsts % 2 == 0)
3258 CondCycles = TrueCycles = FalseCycles = NumInsts;
3259 return RI.isSGPRClass(RC);
3270 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3271 if (Pred == VCCZ || Pred == SCC_FALSE) {
3272 Pred =
static_cast<BranchPredicate
>(-Pred);
3278 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3280 if (DstSize == 32) {
3282 if (Pred == SCC_TRUE) {
3297 if (DstSize == 64 && Pred == SCC_TRUE) {
3307 static const int16_t Sub0_15[] = {
3308 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3309 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3310 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3311 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3314 static const int16_t Sub0_15_64[] = {
3315 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3316 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3317 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3318 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3321 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3323 const int16_t *SubIndices = Sub0_15;
3324 int NElts = DstSize / 32;
3328 if (Pred == SCC_TRUE) {
3330 SelOp = AMDGPU::S_CSELECT_B32;
3331 EltRC = &AMDGPU::SGPR_32RegClass;
3333 SelOp = AMDGPU::S_CSELECT_B64;
3334 EltRC = &AMDGPU::SGPR_64RegClass;
3335 SubIndices = Sub0_15_64;
3341 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3346 for (
int Idx = 0; Idx != NElts; ++Idx) {
3350 unsigned SubIdx = SubIndices[Idx];
3353 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3355 .
addReg(FalseReg, {}, SubIdx)
3356 .addReg(TrueReg, {}, SubIdx);
3359 .
addReg(TrueReg, {}, SubIdx)
3360 .addReg(FalseReg, {}, SubIdx);
3373 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3376 switch (
MI.getOpcode()) {
3377 case AMDGPU::S_ENDPGM:
3378 case AMDGPU::S_ENDPGM_SAVED:
3379 case AMDGPU::S_TRAP:
3380 case AMDGPU::S_GETREG_B32:
3381 case AMDGPU::S_SETREG_B32:
3382 case AMDGPU::S_SETREG_B32_mode:
3383 case AMDGPU::S_SETREG_IMM32_B32:
3384 case AMDGPU::S_SETREG_IMM32_B32_mode:
3385 case AMDGPU::S_SENDMSG:
3386 case AMDGPU::S_SENDMSGHALT:
3387 case AMDGPU::S_SENDMSG_RTN_B32:
3388 case AMDGPU::S_SENDMSG_RTN_B64:
3389 case AMDGPU::S_BARRIER_WAIT:
3390 case AMDGPU::S_BARRIER_SIGNAL_M0:
3391 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3392 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3393 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3401 switch (
MI.getOpcode()) {
3402 case AMDGPU::V_MOV_B16_t16_e32:
3403 case AMDGPU::V_MOV_B16_t16_e64:
3404 case AMDGPU::V_MOV_B32_e32:
3405 case AMDGPU::V_MOV_B32_e64:
3406 case AMDGPU::V_MOV_B64_PSEUDO:
3407 case AMDGPU::V_MOV_B64_e32:
3408 case AMDGPU::V_MOV_B64_e64:
3409 case AMDGPU::S_MOV_B32:
3410 case AMDGPU::S_MOV_B64:
3411 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3413 case AMDGPU::WWM_COPY:
3414 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3415 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3416 case AMDGPU::V_ACCVGPR_MOV_B32:
3417 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3418 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3426 switch (
MI.getOpcode()) {
3427 case AMDGPU::V_MOV_B16_t16_e32:
3428 case AMDGPU::V_MOV_B16_t16_e64:
3430 case AMDGPU::V_MOV_B32_e32:
3431 case AMDGPU::V_MOV_B32_e64:
3432 case AMDGPU::V_MOV_B64_PSEUDO:
3433 case AMDGPU::V_MOV_B64_e32:
3434 case AMDGPU::V_MOV_B64_e64:
3435 case AMDGPU::S_MOV_B32:
3436 case AMDGPU::S_MOV_B64:
3437 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3439 case AMDGPU::WWM_COPY:
3440 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3441 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3442 case AMDGPU::V_ACCVGPR_MOV_B32:
3443 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3444 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3452 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3453 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3454 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3457 unsigned Opc =
MI.getOpcode();
3459 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3461 MI.removeOperand(Idx);
3467 MI.setDesc(NewDesc);
3473 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3474 Desc.implicit_defs().size();
3476 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3477 MI.removeOperand(
I);
3481 unsigned SubRegIndex) {
3482 switch (SubRegIndex) {
3483 case AMDGPU::NoSubRegister:
3493 case AMDGPU::sub1_lo16:
3495 case AMDGPU::sub1_hi16:
3498 return std::nullopt;
3506 case AMDGPU::V_MAC_F16_e32:
3507 case AMDGPU::V_MAC_F16_e64:
3508 case AMDGPU::V_MAD_F16_e64:
3509 return AMDGPU::V_MADAK_F16;
3510 case AMDGPU::V_MAC_F32_e32:
3511 case AMDGPU::V_MAC_F32_e64:
3512 case AMDGPU::V_MAD_F32_e64:
3513 return AMDGPU::V_MADAK_F32;
3514 case AMDGPU::V_FMAC_F32_e32:
3515 case AMDGPU::V_FMAC_F32_e64:
3516 case AMDGPU::V_FMA_F32_e64:
3517 return AMDGPU::V_FMAAK_F32;
3518 case AMDGPU::V_FMAC_F16_e32:
3519 case AMDGPU::V_FMAC_F16_e64:
3520 case AMDGPU::V_FMAC_F16_t16_e64:
3521 case AMDGPU::V_FMAC_F16_fake16_e64:
3522 case AMDGPU::V_FMAC_F16_t16_e32:
3523 case AMDGPU::V_FMAC_F16_fake16_e32:
3524 case AMDGPU::V_FMA_F16_e64:
3525 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3526 ? AMDGPU::V_FMAAK_F16_t16
3527 : AMDGPU::V_FMAAK_F16_fake16
3528 : AMDGPU::V_FMAAK_F16;
3529 case AMDGPU::V_FMAC_F64_e32:
3530 case AMDGPU::V_FMAC_F64_e64:
3531 case AMDGPU::V_FMA_F64_e64:
3532 return AMDGPU::V_FMAAK_F64;
3540 case AMDGPU::V_MAC_F16_e32:
3541 case AMDGPU::V_MAC_F16_e64:
3542 case AMDGPU::V_MAD_F16_e64:
3543 return AMDGPU::V_MADMK_F16;
3544 case AMDGPU::V_MAC_F32_e32:
3545 case AMDGPU::V_MAC_F32_e64:
3546 case AMDGPU::V_MAD_F32_e64:
3547 return AMDGPU::V_MADMK_F32;
3548 case AMDGPU::V_FMAC_F32_e32:
3549 case AMDGPU::V_FMAC_F32_e64:
3550 case AMDGPU::V_FMA_F32_e64:
3551 return AMDGPU::V_FMAMK_F32;
3552 case AMDGPU::V_FMAC_F16_e32:
3553 case AMDGPU::V_FMAC_F16_e64:
3554 case AMDGPU::V_FMAC_F16_t16_e64:
3555 case AMDGPU::V_FMAC_F16_fake16_e64:
3556 case AMDGPU::V_FMAC_F16_t16_e32:
3557 case AMDGPU::V_FMAC_F16_fake16_e32:
3558 case AMDGPU::V_FMA_F16_e64:
3559 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3560 ? AMDGPU::V_FMAMK_F16_t16
3561 : AMDGPU::V_FMAMK_F16_fake16
3562 : AMDGPU::V_FMAMK_F16;
3563 case AMDGPU::V_FMAC_F64_e32:
3564 case AMDGPU::V_FMAC_F64_e64:
3565 case AMDGPU::V_FMA_F64_e64:
3566 return AMDGPU::V_FMAMK_F64;
3580 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3583 if (
Opc == AMDGPU::COPY) {
3584 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3591 if (HasMultipleUses) {
3594 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3597 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3605 if (ImmDefSize == 32 &&
3610 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3611 RI.getSubRegIdxSize(UseSubReg) == 16;
3614 if (RI.hasVGPRs(DstRC))
3617 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3623 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3630 for (
unsigned MovOp :
3631 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3632 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3640 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3644 if (MovDstPhysReg) {
3648 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3655 if (MovDstPhysReg) {
3656 if (!MovDstRC->
contains(MovDstPhysReg))
3672 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3680 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3684 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3686 UseMI.getOperand(0).setReg(MovDstPhysReg);
3691 UseMI.setDesc(NewMCID);
3692 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3693 UseMI.addImplicitDefUseOperands(*MF);
3697 if (HasMultipleUses)
3700 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3701 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3702 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3703 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3704 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3705 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3706 Opc == AMDGPU::V_FMAC_F64_e64) {
3715 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3726 auto CopyRegOperandToNarrowerRC =
3729 if (!
MI.getOperand(OpNo).isReg())
3733 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3736 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3737 get(AMDGPU::COPY), Tmp)
3739 MI.getOperand(OpNo).setReg(Tmp);
3740 MI.getOperand(OpNo).setIsKill();
3747 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3748 if (!RegSrc->
isReg())
3751 ST.getConstantBusLimit(
Opc) < 2)
3766 if (Def && Def->isMoveImmediate() &&
3781 unsigned SrcSubReg = RegSrc->
getSubReg();
3786 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3787 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3788 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3789 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3790 UseMI.untieRegOperand(
3791 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3798 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3799 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3803 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3804 UseMI.getOperand(0).getReg())
3806 UseMI.getOperand(0).setReg(Tmp);
3807 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3808 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
3813 DefMI.eraseFromParent();
3820 if (ST.getConstantBusLimit(
Opc) < 2) {
3823 bool Src0Inlined =
false;
3824 if (Src0->
isReg()) {
3829 if (Def && Def->isMoveImmediate() &&
3834 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
3835 RI.isSGPRReg(*MRI, Src0->
getReg())) {
3841 if (Src1->
isReg() && !Src0Inlined) {
3844 if (Def && Def->isMoveImmediate() &&
3848 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
3861 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3862 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3863 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3864 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3865 UseMI.untieRegOperand(
3866 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3868 const std::optional<int64_t> SubRegImm =
3878 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
3879 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
3883 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3884 UseMI.getOperand(0).getReg())
3886 UseMI.getOperand(0).setReg(Tmp);
3887 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3888 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
3898 DefMI.eraseFromParent();
3910 if (BaseOps1.
size() != BaseOps2.
size())
3912 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
3913 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
3921 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
3922 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
3923 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3925 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
3928bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
3931 int64_t Offset0, Offset1;
3934 bool Offset0IsScalable, Offset1IsScalable;
3948 LocationSize Width0 = MIa.
memoperands().front()->getSize();
3949 LocationSize Width1 = MIb.
memoperands().front()->getSize();
3956 "MIa must load from or modify a memory location");
3958 "MIb must load from or modify a memory location");
3980 return checkInstOffsetsDoNotOverlap(MIa, MIb);
3987 return checkInstOffsetsDoNotOverlap(MIa, MIb);
3997 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4011 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4022 if (
Reg.isPhysical())
4026 Imm = Def->getOperand(1).getImm();
4046 unsigned NumOps =
MI.getNumOperands();
4049 if (
Op.isReg() &&
Op.isKill())
4057 case AMDGPU::V_MAC_F16_e32:
4058 case AMDGPU::V_MAC_F16_e64:
4059 return AMDGPU::V_MAD_F16_e64;
4060 case AMDGPU::V_MAC_F32_e32:
4061 case AMDGPU::V_MAC_F32_e64:
4062 return AMDGPU::V_MAD_F32_e64;
4063 case AMDGPU::V_MAC_LEGACY_F32_e32:
4064 case AMDGPU::V_MAC_LEGACY_F32_e64:
4065 return AMDGPU::V_MAD_LEGACY_F32_e64;
4066 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4067 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4068 return AMDGPU::V_FMA_LEGACY_F32_e64;
4069 case AMDGPU::V_FMAC_F16_e32:
4070 case AMDGPU::V_FMAC_F16_e64:
4071 case AMDGPU::V_FMAC_F16_t16_e64:
4072 case AMDGPU::V_FMAC_F16_fake16_e64:
4073 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4074 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4075 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4076 : AMDGPU::V_FMA_F16_gfx9_e64;
4077 case AMDGPU::V_FMAC_F32_e32:
4078 case AMDGPU::V_FMAC_F32_e64:
4079 return AMDGPU::V_FMA_F32_e64;
4080 case AMDGPU::V_FMAC_F64_e32:
4081 case AMDGPU::V_FMAC_F64_e64:
4082 return AMDGPU::V_FMA_F64_e64;
4102 if (
MI.isBundle()) {
4105 if (
MI.getBundleSize() != 1)
4107 CandidateMI =
MI.getNextNode();
4111 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4115 if (
MI.isBundle()) {
4120 MI.untieRegOperand(MO.getOperandNo());
4128 if (Def.isEarlyClobber() && Def.isReg() &&
4133 auto UpdateDefIndex = [&](
LiveRange &LR) {
4134 auto *S = LR.find(OldIndex);
4135 if (S != LR.end() && S->start == OldIndex) {
4136 assert(S->valno && S->valno->def == OldIndex);
4137 S->start = NewIndex;
4138 S->valno->def = NewIndex;
4142 for (
auto &SR : LI.subranges())
4148 if (U.RemoveMIUse) {
4151 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4155 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4156 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4157 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4158 U.RemoveMIUse->removeOperand(
I);
4163 if (
MI.isBundle()) {
4167 if (MO.isReg() && MO.getReg() == DefReg) {
4168 assert(MO.getSubReg() == 0 &&
4169 "tied sub-registers in bundles currently not supported");
4170 MI.removeOperand(MO.getOperandNo());
4187 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4188 MIOp.setIsUndef(
true);
4189 MIOp.setReg(DummyReg);
4193 if (
MI.isBundle()) {
4197 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4198 MIOp.setIsUndef(
true);
4199 MIOp.setReg(DummyReg);
4212 return MI.isBundle() ? &
MI : NewMI;
4217 ThreeAddressUpdates &U)
const {
4219 unsigned Opc =
MI.getOpcode();
4223 if (NewMFMAOpc != -1) {
4226 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4227 MIB.
add(
MI.getOperand(
I));
4235 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4240 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4241 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4242 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4246 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4247 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4248 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4249 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4250 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4251 bool Src0Literal =
false;
4256 case AMDGPU::V_MAC_F16_e64:
4257 case AMDGPU::V_FMAC_F16_e64:
4258 case AMDGPU::V_FMAC_F16_t16_e64:
4259 case AMDGPU::V_FMAC_F16_fake16_e64:
4260 case AMDGPU::V_MAC_F32_e64:
4261 case AMDGPU::V_MAC_LEGACY_F32_e64:
4262 case AMDGPU::V_FMAC_F32_e64:
4263 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4264 case AMDGPU::V_FMAC_F64_e64:
4266 case AMDGPU::V_MAC_F16_e32:
4267 case AMDGPU::V_FMAC_F16_e32:
4268 case AMDGPU::V_MAC_F32_e32:
4269 case AMDGPU::V_MAC_LEGACY_F32_e32:
4270 case AMDGPU::V_FMAC_F32_e32:
4271 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4272 case AMDGPU::V_FMAC_F64_e32: {
4273 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4274 AMDGPU::OpName::src0);
4275 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4286 MachineInstrBuilder MIB;
4289 const MachineOperand *Src0Mods =
4292 const MachineOperand *Src1Mods =
4295 const MachineOperand *Src2Mods =
4301 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4302 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4304 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4306 MachineInstr *
DefMI =
nullptr;
4342 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4358 if (Src0Literal && !ST.hasVOP3Literal())
4386 switch (
MI.getOpcode()) {
4387 case AMDGPU::S_SET_GPR_IDX_ON:
4388 case AMDGPU::S_SET_GPR_IDX_MODE:
4389 case AMDGPU::S_SET_GPR_IDX_OFF:
4407 if (
MI.isTerminator() ||
MI.isPosition())
4411 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4414 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4420 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4421 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4422 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4423 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4424 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4429 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4430 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4431 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4445 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4450 if (
MI.memoperands_empty())
4455 unsigned AS = Memop->getAddrSpace();
4456 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4457 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4458 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4459 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4474 if (
MI.memoperands_empty())
4483 unsigned AS = Memop->getAddrSpace();
4493 bool TgSplit)
const {
4506 if (
MI.memoperands_empty())
4511 unsigned AS = Memop->getAddrSpace();
4527 unsigned Opcode =
MI.getOpcode();
4542 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4543 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4544 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4545 Opcode == AMDGPU::S_SETHALT)
4548 if (
MI.isCall() ||
MI.isInlineAsm())
4564 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4565 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4566 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4567 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4575 if (
MI.isMetaInstruction())
4579 if (
MI.isCopyLike()) {
4580 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4584 return MI.readsRegister(AMDGPU::EXEC, &RI);
4595 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4599 switch (Imm.getBitWidth()) {
4605 ST.hasInv2PiInlineImm());
4608 ST.hasInv2PiInlineImm());
4610 return ST.has16BitInsts() &&
4612 ST.hasInv2PiInlineImm());
4619 APInt IntImm = Imm.bitcastToAPInt();
4621 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4629 return ST.has16BitInsts() &&
4632 return ST.has16BitInsts() &&
4642 switch (OperandType) {
4652 int32_t Trunc =
static_cast<int32_t
>(Imm);
4696 int16_t Trunc =
static_cast<int16_t
>(Imm);
4697 return ST.has16BitInsts() &&
4706 int16_t Trunc =
static_cast<int16_t
>(Imm);
4707 return ST.has16BitInsts() &&
4758 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4764 return ST.hasVOP3Literal();
4768 int64_t ImmVal)
const {
4770 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4771 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4772 OpNo ==
static_cast<unsigned>(Src1Idx))
4777 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4778 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4779 AMDGPU::OpName::src2))
4781 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4793 "unexpected imm-like operand kind");
4806 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4824 AMDGPU::OpName
OpName)
const {
4826 return Mods && Mods->
getImm();
4839 switch (
MI.getOpcode()) {
4840 default:
return false;
4842 case AMDGPU::V_ADDC_U32_e64:
4843 case AMDGPU::V_SUBB_U32_e64:
4844 case AMDGPU::V_SUBBREV_U32_e64: {
4847 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
4852 case AMDGPU::V_MAC_F16_e64:
4853 case AMDGPU::V_MAC_F32_e64:
4854 case AMDGPU::V_MAC_LEGACY_F32_e64:
4855 case AMDGPU::V_FMAC_F16_e64:
4856 case AMDGPU::V_FMAC_F16_t16_e64:
4857 case AMDGPU::V_FMAC_F16_fake16_e64:
4858 case AMDGPU::V_FMAC_F32_e64:
4859 case AMDGPU::V_FMAC_F64_e64:
4860 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4861 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
4866 case AMDGPU::V_CNDMASK_B32_e64:
4872 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
4902 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
4911 unsigned Op32)
const {
4925 Inst32.
add(
MI.getOperand(
I));
4929 int Idx =
MI.getNumExplicitDefs();
4931 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
4936 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
4958 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
4966 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
4969 return AMDGPU::SReg_32RegClass.contains(Reg) ||
4970 AMDGPU::SReg_64RegClass.contains(Reg);
4998 switch (MO.getReg()) {
5000 case AMDGPU::VCC_LO:
5001 case AMDGPU::VCC_HI:
5003 case AMDGPU::FLAT_SCR:
5016 switch (
MI.getOpcode()) {
5017 case AMDGPU::V_READLANE_B32:
5018 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5019 case AMDGPU::V_WRITELANE_B32:
5020 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5027 if (
MI.isPreISelOpcode() ||
5028 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5046 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5057 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5058 ErrInfo =
"illegal copy from vector register to SGPR";
5076 if (!MRI.
isSSA() &&
MI.isCopy())
5077 return verifyCopy(
MI, MRI, ErrInfo);
5079 if (SIInstrInfo::isGenericOpcode(Opcode))
5082 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5083 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5084 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5086 if (Src0Idx == -1) {
5088 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5089 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5090 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5091 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5096 if (!
Desc.isVariadic() &&
5097 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5098 ErrInfo =
"Instruction has wrong number of operands.";
5102 if (
MI.isInlineAsm()) {
5115 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5116 ErrInfo =
"inlineasm operand has incorrect register class.";
5124 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5125 ErrInfo =
"missing memory operand from image instruction.";
5130 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5133 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5134 "all fp values to integers.";
5139 int16_t RegClass = getOpRegClassID(OpInfo);
5141 switch (OpInfo.OperandType) {
5143 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5144 ErrInfo =
"Illegal immediate value for operand.";
5177 ErrInfo =
"Illegal immediate value for operand.";
5186 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5189 OpInfo.OperandType ==
5191 ErrInfo =
"illegal 64-bit immediate value for operand.";
5198 ErrInfo =
"Expected inline constant for operand.";
5212 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5213 ErrInfo =
"Expected immediate, but got non-immediate";
5222 if (OpInfo.isGenericType())
5237 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5238 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5240 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5242 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5243 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5250 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5251 ErrInfo =
"Subtarget requires even aligned vector registers";
5256 if (RegClass != -1) {
5257 if (Reg.isVirtual())
5262 ErrInfo =
"Operand has incorrect register class.";
5270 if (!ST.hasSDWA()) {
5271 ErrInfo =
"SDWA is not supported on this target";
5275 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5276 AMDGPU::OpName::dst_sel}) {
5280 int64_t Imm = MO->
getImm();
5282 ErrInfo =
"Invalid SDWA selection";
5287 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5289 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5294 if (!ST.hasSDWAScalar()) {
5296 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5297 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5304 "Only reg allowed as operands in SDWA instructions on GFX9+";
5310 if (!ST.hasSDWAOmod()) {
5313 if (OMod !=
nullptr &&
5315 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5320 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5321 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5322 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5323 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5326 unsigned Mods = Src0ModsMO->
getImm();
5329 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5335 if (
isVOPC(BasicOpcode)) {
5336 if (!ST.hasSDWASdst() && DstIdx != -1) {
5339 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5340 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5343 }
else if (!ST.hasSDWAOutModsVOPC()) {
5346 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5347 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5353 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5354 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5361 if (DstUnused && DstUnused->isImm() &&
5364 if (!Dst.isReg() || !Dst.isTied()) {
5365 ErrInfo =
"Dst register should have tied register";
5370 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5373 "Dst register should be tied to implicit use of preserved register";
5377 ErrInfo =
"Dst register should use same physical register as preserved";
5383 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5385 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5386 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5389 if (Src1MO.
isImm()) {
5390 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5396 if (
isImage(Opcode) && !
MI.mayStore()) {
5408 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5416 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5420 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5421 if (RegCount > DstSize) {
5422 ErrInfo =
"Image instruction returns too many registers for dst "
5432 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5433 unsigned ConstantBusCount = 0;
5434 bool UsesLiteral =
false;
5437 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5441 LiteralVal = &
MI.getOperand(ImmIdx);
5450 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5461 }
else if (!MO.
isFI()) {
5468 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5478 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5479 return !RI.regsOverlap(SGPRUsed, SGPR);
5488 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5489 Opcode != AMDGPU::V_WRITELANE_B32) {
5490 ErrInfo =
"VOP* instruction violates constant bus restriction";
5494 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5495 ErrInfo =
"VOP3 instruction uses literal";
5502 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5503 unsigned SGPRCount = 0;
5506 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5514 if (MO.
getReg() != SGPRUsed)
5519 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5520 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5527 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5528 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5535 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5545 ErrInfo =
"ABS not allowed in VOP3B instructions";
5558 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5565 if (
Desc.isBranch()) {
5567 ErrInfo =
"invalid branch target for SOPK instruction";
5574 ErrInfo =
"invalid immediate for SOPK instruction";
5579 ErrInfo =
"invalid immediate for SOPK instruction";
5586 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5587 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5588 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5589 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5590 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5591 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5593 const unsigned StaticNumOps =
5594 Desc.getNumOperands() +
Desc.implicit_uses().size();
5595 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5601 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5602 ErrInfo =
"missing implicit register operands";
5608 if (!Dst->isUse()) {
5609 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5614 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5615 UseOpIdx != StaticNumOps + 1) {
5616 ErrInfo =
"movrel implicit operands should be tied";
5623 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5625 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5626 ErrInfo =
"src0 should be subreg of implicit vector use";
5634 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5635 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5641 if (
MI.mayStore() &&
5646 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5647 ErrInfo =
"scalar stores must use m0 as offset register";
5653 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5655 if (
Offset->getImm() != 0) {
5656 ErrInfo =
"subtarget does not support offsets in flat instructions";
5661 if (
isDS(
MI) && !ST.hasGDS()) {
5663 if (GDSOp && GDSOp->
getImm() != 0) {
5664 ErrInfo =
"GDS is not supported on this subtarget";
5672 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5673 AMDGPU::OpName::vaddr0);
5674 AMDGPU::OpName RSrcOpName =
5675 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5676 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5684 ErrInfo =
"dim is out of range";
5689 if (ST.hasR128A16()) {
5691 IsA16 = R128A16->
getImm() != 0;
5692 }
else if (ST.hasA16()) {
5694 IsA16 = A16->
getImm() != 0;
5697 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5699 unsigned AddrWords =
5702 unsigned VAddrWords;
5704 VAddrWords = RsrcIdx - VAddr0Idx;
5705 if (ST.hasPartialNSAEncoding() &&
5707 unsigned LastVAddrIdx = RsrcIdx - 1;
5708 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5716 if (VAddrWords != AddrWords) {
5718 <<
" but got " << VAddrWords <<
"\n");
5719 ErrInfo =
"bad vaddr size";
5729 unsigned DC = DppCt->
getImm();
5730 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5731 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5732 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5733 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5734 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5735 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5736 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5737 ErrInfo =
"Invalid dpp_ctrl value";
5740 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5741 !ST.hasDPPWavefrontShifts()) {
5742 ErrInfo =
"Invalid dpp_ctrl value: "
5743 "wavefront shifts are not supported on GFX10+";
5746 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5747 !ST.hasDPPBroadcasts()) {
5748 ErrInfo =
"Invalid dpp_ctrl value: "
5749 "broadcasts are not supported on GFX10+";
5752 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5754 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5755 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5756 !ST.hasGFX90AInsts()) {
5757 ErrInfo =
"Invalid dpp_ctrl value: "
5758 "row_newbroadcast/row_share is not supported before "
5762 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5763 ErrInfo =
"Invalid dpp_ctrl value: "
5764 "row_share and row_xmask are not supported before GFX10";
5769 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5772 ErrInfo =
"Invalid dpp_ctrl value: "
5773 "DP ALU dpp only support row_newbcast";
5780 AMDGPU::OpName DataName =
5781 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5787 if (ST.hasGFX90AInsts()) {
5788 if (Dst &&
Data && !Dst->isTied() && !
Data->isTied() &&
5789 (RI.isAGPR(MRI, Dst->getReg()) != RI.isAGPR(MRI,
Data->getReg()))) {
5790 ErrInfo =
"Invalid register class: "
5791 "vdata and vdst should be both VGPR or AGPR";
5794 if (
Data && Data2 &&
5795 (RI.isAGPR(MRI,
Data->getReg()) != RI.isAGPR(MRI, Data2->
getReg()))) {
5796 ErrInfo =
"Invalid register class: "
5797 "both data operands should be VGPR or AGPR";
5801 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5802 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
5803 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
5804 ErrInfo =
"Invalid register class: "
5805 "agpr loads and stores not supported on this GPU";
5811 if (ST.needsAlignedVGPRs()) {
5812 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
5817 if (Reg.isPhysical())
5818 return !(RI.getHWRegIndex(Reg) & 1);
5820 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5821 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
5824 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5825 Opcode == AMDGPU::DS_GWS_BARRIER) {
5827 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5828 ErrInfo =
"Subtarget requires even aligned vector registers "
5829 "for DS_GWS instructions";
5835 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5836 ErrInfo =
"Subtarget requires even aligned vector registers "
5837 "for vaddr operand of image instructions";
5843 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5845 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5846 ErrInfo =
"Invalid register class: "
5847 "v_accvgpr_write with an SGPR is not supported on this GPU";
5852 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5855 ErrInfo =
"pseudo expects only physical SGPRs";
5862 if (!ST.hasScaleOffset()) {
5863 ErrInfo =
"Subtarget does not support offset scaling";
5867 ErrInfo =
"Instruction does not support offset scaling";
5876 for (
unsigned I = 0;
I < 3; ++
I) {
5882 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
5883 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
5885 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
5886 &AMDGPU::SReg_64RegClass) ||
5887 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
5888 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
5897 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
5899 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
5901 : AMDGPU::V_MOV_B32_e32;
5911 default:
return AMDGPU::INSTRUCTION_LIST_END;
5912 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
5913 case AMDGPU::COPY:
return AMDGPU::COPY;
5914 case AMDGPU::PHI:
return AMDGPU::PHI;
5915 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
5916 case AMDGPU::WQM:
return AMDGPU::WQM;
5917 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
5918 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
5919 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
5920 case AMDGPU::S_ADD_I32:
5921 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
5922 case AMDGPU::S_ADDC_U32:
5923 return AMDGPU::V_ADDC_U32_e32;
5924 case AMDGPU::S_SUB_I32:
5925 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
5928 case AMDGPU::S_ADD_U32:
5929 return AMDGPU::V_ADD_CO_U32_e32;
5930 case AMDGPU::S_SUB_U32:
5931 return AMDGPU::V_SUB_CO_U32_e32;
5932 case AMDGPU::S_ADD_U64_PSEUDO:
5933 return AMDGPU::V_ADD_U64_PSEUDO;
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 return AMDGPU::V_SUB_U64_PSEUDO;
5936 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
5937 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
5938 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
5939 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
5940 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
5941 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
5942 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
5943 case AMDGPU::S_XNOR_B32:
5944 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
5945 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
5946 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
5947 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
5948 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
5949 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
5950 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
5951 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
5952 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
5953 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
5954 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
5955 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
5956 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
5957 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
5958 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
5959 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
5960 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
5961 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
5962 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
5963 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
5964 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
5965 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
5966 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
5967 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
5968 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
5969 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
5970 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
5971 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
5972 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
5973 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
5974 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
5975 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
5976 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
5977 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
5978 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
5979 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
5980 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
5981 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
5982 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
5983 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
5984 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
5985 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
5986 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
5987 case AMDGPU::S_CVT_F32_F16:
5988 case AMDGPU::S_CVT_HI_F32_F16:
5989 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
5990 : AMDGPU::V_CVT_F32_F16_fake16_e64;
5991 case AMDGPU::S_CVT_F16_F32:
5992 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
5993 : AMDGPU::V_CVT_F16_F32_fake16_e64;
5994 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
5995 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
5996 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
5997 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
5998 case AMDGPU::S_CEIL_F16:
5999 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6000 : AMDGPU::V_CEIL_F16_fake16_e64;
6001 case AMDGPU::S_FLOOR_F16:
6002 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6003 : AMDGPU::V_FLOOR_F16_fake16_e64;
6004 case AMDGPU::S_TRUNC_F16:
6005 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6006 : AMDGPU::V_TRUNC_F16_fake16_e64;
6007 case AMDGPU::S_RNDNE_F16:
6008 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6009 : AMDGPU::V_RNDNE_F16_fake16_e64;
6010 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6011 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6012 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6013 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6014 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6015 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6016 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6017 case AMDGPU::S_ADD_F16:
6018 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6019 : AMDGPU::V_ADD_F16_fake16_e64;
6020 case AMDGPU::S_SUB_F16:
6021 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6022 : AMDGPU::V_SUB_F16_fake16_e64;
6023 case AMDGPU::S_MIN_F16:
6024 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6025 : AMDGPU::V_MIN_F16_fake16_e64;
6026 case AMDGPU::S_MAX_F16:
6027 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6028 : AMDGPU::V_MAX_F16_fake16_e64;
6029 case AMDGPU::S_MINIMUM_F16:
6030 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6031 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6032 case AMDGPU::S_MAXIMUM_F16:
6033 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6034 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6035 case AMDGPU::S_MUL_F16:
6036 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6037 : AMDGPU::V_MUL_F16_fake16_e64;
6038 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6039 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6040 case AMDGPU::S_FMAC_F16:
6041 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6042 : AMDGPU::V_FMAC_F16_fake16_e64;
6043 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6044 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6045 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6046 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6047 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6048 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6049 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6050 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6051 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6052 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6053 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6054 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6055 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6056 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6057 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6058 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6059 case AMDGPU::S_CMP_LT_F16:
6060 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6061 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6062 case AMDGPU::S_CMP_EQ_F16:
6063 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6064 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6065 case AMDGPU::S_CMP_LE_F16:
6066 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6067 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6068 case AMDGPU::S_CMP_GT_F16:
6069 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6070 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6071 case AMDGPU::S_CMP_LG_F16:
6072 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6073 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6074 case AMDGPU::S_CMP_GE_F16:
6075 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6076 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6077 case AMDGPU::S_CMP_O_F16:
6078 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6079 : AMDGPU::V_CMP_O_F16_fake16_e64;
6080 case AMDGPU::S_CMP_U_F16:
6081 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6082 : AMDGPU::V_CMP_U_F16_fake16_e64;
6083 case AMDGPU::S_CMP_NGE_F16:
6084 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6085 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6086 case AMDGPU::S_CMP_NLG_F16:
6087 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6088 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6089 case AMDGPU::S_CMP_NGT_F16:
6090 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6091 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6092 case AMDGPU::S_CMP_NLE_F16:
6093 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6094 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6095 case AMDGPU::S_CMP_NEQ_F16:
6096 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6097 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6098 case AMDGPU::S_CMP_NLT_F16:
6099 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6100 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6101 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6102 case AMDGPU::V_S_EXP_F16_e64:
6103 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6104 : AMDGPU::V_EXP_F16_fake16_e64;
6105 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6106 case AMDGPU::V_S_LOG_F16_e64:
6107 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6108 : AMDGPU::V_LOG_F16_fake16_e64;
6109 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6110 case AMDGPU::V_S_RCP_F16_e64:
6111 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6112 : AMDGPU::V_RCP_F16_fake16_e64;
6113 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6114 case AMDGPU::V_S_RSQ_F16_e64:
6115 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6116 : AMDGPU::V_RSQ_F16_fake16_e64;
6117 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6118 case AMDGPU::V_S_SQRT_F16_e64:
6119 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6120 : AMDGPU::V_SQRT_F16_fake16_e64;
6123 "Unexpected scalar opcode without corresponding vector one!");
6172 "Not a whole wave func");
6175 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6176 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6183 unsigned OpNo)
const {
6185 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6186 Desc.operands()[OpNo].RegClass == -1) {
6189 if (Reg.isVirtual()) {
6193 return RI.getPhysRegBaseClass(Reg);
6196 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6197 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6205 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[
OpIdx]);
6207 unsigned Size = RI.getRegSizeInBits(*RC);
6208 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6209 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6210 : AMDGPU::V_MOV_B32_e32;
6212 Opcode = AMDGPU::COPY;
6213 else if (RI.isSGPRClass(RC))
6214 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6228 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6234 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6245 if (SubIdx == AMDGPU::sub0)
6247 if (SubIdx == AMDGPU::sub1)
6259void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6275 if (Reg.isPhysical())
6285 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6288 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6295 unsigned Opc =
MI.getOpcode();
6301 constexpr AMDGPU::OpName OpNames[] = {
6302 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6305 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6306 if (
static_cast<unsigned>(SrcIdx) ==
OpIdx &&
6316 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6317 if (IsAGPR && !ST.hasMAIInsts())
6323 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6324 const int DataIdx = AMDGPU::getNamedOperandIdx(
6325 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6326 if ((
int)
OpIdx == VDstIdx && DataIdx != -1 &&
6327 MI.getOperand(DataIdx).isReg() &&
6328 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6330 if ((
int)
OpIdx == DataIdx) {
6331 if (VDstIdx != -1 &&
6332 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6335 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6336 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6337 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6342 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6343 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6344 RI.isSGPRReg(MRI, MO.
getReg()))
6347 if (ST.hasFlatScratchHiInB64InstHazard() &&
6354 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6357 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6358 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6378 constexpr unsigned NumOps = 3;
6379 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6380 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6381 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6382 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6387 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6390 MO = &
MI.getOperand(SrcIdx);
6393 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6397 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6401 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6405 return !OpSel && !OpSelHi;
6414 int64_t RegClass = getOpRegClassID(OpInfo);
6416 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6422 if (
isVALU(
MI,
true) && !IsInlineConst &&
6426 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6427 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6431 if (!LiteralLimit--)
6441 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6449 if (--ConstantBusLimit <= 0)
6461 if (!LiteralLimit--)
6463 if (--ConstantBusLimit <= 0)
6469 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6473 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6475 !
Op.isIdenticalTo(*MO))
6485 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6500 bool Is64BitOp = Is64BitFPOp ||
6508 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6517 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6535 bool IsGFX950Only = ST.hasGFX950Insts();
6536 bool IsGFX940Only = ST.hasGFX940Insts();
6538 if (!IsGFX950Only && !IsGFX940Only)
6556 unsigned Opcode =
MI.getOpcode();
6558 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6559 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6560 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6561 case AMDGPU::V_MQSAD_U32_U8_e64:
6562 case AMDGPU::V_PK_ADD_F16:
6563 case AMDGPU::V_PK_ADD_F32:
6564 case AMDGPU::V_PK_ADD_I16:
6565 case AMDGPU::V_PK_ADD_U16:
6566 case AMDGPU::V_PK_ASHRREV_I16:
6567 case AMDGPU::V_PK_FMA_F16:
6568 case AMDGPU::V_PK_FMA_F32:
6569 case AMDGPU::V_PK_FMAC_F16_e32:
6570 case AMDGPU::V_PK_FMAC_F16_e64:
6571 case AMDGPU::V_PK_LSHLREV_B16:
6572 case AMDGPU::V_PK_LSHRREV_B16:
6573 case AMDGPU::V_PK_MAD_I16:
6574 case AMDGPU::V_PK_MAD_U16:
6575 case AMDGPU::V_PK_MAX_F16:
6576 case AMDGPU::V_PK_MAX_I16:
6577 case AMDGPU::V_PK_MAX_U16:
6578 case AMDGPU::V_PK_MIN_F16:
6579 case AMDGPU::V_PK_MIN_I16:
6580 case AMDGPU::V_PK_MIN_U16:
6581 case AMDGPU::V_PK_MOV_B32:
6582 case AMDGPU::V_PK_MUL_F16:
6583 case AMDGPU::V_PK_MUL_F32:
6584 case AMDGPU::V_PK_MUL_LO_U16:
6585 case AMDGPU::V_PK_SUB_I16:
6586 case AMDGPU::V_PK_SUB_U16:
6587 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6596 unsigned Opc =
MI.getOpcode();
6599 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6602 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6608 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6609 RI.isSGPRReg(MRI, Src0.
getReg()))
6615 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6617 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6623 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6634 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6635 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6636 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6648 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6649 RI.isVGPR(MRI, Src1.
getReg())) {
6662 if (HasImplicitSGPR || !
MI.isCommutable()) {
6679 if (CommutedOpc == -1) {
6684 MI.setDesc(
get(CommutedOpc));
6688 bool Src0Kill = Src0.
isKill();
6692 else if (Src1.
isReg()) {
6707 unsigned Opc =
MI.getOpcode();
6710 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6711 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6712 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6715 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6716 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6717 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6718 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6719 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6720 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6721 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6731 if (VOP3Idx[2] != -1) {
6743 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6744 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6746 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6748 SGPRsUsed.
insert(SGPRReg);
6752 for (
int Idx : VOP3Idx) {
6761 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6773 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
6780 if (ConstantBusLimit > 0) {
6792 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
6793 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
6800 for (
unsigned I = 0;
I < 3; ++
I) {
6813 SRC = RI.getCommonSubClass(SRC, DstRC);
6816 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6818 if (RI.hasAGPRs(VRC)) {
6819 VRC = RI.getEquivalentVGPRClass(VRC);
6822 get(TargetOpcode::COPY), NewSrcReg)
6829 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6835 for (
unsigned i = 0; i < SubRegs; ++i) {
6838 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6839 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6845 get(AMDGPU::REG_SEQUENCE), DstReg);
6846 for (
unsigned i = 0; i < SubRegs; ++i) {
6848 MIB.
addImm(RI.getSubRegFromChannel(i));
6861 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
6863 SBase->setReg(SGPR);
6866 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
6874 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
6875 if (OldSAddrIdx < 0)
6888 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
6891 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
6892 if (NewVAddrIdx < 0)
6895 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
6899 if (OldVAddrIdx >= 0) {
6913 if (OldVAddrIdx == NewVAddrIdx) {
6924 assert(OldSAddrIdx == NewVAddrIdx);
6926 if (OldVAddrIdx >= 0) {
6927 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
6928 AMDGPU::OpName::vdst_in);
6932 if (NewVDstIn != -1) {
6933 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
6939 if (NewVDstIn != -1) {
6940 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
6981 unsigned OpSubReg =
Op.getSubReg();
6984 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7000 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7003 bool ImpDef = Def->isImplicitDef();
7004 while (!ImpDef && Def && Def->isCopy()) {
7005 if (Def->getOperand(1).getReg().isPhysical())
7008 ImpDef = Def && Def->isImplicitDef();
7010 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7026 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7031 bool UseNewExecInstructions =
7040 if (UseNewExecInstructions) {
7075 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7076 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7077 unsigned NumSubRegs =
RegSize / 32;
7078 Register VScalarOp = ScalarOp->getReg();
7081 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7083 if (NumSubRegs == 1) {
7086 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7087 Common != VScalarOpRC) {
7094 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7097 if (UseNewExecInstructions) {
7099 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7102 if (
I == LoopBB.
end())
7107 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7113 CondReg = NewCondReg;
7124 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7125 ScalarOp->setReg(CurReg);
7128 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7129 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7131 ScalarOp->setReg(PhySGPRs[Idx]);
7133 ScalarOp->setIsKill();
7137 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7138 "Unhandled register size");
7140 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7147 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7148 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7151 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7152 .
addReg(VScalarOp, VScalarOpUndef,
7153 TRI->getSubRegFromChannel(Idx + 1));
7160 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7167 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7169 if (UseNewExecInstructions) {
7171 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7173 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7174 if (
I == LoopBB.
end())
7178 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7180 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7184 CondReg = NewCondReg;
7195 const auto *SScalarOpRC =
7201 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7202 unsigned Channel = 0;
7203 for (
Register Piece : ReadlanePieces) {
7204 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7208 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7209 ScalarOp->setReg(SScalarOp);
7211 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7212 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7214 ScalarOp->setReg(PhySGPRs[Idx]);
7216 ScalarOp->setIsKill();
7224 if (!UseNewExecInstructions) {
7236 if (UseNewExecInstructions) {
7260 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7261 "Physical SGPRs must be empty or match the number of scalar operands");
7267 if (!Begin.isValid())
7269 if (!End.isValid()) {
7275 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7284 std::numeric_limits<unsigned>::max()) !=
7302 for (
auto I = Begin;
I != AfterMI;
I++) {
7303 for (
auto &MO :
I->all_uses())
7339 for (
auto &Succ : RemainderBB->
successors()) {
7364static std::tuple<unsigned, unsigned>
7372 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7373 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7380 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7397 .
addImm(AMDGPU::sub0_sub1)
7403 return std::tuple(RsrcPtr, NewSRsrc);
7440 if (
MI.getOpcode() == AMDGPU::PHI) {
7442 assert(!RI.isSGPRClass(VRC));
7445 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7447 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7463 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7466 if (RI.hasVGPRs(DstRC)) {
7470 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7472 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7490 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7495 if (DstRC != Src0RC) {
7504 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7506 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7512 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7513 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7514 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7515 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7516 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7517 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7518 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7520 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7533 ? AMDGPU::OpName::rsrc
7534 : AMDGPU::OpName::srsrc;
7539 AMDGPU::OpName SampOpName =
7540 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7549 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7557 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7561 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7571 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7572 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7573 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7574 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7576 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7583 bool isSoffsetLegal =
true;
7585 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7586 if (SoffsetIdx != -1) {
7590 isSoffsetLegal =
false;
7594 bool isRsrcLegal =
true;
7596 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7597 if (RsrcIdx != -1) {
7599 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7600 isRsrcLegal =
false;
7604 if (isRsrcLegal && isSoffsetLegal)
7632 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7636 unsigned RsrcPtr, NewSRsrc;
7643 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7644 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7650 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7651 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7664 }
else if (!VAddr && ST.hasAddr64()) {
7668 "FIXME: Need to emit flat atomics here");
7670 unsigned RsrcPtr, NewSRsrc;
7696 MIB.
addImm(CPol->getImm());
7701 MIB.
addImm(TFE->getImm());
7721 MI.removeFromParent();
7726 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7727 .addImm(AMDGPU::sub0)
7728 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7729 .addImm(AMDGPU::sub1);
7732 if (!isSoffsetLegal) {
7743 if (!isSoffsetLegal) {
7755 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
7756 if (RsrcIdx != -1) {
7757 DeferredList.insert(
MI);
7762 return DeferredList.contains(
MI);
7772 if (!ST.useRealTrue16Insts())
7775 unsigned Opcode =
MI.getOpcode();
7779 OpIdx >=
get(Opcode).getNumOperands() ||
7780 get(Opcode).operands()[
OpIdx].RegClass == -1)
7784 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7788 if (!RI.isVGPRClass(CurrRC))
7791 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[
OpIdx]);
7793 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7794 Op.setSubReg(AMDGPU::lo16);
7795 }
else if (RI.getMatchingSuperRegClass(ExpectedRC, CurrRC, AMDGPU::lo16)) {
7805 Op.setReg(NewDstReg);
7818 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7819 "This only handle waterfall for SI_CALL_ISEL");
7826 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7829 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7834 while (End !=
MBB.end() && End->isCopy() &&
7835 MI->definesRegister(End->getOperand(1).getReg(), &RI))
7845 while (!Worklist.
empty()) {
7851 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
7857 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
7859 "Deferred MachineInstr are not supposed to re-populate worklist");
7862 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
7863 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
7865 Entry.second.SGPRs);
7868 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
7870 Entry.first->eraseFromParent();
7878 if (SubRegIndices.
size() <= 1) {
7881 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7888 for (int16_t Indice : SubRegIndices) {
7891 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7898 get(AMDGPU::REG_SEQUENCE), DstReg);
7899 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
7901 MIB.
addImm(RI.getSubRegFromChannel(i));
7911 if (DstReg == AMDGPU::M0) {
7924 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
7926 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
7927 if (
UseMI->getOperand(i).isReg() &&
7928 UseMI->getOperand(i).getReg() == DstReg) {
7932 V2SCopyInfo.MOs.push_back(MO);
7933 V2SCopyInfo.SGPRs.push_back(DstReg);
7937 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
7938 I->getOperand(0).isReg() &&
7939 I->getOperand(0).getReg() == DstReg) {
7942 }
else if (
I->readsRegister(DstReg, &RI)) {
7944 V2SPhyCopiesToErase[&Inst] =
false;
7946 if (
I->findRegisterDefOperand(DstReg, &RI))
7968 case AMDGPU::S_ADD_I32:
7969 case AMDGPU::S_SUB_I32: {
7973 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
7981 case AMDGPU::S_MUL_U64:
7982 if (ST.hasVMulU64Inst()) {
7983 NewOpcode = AMDGPU::V_MUL_U64_e64;
7987 splitScalarSMulU64(Worklist, Inst, MDT);
7991 case AMDGPU::S_MUL_U64_U32_PSEUDO:
7992 case AMDGPU::S_MUL_I64_I32_PSEUDO:
7995 splitScalarSMulPseudo(Worklist, Inst, MDT);
7999 case AMDGPU::S_AND_B64:
8000 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8004 case AMDGPU::S_OR_B64:
8005 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8009 case AMDGPU::S_XOR_B64:
8010 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8014 case AMDGPU::S_NAND_B64:
8015 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8019 case AMDGPU::S_NOR_B64:
8020 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8024 case AMDGPU::S_XNOR_B64:
8025 if (ST.hasDLInsts())
8026 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8028 splitScalar64BitXnor(Worklist, Inst, MDT);
8032 case AMDGPU::S_ANDN2_B64:
8033 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8037 case AMDGPU::S_ORN2_B64:
8038 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8042 case AMDGPU::S_BREV_B64:
8043 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8047 case AMDGPU::S_NOT_B64:
8048 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8052 case AMDGPU::S_BCNT1_I32_B64:
8053 splitScalar64BitBCNT(Worklist, Inst);
8057 case AMDGPU::S_BFE_I64:
8058 splitScalar64BitBFE(Worklist, Inst);
8062 case AMDGPU::S_FLBIT_I32_B64:
8063 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8066 case AMDGPU::S_FF1_I32_B64:
8067 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8071 case AMDGPU::S_LSHL_B32:
8072 if (ST.hasOnlyRevVALUShifts()) {
8073 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8077 case AMDGPU::S_ASHR_I32:
8078 if (ST.hasOnlyRevVALUShifts()) {
8079 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8083 case AMDGPU::S_LSHR_B32:
8084 if (ST.hasOnlyRevVALUShifts()) {
8085 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8089 case AMDGPU::S_LSHL_B64:
8090 if (ST.hasOnlyRevVALUShifts()) {
8092 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8093 : AMDGPU::V_LSHLREV_B64_e64;
8097 case AMDGPU::S_ASHR_I64:
8098 if (ST.hasOnlyRevVALUShifts()) {
8099 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8103 case AMDGPU::S_LSHR_B64:
8104 if (ST.hasOnlyRevVALUShifts()) {
8105 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8110 case AMDGPU::S_ABS_I32:
8111 lowerScalarAbs(Worklist, Inst);
8115 case AMDGPU::S_ABSDIFF_I32:
8116 lowerScalarAbsDiff(Worklist, Inst);
8120 case AMDGPU::S_CBRANCH_SCC0:
8121 case AMDGPU::S_CBRANCH_SCC1: {
8124 bool IsSCC = CondReg == AMDGPU::SCC;
8132 case AMDGPU::S_BFE_U64:
8133 case AMDGPU::S_BFM_B64:
8136 case AMDGPU::S_PACK_LL_B32_B16:
8137 case AMDGPU::S_PACK_LH_B32_B16:
8138 case AMDGPU::S_PACK_HL_B32_B16:
8139 case AMDGPU::S_PACK_HH_B32_B16:
8140 movePackToVALU(Worklist, MRI, Inst);
8144 case AMDGPU::S_XNOR_B32:
8145 lowerScalarXnor(Worklist, Inst);
8149 case AMDGPU::S_NAND_B32:
8150 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8154 case AMDGPU::S_NOR_B32:
8155 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8159 case AMDGPU::S_ANDN2_B32:
8160 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8164 case AMDGPU::S_ORN2_B32:
8165 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8173 case AMDGPU::S_ADD_CO_PSEUDO:
8174 case AMDGPU::S_SUB_CO_PSEUDO: {
8175 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8176 ? AMDGPU::V_ADDC_U32_e64
8177 : AMDGPU::V_SUBB_U32_e64;
8178 const auto *CarryRC = RI.getWaveMaskRegClass();
8200 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8204 case AMDGPU::S_UADDO_PSEUDO:
8205 case AMDGPU::S_USUBO_PSEUDO: {
8211 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8212 ? AMDGPU::V_ADD_CO_U32_e64
8213 : AMDGPU::V_SUB_CO_U32_e64;
8225 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8229 case AMDGPU::S_LSHL1_ADD_U32:
8230 case AMDGPU::S_LSHL2_ADD_U32:
8231 case AMDGPU::S_LSHL3_ADD_U32:
8232 case AMDGPU::S_LSHL4_ADD_U32: {
8236 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8237 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8238 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8252 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8256 case AMDGPU::S_CSELECT_B32:
8257 case AMDGPU::S_CSELECT_B64:
8258 lowerSelect(Worklist, Inst, MDT);
8261 case AMDGPU::S_CMP_EQ_I32:
8262 case AMDGPU::S_CMP_LG_I32:
8263 case AMDGPU::S_CMP_GT_I32:
8264 case AMDGPU::S_CMP_GE_I32:
8265 case AMDGPU::S_CMP_LT_I32:
8266 case AMDGPU::S_CMP_LE_I32:
8267 case AMDGPU::S_CMP_EQ_U32:
8268 case AMDGPU::S_CMP_LG_U32:
8269 case AMDGPU::S_CMP_GT_U32:
8270 case AMDGPU::S_CMP_GE_U32:
8271 case AMDGPU::S_CMP_LT_U32:
8272 case AMDGPU::S_CMP_LE_U32:
8273 case AMDGPU::S_CMP_EQ_U64:
8274 case AMDGPU::S_CMP_LG_U64:
8275 case AMDGPU::S_CMP_LT_F32:
8276 case AMDGPU::S_CMP_EQ_F32:
8277 case AMDGPU::S_CMP_LE_F32:
8278 case AMDGPU::S_CMP_GT_F32:
8279 case AMDGPU::S_CMP_LG_F32:
8280 case AMDGPU::S_CMP_GE_F32:
8281 case AMDGPU::S_CMP_O_F32:
8282 case AMDGPU::S_CMP_U_F32:
8283 case AMDGPU::S_CMP_NGE_F32:
8284 case AMDGPU::S_CMP_NLG_F32:
8285 case AMDGPU::S_CMP_NGT_F32:
8286 case AMDGPU::S_CMP_NLE_F32:
8287 case AMDGPU::S_CMP_NEQ_F32:
8288 case AMDGPU::S_CMP_NLT_F32: {
8293 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8307 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8311 case AMDGPU::S_CMP_LT_F16:
8312 case AMDGPU::S_CMP_EQ_F16:
8313 case AMDGPU::S_CMP_LE_F16:
8314 case AMDGPU::S_CMP_GT_F16:
8315 case AMDGPU::S_CMP_LG_F16:
8316 case AMDGPU::S_CMP_GE_F16:
8317 case AMDGPU::S_CMP_O_F16:
8318 case AMDGPU::S_CMP_U_F16:
8319 case AMDGPU::S_CMP_NGE_F16:
8320 case AMDGPU::S_CMP_NLG_F16:
8321 case AMDGPU::S_CMP_NGT_F16:
8322 case AMDGPU::S_CMP_NLE_F16:
8323 case AMDGPU::S_CMP_NEQ_F16:
8324 case AMDGPU::S_CMP_NLT_F16: {
8347 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8351 case AMDGPU::S_CVT_HI_F32_F16: {
8354 if (ST.useRealTrue16Insts()) {
8359 .
addReg(TmpReg, {}, AMDGPU::hi16)
8375 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8379 case AMDGPU::S_MINIMUM_F32:
8380 case AMDGPU::S_MAXIMUM_F32: {
8392 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8396 case AMDGPU::S_MINIMUM_F16:
8397 case AMDGPU::S_MAXIMUM_F16: {
8399 ? &AMDGPU::VGPR_16RegClass
8400 : &AMDGPU::VGPR_32RegClass);
8412 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8416 case AMDGPU::V_S_EXP_F16_e64:
8417 case AMDGPU::V_S_LOG_F16_e64:
8418 case AMDGPU::V_S_RCP_F16_e64:
8419 case AMDGPU::V_S_RSQ_F16_e64:
8420 case AMDGPU::V_S_SQRT_F16_e64: {
8422 ? &AMDGPU::VGPR_16RegClass
8423 : &AMDGPU::VGPR_32RegClass);
8435 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8441 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8449 if (NewOpcode == Opcode) {
8456 V2SPhyCopiesToErase);
8464 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8471 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8502 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8506 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8512 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8519 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8521 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8526 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8534 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8544 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8545 AMDGPU::OpName::src0_modifiers) >= 0)
8549 NewInstr->addOperand(Src);
8552 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8555 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8557 NewInstr.addImm(
Size);
8558 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8562 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8567 "Scalar BFE is only implemented for constant width and offset");
8575 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8576 AMDGPU::OpName::src1_modifiers) >= 0)
8578 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8580 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8581 AMDGPU::OpName::src2_modifiers) >= 0)
8583 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8585 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8587 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8589 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8595 NewInstr->addOperand(
Op);
8602 if (
Op.getReg() == AMDGPU::SCC) {
8604 if (
Op.isDef() && !
Op.isDead())
8605 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8607 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8612 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8613 Register DstReg = NewInstr->getOperand(0).getReg();
8628 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8632std::pair<bool, MachineBasicBlock *>
8635 if (ST.hasAddNoCarryInsts()) {
8647 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8649 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8650 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8661 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8662 return std::pair(
true, NewBB);
8665 return std::pair(
false,
nullptr);
8682 bool IsSCC = (CondReg == AMDGPU::SCC);
8690 for (MachineOperand &UseMO :
8692 MachineInstr &
UseMI = *UseMO.getParent();
8693 switch (
UseMI.getOpcode()) {
8694 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8695 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8696 case AMDGPU::V_CNDMASK_B16_t16_e32:
8697 case AMDGPU::V_CNDMASK_B16_t16_e64:
8698 case AMDGPU::V_CNDMASK_B32_e32:
8699 case AMDGPU::V_CNDMASK_B32_e64:
8700 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8701 if (UseMO.isImplicit() ||
8703 UseMO.setReg(CondReg);
8717 bool CopyFound =
false;
8718 for (MachineInstr &CandI :
8721 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8723 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8725 .
addReg(CandI.getOperand(1).getReg());
8737 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8746 MachineInstr *NewInst;
8747 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
8748 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8763 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8778 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8779 : AMDGPU::V_SUB_CO_U32_e32;
8790 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8807 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8808 : AMDGPU::V_SUB_CO_U32_e32;
8821 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8835 if (ST.hasDLInsts()) {
8845 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8851 bool Src0IsSGPR = Src0.
isReg() &&
8853 bool Src1IsSGPR = Src1.
isReg() &&
8867 }
else if (Src1IsSGPR) {
8885 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8891 unsigned Opcode)
const {
8915 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8920 unsigned Opcode)
const {
8944 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8959 const MCInstrDesc &InstDesc =
get(Opcode);
8962 &AMDGPU::SGPR_32RegClass;
8965 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
8968 AMDGPU::sub0, Src0SubRC);
8973 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
8976 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
8979 AMDGPU::sub1, Src0SubRC);
8982 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
8996 Worklist.
insert(&LoHalf);
8997 Worklist.
insert(&HiHalf);
9003 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9027 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9028 if (RI.isSGPRClass(Src0SubRC))
9029 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9031 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9032 if (RI.isSGPRClass(Src1SubRC))
9033 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9037 MachineOperand Op0L =
9039 MachineOperand Op1L =
9041 MachineOperand Op0H =
9043 MachineOperand Op1H =
9062 MachineInstr *Op1L_Op0H =
9068 MachineInstr *Op1H_Op0L =
9074 MachineInstr *Carry =
9079 MachineInstr *LoHalf =
9089 MachineInstr *HiHalf =
9112 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9136 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9137 if (RI.isSGPRClass(Src0SubRC))
9138 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9140 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9141 if (RI.isSGPRClass(Src1SubRC))
9142 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9146 MachineOperand Op0L =
9148 MachineOperand Op1L =
9152 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9153 ? AMDGPU::V_MUL_HI_U32_e64
9154 : AMDGPU::V_MUL_HI_I32_e64;
9155 MachineInstr *HiHalf =
9158 MachineInstr *LoHalf =
9177 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9193 const MCInstrDesc &InstDesc =
get(Opcode);
9196 &AMDGPU::SGPR_32RegClass;
9199 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9202 &AMDGPU::SGPR_32RegClass;
9205 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9208 AMDGPU::sub0, Src0SubRC);
9210 AMDGPU::sub0, Src1SubRC);
9212 AMDGPU::sub1, Src0SubRC);
9214 AMDGPU::sub1, Src1SubRC);
9219 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9222 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9227 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9240 Worklist.
insert(&LoHalf);
9241 Worklist.
insert(&HiHalf);
9244 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9264 MachineOperand* Op0;
9265 MachineOperand* Op1;
9267 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9300 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9303 &AMDGPU::SGPR_32RegClass;
9309 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9312 AMDGPU::sub0, SrcSubRC);
9314 AMDGPU::sub1, SrcSubRC);
9324 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9343 Offset == 0 &&
"Not implemented");
9366 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9376 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9379 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9385 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9404 const MCInstrDesc &InstDesc =
get(Opcode);
9406 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9407 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9408 : AMDGPU::V_ADD_CO_U32_e32;
9411 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9413 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9415 MachineOperand SrcRegSub0 =
9417 MachineOperand SrcRegSub1 =
9430 .
addReg(IsCtlz ? MidReg1 : MidReg2)
9436 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9440 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9443void SIInstrInfo::addUsersToMoveToVALUWorklist(
9447 MachineInstr &
UseMI = *MO.getParent();
9451 switch (
UseMI.getOpcode()) {
9454 case AMDGPU::SOFT_WQM:
9455 case AMDGPU::STRICT_WWM:
9456 case AMDGPU::STRICT_WQM:
9457 case AMDGPU::REG_SEQUENCE:
9459 case AMDGPU::INSERT_SUBREG:
9462 OpNo = MO.getOperandNo();
9469 if (!RI.hasVectorRegisters(OpRC))
9486 if (ST.useRealTrue16Insts()) {
9488 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9491 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9497 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9500 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9509 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9511 case AMDGPU::S_PACK_LL_B32_B16:
9513 .addReg(SrcReg0, {},
9514 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9515 .addImm(AMDGPU::lo16)
9516 .addReg(SrcReg1, {},
9517 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9518 .addImm(AMDGPU::hi16);
9520 case AMDGPU::S_PACK_LH_B32_B16:
9522 .addReg(SrcReg0, {},
9523 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9524 .addImm(AMDGPU::lo16)
9525 .addReg(SrcReg1, {}, AMDGPU::hi16)
9526 .addImm(AMDGPU::hi16);
9528 case AMDGPU::S_PACK_HL_B32_B16:
9529 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9530 .addImm(AMDGPU::lo16)
9531 .addReg(SrcReg1, {},
9532 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9533 .addImm(AMDGPU::hi16);
9535 case AMDGPU::S_PACK_HH_B32_B16:
9536 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9537 .addImm(AMDGPU::lo16)
9538 .addReg(SrcReg1, {}, AMDGPU::hi16)
9539 .addImm(AMDGPU::hi16);
9547 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9552 case AMDGPU::S_PACK_LL_B32_B16: {
9571 case AMDGPU::S_PACK_LH_B32_B16: {
9581 case AMDGPU::S_PACK_HL_B32_B16: {
9592 case AMDGPU::S_PACK_HH_B32_B16: {
9612 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9621 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9622 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9623 SmallVector<MachineInstr *, 4> CopyToDelete;
9626 for (MachineInstr &
MI :
9630 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9633 MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9634 Register DestReg =
MI.getOperand(0).getReg();
9641 MI.getOperand(SCCIdx).setReg(NewCond);
9647 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9650 for (
auto &Copy : CopyToDelete)
9651 Copy->eraseFromParent();
9659void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9665 for (MachineInstr &
MI :
9668 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9670 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9687 case AMDGPU::REG_SEQUENCE:
9688 case AMDGPU::INSERT_SUBREG:
9690 case AMDGPU::SOFT_WQM:
9691 case AMDGPU::STRICT_WWM:
9692 case AMDGPU::STRICT_WQM: {
9694 if (RI.isAGPRClass(SrcRC)) {
9695 if (RI.isAGPRClass(NewDstRC))
9700 case AMDGPU::REG_SEQUENCE:
9701 case AMDGPU::INSERT_SUBREG:
9702 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9705 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9711 if (RI.isVGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9714 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9728 int OpIndices[3])
const {
9729 const MCInstrDesc &
Desc =
MI.getDesc();
9745 const MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9747 for (
unsigned i = 0; i < 3; ++i) {
9748 int Idx = OpIndices[i];
9752 const MachineOperand &MO =
MI.getOperand(Idx);
9759 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
9760 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9767 if (RI.isSGPRClass(RegRC))
9785 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9786 SGPRReg = UsedSGPRs[0];
9789 if (!SGPRReg && UsedSGPRs[1]) {
9790 if (UsedSGPRs[1] == UsedSGPRs[2])
9791 SGPRReg = UsedSGPRs[1];
9798 AMDGPU::OpName OperandName)
const {
9799 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9802 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
9806 return &
MI.getOperand(Idx);
9820 if (ST.isAmdHsaOS()) {
9823 RsrcDataFormat |= (1ULL << 56);
9828 RsrcDataFormat |= (2ULL << 59);
9831 return RsrcDataFormat;
9841 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
9846 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
9853 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
9859 unsigned Opc =
MI.getOpcode();
9865 return get(
Opc).mayLoad() &&
9872 if (!Addr || !Addr->
isFI())
9881 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
9883 return MI.getOperand(VDataIdx).getReg();
9893 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
9895 return MI.getOperand(DataIdx).getReg();
9929 unsigned Opc =
MI.getOpcode();
9931 unsigned DescSize =
Desc.getSize();
9936 unsigned Size = DescSize;
9940 if (
MI.isBranch() && ST.hasOffset3fBug())
9951 bool HasLiteral =
false;
9952 unsigned LiteralSize = 4;
9953 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
9958 if (ST.has64BitLiterals()) {
9959 switch (OpInfo.OperandType) {
9984 return HasLiteral ? DescSize + LiteralSize : DescSize;
9989 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
9993 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
9994 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
9998 case TargetOpcode::BUNDLE:
9999 return getInstBundleSize(
MI);
10000 case TargetOpcode::INLINEASM:
10001 case TargetOpcode::INLINEASM_BR: {
10003 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10007 if (
MI.isMetaInstruction())
10011 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10014 unsigned LoInstOpcode = D16Info->LoOp;
10016 DescSize =
Desc.getSize();
10020 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10023 DescSize =
Desc.getSize();
10032 if (
MI.isBranch() && ST.hasOffset3fBug())
10033 return InstSizeVerifyMode::NoVerify;
10034 return InstSizeVerifyMode::ExactSize;
10041 if (
MI.memoperands_empty())
10053 static const std::pair<int, const char *> TargetIndices[] = {
10092std::pair<unsigned, unsigned>
10099 static const std::pair<unsigned, const char *> TargetFlags[] = {
10117 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10133 return AMDGPU::WWM_COPY;
10135 return AMDGPU::COPY;
10152 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10156 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10157 return IsLRSplitInst;
10170 bool IsNullOrVectorRegister =
true;
10174 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10177 return IsNullOrVectorRegister &&
10179 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10180 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10188 if (ST.hasAddNoCarryInsts())
10204 if (ST.hasAddNoCarryInsts())
10208 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10210 : RS.scavengeRegisterBackwards(
10211 *RI.getBoolRC(),
I,
false,
10224 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10225 case AMDGPU::SI_KILL_I1_TERMINATOR:
10234 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10235 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10236 case AMDGPU::SI_KILL_I1_PSEUDO:
10237 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10249 const unsigned OffsetBits =
10251 return (1 << OffsetBits) - 1;
10255 if (!ST.isWave32())
10258 if (
MI.isInlineAsm())
10261 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10264 for (
auto &
Op :
MI.implicit_operands()) {
10265 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10266 Op.setReg(AMDGPU::VCC_LO);
10275 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10279 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10280 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10296 if (Imm > MaxImm) {
10297 if (Imm <= MaxImm + 64) {
10299 Overflow = Imm - MaxImm;
10318 if (Overflow > 0) {
10326 if (ST.hasRestrictedSOffset())
10331 SOffset = Overflow;
10369 if (!ST.hasFlatInstOffsets())
10373 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10378 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10379 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10390std::pair<int64_t, int64_t>
10393 int64_t RemainderOffset = COffsetVal;
10394 int64_t ImmField = 0;
10399 if (AllowNegative) {
10401 int64_t
D = 1LL << NumBits;
10402 RemainderOffset = (COffsetVal /
D) *
D;
10403 ImmField = COffsetVal - RemainderOffset;
10405 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10407 (ImmField % 4) != 0) {
10409 RemainderOffset += ImmField % 4;
10410 ImmField -= ImmField % 4;
10412 }
else if (COffsetVal >= 0) {
10414 RemainderOffset = COffsetVal - ImmField;
10418 assert(RemainderOffset + ImmField == COffsetVal);
10419 return {ImmField, RemainderOffset};
10424 if (ST.hasNegativeScratchOffsetBug() &&
10432 switch (ST.getGeneration()) {
10461 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10462 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10463 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10464 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10465 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10466 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10467 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10468 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10475#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10476 case OPCODE##_dpp: \
10477 case OPCODE##_e32: \
10478 case OPCODE##_e64: \
10479 case OPCODE##_e64_dpp: \
10480 case OPCODE##_sdwa:
10494 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10495 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10496 case AMDGPU::V_FMA_F16_gfx9_e64:
10497 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10498 case AMDGPU::V_INTERP_P2_F16:
10499 case AMDGPU::V_MAD_F16_e64:
10500 case AMDGPU::V_MAD_U16_e64:
10501 case AMDGPU::V_MAD_I16_e64:
10510 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10524 switch (ST.getGeneration()) {
10537 if (
isMAI(Opcode)) {
10545 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10548 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10555 if (ST.hasGFX90AInsts()) {
10556 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10557 if (ST.hasGFX940Insts())
10559 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10561 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10563 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10569 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10588 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10589 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10590 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10602 switch (
MI.getOpcode()) {
10604 case AMDGPU::REG_SEQUENCE:
10608 case AMDGPU::INSERT_SUBREG:
10609 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10626 if (!
P.Reg.isVirtual())
10631 while (
auto *
MI = DefInst) {
10633 switch (
MI->getOpcode()) {
10635 case AMDGPU::V_MOV_B32_e32: {
10636 auto &Op1 =
MI->getOperand(1);
10665 auto *DefBB =
DefMI.getParent();
10669 if (
UseMI.getParent() != DefBB)
10672 const int MaxInstScan = 20;
10676 auto E =
UseMI.getIterator();
10677 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10678 if (
I->isDebugInstr())
10681 if (++NumInst > MaxInstScan)
10684 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10697 auto *DefBB =
DefMI.getParent();
10699 const int MaxUseScan = 10;
10703 auto &UseInst = *
Use.getParent();
10706 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10709 if (++NumUse > MaxUseScan)
10716 const int MaxInstScan = 20;
10720 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10723 if (
I->isDebugInstr())
10726 if (++NumInst > MaxInstScan)
10739 if (Reg == VReg && --NumUse == 0)
10741 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
10750 auto Cur =
MBB.begin();
10751 if (Cur !=
MBB.end())
10753 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
10756 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
10765 if (InsPt !=
MBB.end() &&
10766 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10767 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10768 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10769 InsPt->definesRegister(Src,
nullptr)) {
10773 .
addReg(Src, {}, SrcSubReg)
10816 if (isFullCopyInstr(
MI)) {
10817 Register DstReg =
MI.getOperand(0).getReg();
10818 Register SrcReg =
MI.getOperand(1).getReg();
10840 unsigned *PredCost)
const {
10841 if (
MI.isBundle()) {
10844 unsigned Lat = 0,
Count = 0;
10845 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
10847 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
10849 return Lat +
Count - 1;
10852 return SchedModel.computeInstrLatency(&
MI);
10859 return *CallAddrOp;
10866 unsigned Opcode =
MI.getOpcode();
10868 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
10871 :
MI.getOperand(1).getReg();
10875 unsigned SrcAS = SrcTy.getAddressSpace();
10878 ST.hasGloballyAddressableScratch()
10886 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
10887 return HandleAddrSpaceCast(
MI);
10890 auto IID = GI->getIntrinsicID();
10897 case Intrinsic::amdgcn_addrspacecast_nonnull:
10898 return HandleAddrSpaceCast(
MI);
10899 case Intrinsic::amdgcn_if:
10900 case Intrinsic::amdgcn_else:
10914 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
10915 Opcode == AMDGPU::G_SEXTLOAD) {
10916 if (
MI.memoperands_empty())
10920 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
10921 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
10929 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
10930 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
10931 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
10937 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
10940 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
10948 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
10949 return Formatter.get();
10957 unsigned opcode =
MI.getOpcode();
10958 if (opcode == AMDGPU::V_READLANE_B32 ||
10959 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
10960 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
10965 if (
MI.isInlineAsm()) {
10971 if (!RC || !RI.isSGPRClass(RC))
10976 if (isCopyInstr(
MI)) {
10980 RI.getPhysRegBaseClass(srcOp.
getReg());
10988 if (
MI.isPreISelOpcode())
11003 if (
MI.memoperands_empty())
11007 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11008 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11023 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11025 if (!
SrcOp.isReg())
11029 if (!Reg || !
SrcOp.readsReg())
11035 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11062 F,
"ds_ordered_count unsupported for this calling conv"));
11076 Register &SrcReg2, int64_t &CmpMask,
11077 int64_t &CmpValue)
const {
11078 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11081 switch (
MI.getOpcode()) {
11084 case AMDGPU::S_CMP_EQ_U32:
11085 case AMDGPU::S_CMP_EQ_I32:
11086 case AMDGPU::S_CMP_LG_U32:
11087 case AMDGPU::S_CMP_LG_I32:
11088 case AMDGPU::S_CMP_LT_U32:
11089 case AMDGPU::S_CMP_LT_I32:
11090 case AMDGPU::S_CMP_GT_U32:
11091 case AMDGPU::S_CMP_GT_I32:
11092 case AMDGPU::S_CMP_LE_U32:
11093 case AMDGPU::S_CMP_LE_I32:
11094 case AMDGPU::S_CMP_GE_U32:
11095 case AMDGPU::S_CMP_GE_I32:
11096 case AMDGPU::S_CMP_EQ_U64:
11097 case AMDGPU::S_CMP_LG_U64:
11098 SrcReg =
MI.getOperand(0).getReg();
11099 if (
MI.getOperand(1).isReg()) {
11100 if (
MI.getOperand(1).getSubReg())
11102 SrcReg2 =
MI.getOperand(1).getReg();
11104 }
else if (
MI.getOperand(1).isImm()) {
11106 CmpValue =
MI.getOperand(1).getImm();
11112 case AMDGPU::S_CMPK_EQ_U32:
11113 case AMDGPU::S_CMPK_EQ_I32:
11114 case AMDGPU::S_CMPK_LG_U32:
11115 case AMDGPU::S_CMPK_LG_I32:
11116 case AMDGPU::S_CMPK_LT_U32:
11117 case AMDGPU::S_CMPK_LT_I32:
11118 case AMDGPU::S_CMPK_GT_U32:
11119 case AMDGPU::S_CMPK_GT_I32:
11120 case AMDGPU::S_CMPK_LE_U32:
11121 case AMDGPU::S_CMPK_LE_I32:
11122 case AMDGPU::S_CMPK_GE_U32:
11123 case AMDGPU::S_CMPK_GE_I32:
11124 SrcReg =
MI.getOperand(0).getReg();
11126 CmpValue =
MI.getOperand(1).getImm();
11136 if (S->isLiveIn(AMDGPU::SCC))
11145bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11148 bool SCCIsDead =
false;
11151 constexpr unsigned ScanLimit = 12;
11152 unsigned Count = 0;
11153 for (MachineInstr &
MI :
11155 if (++
Count > ScanLimit)
11157 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11158 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11159 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11160 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11161 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11166 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11179 for (MachineInstr *
MI : InvertInstr) {
11180 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11181 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11183 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11184 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11185 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11186 ? AMDGPU::S_CBRANCH_SCC1
11187 : AMDGPU::S_CBRANCH_SCC0));
11200 bool NeedInversion)
const {
11201 MachineInstr *KillsSCC =
nullptr;
11206 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11208 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11211 if (NeedInversion && !invertSCCUse(SCCRedefine))
11213 if (MachineOperand *SccDef =
11215 SccDef->setIsDead(
false);
11223 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11224 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11226 bool Op1IsNonZeroImm =
11227 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11228 bool Op2IsZeroImm =
11229 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11230 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11236 unsigned &NewDefOpc) {
11239 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11240 Def.getOpcode() != AMDGPU::S_ADD_U32)
11246 if ((!AddSrc1.
isImm() || AddSrc1.
getImm() != 1) &&
11252 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11254 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11257 NewDefOpc = AMDGPU::S_ADD_U32;
11259 NeedInversion = !NeedInversion;
11264 Register SrcReg2, int64_t CmpMask,
11273 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11274 this](
bool NeedInversion) ->
bool {
11298 unsigned NewDefOpc = Def->getOpcode();
11304 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11307 if (NewDefOpc != Def->getOpcode())
11308 Def->setDesc(
get(NewDefOpc));
11317 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11324 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11332 optimizeSCC(
Select, Def,
false);
11339 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11340 this](int64_t ExpectedValue,
unsigned SrcSize,
11341 bool IsReversible,
bool IsSigned) ->
bool {
11369 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11370 Def->getOpcode() != AMDGPU::S_AND_B64)
11374 const auto isMask = [&Mask, SrcSize](
const MachineOperand *MO) ->
bool {
11385 SrcOp = &Def->getOperand(2);
11386 else if (isMask(&Def->getOperand(2)))
11387 SrcOp = &Def->getOperand(1);
11395 if (IsSigned && BitNo == SrcSize - 1)
11398 ExpectedValue <<= BitNo;
11400 bool IsReversedCC =
false;
11401 if (CmpValue != ExpectedValue) {
11404 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11409 Register DefReg = Def->getOperand(0).getReg();
11413 if (!optimizeSCC(Def, &CmpInstr,
false))
11424 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11425 : AMDGPU::S_BITCMP1_B32
11426 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11427 : AMDGPU::S_BITCMP1_B64;
11432 Def->eraseFromParent();
11440 case AMDGPU::S_CMP_EQ_U32:
11441 case AMDGPU::S_CMP_EQ_I32:
11442 case AMDGPU::S_CMPK_EQ_U32:
11443 case AMDGPU::S_CMPK_EQ_I32:
11444 return optimizeCmpAnd(1, 32,
true,
false) ||
11445 optimizeCmpSelect(
true);
11446 case AMDGPU::S_CMP_GE_U32:
11447 case AMDGPU::S_CMPK_GE_U32:
11448 return optimizeCmpAnd(1, 32,
false,
false);
11449 case AMDGPU::S_CMP_GE_I32:
11450 case AMDGPU::S_CMPK_GE_I32:
11451 return optimizeCmpAnd(1, 32,
false,
true);
11452 case AMDGPU::S_CMP_EQ_U64:
11453 return optimizeCmpAnd(1, 64,
true,
false);
11454 case AMDGPU::S_CMP_LG_U32:
11455 case AMDGPU::S_CMP_LG_I32:
11456 case AMDGPU::S_CMPK_LG_U32:
11457 case AMDGPU::S_CMPK_LG_I32:
11458 return optimizeCmpAnd(0, 32,
true,
false) ||
11459 optimizeCmpSelect(
false);
11460 case AMDGPU::S_CMP_GT_U32:
11461 case AMDGPU::S_CMPK_GT_U32:
11462 return optimizeCmpAnd(0, 32,
false,
false);
11463 case AMDGPU::S_CMP_GT_I32:
11464 case AMDGPU::S_CMPK_GT_I32:
11465 return optimizeCmpAnd(0, 32,
false,
true);
11466 case AMDGPU::S_CMP_LG_U64:
11467 return optimizeCmpAnd(0, 64,
true,
false) ||
11468 optimizeCmpSelect(
false);
11475 AMDGPU::OpName
OpName)
const {
11476 if (!ST.needsAlignedVGPRs())
11479 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11491 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11493 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11497 : &AMDGPU::VReg_64_Align2RegClass);
11499 .
addReg(DataReg, {},
Op.getSubReg())
11504 Op.setSubReg(AMDGPU::sub0);
11519 if (ST.hasGFX1250Insts())
11526 unsigned Opcode =
MI.getOpcode();
11532 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11533 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11536 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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-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)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static 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 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 bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI, int64_t &Imm, MachineInstr **DefMI=nullptr)
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 void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
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 unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
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 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.
uint64_t getZExtValue() const
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.
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
void getExitingBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of this cycle that have successor outside of this cycle.
bool contains(const BlockT *Block) const
Return whether Block is contained in the cycle.
const GenericCycle * getParentCycle() const
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.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
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.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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...
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 & 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 & 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.
unsigned getAddrSpace() const
@ 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.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
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
bool isSpill(uint32_t Opcode) const
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 mayAccessFlatAddressSpace(const MachineInstr &MI) const
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
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)
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
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
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
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 getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
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)
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
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 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 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)
bool isIgnorableUse(const MachineOperand &MO) const override
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
static bool isF16PseudoScalarTrans(unsigned Opcode)
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)
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
bool isLegalGFX12PlusPackedMathFP32or64BitOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for gfx12+ packed math FP32 or 64 instructions.
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
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 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 canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
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
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) 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.
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.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
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)
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
unsigned getMaxMemoryClusterDWords() const
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
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 bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
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.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
bool isPackedFP32or64BitInst(unsigned Opc)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ 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 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 isD16Buf(const T &...O)
constexpr bool isSDWA(const T &...O)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
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
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
MachineCycleInfo::CycleT MachineCycle
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.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
constexpr bool all() const
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
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.