34#include "llvm/IR/IntrinsicsAMDGPU.h"
42#define DEBUG_TYPE "si-instr-info"
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
48#define GET_D16ImageDimIntrinsics_IMPL
49#define GET_ImageDimIntrinsicTable_IMPL
50#define GET_RsrcIntrinsics_IMPL
51#include "AMDGPUGenSearchableTables.inc"
59 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
62 "amdgpu-fix-16-bit-physreg-copies",
63 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
79 unsigned N =
Node->getNumOperands();
80 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
92 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
93 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
95 if (Op0Idx == -1 && Op1Idx == -1)
99 if ((Op0Idx == -1 && Op1Idx != -1) ||
100 (Op1Idx == -1 && Op0Idx != -1))
121 return !
MI.memoperands_empty() &&
123 return MMO->isLoad() && MMO->isInvariant();
132static std::tuple<unsigned, unsigned, unsigned>
135 unsigned SrcFlags =
SrcOp.getTargetFlags();
160 return std::make_tuple(BaseFlags, LoReloc, HiReloc);
178 if (!
MI.hasImplicitDef() &&
179 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
180 !
MI.mayRaiseFPException())
189 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
204 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
205 MI.hasUnmodeledSideEffects())
210 if (
MI.isInlineAsm())
214 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
229 if (Reg.isPhysical()) {
245 if (MO.isDef() && Reg != DefReg)
253bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
257 if (
MI.isConvergent())
285 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
290 for (
auto Op :
MI.uses()) {
291 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
303 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
323 int64_t &Offset1)
const {
331 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
335 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
351 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
352 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
353 if (Offset0Idx == -1 || Offset1Idx == -1)
360 Offset0Idx -=
get(Opc0).NumDefs;
361 Offset1Idx -=
get(Opc1).NumDefs;
391 if (!Load0Offset || !Load1Offset)
408 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
409 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
411 if (OffIdx0 == -1 || OffIdx1 == -1)
417 OffIdx0 -=
get(Opc0).NumDefs;
418 OffIdx1 -=
get(Opc1).NumDefs;
437 case AMDGPU::DS_READ2ST64_B32:
438 case AMDGPU::DS_READ2ST64_B64:
439 case AMDGPU::DS_WRITE2ST64_B32:
440 case AMDGPU::DS_WRITE2ST64_B64:
455 OffsetIsScalable =
false;
472 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
474 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
475 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
488 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
489 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
490 if (Offset0 + 1 != Offset1)
501 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
509 Offset = EltSize * Offset0;
511 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
512 if (DataOpIdx == -1) {
513 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
515 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
531 if (BaseOp && !BaseOp->
isFI())
539 if (SOffset->
isReg())
545 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
547 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
556 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
557 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
559 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
560 if (VAddr0Idx >= 0) {
562 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
569 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
584 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
601 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
603 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
620 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
628 if (MO1->getAddrSpace() != MO2->getAddrSpace())
631 const auto *Base1 = MO1->getValue();
632 const auto *Base2 = MO2->getValue();
633 if (!Base1 || !Base2)
641 return Base1 == Base2;
645 int64_t Offset1,
bool OffsetIsScalable1,
647 int64_t Offset2,
bool OffsetIsScalable2,
648 unsigned ClusterSize,
649 unsigned NumBytes)
const {
662 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
681 const unsigned LoadSize = NumBytes / ClusterSize;
682 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
683 return NumDWords <= MaxMemoryClusterDWords;
697 int64_t Offset0, int64_t Offset1,
698 unsigned NumLoads)
const {
699 assert(Offset1 > Offset0 &&
700 "Second offset should be larger than first offset!");
705 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
712 const char *
Msg =
"illegal VGPR to SGPR copy") {
731 assert((
TII.getSubtarget().hasMAIInsts() &&
732 !
TII.getSubtarget().hasGFX90AInsts()) &&
733 "Expected GFX908 subtarget.");
736 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
737 "Source register of the copy should be either an SGPR or an AGPR.");
740 "Destination register of the copy should be an AGPR.");
749 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
752 if (!Def->modifiesRegister(SrcReg, &RI))
755 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
756 Def->getOperand(0).getReg() != SrcReg)
763 bool SafeToPropagate =
true;
766 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
767 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
768 SafeToPropagate =
false;
770 if (!SafeToPropagate)
773 for (
auto I = Def;
I !=
MI; ++
I)
774 I->clearRegisterKills(DefOp.
getReg(), &RI);
782 if (ImpUseSuperReg) {
783 Builder.addReg(ImpUseSuperReg,
791 RS.enterBasicBlockEnd(
MBB);
792 RS.backward(std::next(
MI));
801 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
804 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
805 "VGPR used for an intermediate copy should have been reserved.");
810 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
820 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
821 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
822 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
829 if (ImpUseSuperReg) {
830 UseBuilder.
addReg(ImpUseSuperReg,
847 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
848 int16_t SubIdx = BaseIndices[Idx];
849 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
850 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
851 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
852 unsigned Opcode = AMDGPU::S_MOV_B32;
855 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
856 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
857 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
861 DestSubReg = RI.getSubReg(DestReg, SubIdx);
862 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
863 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
864 Opcode = AMDGPU::S_MOV_B64;
879 assert(FirstMI && LastMI);
884 LastMI->addRegisterKilled(SrcReg, &RI);
890 Register SrcReg,
bool KillSrc,
bool RenamableDest,
891 bool RenamableSrc)
const {
893 unsigned Size = RI.getRegSizeInBits(*RC);
895 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
901 if (((
Size == 16) != (SrcSize == 16))) {
903 assert(ST.useRealTrue16Insts());
905 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
908 if (DestReg == SrcReg) {
914 RC = RI.getPhysRegBaseClass(DestReg);
915 Size = RI.getRegSizeInBits(*RC);
916 SrcRC = RI.getPhysRegBaseClass(SrcReg);
917 SrcSize = RI.getRegSizeInBits(*SrcRC);
921 if (RC == &AMDGPU::VGPR_32RegClass) {
923 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
924 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
925 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
926 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
932 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
933 RC == &AMDGPU::SReg_32RegClass) {
934 if (SrcReg == AMDGPU::SCC) {
941 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
942 if (DestReg == AMDGPU::VCC_LO) {
960 if (RC == &AMDGPU::SReg_64RegClass) {
961 if (SrcReg == AMDGPU::SCC) {
968 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
969 if (DestReg == AMDGPU::VCC) {
987 if (DestReg == AMDGPU::SCC) {
990 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
994 assert(ST.hasScalarCompareEq64());
1008 if (RC == &AMDGPU::AGPR_32RegClass) {
1009 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1010 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1016 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1025 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1032 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1033 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1035 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1036 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1037 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1038 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1041 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1042 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1055 if (IsAGPRDst || IsAGPRSrc) {
1056 if (!DstLow || !SrcLow) {
1058 "Cannot use hi16 subreg with an AGPR!");
1065 if (ST.useRealTrue16Insts()) {
1071 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1072 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1084 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1085 if (!DstLow || !SrcLow) {
1087 "Cannot use hi16 subreg on VI!");
1110 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1111 if (ST.hasVMovB64Inst()) {
1116 if (ST.hasPkMovB32()) {
1132 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1133 if (RI.isSGPRClass(RC)) {
1134 if (!RI.isSGPRClass(SrcRC)) {
1138 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1144 unsigned EltSize = 4;
1145 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1146 if (RI.isAGPRClass(RC)) {
1147 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1148 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1149 else if (RI.hasVGPRs(SrcRC) ||
1150 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1151 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1153 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1154 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1155 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1156 }
else if ((
Size % 64 == 0) && RI.hasVGPRs(RC) &&
1157 (RI.isProperlyAlignedRC(*RC) &&
1158 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1160 if (ST.hasVMovB64Inst()) {
1161 Opcode = AMDGPU::V_MOV_B64_e32;
1163 }
else if (ST.hasPkMovB32()) {
1164 Opcode = AMDGPU::V_PK_MOV_B32;
1174 std::unique_ptr<RegScavenger> RS;
1175 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1176 RS = std::make_unique<RegScavenger>();
1182 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1183 const bool CanKillSuperReg = KillSrc && !Overlap;
1185 for (
unsigned Idx = 0; Idx < SubIndices.
size(); ++Idx) {
1188 SubIdx = SubIndices[Idx];
1190 SubIdx = SubIndices[SubIndices.
size() - Idx - 1];
1191 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1192 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1193 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1195 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size() - 1;
1197 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1200 *RS, Overlap, ImpUseSuper);
1201 }
else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1242 int64_t &ImmVal)
const {
1243 switch (
MI.getOpcode()) {
1244 case AMDGPU::V_MOV_B32_e32:
1245 case AMDGPU::S_MOV_B32:
1246 case AMDGPU::S_MOVK_I32:
1247 case AMDGPU::S_MOV_B64:
1248 case AMDGPU::V_MOV_B64_e32:
1249 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1250 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1251 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1252 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1253 case AMDGPU::V_MOV_B64_PSEUDO:
1254 case AMDGPU::V_MOV_B16_t16_e32: {
1258 return MI.getOperand(0).getReg() == Reg;
1263 case AMDGPU::V_MOV_B16_t16_e64: {
1265 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1267 return MI.getOperand(0).getReg() == Reg;
1272 case AMDGPU::S_BREV_B32:
1273 case AMDGPU::V_BFREV_B32_e32:
1274 case AMDGPU::V_BFREV_B32_e64: {
1278 return MI.getOperand(0).getReg() == Reg;
1283 case AMDGPU::S_NOT_B32:
1284 case AMDGPU::V_NOT_B32_e32:
1285 case AMDGPU::V_NOT_B32_e64: {
1288 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1289 return MI.getOperand(0).getReg() == Reg;
1299std::optional<int64_t>
1304 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1305 return std::nullopt;
1308 if (Def && Def->isMoveImmediate()) {
1314 return std::nullopt;
1319 if (RI.isAGPRClass(DstRC))
1320 return AMDGPU::COPY;
1321 if (RI.getRegSizeInBits(*DstRC) == 16) {
1324 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1326 if (RI.getRegSizeInBits(*DstRC) == 32)
1327 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1328 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1329 return AMDGPU::S_MOV_B64;
1330 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1331 return AMDGPU::V_MOV_B64_PSEUDO;
1332 return AMDGPU::COPY;
1337 bool IsIndirectSrc)
const {
1338 if (IsIndirectSrc) {
1340 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1342 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1344 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1346 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1348 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1350 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1352 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1354 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1356 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1358 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1360 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1362 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1364 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1365 if (VecSize <= 1024)
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1372 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1374 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1376 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1378 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1380 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1382 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1384 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1386 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1388 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1390 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1392 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1394 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1396 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1397 if (VecSize <= 1024)
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1405 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1407 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1409 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1411 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1413 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1415 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1417 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1419 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1421 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1423 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1425 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1427 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1429 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1430 if (VecSize <= 1024)
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1438 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1440 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1442 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1444 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1446 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1448 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1450 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1452 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1454 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1456 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1458 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1460 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1462 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1463 if (VecSize <= 1024)
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1471 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1473 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1475 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1477 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1478 if (VecSize <= 1024)
1479 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1486 bool IsSGPR)
const {
1498 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1505 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1507 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1509 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1511 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1512 : AMDGPU::SI_SPILL_S128_SAVE;
1514 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1515 : AMDGPU::SI_SPILL_S160_SAVE;
1517 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1518 : AMDGPU::SI_SPILL_S192_SAVE;
1520 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1521 : AMDGPU::SI_SPILL_S224_SAVE;
1523 return AMDGPU::SI_SPILL_S256_SAVE;
1525 return AMDGPU::SI_SPILL_S288_SAVE;
1527 return AMDGPU::SI_SPILL_S320_SAVE;
1529 return AMDGPU::SI_SPILL_S352_SAVE;
1531 return AMDGPU::SI_SPILL_S384_SAVE;
1533 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1534 : AMDGPU::SI_SPILL_S512_SAVE;
1536 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1537 : AMDGPU::SI_SPILL_S1024_SAVE;
1546 return AMDGPU::SI_SPILL_V16_SAVE;
1548 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1550 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1552 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1554 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1555 : AMDGPU::SI_SPILL_V128_SAVE;
1557 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1558 : AMDGPU::SI_SPILL_V160_SAVE;
1560 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1561 : AMDGPU::SI_SPILL_V192_SAVE;
1563 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1564 : AMDGPU::SI_SPILL_V224_SAVE;
1566 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1567 : AMDGPU::SI_SPILL_V256_SAVE;
1569 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1570 : AMDGPU::SI_SPILL_V288_SAVE;
1572 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1573 : AMDGPU::SI_SPILL_V320_SAVE;
1575 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1576 : AMDGPU::SI_SPILL_V352_SAVE;
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1579 : AMDGPU::SI_SPILL_V384_SAVE;
1581 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1582 : AMDGPU::SI_SPILL_V512_SAVE;
1584 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1585 : AMDGPU::SI_SPILL_V1024_SAVE;
1594 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1595 : AMDGPU::SI_SPILL_AV32_SAVE;
1597 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1598 : AMDGPU::SI_SPILL_AV64_SAVE;
1600 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1601 : AMDGPU::SI_SPILL_AV96_SAVE;
1603 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1604 : AMDGPU::SI_SPILL_AV128_SAVE;
1606 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1607 : AMDGPU::SI_SPILL_AV160_SAVE;
1609 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1610 : AMDGPU::SI_SPILL_AV192_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1613 : AMDGPU::SI_SPILL_AV224_SAVE;
1615 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1616 : AMDGPU::SI_SPILL_AV256_SAVE;
1618 return AMDGPU::SI_SPILL_AV288_SAVE;
1620 return AMDGPU::SI_SPILL_AV320_SAVE;
1622 return AMDGPU::SI_SPILL_AV352_SAVE;
1624 return AMDGPU::SI_SPILL_AV384_SAVE;
1626 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1627 : AMDGPU::SI_SPILL_AV512_SAVE;
1629 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1630 : AMDGPU::SI_SPILL_AV1024_SAVE;
1637 bool IsVectorSuperClass) {
1642 if (IsVectorSuperClass)
1643 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1645 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1651 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1658 if (ST.hasMAIInsts())
1664void SIInstrInfo::storeRegToStackSlotImpl(
1677 FrameInfo.getObjectAlign(FrameIndex));
1678 unsigned SpillSize = RI.getSpillSize(*RC);
1684 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1685 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1686 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1695 if (SrcReg.
isVirtual() && SpillSize == 4) {
1709 SpillSize, *MFI, NeedsCFI);
1724 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1733 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1740 return AMDGPU::SI_SPILL_S32_RESTORE;
1742 return AMDGPU::SI_SPILL_S64_RESTORE;
1744 return AMDGPU::SI_SPILL_S96_RESTORE;
1746 return AMDGPU::SI_SPILL_S128_RESTORE;
1748 return AMDGPU::SI_SPILL_S160_RESTORE;
1750 return AMDGPU::SI_SPILL_S192_RESTORE;
1752 return AMDGPU::SI_SPILL_S224_RESTORE;
1754 return AMDGPU::SI_SPILL_S256_RESTORE;
1756 return AMDGPU::SI_SPILL_S288_RESTORE;
1758 return AMDGPU::SI_SPILL_S320_RESTORE;
1760 return AMDGPU::SI_SPILL_S352_RESTORE;
1762 return AMDGPU::SI_SPILL_S384_RESTORE;
1764 return AMDGPU::SI_SPILL_S512_RESTORE;
1766 return AMDGPU::SI_SPILL_S1024_RESTORE;
1775 return AMDGPU::SI_SPILL_V16_RESTORE;
1777 return AMDGPU::SI_SPILL_V32_RESTORE;
1779 return AMDGPU::SI_SPILL_V64_RESTORE;
1781 return AMDGPU::SI_SPILL_V96_RESTORE;
1783 return AMDGPU::SI_SPILL_V128_RESTORE;
1785 return AMDGPU::SI_SPILL_V160_RESTORE;
1787 return AMDGPU::SI_SPILL_V192_RESTORE;
1789 return AMDGPU::SI_SPILL_V224_RESTORE;
1791 return AMDGPU::SI_SPILL_V256_RESTORE;
1793 return AMDGPU::SI_SPILL_V288_RESTORE;
1795 return AMDGPU::SI_SPILL_V320_RESTORE;
1797 return AMDGPU::SI_SPILL_V352_RESTORE;
1799 return AMDGPU::SI_SPILL_V384_RESTORE;
1801 return AMDGPU::SI_SPILL_V512_RESTORE;
1803 return AMDGPU::SI_SPILL_V1024_RESTORE;
1812 return AMDGPU::SI_SPILL_AV32_RESTORE;
1814 return AMDGPU::SI_SPILL_AV64_RESTORE;
1816 return AMDGPU::SI_SPILL_AV96_RESTORE;
1818 return AMDGPU::SI_SPILL_AV128_RESTORE;
1820 return AMDGPU::SI_SPILL_AV160_RESTORE;
1822 return AMDGPU::SI_SPILL_AV192_RESTORE;
1824 return AMDGPU::SI_SPILL_AV224_RESTORE;
1826 return AMDGPU::SI_SPILL_AV256_RESTORE;
1828 return AMDGPU::SI_SPILL_AV288_RESTORE;
1830 return AMDGPU::SI_SPILL_AV320_RESTORE;
1832 return AMDGPU::SI_SPILL_AV352_RESTORE;
1834 return AMDGPU::SI_SPILL_AV384_RESTORE;
1836 return AMDGPU::SI_SPILL_AV512_RESTORE;
1838 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1845 bool IsVectorSuperClass) {
1850 if (IsVectorSuperClass)
1851 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1853 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1859 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1866 if (ST.hasMAIInsts())
1869 assert(!RI.isAGPRClass(RC));
1883 unsigned SpillSize = RI.getSpillSize(*RC);
1890 FrameInfo.getObjectAlign(FrameIndex));
1892 if (RI.isSGPRClass(RC)) {
1895 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1896 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1897 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1902 if (DestReg.
isVirtual() && SpillSize == 4) {
1931 unsigned Quantity)
const {
1933 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1934 while (Quantity > 0) {
1935 unsigned Arg = std::min(Quantity, MaxSNopCount);
1946 constexpr unsigned DoorbellIDMask = 0x3ff;
1947 constexpr unsigned ECQueueWaveAbort = 0x400;
1952 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1953 MBB.splitAt(
MI,
false);
1957 MBB.addSuccessor(TrapBB);
1967 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1971 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1976 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1977 .
addUse(DoorbellRegMasked)
1978 .
addImm(ECQueueWaveAbort);
1979 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1980 .
addUse(SetWaveAbortBit);
1983 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1994 return MBB.getNextNode();
1998 switch (
MI.getOpcode()) {
2000 if (
MI.isMetaInstruction())
2005 return MI.getOperand(0).getImm() + 1;
2016 switch (
MI.getOpcode()) {
2018 case AMDGPU::S_MOV_B64_term:
2021 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2024 case AMDGPU::S_MOV_B32_term:
2027 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2030 case AMDGPU::S_XOR_B64_term:
2033 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2036 case AMDGPU::S_XOR_B32_term:
2039 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2041 case AMDGPU::S_OR_B64_term:
2044 MI.setDesc(
get(AMDGPU::S_OR_B64));
2046 case AMDGPU::S_OR_B32_term:
2049 MI.setDesc(
get(AMDGPU::S_OR_B32));
2052 case AMDGPU::S_ANDN2_B64_term:
2055 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2058 case AMDGPU::S_ANDN2_B32_term:
2061 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2064 case AMDGPU::S_AND_B64_term:
2067 MI.setDesc(
get(AMDGPU::S_AND_B64));
2070 case AMDGPU::S_AND_B32_term:
2073 MI.setDesc(
get(AMDGPU::S_AND_B32));
2076 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2079 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2082 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2085 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2088 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2089 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2091 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2092 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2095 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2096 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2099 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2100 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2102 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2106 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2109 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2112 int64_t Imm =
MI.getOperand(1).getImm();
2114 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2115 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2120 MI.eraseFromParent();
2126 case AMDGPU::V_MOV_B64_PSEUDO: {
2128 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2129 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2137 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2138 MI.setDesc(Mov64Desc);
2142 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2145 if (
SrcOp.isGlobal()) {
2150 unsigned BaseFlags, LoReloc, HiReloc;
2151 std::tie(BaseFlags, LoReloc, HiReloc) =
2158 }
else if (
SrcOp.isImm()) {
2160 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2161 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2185 if (ST.hasPkMovB32() &&
2204 MI.eraseFromParent();
2207 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2211 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2215 if (ST.has64BitLiterals()) {
2216 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2220 if (
SrcOp.isGlobal()) {
2222 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2223 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2226 unsigned BaseFlags, LoReloc, HiReloc;
2227 std::tie(BaseFlags, LoReloc, HiReloc) =
2234 MI.eraseFromParent();
2241 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2246 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2247 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2249 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2250 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2255 MI.eraseFromParent();
2258 case AMDGPU::V_SET_INACTIVE_B32: {
2262 .
add(
MI.getOperand(3))
2263 .
add(
MI.getOperand(4))
2264 .
add(
MI.getOperand(1))
2265 .
add(
MI.getOperand(2))
2266 .
add(
MI.getOperand(5));
2267 MI.eraseFromParent();
2270 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2271 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2272 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2273 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2274 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2275 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2276 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2277 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2278 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2279 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2280 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2281 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2282 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2283 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2284 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2285 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2286 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2287 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2288 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2289 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2290 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2291 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2292 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2293 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2294 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2295 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2296 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2297 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2298 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2299 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2300 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2301 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2302 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2306 if (RI.hasVGPRs(EltRC)) {
2307 Opc = AMDGPU::V_MOVRELD_B32_e32;
2309 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2310 : AMDGPU::S_MOVRELD_B32;
2315 bool IsUndef =
MI.getOperand(1).isUndef();
2316 unsigned SubReg =
MI.getOperand(3).getImm();
2317 assert(VecReg ==
MI.getOperand(1).getReg());
2322 .
add(
MI.getOperand(2))
2326 const int ImpDefIdx =
2328 const int ImpUseIdx = ImpDefIdx + 1;
2330 MI.eraseFromParent();
2333 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2334 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2335 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2336 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2337 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2338 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2339 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2340 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2341 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2342 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2343 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2344 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2345 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2346 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2347 assert(ST.useVGPRIndexMode());
2349 bool IsUndef =
MI.getOperand(1).isUndef();
2358 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2362 .
add(
MI.getOperand(2))
2366 const int ImpDefIdx =
2368 const int ImpUseIdx = ImpDefIdx + 1;
2375 MI.eraseFromParent();
2378 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2379 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2380 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2381 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2382 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2383 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2384 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2385 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2386 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2387 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2388 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2389 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2390 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2391 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2392 assert(ST.useVGPRIndexMode());
2395 bool IsUndef =
MI.getOperand(1).isUndef();
2399 .
add(
MI.getOperand(2))
2412 MI.eraseFromParent();
2415 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2418 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2419 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2438 if (ST.hasGetPCZeroExtension()) {
2442 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2449 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2459 MI.eraseFromParent();
2462 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2472 Op.setOffset(
Op.getOffset() + 4);
2474 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2478 MI.eraseFromParent();
2481 case AMDGPU::ENTER_STRICT_WWM: {
2487 case AMDGPU::ENTER_STRICT_WQM: {
2494 MI.eraseFromParent();
2497 case AMDGPU::EXIT_STRICT_WWM:
2498 case AMDGPU::EXIT_STRICT_WQM: {
2504 case AMDGPU::SI_RETURN: {
2518 MI.eraseFromParent();
2522 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2523 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2524 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2527 case AMDGPU::S_GETPC_B64_pseudo:
2528 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2529 if (ST.hasGetPCZeroExtension()) {
2531 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2540 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2541 assert(ST.hasBF16PackedInsts());
2542 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2553 case AMDGPU::GET_STACK_BASE:
2556 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2563 Register DestReg =
MI.getOperand(0).getReg();
2573 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2574 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2575 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2578 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2581 MI.getNumExplicitOperands());
2599 case AMDGPU::S_MOV_B64:
2600 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2609 if (UsedLanes.
all())
2614 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2615 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2617 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2618 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2620 if (NeedLo && NeedHi)
2624 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2626 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2635 case AMDGPU::S_LOAD_DWORDX16_IMM:
2636 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2649 for (
auto &CandMO :
I->operands()) {
2650 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2658 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2662 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2668 unsigned NewOpcode = -1;
2669 if (SubregSize == 256)
2670 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2671 else if (SubregSize == 128)
2672 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2682 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2687 MI->getOperand(0).setReg(DestReg);
2688 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2692 OffsetMO->
setImm(FinalOffset);
2698 MI->setMemRefs(*MF, NewMMOs);
2711std::pair<MachineInstr*, MachineInstr*>
2713 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2715 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2718 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2719 return std::pair(&
MI,
nullptr);
2730 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2732 if (Dst.isPhysical()) {
2733 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2740 for (
unsigned I = 1;
I <= 2; ++
I) {
2743 if (
SrcOp.isImm()) {
2745 Imm.ashrInPlace(Part * 32);
2746 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2750 if (Src.isPhysical())
2751 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2758 MovDPP.addImm(MO.getImm());
2760 Split[Part] = MovDPP;
2764 if (Dst.isVirtual())
2771 MI.eraseFromParent();
2772 return std::pair(Split[0], Split[1]);
2775std::optional<DestSourcePair>
2777 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2780 return std::nullopt;
2784 AMDGPU::OpName Src0OpName,
2786 AMDGPU::OpName Src1OpName)
const {
2793 "All commutable instructions have both src0 and src1 modifiers");
2795 int Src0ModsVal = Src0Mods->
getImm();
2796 int Src1ModsVal = Src1Mods->
getImm();
2798 Src1Mods->
setImm(Src0ModsVal);
2799 Src0Mods->
setImm(Src1ModsVal);
2808 bool IsKill = RegOp.
isKill();
2810 bool IsUndef = RegOp.
isUndef();
2811 bool IsDebug = RegOp.
isDebug();
2813 if (NonRegOp.
isImm())
2815 else if (NonRegOp.
isFI())
2836 int64_t NonRegVal = NonRegOp1.
getImm();
2839 NonRegOp2.
setImm(NonRegVal);
2846 unsigned OpIdx1)
const {
2851 unsigned Opc =
MI.getOpcode();
2852 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2862 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2865 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2870 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2876 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2891 unsigned Src1Idx)
const {
2892 assert(!NewMI &&
"this should never be used");
2894 unsigned Opc =
MI.getOpcode();
2896 if (CommutedOpcode == -1)
2899 if (Src0Idx > Src1Idx)
2902 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2903 static_cast<int>(Src0Idx) &&
2904 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2905 static_cast<int>(Src1Idx) &&
2906 "inconsistency with findCommutedOpIndices");
2931 Src1, AMDGPU::OpName::src1_modifiers);
2934 AMDGPU::OpName::src1_sel);
2946 unsigned &SrcOpIdx0,
2947 unsigned &SrcOpIdx1)
const {
2952 unsigned &SrcOpIdx0,
2953 unsigned &SrcOpIdx1)
const {
2954 if (!
Desc.isCommutable())
2957 unsigned Opc =
Desc.getOpcode();
2958 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2962 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2966 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2970 int64_t BrOffset)
const {
2987 return MI.getOperand(0).getMBB();
2992 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
2993 MI.getOpcode() == AMDGPU::SI_LOOP)
3005 "new block should be inserted for expanding unconditional branch");
3008 "restore block should be inserted for restoring clobbered registers");
3016 if (ST.useAddPC64Inst()) {
3018 MCCtx.createTempSymbol(
"offset",
true);
3022 MCCtx.createTempSymbol(
"post_addpc",
true);
3023 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3027 Offset->setVariableValue(OffsetExpr);
3031 assert(RS &&
"RegScavenger required for long branching");
3039 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3040 ST.hasVALUReadSGPRHazard();
3041 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3042 if (FlushSGPRWrites)
3050 ApplyHazardWorkarounds();
3053 MCCtx.createTempSymbol(
"post_getpc",
true);
3057 MCCtx.createTempSymbol(
"offset_lo",
true);
3059 MCCtx.createTempSymbol(
"offset_hi",
true);
3062 .
addReg(PCReg, {}, AMDGPU::sub0)
3066 .
addReg(PCReg, {}, AMDGPU::sub1)
3068 ApplyHazardWorkarounds();
3109 if (LongBranchReservedReg) {
3110 RS->enterBasicBlock(
MBB);
3111 Scav = LongBranchReservedReg;
3113 RS->enterBasicBlockEnd(
MBB);
3114 Scav = RS->scavengeRegisterBackwards(
3119 RS->setRegUsed(Scav);
3127 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3144unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3146 case SIInstrInfo::SCC_TRUE:
3147 return AMDGPU::S_CBRANCH_SCC1;
3148 case SIInstrInfo::SCC_FALSE:
3149 return AMDGPU::S_CBRANCH_SCC0;
3150 case SIInstrInfo::VCCNZ:
3151 return AMDGPU::S_CBRANCH_VCCNZ;
3152 case SIInstrInfo::VCCZ:
3153 return AMDGPU::S_CBRANCH_VCCZ;
3154 case SIInstrInfo::EXECNZ:
3155 return AMDGPU::S_CBRANCH_EXECNZ;
3156 case SIInstrInfo::EXECZ:
3157 return AMDGPU::S_CBRANCH_EXECZ;
3163SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3165 case AMDGPU::S_CBRANCH_SCC0:
3167 case AMDGPU::S_CBRANCH_SCC1:
3169 case AMDGPU::S_CBRANCH_VCCNZ:
3171 case AMDGPU::S_CBRANCH_VCCZ:
3173 case AMDGPU::S_CBRANCH_EXECNZ:
3175 case AMDGPU::S_CBRANCH_EXECZ:
3187 bool AllowModify)
const {
3188 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3190 TBB =
I->getOperand(0).getMBB();
3194 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3195 if (Pred == INVALID_BR)
3200 Cond.push_back(
I->getOperand(1));
3204 if (
I ==
MBB.end()) {
3210 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3212 FBB =
I->getOperand(0).getMBB();
3222 bool AllowModify)
const {
3230 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3231 switch (
I->getOpcode()) {
3232 case AMDGPU::S_MOV_B64_term:
3233 case AMDGPU::S_XOR_B64_term:
3234 case AMDGPU::S_OR_B64_term:
3235 case AMDGPU::S_ANDN2_B64_term:
3236 case AMDGPU::S_AND_B64_term:
3237 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3238 case AMDGPU::S_MOV_B32_term:
3239 case AMDGPU::S_XOR_B32_term:
3240 case AMDGPU::S_OR_B32_term:
3241 case AMDGPU::S_ANDN2_B32_term:
3242 case AMDGPU::S_AND_B32_term:
3243 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3244 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3245 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3248 case AMDGPU::SI_ELSE:
3249 case AMDGPU::SI_KILL_I1_TERMINATOR:
3250 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3267 int *BytesRemoved)
const {
3269 unsigned RemovedSize = 0;
3272 if (
MI.isBranch() ||
MI.isReturn()) {
3274 MI.eraseFromParent();
3280 *BytesRemoved = RemovedSize;
3297 int *BytesAdded)
const {
3298 if (!FBB &&
Cond.empty()) {
3302 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3309 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3321 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3339 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3346 if (
Cond.size() != 2) {
3350 if (
Cond[0].isImm()) {
3361 Register FalseReg,
int &CondCycles,
3362 int &TrueCycles,
int &FalseCycles)
const {
3372 CondCycles = TrueCycles = FalseCycles = NumInsts;
3375 return RI.hasVGPRs(RC) && NumInsts <= 6;
3389 if (NumInsts % 2 == 0)
3392 CondCycles = TrueCycles = FalseCycles = NumInsts;
3393 return RI.isSGPRClass(RC);
3404 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3405 if (Pred == VCCZ || Pred == SCC_FALSE) {
3406 Pred =
static_cast<BranchPredicate
>(-Pred);
3412 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3414 if (DstSize == 32) {
3416 if (Pred == SCC_TRUE) {
3431 if (DstSize == 64 && Pred == SCC_TRUE) {
3441 static const int16_t Sub0_15[] = {
3442 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3443 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3444 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3445 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3448 static const int16_t Sub0_15_64[] = {
3449 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3450 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3451 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3452 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3455 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3457 const int16_t *SubIndices = Sub0_15;
3458 int NElts = DstSize / 32;
3462 if (Pred == SCC_TRUE) {
3464 SelOp = AMDGPU::S_CSELECT_B32;
3465 EltRC = &AMDGPU::SGPR_32RegClass;
3467 SelOp = AMDGPU::S_CSELECT_B64;
3468 EltRC = &AMDGPU::SGPR_64RegClass;
3469 SubIndices = Sub0_15_64;
3475 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3480 for (
int Idx = 0; Idx != NElts; ++Idx) {
3484 unsigned SubIdx = SubIndices[Idx];
3487 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3489 .
addReg(FalseReg, {}, SubIdx)
3490 .addReg(TrueReg, {}, SubIdx);
3493 .
addReg(TrueReg, {}, SubIdx)
3494 .addReg(FalseReg, {}, SubIdx);
3507 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3510 switch (
MI.getOpcode()) {
3511 case AMDGPU::S_ENDPGM:
3512 case AMDGPU::S_ENDPGM_SAVED:
3513 case AMDGPU::S_TRAP:
3514 case AMDGPU::S_GETREG_B32:
3515 case AMDGPU::S_SETREG_B32:
3516 case AMDGPU::S_SETREG_B32_mode:
3517 case AMDGPU::S_SETREG_IMM32_B32:
3518 case AMDGPU::S_SETREG_IMM32_B32_mode:
3519 case AMDGPU::S_SENDMSG:
3520 case AMDGPU::S_SENDMSGHALT:
3521 case AMDGPU::S_SENDMSG_RTN_B32:
3522 case AMDGPU::S_SENDMSG_RTN_B64:
3523 case AMDGPU::S_BARRIER_WAIT:
3524 case AMDGPU::S_BARRIER_SIGNAL_M0:
3525 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3526 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3527 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3535 switch (
MI.getOpcode()) {
3536 case AMDGPU::V_MOV_B16_t16_e32:
3537 case AMDGPU::V_MOV_B16_t16_e64:
3538 case AMDGPU::V_MOV_B32_e32:
3539 case AMDGPU::V_MOV_B32_e64:
3540 case AMDGPU::V_MOV_B64_PSEUDO:
3541 case AMDGPU::V_MOV_B64_e32:
3542 case AMDGPU::V_MOV_B64_e64:
3543 case AMDGPU::S_MOV_B32:
3544 case AMDGPU::S_MOV_B64:
3545 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3547 case AMDGPU::WWM_COPY:
3548 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3549 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3550 case AMDGPU::V_ACCVGPR_MOV_B32:
3551 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3552 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3560 switch (
MI.getOpcode()) {
3561 case AMDGPU::V_MOV_B16_t16_e32:
3562 case AMDGPU::V_MOV_B16_t16_e64:
3564 case AMDGPU::V_MOV_B32_e32:
3565 case AMDGPU::V_MOV_B32_e64:
3566 case AMDGPU::V_MOV_B64_PSEUDO:
3567 case AMDGPU::V_MOV_B64_e32:
3568 case AMDGPU::V_MOV_B64_e64:
3569 case AMDGPU::S_MOV_B32:
3570 case AMDGPU::S_MOV_B64:
3571 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3573 case AMDGPU::WWM_COPY:
3574 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3575 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3576 case AMDGPU::V_ACCVGPR_MOV_B32:
3577 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3578 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3586 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3587 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3588 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3591 unsigned Opc =
MI.getOpcode();
3593 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3595 MI.removeOperand(Idx);
3601 MI.setDesc(NewDesc);
3607 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3608 Desc.implicit_defs().size();
3610 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3611 MI.removeOperand(
I);
3615 unsigned SubRegIndex) {
3616 switch (SubRegIndex) {
3617 case AMDGPU::NoSubRegister:
3627 case AMDGPU::sub1_lo16:
3629 case AMDGPU::sub1_hi16:
3632 return std::nullopt;
3640 case AMDGPU::V_MAC_F16_e32:
3641 case AMDGPU::V_MAC_F16_e64:
3642 case AMDGPU::V_MAD_F16_e64:
3643 return AMDGPU::V_MADAK_F16;
3644 case AMDGPU::V_MAC_F32_e32:
3645 case AMDGPU::V_MAC_F32_e64:
3646 case AMDGPU::V_MAD_F32_e64:
3647 return AMDGPU::V_MADAK_F32;
3648 case AMDGPU::V_FMAC_F32_e32:
3649 case AMDGPU::V_FMAC_F32_e64:
3650 case AMDGPU::V_FMA_F32_e64:
3651 return AMDGPU::V_FMAAK_F32;
3652 case AMDGPU::V_FMAC_F16_e32:
3653 case AMDGPU::V_FMAC_F16_e64:
3654 case AMDGPU::V_FMAC_F16_t16_e64:
3655 case AMDGPU::V_FMAC_F16_fake16_e64:
3656 case AMDGPU::V_FMAC_F16_t16_e32:
3657 case AMDGPU::V_FMAC_F16_fake16_e32:
3658 case AMDGPU::V_FMA_F16_e64:
3659 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3660 ? AMDGPU::V_FMAAK_F16_t16
3661 : AMDGPU::V_FMAAK_F16_fake16
3662 : AMDGPU::V_FMAAK_F16;
3663 case AMDGPU::V_FMAC_F64_e32:
3664 case AMDGPU::V_FMAC_F64_e64:
3665 case AMDGPU::V_FMA_F64_e64:
3666 return AMDGPU::V_FMAAK_F64;
3674 case AMDGPU::V_MAC_F16_e32:
3675 case AMDGPU::V_MAC_F16_e64:
3676 case AMDGPU::V_MAD_F16_e64:
3677 return AMDGPU::V_MADMK_F16;
3678 case AMDGPU::V_MAC_F32_e32:
3679 case AMDGPU::V_MAC_F32_e64:
3680 case AMDGPU::V_MAD_F32_e64:
3681 return AMDGPU::V_MADMK_F32;
3682 case AMDGPU::V_FMAC_F32_e32:
3683 case AMDGPU::V_FMAC_F32_e64:
3684 case AMDGPU::V_FMA_F32_e64:
3685 return AMDGPU::V_FMAMK_F32;
3686 case AMDGPU::V_FMAC_F16_e32:
3687 case AMDGPU::V_FMAC_F16_e64:
3688 case AMDGPU::V_FMAC_F16_t16_e64:
3689 case AMDGPU::V_FMAC_F16_fake16_e64:
3690 case AMDGPU::V_FMAC_F16_t16_e32:
3691 case AMDGPU::V_FMAC_F16_fake16_e32:
3692 case AMDGPU::V_FMA_F16_e64:
3693 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3694 ? AMDGPU::V_FMAMK_F16_t16
3695 : AMDGPU::V_FMAMK_F16_fake16
3696 : AMDGPU::V_FMAMK_F16;
3697 case AMDGPU::V_FMAC_F64_e32:
3698 case AMDGPU::V_FMAC_F64_e64:
3699 case AMDGPU::V_FMA_F64_e64:
3700 return AMDGPU::V_FMAMK_F64;
3714 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3717 if (
Opc == AMDGPU::COPY) {
3718 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3725 if (HasMultipleUses) {
3728 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3731 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3739 if (ImmDefSize == 32 &&
3744 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3745 RI.getSubRegIdxSize(UseSubReg) == 16;
3748 if (RI.hasVGPRs(DstRC))
3751 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3757 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3764 for (
unsigned MovOp :
3765 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3766 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3774 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3778 if (MovDstPhysReg) {
3782 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3789 if (MovDstPhysReg) {
3790 if (!MovDstRC->
contains(MovDstPhysReg))
3806 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3814 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3818 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3820 UseMI.getOperand(0).setReg(MovDstPhysReg);
3825 UseMI.setDesc(NewMCID);
3826 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3827 UseMI.addImplicitDefUseOperands(*MF);
3831 if (HasMultipleUses)
3834 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3835 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3836 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3837 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3838 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3839 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3840 Opc == AMDGPU::V_FMAC_F64_e64) {
3849 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3860 auto CopyRegOperandToNarrowerRC =
3863 if (!
MI.getOperand(OpNo).isReg())
3867 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3870 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3871 get(AMDGPU::COPY), Tmp)
3873 MI.getOperand(OpNo).setReg(Tmp);
3874 MI.getOperand(OpNo).setIsKill();
3881 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3882 if (!RegSrc->
isReg())
3885 ST.getConstantBusLimit(
Opc) < 2)
3900 if (Def && Def->isMoveImmediate() &&
3915 unsigned SrcSubReg = RegSrc->
getSubReg();
3920 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3921 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3922 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3923 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3924 UseMI.untieRegOperand(
3925 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3932 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3933 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3937 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3938 UseMI.getOperand(0).getReg())
3940 UseMI.getOperand(0).setReg(Tmp);
3941 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3942 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
3947 DefMI.eraseFromParent();
3954 if (ST.getConstantBusLimit(
Opc) < 2) {
3957 bool Src0Inlined =
false;
3958 if (Src0->
isReg()) {
3963 if (Def && Def->isMoveImmediate() &&
3968 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
3969 RI.isSGPRReg(*MRI, Src0->
getReg())) {
3975 if (Src1->
isReg() && !Src0Inlined) {
3978 if (Def && Def->isMoveImmediate() &&
3982 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
3995 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3996 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3997 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3998 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3999 UseMI.untieRegOperand(
4000 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4002 const std::optional<int64_t> SubRegImm =
4012 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4013 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4017 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4018 UseMI.getOperand(0).getReg())
4020 UseMI.getOperand(0).setReg(Tmp);
4021 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4022 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4032 DefMI.eraseFromParent();
4044 if (BaseOps1.
size() != BaseOps2.
size())
4046 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4047 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4055 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4056 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4057 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4059 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4062bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4065 int64_t Offset0, Offset1;
4068 bool Offset0IsScalable, Offset1IsScalable;
4082 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4083 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4090 "MIa must load from or modify a memory location");
4092 "MIb must load from or modify a memory location");
4114 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4121 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4131 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4145 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4156 if (
Reg.isPhysical())
4160 Imm = Def->getOperand(1).getImm();
4180 unsigned NumOps =
MI.getNumOperands();
4183 if (
Op.isReg() &&
Op.isKill())
4191 case AMDGPU::V_MAC_F16_e32:
4192 case AMDGPU::V_MAC_F16_e64:
4193 return AMDGPU::V_MAD_F16_e64;
4194 case AMDGPU::V_MAC_F32_e32:
4195 case AMDGPU::V_MAC_F32_e64:
4196 return AMDGPU::V_MAD_F32_e64;
4197 case AMDGPU::V_MAC_LEGACY_F32_e32:
4198 case AMDGPU::V_MAC_LEGACY_F32_e64:
4199 return AMDGPU::V_MAD_LEGACY_F32_e64;
4200 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4201 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4202 return AMDGPU::V_FMA_LEGACY_F32_e64;
4203 case AMDGPU::V_FMAC_F16_e32:
4204 case AMDGPU::V_FMAC_F16_e64:
4205 case AMDGPU::V_FMAC_F16_t16_e64:
4206 case AMDGPU::V_FMAC_F16_fake16_e64:
4207 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4208 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4209 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4210 : AMDGPU::V_FMA_F16_gfx9_e64;
4211 case AMDGPU::V_FMAC_F32_e32:
4212 case AMDGPU::V_FMAC_F32_e64:
4213 return AMDGPU::V_FMA_F32_e64;
4214 case AMDGPU::V_FMAC_F64_e32:
4215 case AMDGPU::V_FMAC_F64_e64:
4216 return AMDGPU::V_FMA_F64_e64;
4236 if (
MI.isBundle()) {
4239 if (
MI.getBundleSize() != 1)
4241 CandidateMI =
MI.getNextNode();
4245 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4249 if (
MI.isBundle()) {
4254 MI.untieRegOperand(MO.getOperandNo());
4262 if (Def.isEarlyClobber() && Def.isReg() &&
4267 auto UpdateDefIndex = [&](
LiveRange &LR) {
4268 auto *S = LR.find(OldIndex);
4269 if (S != LR.end() && S->start == OldIndex) {
4270 assert(S->valno && S->valno->def == OldIndex);
4271 S->start = NewIndex;
4272 S->valno->def = NewIndex;
4276 for (
auto &SR : LI.subranges())
4282 if (U.RemoveMIUse) {
4285 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4289 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4290 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4291 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4292 U.RemoveMIUse->removeOperand(
I);
4297 if (
MI.isBundle()) {
4301 if (MO.isReg() && MO.getReg() == DefReg) {
4302 assert(MO.getSubReg() == 0 &&
4303 "tied sub-registers in bundles currently not supported");
4304 MI.removeOperand(MO.getOperandNo());
4321 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4322 MIOp.setIsUndef(
true);
4323 MIOp.setReg(DummyReg);
4327 if (
MI.isBundle()) {
4331 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4332 MIOp.setIsUndef(
true);
4333 MIOp.setReg(DummyReg);
4346 return MI.isBundle() ? &
MI : NewMI;
4351 ThreeAddressUpdates &U)
const {
4353 unsigned Opc =
MI.getOpcode();
4357 if (NewMFMAOpc != -1) {
4360 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4361 MIB.
add(
MI.getOperand(
I));
4369 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4374 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4375 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4376 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4380 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4381 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4382 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4383 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4384 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4385 bool Src0Literal =
false;
4390 case AMDGPU::V_MAC_F16_e64:
4391 case AMDGPU::V_FMAC_F16_e64:
4392 case AMDGPU::V_FMAC_F16_t16_e64:
4393 case AMDGPU::V_FMAC_F16_fake16_e64:
4394 case AMDGPU::V_MAC_F32_e64:
4395 case AMDGPU::V_MAC_LEGACY_F32_e64:
4396 case AMDGPU::V_FMAC_F32_e64:
4397 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4398 case AMDGPU::V_FMAC_F64_e64:
4400 case AMDGPU::V_MAC_F16_e32:
4401 case AMDGPU::V_FMAC_F16_e32:
4402 case AMDGPU::V_MAC_F32_e32:
4403 case AMDGPU::V_MAC_LEGACY_F32_e32:
4404 case AMDGPU::V_FMAC_F32_e32:
4405 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4406 case AMDGPU::V_FMAC_F64_e32: {
4407 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4408 AMDGPU::OpName::src0);
4409 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4420 MachineInstrBuilder MIB;
4423 const MachineOperand *Src0Mods =
4426 const MachineOperand *Src1Mods =
4429 const MachineOperand *Src2Mods =
4435 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4436 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4438 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4440 MachineInstr *
DefMI =
nullptr;
4476 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4492 if (Src0Literal && !ST.hasVOP3Literal())
4520 switch (
MI.getOpcode()) {
4521 case AMDGPU::S_SET_GPR_IDX_ON:
4522 case AMDGPU::S_SET_GPR_IDX_MODE:
4523 case AMDGPU::S_SET_GPR_IDX_OFF:
4541 if (
MI.isTerminator() ||
MI.isPosition())
4545 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4548 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4554 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4555 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4556 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4557 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4558 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4563 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4564 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4565 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4579 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4584 if (
MI.memoperands_empty())
4589 unsigned AS = Memop->getAddrSpace();
4590 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4591 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4592 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4593 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4608 if (
MI.memoperands_empty())
4617 unsigned AS = Memop->getAddrSpace();
4627 bool TgSplit)
const {
4640 if (
MI.memoperands_empty())
4645 unsigned AS = Memop->getAddrSpace();
4661 unsigned Opcode =
MI.getOpcode();
4676 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4677 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4678 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4679 Opcode == AMDGPU::S_SETHALT)
4682 if (
MI.isCall() ||
MI.isInlineAsm())
4698 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4699 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4700 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4701 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4709 if (
MI.isMetaInstruction())
4713 if (
MI.isCopyLike()) {
4714 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4718 return MI.readsRegister(AMDGPU::EXEC, &RI);
4729 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4733 switch (Imm.getBitWidth()) {
4739 ST.hasInv2PiInlineImm());
4742 ST.hasInv2PiInlineImm());
4744 return ST.has16BitInsts() &&
4746 ST.hasInv2PiInlineImm());
4753 APInt IntImm = Imm.bitcastToAPInt();
4755 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4763 return ST.has16BitInsts() &&
4766 return ST.has16BitInsts() &&
4776 switch (OperandType) {
4786 int32_t Trunc =
static_cast<int32_t
>(Imm);
4830 int16_t Trunc =
static_cast<int16_t
>(Imm);
4831 return ST.has16BitInsts() &&
4840 int16_t Trunc =
static_cast<int16_t
>(Imm);
4841 return ST.has16BitInsts() &&
4892 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4898 return ST.hasVOP3Literal();
4902 int64_t ImmVal)
const {
4904 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4905 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4906 OpNo ==
static_cast<unsigned>(Src1Idx))
4911 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4912 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4913 AMDGPU::OpName::src2))
4915 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4927 "unexpected imm-like operand kind");
4940 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4958 AMDGPU::OpName
OpName)
const {
4960 return Mods && Mods->
getImm();
4973 switch (
MI.getOpcode()) {
4974 default:
return false;
4976 case AMDGPU::V_ADDC_U32_e64:
4977 case AMDGPU::V_SUBB_U32_e64:
4978 case AMDGPU::V_SUBBREV_U32_e64: {
4981 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
4986 case AMDGPU::V_MAC_F16_e64:
4987 case AMDGPU::V_MAC_F32_e64:
4988 case AMDGPU::V_MAC_LEGACY_F32_e64:
4989 case AMDGPU::V_FMAC_F16_e64:
4990 case AMDGPU::V_FMAC_F16_t16_e64:
4991 case AMDGPU::V_FMAC_F16_fake16_e64:
4992 case AMDGPU::V_FMAC_F32_e64:
4993 case AMDGPU::V_FMAC_F64_e64:
4994 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4995 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5000 case AMDGPU::V_CNDMASK_B32_e64:
5006 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5036 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5045 unsigned Op32)
const {
5059 Inst32.
add(
MI.getOperand(
I));
5063 int Idx =
MI.getNumExplicitDefs();
5065 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5070 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5092 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5100 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5103 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5104 AMDGPU::SReg_64RegClass.contains(Reg);
5132 switch (MO.getReg()) {
5134 case AMDGPU::VCC_LO:
5135 case AMDGPU::VCC_HI:
5137 case AMDGPU::FLAT_SCR:
5150 switch (
MI.getOpcode()) {
5151 case AMDGPU::V_READLANE_B32:
5152 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5153 case AMDGPU::V_WRITELANE_B32:
5154 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5161 if (
MI.isPreISelOpcode() ||
5162 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5180 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5191 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5192 ErrInfo =
"illegal copy from vector register to SGPR";
5210 if (!MRI.
isSSA() &&
MI.isCopy())
5211 return verifyCopy(
MI, MRI, ErrInfo);
5213 if (SIInstrInfo::isGenericOpcode(Opcode))
5216 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5217 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5218 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5220 if (Src0Idx == -1) {
5222 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5223 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5224 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5225 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5230 if (!
Desc.isVariadic() &&
5231 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5232 ErrInfo =
"Instruction has wrong number of operands.";
5236 if (
MI.isInlineAsm()) {
5249 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5250 ErrInfo =
"inlineasm operand has incorrect register class.";
5258 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5259 ErrInfo =
"missing memory operand from image instruction.";
5264 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5267 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5268 "all fp values to integers.";
5273 int16_t RegClass = getOpRegClassID(OpInfo);
5275 switch (OpInfo.OperandType) {
5277 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5278 ErrInfo =
"Illegal immediate value for operand.";
5311 ErrInfo =
"Illegal immediate value for operand.";
5320 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5323 OpInfo.OperandType ==
5325 ErrInfo =
"illegal 64-bit immediate value for operand.";
5332 ErrInfo =
"Expected inline constant for operand.";
5346 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5347 ErrInfo =
"Expected immediate, but got non-immediate";
5356 if (OpInfo.isGenericType())
5371 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5372 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5374 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5376 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5377 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5384 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5385 ErrInfo =
"Subtarget requires even aligned vector registers";
5390 if (RegClass != -1) {
5391 if (Reg.isVirtual())
5396 ErrInfo =
"Operand has incorrect register class.";
5404 if (!ST.hasSDWA()) {
5405 ErrInfo =
"SDWA is not supported on this target";
5409 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5410 AMDGPU::OpName::dst_sel}) {
5414 int64_t Imm = MO->
getImm();
5416 ErrInfo =
"Invalid SDWA selection";
5421 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5423 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5428 if (!ST.hasSDWAScalar()) {
5430 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5431 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5438 "Only reg allowed as operands in SDWA instructions on GFX9+";
5444 if (!ST.hasSDWAOmod()) {
5447 if (OMod !=
nullptr &&
5449 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5454 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5455 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5456 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5457 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5460 unsigned Mods = Src0ModsMO->
getImm();
5463 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5469 if (
isVOPC(BasicOpcode)) {
5470 if (!ST.hasSDWASdst() && DstIdx != -1) {
5473 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5474 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5477 }
else if (!ST.hasSDWAOutModsVOPC()) {
5480 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5481 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5487 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5488 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5495 if (DstUnused && DstUnused->isImm() &&
5498 if (!Dst.isReg() || !Dst.isTied()) {
5499 ErrInfo =
"Dst register should have tied register";
5504 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5507 "Dst register should be tied to implicit use of preserved register";
5511 ErrInfo =
"Dst register should use same physical register as preserved";
5517 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5519 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5520 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5523 if (Src1MO.
isImm()) {
5524 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5530 if (
isImage(Opcode) && !
MI.mayStore()) {
5542 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5550 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5554 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5555 if (RegCount > DstSize) {
5556 ErrInfo =
"Image instruction returns too many registers for dst "
5566 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5567 unsigned ConstantBusCount = 0;
5568 bool UsesLiteral =
false;
5571 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5575 LiteralVal = &
MI.getOperand(ImmIdx);
5584 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5595 }
else if (!MO.
isFI()) {
5602 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5612 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5613 return !RI.regsOverlap(SGPRUsed, SGPR);
5622 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5623 Opcode != AMDGPU::V_WRITELANE_B32) {
5624 ErrInfo =
"VOP* instruction violates constant bus restriction";
5628 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5629 ErrInfo =
"VOP3 instruction uses literal";
5636 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5637 unsigned SGPRCount = 0;
5640 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5648 if (MO.
getReg() != SGPRUsed)
5653 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5654 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5661 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5662 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5669 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5679 ErrInfo =
"ABS not allowed in VOP3B instructions";
5692 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5699 if (
Desc.isBranch()) {
5701 ErrInfo =
"invalid branch target for SOPK instruction";
5708 ErrInfo =
"invalid immediate for SOPK instruction";
5713 ErrInfo =
"invalid immediate for SOPK instruction";
5720 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5721 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5722 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5723 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5724 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5725 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5727 const unsigned StaticNumOps =
5728 Desc.getNumOperands() +
Desc.implicit_uses().size();
5729 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5735 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5736 ErrInfo =
"missing implicit register operands";
5742 if (!Dst->isUse()) {
5743 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5748 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5749 UseOpIdx != StaticNumOps + 1) {
5750 ErrInfo =
"movrel implicit operands should be tied";
5757 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5759 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5760 ErrInfo =
"src0 should be subreg of implicit vector use";
5768 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5769 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5775 if (
MI.mayStore() &&
5780 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5781 ErrInfo =
"scalar stores must use m0 as offset register";
5787 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5789 if (
Offset->getImm() != 0) {
5790 ErrInfo =
"subtarget does not support offsets in flat instructions";
5795 if (
isDS(
MI) && !ST.hasGDS()) {
5797 if (GDSOp && GDSOp->
getImm() != 0) {
5798 ErrInfo =
"GDS is not supported on this subtarget";
5806 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5807 AMDGPU::OpName::vaddr0);
5808 AMDGPU::OpName RSrcOpName =
5809 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5810 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5818 ErrInfo =
"dim is out of range";
5823 if (ST.hasR128A16()) {
5825 IsA16 = R128A16->
getImm() != 0;
5826 }
else if (ST.hasA16()) {
5828 IsA16 = A16->
getImm() != 0;
5831 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5833 unsigned AddrWords =
5836 unsigned VAddrWords;
5838 VAddrWords = RsrcIdx - VAddr0Idx;
5839 if (ST.hasPartialNSAEncoding() &&
5841 unsigned LastVAddrIdx = RsrcIdx - 1;
5842 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5850 if (VAddrWords != AddrWords) {
5852 <<
" but got " << VAddrWords <<
"\n");
5853 ErrInfo =
"bad vaddr size";
5863 unsigned DC = DppCt->
getImm();
5864 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5865 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5866 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5867 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5868 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5869 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5870 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5871 ErrInfo =
"Invalid dpp_ctrl value";
5874 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5875 !ST.hasDPPWavefrontShifts()) {
5876 ErrInfo =
"Invalid dpp_ctrl value: "
5877 "wavefront shifts are not supported on GFX10+";
5880 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5881 !ST.hasDPPBroadcasts()) {
5882 ErrInfo =
"Invalid dpp_ctrl value: "
5883 "broadcasts are not supported on GFX10+";
5886 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5888 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5889 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5890 !ST.hasGFX90AInsts()) {
5891 ErrInfo =
"Invalid dpp_ctrl value: "
5892 "row_newbroadcast/row_share is not supported before "
5896 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5897 ErrInfo =
"Invalid dpp_ctrl value: "
5898 "row_share and row_xmask are not supported before GFX10";
5903 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5906 ErrInfo =
"Invalid dpp_ctrl value: "
5907 "DP ALU dpp only support row_newbcast";
5914 AMDGPU::OpName DataName =
5915 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5921 if (!ST.hasGFX90AInsts()) {
5922 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5923 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
5924 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
5925 ErrInfo =
"Invalid register class: "
5926 "agpr loads and stores not supported on this GPU";
5932 if (ST.needsAlignedVGPRs()) {
5933 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
5938 if (Reg.isPhysical())
5939 return !(RI.getHWRegIndex(Reg) & 1);
5941 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5942 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
5945 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5946 Opcode == AMDGPU::DS_GWS_BARRIER) {
5948 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5949 ErrInfo =
"Subtarget requires even aligned vector registers "
5950 "for DS_GWS instructions";
5956 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5957 ErrInfo =
"Subtarget requires even aligned vector registers "
5958 "for vaddr operand of image instructions";
5964 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5966 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5967 ErrInfo =
"Invalid register class: "
5968 "v_accvgpr_write with an SGPR is not supported on this GPU";
5973 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5976 ErrInfo =
"pseudo expects only physical SGPRs";
5983 if (!ST.hasScaleOffset()) {
5984 ErrInfo =
"Subtarget does not support offset scaling";
5988 ErrInfo =
"Instruction does not support offset scaling";
5996 for (
unsigned I = 0;
I < 3; ++
I) {
6002 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6003 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6005 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6006 &AMDGPU::SReg_64RegClass) ||
6007 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6008 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6017 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6019 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6021 : AMDGPU::V_MOV_B32_e32;
6031 default:
return AMDGPU::INSTRUCTION_LIST_END;
6032 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6033 case AMDGPU::COPY:
return AMDGPU::COPY;
6034 case AMDGPU::PHI:
return AMDGPU::PHI;
6035 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6036 case AMDGPU::WQM:
return AMDGPU::WQM;
6037 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6038 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6039 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6040 case AMDGPU::S_ADD_I32:
6041 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6042 case AMDGPU::S_ADDC_U32:
6043 return AMDGPU::V_ADDC_U32_e32;
6044 case AMDGPU::S_SUB_I32:
6045 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6048 case AMDGPU::S_ADD_U32:
6049 return AMDGPU::V_ADD_CO_U32_e32;
6050 case AMDGPU::S_SUB_U32:
6051 return AMDGPU::V_SUB_CO_U32_e32;
6052 case AMDGPU::S_ADD_U64_PSEUDO:
6053 return AMDGPU::V_ADD_U64_PSEUDO;
6054 case AMDGPU::S_SUB_U64_PSEUDO:
6055 return AMDGPU::V_SUB_U64_PSEUDO;
6056 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6057 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6058 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6059 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6060 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6061 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6062 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6063 case AMDGPU::S_XNOR_B32:
6064 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6065 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6066 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6067 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6068 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6069 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6070 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6071 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6072 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6073 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6074 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6075 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6076 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6077 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6078 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6079 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6080 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6081 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6082 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6083 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6084 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6085 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6086 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6087 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6088 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6089 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6090 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6091 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6092 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6093 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6094 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6095 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6096 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6097 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6098 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6099 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6100 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6101 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6102 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6103 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6104 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6105 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6106 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6107 case AMDGPU::S_CVT_F32_F16:
6108 case AMDGPU::S_CVT_HI_F32_F16:
6109 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6110 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6111 case AMDGPU::S_CVT_F16_F32:
6112 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6113 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6114 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6115 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6116 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6117 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6118 case AMDGPU::S_CEIL_F16:
6119 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6120 : AMDGPU::V_CEIL_F16_fake16_e64;
6121 case AMDGPU::S_FLOOR_F16:
6122 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6123 : AMDGPU::V_FLOOR_F16_fake16_e64;
6124 case AMDGPU::S_TRUNC_F16:
6125 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6126 : AMDGPU::V_TRUNC_F16_fake16_e64;
6127 case AMDGPU::S_RNDNE_F16:
6128 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6129 : AMDGPU::V_RNDNE_F16_fake16_e64;
6130 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6131 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6132 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6133 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6134 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6135 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6136 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6137 case AMDGPU::S_ADD_F16:
6138 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6139 : AMDGPU::V_ADD_F16_fake16_e64;
6140 case AMDGPU::S_SUB_F16:
6141 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6142 : AMDGPU::V_SUB_F16_fake16_e64;
6143 case AMDGPU::S_MIN_F16:
6144 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6145 : AMDGPU::V_MIN_F16_fake16_e64;
6146 case AMDGPU::S_MAX_F16:
6147 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6148 : AMDGPU::V_MAX_F16_fake16_e64;
6149 case AMDGPU::S_MINIMUM_F16:
6150 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6151 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6152 case AMDGPU::S_MAXIMUM_F16:
6153 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6154 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6155 case AMDGPU::S_MUL_F16:
6156 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6157 : AMDGPU::V_MUL_F16_fake16_e64;
6158 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6159 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6160 case AMDGPU::S_FMAC_F16:
6161 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6162 : AMDGPU::V_FMAC_F16_fake16_e64;
6163 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6164 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6165 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6166 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6167 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6168 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6169 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6170 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6171 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6172 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6173 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6174 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6175 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6176 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6177 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6178 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6179 case AMDGPU::S_CMP_LT_F16:
6180 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6181 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6182 case AMDGPU::S_CMP_EQ_F16:
6183 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6184 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6185 case AMDGPU::S_CMP_LE_F16:
6186 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6187 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6188 case AMDGPU::S_CMP_GT_F16:
6189 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6190 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6191 case AMDGPU::S_CMP_LG_F16:
6192 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6193 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6194 case AMDGPU::S_CMP_GE_F16:
6195 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6196 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6197 case AMDGPU::S_CMP_O_F16:
6198 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6199 : AMDGPU::V_CMP_O_F16_fake16_e64;
6200 case AMDGPU::S_CMP_U_F16:
6201 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6202 : AMDGPU::V_CMP_U_F16_fake16_e64;
6203 case AMDGPU::S_CMP_NGE_F16:
6204 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6205 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6206 case AMDGPU::S_CMP_NLG_F16:
6207 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6208 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6209 case AMDGPU::S_CMP_NGT_F16:
6210 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6211 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6212 case AMDGPU::S_CMP_NLE_F16:
6213 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6214 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6215 case AMDGPU::S_CMP_NEQ_F16:
6216 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6217 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6218 case AMDGPU::S_CMP_NLT_F16:
6219 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6220 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6221 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6222 case AMDGPU::V_S_EXP_F16_e64:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6224 : AMDGPU::V_EXP_F16_fake16_e64;
6225 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6226 case AMDGPU::V_S_LOG_F16_e64:
6227 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6228 : AMDGPU::V_LOG_F16_fake16_e64;
6229 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6230 case AMDGPU::V_S_RCP_F16_e64:
6231 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6232 : AMDGPU::V_RCP_F16_fake16_e64;
6233 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6234 case AMDGPU::V_S_RSQ_F16_e64:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6236 : AMDGPU::V_RSQ_F16_fake16_e64;
6237 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6238 case AMDGPU::V_S_SQRT_F16_e64:
6239 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6240 : AMDGPU::V_SQRT_F16_fake16_e64;
6243 "Unexpected scalar opcode without corresponding vector one!");
6292 "Not a whole wave func");
6295 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6296 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6303 unsigned OpNo)
const {
6305 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6306 Desc.operands()[OpNo].RegClass == -1) {
6309 if (Reg.isVirtual()) {
6313 return RI.getPhysRegBaseClass(Reg);
6316 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6317 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6322 constexpr AMDGPU::OpName OpNames[] = {
6323 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6326 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6327 if (
static_cast<unsigned>(SrcIdx) ==
OpIdx)
6339 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[
OpIdx]);
6341 unsigned Size = RI.getRegSizeInBits(*RC);
6342 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6343 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6344 : AMDGPU::V_MOV_B32_e32;
6346 Opcode = AMDGPU::COPY;
6347 else if (RI.isSGPRClass(RC))
6348 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6373 .
addImm(AMDGPU::sub0_sub1)
6375 .
addImm(AMDGPU::sub2_sub3);
6388 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6394 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6405 if (SubIdx == AMDGPU::sub0)
6407 if (SubIdx == AMDGPU::sub1)
6419void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6435 if (Reg.isPhysical())
6445 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6448 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6455 unsigned Opc =
MI.getOpcode();
6458 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6468 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6469 if (IsAGPR && !ST.hasMAIInsts())
6475 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6476 const int DataIdx = AMDGPU::getNamedOperandIdx(
6477 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6478 if ((
int)
OpIdx == VDstIdx && DataIdx != -1 &&
6479 MI.getOperand(DataIdx).isReg() &&
6480 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6482 if ((
int)
OpIdx == DataIdx) {
6483 if (VDstIdx != -1 &&
6484 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6487 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6488 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6489 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6494 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6495 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6496 RI.isSGPRReg(MRI, MO.
getReg()))
6499 if (ST.hasFlatScratchHiInB64InstHazard() &&
6506 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6509 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6510 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6530 constexpr unsigned NumOps = 3;
6531 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6532 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6533 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6534 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6539 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6542 MO = &
MI.getOperand(SrcIdx);
6545 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6549 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6553 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6557 return !OpSel && !OpSelHi;
6566 int64_t RegClass = getOpRegClassID(OpInfo);
6568 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6574 if (
isVALU(
MI,
true) && !IsInlineConst &&
6578 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6579 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6583 if (!LiteralLimit--)
6593 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6601 if (--ConstantBusLimit <= 0)
6613 if (!LiteralLimit--)
6615 if (--ConstantBusLimit <= 0)
6621 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6625 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6627 !
Op.isIdenticalTo(*MO))
6637 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6652 bool Is64BitOp = Is64BitFPOp ||
6660 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6669 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6687 bool IsGFX950Only = ST.hasGFX950Insts();
6688 bool IsGFX940Only = ST.hasGFX940Insts();
6690 if (!IsGFX950Only && !IsGFX940Only)
6708 unsigned Opcode =
MI.getOpcode();
6710 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6711 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6712 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6713 case AMDGPU::V_MQSAD_U32_U8_e64:
6714 case AMDGPU::V_PK_ADD_F16:
6715 case AMDGPU::V_PK_ADD_F32:
6716 case AMDGPU::V_PK_ADD_I16:
6717 case AMDGPU::V_PK_ADD_U16:
6718 case AMDGPU::V_PK_ASHRREV_I16:
6719 case AMDGPU::V_PK_FMA_F16:
6720 case AMDGPU::V_PK_FMA_F32:
6721 case AMDGPU::V_PK_FMAC_F16_e32:
6722 case AMDGPU::V_PK_FMAC_F16_e64:
6723 case AMDGPU::V_PK_LSHLREV_B16:
6724 case AMDGPU::V_PK_LSHRREV_B16:
6725 case AMDGPU::V_PK_MAD_I16:
6726 case AMDGPU::V_PK_MAD_U16:
6727 case AMDGPU::V_PK_MAX_F16:
6728 case AMDGPU::V_PK_MAX_I16:
6729 case AMDGPU::V_PK_MAX_U16:
6730 case AMDGPU::V_PK_MIN_F16:
6731 case AMDGPU::V_PK_MIN_I16:
6732 case AMDGPU::V_PK_MIN_U16:
6733 case AMDGPU::V_PK_MOV_B32:
6734 case AMDGPU::V_PK_MUL_F16:
6735 case AMDGPU::V_PK_MUL_F32:
6736 case AMDGPU::V_PK_MUL_LO_U16:
6737 case AMDGPU::V_PK_SUB_I16:
6738 case AMDGPU::V_PK_SUB_U16:
6739 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6748 unsigned Opc =
MI.getOpcode();
6751 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6754 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6760 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6761 RI.isSGPRReg(MRI, Src0.
getReg()))
6767 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6769 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6775 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6786 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6787 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6788 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6800 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6801 RI.isVGPR(MRI, Src1.
getReg())) {
6814 if (HasImplicitSGPR || !
MI.isCommutable()) {
6831 if (CommutedOpc == -1) {
6836 MI.setDesc(
get(CommutedOpc));
6840 bool Src0Kill = Src0.
isKill();
6844 else if (Src1.
isReg()) {
6859 unsigned Opc =
MI.getOpcode();
6862 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6863 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6864 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6867 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6868 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6869 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6870 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6871 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6872 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6873 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6883 if (VOP3Idx[2] != -1) {
6895 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6896 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6898 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6900 SGPRsUsed.
insert(SGPRReg);
6904 for (
int Idx : VOP3Idx) {
6913 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6925 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
6932 if (ConstantBusLimit > 0) {
6944 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
6945 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
6951 for (
unsigned I = 0;
I < 3; ++
I) {
6964 SRC = RI.getCommonSubClass(SRC, DstRC);
6967 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6969 if (RI.hasAGPRs(VRC)) {
6970 VRC = RI.getEquivalentVGPRClass(VRC);
6973 get(TargetOpcode::COPY), NewSrcReg)
6980 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6986 for (
unsigned i = 0; i < SubRegs; ++i) {
6989 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6990 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6996 get(AMDGPU::REG_SEQUENCE), DstReg);
6997 for (
unsigned i = 0; i < SubRegs; ++i) {
6999 MIB.
addImm(RI.getSubRegFromChannel(i));
7012 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7014 SBase->setReg(SGPR);
7017 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7025 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7026 if (OldSAddrIdx < 0)
7039 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7042 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7043 if (NewVAddrIdx < 0)
7046 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7050 if (OldVAddrIdx >= 0) {
7064 if (OldVAddrIdx == NewVAddrIdx) {
7075 assert(OldSAddrIdx == NewVAddrIdx);
7077 if (OldVAddrIdx >= 0) {
7078 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7079 AMDGPU::OpName::vdst_in);
7083 if (NewVDstIn != -1) {
7084 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7090 if (NewVDstIn != -1) {
7091 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7132 unsigned OpSubReg =
Op.getSubReg();
7135 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7142 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7143 .
addReg(OpReg, {}, OpSubReg);
7145 Op.setSubReg(AMDGPU::NoSubRegister);
7152 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7155 bool ImpDef = Def->isImplicitDef();
7156 while (!ImpDef && Def && Def->isCopy()) {
7157 if (Def->getOperand(1).getReg().isPhysical())
7160 ImpDef = Def && Def->isImplicitDef();
7162 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7178 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7183 bool UseNewExecInstructions =
7192 if (UseNewExecInstructions) {
7227 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7228 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7229 unsigned NumSubRegs =
RegSize / 32;
7230 Register VScalarOp = ScalarOp->getReg();
7233 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7235 if (NumSubRegs == 1) {
7238 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7239 Common != VScalarOpRC) {
7246 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7249 if (UseNewExecInstructions) {
7251 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7254 if (
I == LoopBB.
end())
7259 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7265 CondReg = NewCondReg;
7276 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7277 ScalarOp->setReg(CurReg);
7280 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7281 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7283 ScalarOp->setReg(PhySGPRs[Idx]);
7285 ScalarOp->setIsKill();
7289 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7290 "Unhandled register size");
7292 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7299 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7300 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7303 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7304 .
addReg(VScalarOp, VScalarOpUndef,
7305 TRI->getSubRegFromChannel(Idx + 1));
7312 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7319 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7321 if (UseNewExecInstructions) {
7323 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7325 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7326 if (
I == LoopBB.
end())
7330 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7332 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7336 CondReg = NewCondReg;
7347 const auto *SScalarOpRC =
7353 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7354 unsigned Channel = 0;
7355 for (
Register Piece : ReadlanePieces) {
7356 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7360 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7361 ScalarOp->setReg(SScalarOp);
7363 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7364 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7366 ScalarOp->setReg(PhySGPRs[Idx]);
7368 ScalarOp->setIsKill();
7376 if (!UseNewExecInstructions) {
7388 if (UseNewExecInstructions) {
7412 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7413 "Physical SGPRs must be empty or match the number of scalar operands");
7419 if (!Begin.isValid())
7421 if (!End.isValid()) {
7427 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7436 std::numeric_limits<unsigned>::max()) !=
7454 for (
auto I = Begin;
I != AfterMI;
I++) {
7455 for (
auto &MO :
I->all_uses())
7491 for (
auto &Succ : RemainderBB->
successors()) {
7516static std::tuple<unsigned, unsigned>
7524 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7525 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7532 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7549 .
addImm(AMDGPU::sub0_sub1)
7555 return std::tuple(RsrcPtr, NewSRsrc);
7566 if (ST.useRealTrue16Insts())
7596 if (
MI.getOpcode() == AMDGPU::PHI) {
7598 assert(!RI.isSGPRClass(VRC));
7601 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7603 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7619 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7622 if (RI.hasVGPRs(DstRC)) {
7626 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7628 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7646 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7651 if (DstRC != Src0RC) {
7660 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7662 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7668 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7669 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7670 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7671 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7672 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7673 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7674 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7676 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7689 ? AMDGPU::OpName::rsrc
7690 : AMDGPU::OpName::srsrc;
7695 AMDGPU::OpName SampOpName =
7696 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7705 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7713 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7717 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7727 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7728 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7729 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7730 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7732 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7739 bool isSoffsetLegal =
true;
7741 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7742 if (SoffsetIdx != -1) {
7746 isSoffsetLegal =
false;
7750 bool isRsrcLegal =
true;
7752 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7753 if (RsrcIdx != -1) {
7755 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7756 isRsrcLegal =
false;
7760 if (isRsrcLegal && isSoffsetLegal)
7788 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7792 unsigned RsrcPtr, NewSRsrc;
7799 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7800 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7806 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7807 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7820 }
else if (!VAddr && ST.hasAddr64()) {
7824 "FIXME: Need to emit flat atomics here");
7826 unsigned RsrcPtr, NewSRsrc;
7852 MIB.
addImm(CPol->getImm());
7857 MIB.
addImm(TFE->getImm());
7877 MI.removeFromParent();
7882 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7883 .addImm(AMDGPU::sub0)
7884 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7885 .addImm(AMDGPU::sub1);
7888 if (!isSoffsetLegal) {
7899 if (!isSoffsetLegal) {
7908 if (InSet.insert(
MI).second)
7912 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
7913 if (RsrcIdx != -1) {
7914 DeferredList.insert(
MI);
7919 return DeferredList.contains(
MI);
7929 if (!ST.useRealTrue16Insts())
7932 unsigned Opcode =
MI.getOpcode();
7935 if (
OpIdx >=
MI.getNumExplicitOperands() ||
7936 OpIdx >=
get(Opcode).getNumOperands() ||
7937 get(Opcode).operands()[
OpIdx].RegClass == -1)
7941 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
7945 if (!RI.isVGPRClass(CurrRC))
7948 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[
OpIdx]);
7950 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7952 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
7953 Op.setSubReg(AMDGPU::lo16);
7958 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
7959 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7969 Op.setReg(NewDstReg);
7970 Op.setSubReg(AMDGPU::NoSubRegister);
7983 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7984 "This only handle waterfall for SI_CALL_ISEL");
7991 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7994 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7999 while (End !=
MBB.end() && End->isCopy() &&
8000 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8010 while (!Worklist.
empty()) {
8016 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8022 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8024 "Deferred MachineInstr are not supposed to re-populate worklist");
8027 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8028 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8030 Entry.second.SGPRs);
8033 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8035 Entry.first->eraseFromParent();
8043 if (SubRegIndices.
size() <= 1) {
8046 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8053 for (int16_t Indice : SubRegIndices) {
8056 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8063 get(AMDGPU::REG_SEQUENCE), DstReg);
8064 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8066 MIB.
addImm(RI.getSubRegFromChannel(i));
8076 if (DstReg == AMDGPU::M0) {
8089 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8091 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8092 if (
UseMI->getOperand(i).isReg() &&
8093 UseMI->getOperand(i).getReg() == DstReg) {
8097 V2SCopyInfo.MOs.push_back(MO);
8098 V2SCopyInfo.SGPRs.push_back(DstReg);
8102 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8103 I->getOperand(0).isReg() &&
8104 I->getOperand(0).getReg() == DstReg) {
8107 }
else if (
I->readsRegister(DstReg, &RI)) {
8109 V2SPhyCopiesToErase[&Inst] =
false;
8111 if (
I->findRegisterDefOperand(DstReg, &RI))
8133 case AMDGPU::S_ADD_I32:
8134 case AMDGPU::S_SUB_I32: {
8138 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8146 case AMDGPU::S_MUL_U64:
8147 if (ST.hasVMulU64Inst()) {
8148 NewOpcode = AMDGPU::V_MUL_U64_e64;
8152 splitScalarSMulU64(Worklist, Inst, MDT);
8156 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8157 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8160 splitScalarSMulPseudo(Worklist, Inst, MDT);
8164 case AMDGPU::S_AND_B64:
8165 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8169 case AMDGPU::S_OR_B64:
8170 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8174 case AMDGPU::S_XOR_B64:
8175 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8179 case AMDGPU::S_NAND_B64:
8180 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8184 case AMDGPU::S_NOR_B64:
8185 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8189 case AMDGPU::S_XNOR_B64:
8190 if (ST.hasDLInsts())
8191 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8193 splitScalar64BitXnor(Worklist, Inst, MDT);
8197 case AMDGPU::S_ANDN2_B64:
8198 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8202 case AMDGPU::S_ORN2_B64:
8203 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8207 case AMDGPU::S_BREV_B64:
8208 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8212 case AMDGPU::S_NOT_B64:
8213 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8217 case AMDGPU::S_BCNT1_I32_B64:
8218 splitScalar64BitBCNT(Worklist, Inst);
8222 case AMDGPU::S_BFE_I64:
8223 splitScalar64BitBFE(Worklist, Inst);
8227 case AMDGPU::S_FLBIT_I32_B64:
8228 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8231 case AMDGPU::S_FF1_I32_B64:
8232 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8236 case AMDGPU::S_LSHL_B32:
8237 if (ST.hasOnlyRevVALUShifts()) {
8238 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8242 case AMDGPU::S_ASHR_I32:
8243 if (ST.hasOnlyRevVALUShifts()) {
8244 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8248 case AMDGPU::S_LSHR_B32:
8249 if (ST.hasOnlyRevVALUShifts()) {
8250 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8254 case AMDGPU::S_LSHL_B64:
8255 if (ST.hasOnlyRevVALUShifts()) {
8257 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8258 : AMDGPU::V_LSHLREV_B64_e64;
8262 case AMDGPU::S_ASHR_I64:
8263 if (ST.hasOnlyRevVALUShifts()) {
8264 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8268 case AMDGPU::S_LSHR_B64:
8269 if (ST.hasOnlyRevVALUShifts()) {
8270 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8275 case AMDGPU::S_ABS_I32:
8276 lowerScalarAbs(Worklist, Inst);
8280 case AMDGPU::S_ABSDIFF_I32:
8281 lowerScalarAbsDiff(Worklist, Inst);
8285 case AMDGPU::S_CBRANCH_SCC0:
8286 case AMDGPU::S_CBRANCH_SCC1: {
8289 bool IsSCC = CondReg == AMDGPU::SCC;
8297 case AMDGPU::S_BFE_U64:
8298 case AMDGPU::S_BFM_B64:
8301 case AMDGPU::S_PACK_LL_B32_B16:
8302 case AMDGPU::S_PACK_LH_B32_B16:
8303 case AMDGPU::S_PACK_HL_B32_B16:
8304 case AMDGPU::S_PACK_HH_B32_B16:
8305 movePackToVALU(Worklist, MRI, Inst);
8309 case AMDGPU::S_XNOR_B32:
8310 lowerScalarXnor(Worklist, Inst);
8314 case AMDGPU::S_NAND_B32:
8315 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8319 case AMDGPU::S_NOR_B32:
8320 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8324 case AMDGPU::S_ANDN2_B32:
8325 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8329 case AMDGPU::S_ORN2_B32:
8330 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8338 case AMDGPU::S_ADD_CO_PSEUDO:
8339 case AMDGPU::S_SUB_CO_PSEUDO: {
8340 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8341 ? AMDGPU::V_ADDC_U32_e64
8342 : AMDGPU::V_SUBB_U32_e64;
8343 const auto *CarryRC = RI.getWaveMaskRegClass();
8365 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8369 case AMDGPU::S_UADDO_PSEUDO:
8370 case AMDGPU::S_USUBO_PSEUDO: {
8376 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8377 ? AMDGPU::V_ADD_CO_U32_e64
8378 : AMDGPU::V_SUB_CO_U32_e64;
8390 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8394 case AMDGPU::S_LSHL1_ADD_U32:
8395 case AMDGPU::S_LSHL2_ADD_U32:
8396 case AMDGPU::S_LSHL3_ADD_U32:
8397 case AMDGPU::S_LSHL4_ADD_U32: {
8401 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8402 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8403 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8417 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8421 case AMDGPU::S_CSELECT_B32:
8422 case AMDGPU::S_CSELECT_B64:
8423 lowerSelect(Worklist, Inst, MDT);
8426 case AMDGPU::S_CMP_EQ_I32:
8427 case AMDGPU::S_CMP_LG_I32:
8428 case AMDGPU::S_CMP_GT_I32:
8429 case AMDGPU::S_CMP_GE_I32:
8430 case AMDGPU::S_CMP_LT_I32:
8431 case AMDGPU::S_CMP_LE_I32:
8432 case AMDGPU::S_CMP_EQ_U32:
8433 case AMDGPU::S_CMP_LG_U32:
8434 case AMDGPU::S_CMP_GT_U32:
8435 case AMDGPU::S_CMP_GE_U32:
8436 case AMDGPU::S_CMP_LT_U32:
8437 case AMDGPU::S_CMP_LE_U32:
8438 case AMDGPU::S_CMP_EQ_U64:
8439 case AMDGPU::S_CMP_LG_U64:
8440 case AMDGPU::S_CMP_LT_F32:
8441 case AMDGPU::S_CMP_EQ_F32:
8442 case AMDGPU::S_CMP_LE_F32:
8443 case AMDGPU::S_CMP_GT_F32:
8444 case AMDGPU::S_CMP_LG_F32:
8445 case AMDGPU::S_CMP_GE_F32:
8446 case AMDGPU::S_CMP_O_F32:
8447 case AMDGPU::S_CMP_U_F32:
8448 case AMDGPU::S_CMP_NGE_F32:
8449 case AMDGPU::S_CMP_NLG_F32:
8450 case AMDGPU::S_CMP_NGT_F32:
8451 case AMDGPU::S_CMP_NLE_F32:
8452 case AMDGPU::S_CMP_NEQ_F32:
8453 case AMDGPU::S_CMP_NLT_F32: {
8458 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8472 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8476 case AMDGPU::S_CMP_LT_F16:
8477 case AMDGPU::S_CMP_EQ_F16:
8478 case AMDGPU::S_CMP_LE_F16:
8479 case AMDGPU::S_CMP_GT_F16:
8480 case AMDGPU::S_CMP_LG_F16:
8481 case AMDGPU::S_CMP_GE_F16:
8482 case AMDGPU::S_CMP_O_F16:
8483 case AMDGPU::S_CMP_U_F16:
8484 case AMDGPU::S_CMP_NGE_F16:
8485 case AMDGPU::S_CMP_NLG_F16:
8486 case AMDGPU::S_CMP_NGT_F16:
8487 case AMDGPU::S_CMP_NLE_F16:
8488 case AMDGPU::S_CMP_NEQ_F16:
8489 case AMDGPU::S_CMP_NLT_F16: {
8511 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8515 case AMDGPU::S_CVT_HI_F32_F16: {
8518 if (ST.useRealTrue16Insts()) {
8523 .
addReg(TmpReg, {}, AMDGPU::hi16)
8539 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8543 case AMDGPU::S_MINIMUM_F32:
8544 case AMDGPU::S_MAXIMUM_F32: {
8556 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8560 case AMDGPU::S_MINIMUM_F16:
8561 case AMDGPU::S_MAXIMUM_F16: {
8563 ? &AMDGPU::VGPR_16RegClass
8564 : &AMDGPU::VGPR_32RegClass);
8575 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8579 case AMDGPU::V_S_EXP_F16_e64:
8580 case AMDGPU::V_S_LOG_F16_e64:
8581 case AMDGPU::V_S_RCP_F16_e64:
8582 case AMDGPU::V_S_RSQ_F16_e64:
8583 case AMDGPU::V_S_SQRT_F16_e64: {
8585 ? &AMDGPU::VGPR_16RegClass
8586 : &AMDGPU::VGPR_32RegClass);
8597 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8603 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8611 if (NewOpcode == Opcode) {
8618 V2SPhyCopiesToErase);
8626 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8633 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8638 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8639 UseMO.setReg(NewDstReg);
8669 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8673 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8679 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8686 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8688 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8693 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8701 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8711 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8712 AMDGPU::OpName::src0_modifiers) >= 0)
8716 NewInstr->addOperand(Src);
8719 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8722 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8724 NewInstr.addImm(
Size);
8725 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8729 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8734 "Scalar BFE is only implemented for constant width and offset");
8742 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8743 AMDGPU::OpName::src1_modifiers) >= 0)
8745 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8747 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8748 AMDGPU::OpName::src2_modifiers) >= 0)
8750 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8752 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8754 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8756 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8762 NewInstr->addOperand(
Op);
8769 if (
Op.getReg() == AMDGPU::SCC) {
8771 if (
Op.isDef() && !
Op.isDead())
8772 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8774 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8779 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8780 Register DstReg = NewInstr->getOperand(0).getReg();
8793 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8797std::pair<bool, MachineBasicBlock *>
8800 if (ST.hasAddNoCarryInsts()) {
8812 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8814 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8815 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8826 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8827 return std::pair(
true, NewBB);
8830 return std::pair(
false,
nullptr);
8847 bool IsSCC = (CondReg == AMDGPU::SCC);
8855 for (MachineOperand &UseMO :
8857 MachineInstr &
UseMI = *UseMO.getParent();
8858 switch (
UseMI.getOpcode()) {
8859 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8860 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8861 case AMDGPU::V_CNDMASK_B16_t16_e32:
8862 case AMDGPU::V_CNDMASK_B16_t16_e64:
8863 case AMDGPU::V_CNDMASK_B32_e32:
8864 case AMDGPU::V_CNDMASK_B32_e64:
8865 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8866 if (UseMO.isImplicit() ||
8868 UseMO.setReg(CondReg);
8882 bool CopyFound =
false;
8883 for (MachineInstr &CandI :
8886 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8888 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8890 .
addReg(CandI.getOperand(1).getReg());
8902 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8911 MachineInstr *NewInst;
8912 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
8913 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8928 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8943 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8944 : AMDGPU::V_SUB_CO_U32_e32;
8955 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8972 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8973 : AMDGPU::V_SUB_CO_U32_e32;
8986 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9000 if (ST.hasDLInsts()) {
9010 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9016 bool Src0IsSGPR = Src0.
isReg() &&
9018 bool Src1IsSGPR = Src1.
isReg() &&
9032 }
else if (Src1IsSGPR) {
9050 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9056 unsigned Opcode)
const {
9080 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9085 unsigned Opcode)
const {
9109 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9124 const MCInstrDesc &InstDesc =
get(Opcode);
9127 &AMDGPU::SGPR_32RegClass;
9130 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9133 AMDGPU::sub0, Src0SubRC);
9138 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9141 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9144 AMDGPU::sub1, Src0SubRC);
9147 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9161 Worklist.
insert(&LoHalf);
9162 Worklist.
insert(&HiHalf);
9168 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9192 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9193 if (RI.isSGPRClass(Src0SubRC))
9194 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9196 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9197 if (RI.isSGPRClass(Src1SubRC))
9198 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9202 MachineOperand Op0L =
9204 MachineOperand Op1L =
9206 MachineOperand Op0H =
9208 MachineOperand Op1H =
9227 MachineInstr *Op1L_Op0H =
9233 MachineInstr *Op1H_Op0L =
9239 MachineInstr *Carry =
9244 MachineInstr *LoHalf =
9254 MachineInstr *HiHalf =
9277 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9301 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9302 if (RI.isSGPRClass(Src0SubRC))
9303 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9305 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9306 if (RI.isSGPRClass(Src1SubRC))
9307 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9311 MachineOperand Op0L =
9313 MachineOperand Op1L =
9317 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9318 ? AMDGPU::V_MUL_HI_U32_e64
9319 : AMDGPU::V_MUL_HI_I32_e64;
9320 MachineInstr *HiHalf =
9323 MachineInstr *LoHalf =
9342 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9358 const MCInstrDesc &InstDesc =
get(Opcode);
9361 &AMDGPU::SGPR_32RegClass;
9364 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9367 &AMDGPU::SGPR_32RegClass;
9370 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9373 AMDGPU::sub0, Src0SubRC);
9375 AMDGPU::sub0, Src1SubRC);
9377 AMDGPU::sub1, Src0SubRC);
9379 AMDGPU::sub1, Src1SubRC);
9384 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9387 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9392 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9405 Worklist.
insert(&LoHalf);
9406 Worklist.
insert(&HiHalf);
9409 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9429 MachineOperand* Op0;
9430 MachineOperand* Op1;
9432 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9465 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9468 &AMDGPU::SGPR_32RegClass;
9474 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9477 AMDGPU::sub0, SrcSubRC);
9479 AMDGPU::sub1, SrcSubRC);
9489 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9508 Offset == 0 &&
"Not implemented");
9531 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9541 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9544 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9550 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9569 const MCInstrDesc &InstDesc =
get(Opcode);
9571 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9572 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9573 : AMDGPU::V_ADD_CO_U32_e32;
9576 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9578 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9580 MachineOperand SrcRegSub0 =
9582 MachineOperand SrcRegSub1 =
9595 .
addReg(IsCtlz ? MidReg1 : MidReg2)
9601 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9605 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9608void SIInstrInfo::addUsersToMoveToVALUWorklist(
9612 MachineInstr &
UseMI = *MO.getParent();
9616 switch (
UseMI.getOpcode()) {
9619 case AMDGPU::SOFT_WQM:
9620 case AMDGPU::STRICT_WWM:
9621 case AMDGPU::STRICT_WQM:
9622 case AMDGPU::REG_SEQUENCE:
9624 case AMDGPU::INSERT_SUBREG:
9627 OpNo = MO.getOperandNo();
9634 if (!RI.hasVectorRegisters(OpRC))
9651 if (ST.useRealTrue16Insts()) {
9653 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9656 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9662 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9665 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9674 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9676 case AMDGPU::S_PACK_LL_B32_B16:
9678 .addReg(SrcReg0, {},
9679 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9680 .addImm(AMDGPU::lo16)
9681 .addReg(SrcReg1, {},
9682 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9683 .addImm(AMDGPU::hi16);
9685 case AMDGPU::S_PACK_LH_B32_B16:
9687 .addReg(SrcReg0, {},
9688 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9689 .addImm(AMDGPU::lo16)
9690 .addReg(SrcReg1, {}, AMDGPU::hi16)
9691 .addImm(AMDGPU::hi16);
9693 case AMDGPU::S_PACK_HL_B32_B16:
9694 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9695 .addImm(AMDGPU::lo16)
9696 .addReg(SrcReg1, {},
9697 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9698 .addImm(AMDGPU::hi16);
9700 case AMDGPU::S_PACK_HH_B32_B16:
9701 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9702 .addImm(AMDGPU::lo16)
9703 .addReg(SrcReg1, {}, AMDGPU::hi16)
9704 .addImm(AMDGPU::hi16);
9712 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9717 case AMDGPU::S_PACK_LL_B32_B16: {
9736 case AMDGPU::S_PACK_LH_B32_B16: {
9746 case AMDGPU::S_PACK_HL_B32_B16: {
9757 case AMDGPU::S_PACK_HH_B32_B16: {
9777 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9786 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9787 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9788 SmallVector<MachineInstr *, 4> CopyToDelete;
9791 for (MachineInstr &
MI :
9795 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9798 MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9799 Register DestReg =
MI.getOperand(0).getReg();
9806 MI.getOperand(SCCIdx).setReg(NewCond);
9812 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9815 for (
auto &Copy : CopyToDelete)
9816 Copy->eraseFromParent();
9824void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9830 for (MachineInstr &
MI :
9833 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9835 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9852 case AMDGPU::REG_SEQUENCE:
9853 case AMDGPU::INSERT_SUBREG:
9855 case AMDGPU::SOFT_WQM:
9856 case AMDGPU::STRICT_WWM:
9857 case AMDGPU::STRICT_WQM: {
9859 if (RI.isAGPRClass(SrcRC)) {
9860 if (RI.isAGPRClass(NewDstRC))
9865 case AMDGPU::REG_SEQUENCE:
9866 case AMDGPU::INSERT_SUBREG:
9867 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9870 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9876 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9879 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9893 int OpIndices[3])
const {
9894 const MCInstrDesc &
Desc =
MI.getDesc();
9910 const MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9912 for (
unsigned i = 0; i < 3; ++i) {
9913 int Idx = OpIndices[i];
9917 const MachineOperand &MO =
MI.getOperand(Idx);
9924 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
9925 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9932 if (RI.isSGPRClass(RegRC))
9950 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9951 SGPRReg = UsedSGPRs[0];
9954 if (!SGPRReg && UsedSGPRs[1]) {
9955 if (UsedSGPRs[1] == UsedSGPRs[2])
9956 SGPRReg = UsedSGPRs[1];
9963 AMDGPU::OpName OperandName)
const {
9964 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9967 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
9971 return &
MI.getOperand(Idx);
9985 if (ST.isAmdHsaOS()) {
9988 RsrcDataFormat |= (1ULL << 56);
9993 RsrcDataFormat |= (2ULL << 59);
9996 return RsrcDataFormat;
10006 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10011 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10018 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10024 unsigned Opc =
MI.getOpcode();
10030 return get(
Opc).mayLoad() &&
10037 if (!Addr || !Addr->
isFI())
10046 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10048 return MI.getOperand(VDataIdx).getReg();
10058 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10060 return MI.getOperand(DataIdx).getReg();
10081 if (!
MI.mayStore())
10094 unsigned Opc =
MI.getOpcode();
10096 unsigned DescSize =
Desc.getSize();
10101 unsigned Size = DescSize;
10105 if (
MI.isBranch() && ST.hasOffset3fBug())
10116 bool HasLiteral =
false;
10117 unsigned LiteralSize = 4;
10118 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10123 if (ST.has64BitLiterals()) {
10124 switch (OpInfo.OperandType) {
10149 return HasLiteral ? DescSize + LiteralSize : DescSize;
10154 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10158 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10159 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10163 case TargetOpcode::BUNDLE:
10164 return getInstBundleSize(
MI);
10165 case TargetOpcode::INLINEASM:
10166 case TargetOpcode::INLINEASM_BR: {
10168 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10172 if (
MI.isMetaInstruction())
10176 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10179 unsigned LoInstOpcode = D16Info->LoOp;
10181 DescSize =
Desc.getSize();
10185 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10188 DescSize =
Desc.getSize();
10197 if (
MI.isBranch() && ST.hasOffset3fBug())
10198 return InstSizeVerifyMode::NoVerify;
10199 return InstSizeVerifyMode::ExactSize;
10206 if (
MI.memoperands_empty())
10218 static const std::pair<int, const char *> TargetIndices[] = {
10258std::pair<unsigned, unsigned>
10265 static const std::pair<unsigned, const char *> TargetFlags[] = {
10283 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10299 return AMDGPU::WWM_COPY;
10301 return AMDGPU::COPY;
10318 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10322 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10323 return IsLRSplitInst;
10336 bool IsNullOrVectorRegister =
true;
10340 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10343 return IsNullOrVectorRegister &&
10345 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10346 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10354 if (ST.hasAddNoCarryInsts())
10370 if (ST.hasAddNoCarryInsts())
10374 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10376 : RS.scavengeRegisterBackwards(
10377 *RI.getBoolRC(),
I,
false,
10390 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10391 case AMDGPU::SI_KILL_I1_TERMINATOR:
10400 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10401 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10402 case AMDGPU::SI_KILL_I1_PSEUDO:
10403 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10415 const unsigned OffsetBits =
10417 return (1 << OffsetBits) - 1;
10421 if (!ST.isWave32())
10424 if (
MI.isInlineAsm())
10427 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10430 for (
auto &
Op :
MI.implicit_operands()) {
10431 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10432 Op.setReg(AMDGPU::VCC_LO);
10441 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10445 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10446 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10462 if (Imm > MaxImm) {
10463 if (Imm <= MaxImm + 64) {
10465 Overflow = Imm - MaxImm;
10484 if (Overflow > 0) {
10492 if (ST.hasRestrictedSOffset())
10497 SOffset = Overflow;
10535 if (!ST.hasFlatInstOffsets())
10539 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10544 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10545 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10556std::pair<int64_t, int64_t>
10559 int64_t RemainderOffset = COffsetVal;
10560 int64_t ImmField = 0;
10565 if (AllowNegative) {
10567 int64_t
D = 1LL << NumBits;
10568 RemainderOffset = (COffsetVal /
D) *
D;
10569 ImmField = COffsetVal - RemainderOffset;
10571 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10573 (ImmField % 4) != 0) {
10575 RemainderOffset += ImmField % 4;
10576 ImmField -= ImmField % 4;
10578 }
else if (COffsetVal >= 0) {
10580 RemainderOffset = COffsetVal - ImmField;
10584 assert(RemainderOffset + ImmField == COffsetVal);
10585 return {ImmField, RemainderOffset};
10590 if (ST.hasNegativeScratchOffsetBug() &&
10598 switch (ST.getGeneration()) {
10627 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10628 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10629 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10630 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10631 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10632 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10633 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10634 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10641#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10642 case OPCODE##_dpp: \
10643 case OPCODE##_e32: \
10644 case OPCODE##_e64: \
10645 case OPCODE##_e64_dpp: \
10646 case OPCODE##_sdwa:
10660 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10661 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10662 case AMDGPU::V_FMA_F16_gfx9_e64:
10663 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10664 case AMDGPU::V_INTERP_P2_F16:
10665 case AMDGPU::V_MAD_F16_e64:
10666 case AMDGPU::V_MAD_U16_e64:
10667 case AMDGPU::V_MAD_I16_e64:
10676 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10690 switch (ST.getGeneration()) {
10703 if (
isMAI(Opcode)) {
10711 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10714 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10721 if (ST.hasGFX90AInsts()) {
10722 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10723 if (ST.hasGFX940Insts())
10725 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10727 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10729 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10735 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10754 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10755 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10756 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10768 switch (
MI.getOpcode()) {
10770 case AMDGPU::REG_SEQUENCE:
10774 case AMDGPU::INSERT_SUBREG:
10775 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10792 if (!
P.Reg.isVirtual())
10797 while (
auto *
MI = DefInst) {
10799 switch (
MI->getOpcode()) {
10801 case AMDGPU::V_MOV_B32_e32: {
10802 auto &Op1 =
MI->getOperand(1);
10831 auto *DefBB =
DefMI.getParent();
10835 if (
UseMI.getParent() != DefBB)
10838 const int MaxInstScan = 20;
10842 auto E =
UseMI.getIterator();
10843 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10844 if (
I->isDebugInstr())
10847 if (++NumInst > MaxInstScan)
10850 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10863 auto *DefBB =
DefMI.getParent();
10865 const int MaxUseScan = 10;
10869 auto &UseInst = *
Use.getParent();
10872 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10875 if (++NumUse > MaxUseScan)
10882 const int MaxInstScan = 20;
10886 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10889 if (
I->isDebugInstr())
10892 if (++NumInst > MaxInstScan)
10905 if (Reg == VReg && --NumUse == 0)
10907 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
10916 auto Cur =
MBB.begin();
10917 if (Cur !=
MBB.end())
10919 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
10922 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
10931 if (InsPt !=
MBB.end() &&
10932 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10933 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10934 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10935 InsPt->definesRegister(Src,
nullptr)) {
10939 .
addReg(Src, {}, SrcSubReg)
10982 if (isFullCopyInstr(
MI)) {
10983 Register DstReg =
MI.getOperand(0).getReg();
10984 Register SrcReg =
MI.getOperand(1).getReg();
11006 unsigned *PredCost)
const {
11007 if (
MI.isBundle()) {
11010 unsigned Lat = 0,
Count = 0;
11011 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11013 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11015 return Lat +
Count - 1;
11018 return SchedModel.computeInstrLatency(&
MI);
11025 return *CallAddrOp;
11032 unsigned Opcode =
MI.getOpcode();
11034 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11037 :
MI.getOperand(1).getReg();
11041 unsigned SrcAS = SrcTy.getAddressSpace();
11044 ST.hasGloballyAddressableScratch()
11052 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11053 return HandleAddrSpaceCast(
MI);
11056 auto IID = GI->getIntrinsicID();
11063 case Intrinsic::amdgcn_addrspacecast_nonnull:
11064 return HandleAddrSpaceCast(
MI);
11065 case Intrinsic::amdgcn_if:
11066 case Intrinsic::amdgcn_else:
11080 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11081 Opcode == AMDGPU::G_SEXTLOAD) {
11082 if (
MI.memoperands_empty())
11086 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11087 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11095 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11096 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11097 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11103 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11106 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11114 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11115 return Formatter.get();
11123 unsigned opcode =
MI.getOpcode();
11124 if (opcode == AMDGPU::V_READLANE_B32 ||
11125 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11126 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11131 if (
MI.isInlineAsm()) {
11137 if (!RC || !RI.isSGPRClass(RC))
11142 if (isCopyInstr(
MI)) {
11146 RI.getPhysRegBaseClass(srcOp.
getReg());
11154 if (
MI.isPreISelOpcode())
11169 if (
MI.memoperands_empty())
11173 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11174 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11189 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11191 if (!
SrcOp.isReg())
11195 if (!Reg || !
SrcOp.readsReg())
11201 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11228 F,
"ds_ordered_count unsupported for this calling conv"));
11242 Register &SrcReg2, int64_t &CmpMask,
11243 int64_t &CmpValue)
const {
11244 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11247 switch (
MI.getOpcode()) {
11250 case AMDGPU::S_CMP_EQ_U32:
11251 case AMDGPU::S_CMP_EQ_I32:
11252 case AMDGPU::S_CMP_LG_U32:
11253 case AMDGPU::S_CMP_LG_I32:
11254 case AMDGPU::S_CMP_LT_U32:
11255 case AMDGPU::S_CMP_LT_I32:
11256 case AMDGPU::S_CMP_GT_U32:
11257 case AMDGPU::S_CMP_GT_I32:
11258 case AMDGPU::S_CMP_LE_U32:
11259 case AMDGPU::S_CMP_LE_I32:
11260 case AMDGPU::S_CMP_GE_U32:
11261 case AMDGPU::S_CMP_GE_I32:
11262 case AMDGPU::S_CMP_EQ_U64:
11263 case AMDGPU::S_CMP_LG_U64:
11264 SrcReg =
MI.getOperand(0).getReg();
11265 if (
MI.getOperand(1).isReg()) {
11266 if (
MI.getOperand(1).getSubReg())
11268 SrcReg2 =
MI.getOperand(1).getReg();
11270 }
else if (
MI.getOperand(1).isImm()) {
11272 CmpValue =
MI.getOperand(1).getImm();
11278 case AMDGPU::S_CMPK_EQ_U32:
11279 case AMDGPU::S_CMPK_EQ_I32:
11280 case AMDGPU::S_CMPK_LG_U32:
11281 case AMDGPU::S_CMPK_LG_I32:
11282 case AMDGPU::S_CMPK_LT_U32:
11283 case AMDGPU::S_CMPK_LT_I32:
11284 case AMDGPU::S_CMPK_GT_U32:
11285 case AMDGPU::S_CMPK_GT_I32:
11286 case AMDGPU::S_CMPK_LE_U32:
11287 case AMDGPU::S_CMPK_LE_I32:
11288 case AMDGPU::S_CMPK_GE_U32:
11289 case AMDGPU::S_CMPK_GE_I32:
11290 SrcReg =
MI.getOperand(0).getReg();
11292 CmpValue =
MI.getOperand(1).getImm();
11302 if (S->isLiveIn(AMDGPU::SCC))
11311bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11314 bool SCCIsDead =
false;
11317 constexpr unsigned ScanLimit = 12;
11318 unsigned Count = 0;
11319 for (MachineInstr &
MI :
11321 if (++
Count > ScanLimit)
11323 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11324 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11325 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11326 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11327 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11332 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11345 for (MachineInstr *
MI : InvertInstr) {
11346 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11347 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11349 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11350 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11351 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11352 ? AMDGPU::S_CBRANCH_SCC1
11353 : AMDGPU::S_CBRANCH_SCC0));
11366 bool NeedInversion)
const {
11367 MachineInstr *KillsSCC =
nullptr;
11372 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11374 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11377 if (NeedInversion && !invertSCCUse(SCCRedefine))
11379 if (MachineOperand *SccDef =
11381 SccDef->setIsDead(
false);
11389 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11390 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11392 bool Op1IsNonZeroImm =
11393 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11394 bool Op2IsZeroImm =
11395 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11396 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11402 unsigned &NewDefOpc) {
11405 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11406 Def.getOpcode() != AMDGPU::S_ADD_U32)
11412 if ((!AddSrc1.
isImm() || AddSrc1.
getImm() != 1) &&
11418 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11420 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11423 NewDefOpc = AMDGPU::S_ADD_U32;
11425 NeedInversion = !NeedInversion;
11430 Register SrcReg2, int64_t CmpMask,
11439 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11440 this](
bool NeedInversion) ->
bool {
11464 unsigned NewDefOpc = Def->getOpcode();
11470 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11473 if (NewDefOpc != Def->getOpcode())
11474 Def->setDesc(
get(NewDefOpc));
11483 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11490 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11498 optimizeSCC(
Select, Def,
false);
11505 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11506 this](int64_t ExpectedValue,
unsigned SrcSize,
11507 bool IsReversible,
bool IsSigned) ->
bool {
11535 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11536 Def->getOpcode() != AMDGPU::S_AND_B64)
11540 const auto isMask = [&Mask, SrcSize](
const MachineOperand *MO) ->
bool {
11551 SrcOp = &Def->getOperand(2);
11552 else if (isMask(&Def->getOperand(2)))
11553 SrcOp = &Def->getOperand(1);
11561 if (IsSigned && BitNo == SrcSize - 1)
11564 ExpectedValue <<= BitNo;
11566 bool IsReversedCC =
false;
11567 if (CmpValue != ExpectedValue) {
11570 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11575 Register DefReg = Def->getOperand(0).getReg();
11579 if (!optimizeSCC(Def, &CmpInstr,
false))
11590 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11591 : AMDGPU::S_BITCMP1_B32
11592 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11593 : AMDGPU::S_BITCMP1_B64;
11598 Def->eraseFromParent();
11606 case AMDGPU::S_CMP_EQ_U32:
11607 case AMDGPU::S_CMP_EQ_I32:
11608 case AMDGPU::S_CMPK_EQ_U32:
11609 case AMDGPU::S_CMPK_EQ_I32:
11610 return optimizeCmpAnd(1, 32,
true,
false) ||
11611 optimizeCmpSelect(
true);
11612 case AMDGPU::S_CMP_GE_U32:
11613 case AMDGPU::S_CMPK_GE_U32:
11614 return optimizeCmpAnd(1, 32,
false,
false);
11615 case AMDGPU::S_CMP_GE_I32:
11616 case AMDGPU::S_CMPK_GE_I32:
11617 return optimizeCmpAnd(1, 32,
false,
true);
11618 case AMDGPU::S_CMP_EQ_U64:
11619 return optimizeCmpAnd(1, 64,
true,
false);
11620 case AMDGPU::S_CMP_LG_U32:
11621 case AMDGPU::S_CMP_LG_I32:
11622 case AMDGPU::S_CMPK_LG_U32:
11623 case AMDGPU::S_CMPK_LG_I32:
11624 return optimizeCmpAnd(0, 32,
true,
false) ||
11625 optimizeCmpSelect(
false);
11626 case AMDGPU::S_CMP_GT_U32:
11627 case AMDGPU::S_CMPK_GT_U32:
11628 return optimizeCmpAnd(0, 32,
false,
false);
11629 case AMDGPU::S_CMP_GT_I32:
11630 case AMDGPU::S_CMPK_GT_I32:
11631 return optimizeCmpAnd(0, 32,
false,
true);
11632 case AMDGPU::S_CMP_LG_U64:
11633 return optimizeCmpAnd(0, 64,
true,
false) ||
11634 optimizeCmpSelect(
false);
11641 AMDGPU::OpName
OpName)
const {
11642 if (!ST.needsAlignedVGPRs())
11645 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11657 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11659 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11663 : &AMDGPU::VReg_64_Align2RegClass);
11665 .
addReg(DataReg, {},
Op.getSubReg())
11670 Op.setSubReg(AMDGPU::sub0);
11675 if (!SchedModel.hasInstrSchedModel())
11681 unsigned RepeatRate = 0;
11683 PI = SchedModel.getWriteProcResBegin(SCDesc),
11684 PE = SchedModel.getWriteProcResEnd(SCDesc);
11686 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11703 if (ST.hasGFX1250Insts())
11710 unsigned Opcode =
MI.getOpcode();
11716 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11717 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11720 if (!ST.hasGFX940Insts())
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< 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 unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static 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 std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool 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
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
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.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
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 bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI 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 getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
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
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 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...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool 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.
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.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
MachineInstr * top() const
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.