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())
188bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
192 if (
MI.isConvergent())
220 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
225 for (
auto Op :
MI.uses()) {
226 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
238 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
258 int64_t &Offset1)
const {
266 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
270 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
286 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
287 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
288 if (Offset0Idx == -1 || Offset1Idx == -1)
295 Offset0Idx -=
get(Opc0).NumDefs;
296 Offset1Idx -=
get(Opc1).NumDefs;
326 if (!Load0Offset || !Load1Offset)
343 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
344 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
346 if (OffIdx0 == -1 || OffIdx1 == -1)
352 OffIdx0 -=
get(Opc0).NumDefs;
353 OffIdx1 -=
get(Opc1).NumDefs;
372 case AMDGPU::DS_READ2ST64_B32:
373 case AMDGPU::DS_READ2ST64_B64:
374 case AMDGPU::DS_WRITE2ST64_B32:
375 case AMDGPU::DS_WRITE2ST64_B64:
390 OffsetIsScalable =
false;
407 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
409 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
410 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
423 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
424 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
425 if (Offset0 + 1 != Offset1)
436 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
444 Offset = EltSize * Offset0;
446 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
447 if (DataOpIdx == -1) {
448 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
450 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
466 if (BaseOp && !BaseOp->
isFI())
474 if (SOffset->
isReg())
480 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
482 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
491 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
492 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
494 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
495 if (VAddr0Idx >= 0) {
497 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
504 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
519 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
536 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
538 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
555 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
563 if (MO1->getAddrSpace() != MO2->getAddrSpace())
566 const auto *Base1 = MO1->getValue();
567 const auto *Base2 = MO2->getValue();
568 if (!Base1 || !Base2)
576 return Base1 == Base2;
580 int64_t Offset1,
bool OffsetIsScalable1,
582 int64_t Offset2,
bool OffsetIsScalable2,
583 unsigned ClusterSize,
584 unsigned NumBytes)
const {
597 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
616 const unsigned LoadSize = NumBytes / ClusterSize;
617 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
618 return NumDWords <= MaxMemoryClusterDWords;
632 int64_t Offset0, int64_t Offset1,
633 unsigned NumLoads)
const {
634 assert(Offset1 > Offset0 &&
635 "Second offset should be larger than first offset!");
640 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
647 const char *
Msg =
"illegal VGPR to SGPR copy") {
666 assert((
TII.getSubtarget().hasMAIInsts() &&
667 !
TII.getSubtarget().hasGFX90AInsts()) &&
668 "Expected GFX908 subtarget.");
671 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
672 "Source register of the copy should be either an SGPR or an AGPR.");
675 "Destination register of the copy should be an AGPR.");
684 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
687 if (!Def->modifiesRegister(SrcReg, &RI))
690 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
691 Def->getOperand(0).getReg() != SrcReg)
698 bool SafeToPropagate =
true;
701 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
702 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
703 SafeToPropagate =
false;
705 if (!SafeToPropagate)
708 for (
auto I = Def;
I !=
MI; ++
I)
709 I->clearRegisterKills(DefOp.
getReg(), &RI);
717 if (ImpUseSuperReg) {
718 Builder.addReg(ImpUseSuperReg,
726 RS.enterBasicBlockEnd(
MBB);
727 RS.backward(std::next(
MI));
736 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
739 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
740 "VGPR used for an intermediate copy should have been reserved.");
745 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
755 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
756 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
757 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
764 if (ImpUseSuperReg) {
765 UseBuilder.
addReg(ImpUseSuperReg,
782 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
783 int16_t SubIdx = BaseIndices[Idx];
784 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
785 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
786 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
787 unsigned Opcode = AMDGPU::S_MOV_B32;
790 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
791 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
792 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
796 DestSubReg = RI.getSubReg(DestReg, SubIdx);
797 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
798 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
799 Opcode = AMDGPU::S_MOV_B64;
814 assert(FirstMI && LastMI);
819 LastMI->addRegisterKilled(SrcReg, &RI);
825 Register SrcReg,
bool KillSrc,
bool RenamableDest,
826 bool RenamableSrc)
const {
828 unsigned Size = RI.getRegSizeInBits(*RC);
830 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
836 if (((
Size == 16) != (SrcSize == 16))) {
838 assert(ST.useRealTrue16Insts());
840 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
843 if (DestReg == SrcReg) {
849 RC = RI.getPhysRegBaseClass(DestReg);
850 Size = RI.getRegSizeInBits(*RC);
851 SrcRC = RI.getPhysRegBaseClass(SrcReg);
852 SrcSize = RI.getRegSizeInBits(*SrcRC);
856 if (RC == &AMDGPU::VGPR_32RegClass) {
858 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
859 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
860 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
861 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
867 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
868 RC == &AMDGPU::SReg_32RegClass) {
869 if (SrcReg == AMDGPU::SCC) {
876 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
877 if (DestReg == AMDGPU::VCC_LO) {
895 if (RC == &AMDGPU::SReg_64RegClass) {
896 if (SrcReg == AMDGPU::SCC) {
903 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
904 if (DestReg == AMDGPU::VCC) {
922 if (DestReg == AMDGPU::SCC) {
925 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
929 assert(ST.hasScalarCompareEq64());
943 if (RC == &AMDGPU::AGPR_32RegClass) {
944 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
945 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
951 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
960 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
967 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
968 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
970 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
971 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
972 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
973 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
976 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
977 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
990 if (IsAGPRDst || IsAGPRSrc) {
991 if (!DstLow || !SrcLow) {
993 "Cannot use hi16 subreg with an AGPR!");
1000 if (ST.useRealTrue16Insts()) {
1006 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1007 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1019 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1020 if (!DstLow || !SrcLow) {
1022 "Cannot use hi16 subreg on VI!");
1045 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1046 if (ST.hasVMovB64Inst()) {
1051 if (ST.hasPkMovB32()) {
1067 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1068 if (RI.isSGPRClass(RC)) {
1069 if (!RI.isSGPRClass(SrcRC)) {
1073 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1079 unsigned EltSize = 4;
1080 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1081 if (RI.isAGPRClass(RC)) {
1082 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1083 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1084 else if (RI.hasVGPRs(SrcRC) ||
1085 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1086 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1088 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1089 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1090 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1091 }
else if ((
Size % 64 == 0) && RI.hasVGPRs(RC) &&
1092 (RI.isProperlyAlignedRC(*RC) &&
1093 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1095 if (ST.hasVMovB64Inst()) {
1096 Opcode = AMDGPU::V_MOV_B64_e32;
1098 }
else if (ST.hasPkMovB32()) {
1099 Opcode = AMDGPU::V_PK_MOV_B32;
1109 std::unique_ptr<RegScavenger> RS;
1110 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1111 RS = std::make_unique<RegScavenger>();
1117 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1118 const bool CanKillSuperReg = KillSrc && !Overlap;
1120 for (
unsigned Idx = 0; Idx < SubIndices.
size(); ++Idx) {
1123 SubIdx = SubIndices[Idx];
1125 SubIdx = SubIndices[SubIndices.
size() - Idx - 1];
1126 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1127 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1128 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1130 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size() - 1;
1132 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1135 *RS, Overlap, ImpUseSuper);
1136 }
else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1177 int64_t &ImmVal)
const {
1178 switch (
MI.getOpcode()) {
1179 case AMDGPU::V_MOV_B32_e32:
1180 case AMDGPU::S_MOV_B32:
1181 case AMDGPU::S_MOVK_I32:
1182 case AMDGPU::S_MOV_B64:
1183 case AMDGPU::V_MOV_B64_e32:
1184 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1185 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1186 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1187 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1188 case AMDGPU::V_MOV_B64_PSEUDO:
1189 case AMDGPU::V_MOV_B16_t16_e32: {
1193 return MI.getOperand(0).getReg() == Reg;
1198 case AMDGPU::V_MOV_B16_t16_e64: {
1200 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1202 return MI.getOperand(0).getReg() == Reg;
1207 case AMDGPU::S_BREV_B32:
1208 case AMDGPU::V_BFREV_B32_e32:
1209 case AMDGPU::V_BFREV_B32_e64: {
1213 return MI.getOperand(0).getReg() == Reg;
1218 case AMDGPU::S_NOT_B32:
1219 case AMDGPU::V_NOT_B32_e32:
1220 case AMDGPU::V_NOT_B32_e64: {
1223 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1224 return MI.getOperand(0).getReg() == Reg;
1234std::optional<int64_t>
1239 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1240 return std::nullopt;
1243 if (Def && Def->isMoveImmediate()) {
1249 return std::nullopt;
1254 if (RI.isAGPRClass(DstRC))
1255 return AMDGPU::COPY;
1256 if (RI.getRegSizeInBits(*DstRC) == 16) {
1259 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1261 if (RI.getRegSizeInBits(*DstRC) == 32)
1262 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1263 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1264 return AMDGPU::S_MOV_B64;
1265 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1266 return AMDGPU::V_MOV_B64_PSEUDO;
1267 return AMDGPU::COPY;
1272 bool IsIndirectSrc)
const {
1273 if (IsIndirectSrc) {
1275 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1277 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1279 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1281 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1283 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1285 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1287 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1289 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1291 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1293 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1295 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1297 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1299 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1300 if (VecSize <= 1024)
1301 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1307 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1309 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1311 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1313 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1315 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1317 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1319 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1321 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1323 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1325 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1327 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1329 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1331 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1332 if (VecSize <= 1024)
1333 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1340 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1342 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1344 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1346 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1348 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1350 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1352 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1354 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1356 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1358 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1360 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1362 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1364 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1365 if (VecSize <= 1024)
1366 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1373 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1375 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1377 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1379 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1381 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1383 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1385 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1387 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1389 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1391 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1393 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1395 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1397 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1398 if (VecSize <= 1024)
1399 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1406 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1408 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1410 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1412 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1413 if (VecSize <= 1024)
1414 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1421 bool IsSGPR)
const {
1433 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1440 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1442 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1444 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1446 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1447 : AMDGPU::SI_SPILL_S128_SAVE;
1449 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1450 : AMDGPU::SI_SPILL_S160_SAVE;
1452 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1453 : AMDGPU::SI_SPILL_S192_SAVE;
1455 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1456 : AMDGPU::SI_SPILL_S224_SAVE;
1458 return AMDGPU::SI_SPILL_S256_SAVE;
1460 return AMDGPU::SI_SPILL_S288_SAVE;
1462 return AMDGPU::SI_SPILL_S320_SAVE;
1464 return AMDGPU::SI_SPILL_S352_SAVE;
1466 return AMDGPU::SI_SPILL_S384_SAVE;
1468 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1469 : AMDGPU::SI_SPILL_S512_SAVE;
1471 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1472 : AMDGPU::SI_SPILL_S1024_SAVE;
1481 return AMDGPU::SI_SPILL_V16_SAVE;
1483 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1485 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1487 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1489 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1490 : AMDGPU::SI_SPILL_V128_SAVE;
1492 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1493 : AMDGPU::SI_SPILL_V160_SAVE;
1495 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1496 : AMDGPU::SI_SPILL_V192_SAVE;
1498 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1499 : AMDGPU::SI_SPILL_V224_SAVE;
1501 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1502 : AMDGPU::SI_SPILL_V256_SAVE;
1504 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1505 : AMDGPU::SI_SPILL_V288_SAVE;
1507 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1508 : AMDGPU::SI_SPILL_V320_SAVE;
1510 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1511 : AMDGPU::SI_SPILL_V352_SAVE;
1513 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1514 : AMDGPU::SI_SPILL_V384_SAVE;
1516 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1517 : AMDGPU::SI_SPILL_V512_SAVE;
1519 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1520 : AMDGPU::SI_SPILL_V1024_SAVE;
1529 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1530 : AMDGPU::SI_SPILL_AV32_SAVE;
1532 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1533 : AMDGPU::SI_SPILL_AV64_SAVE;
1535 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1536 : AMDGPU::SI_SPILL_AV96_SAVE;
1538 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1539 : AMDGPU::SI_SPILL_AV128_SAVE;
1541 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1542 : AMDGPU::SI_SPILL_AV160_SAVE;
1544 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1545 : AMDGPU::SI_SPILL_AV192_SAVE;
1547 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1548 : AMDGPU::SI_SPILL_AV224_SAVE;
1550 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1551 : AMDGPU::SI_SPILL_AV256_SAVE;
1553 return AMDGPU::SI_SPILL_AV288_SAVE;
1555 return AMDGPU::SI_SPILL_AV320_SAVE;
1557 return AMDGPU::SI_SPILL_AV352_SAVE;
1559 return AMDGPU::SI_SPILL_AV384_SAVE;
1561 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1562 : AMDGPU::SI_SPILL_AV512_SAVE;
1564 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1565 : AMDGPU::SI_SPILL_AV1024_SAVE;
1572 bool IsVectorSuperClass) {
1577 if (IsVectorSuperClass)
1578 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1580 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1586 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1593 if (ST.hasMAIInsts())
1599void SIInstrInfo::storeRegToStackSlotImpl(
1612 FrameInfo.getObjectAlign(FrameIndex));
1613 unsigned SpillSize = RI.getSpillSize(*RC);
1619 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1620 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1621 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1630 if (SrcReg.
isVirtual() && SpillSize == 4) {
1644 SpillSize, *MFI, NeedsCFI);
1659 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1668 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1675 return AMDGPU::SI_SPILL_S32_RESTORE;
1677 return AMDGPU::SI_SPILL_S64_RESTORE;
1679 return AMDGPU::SI_SPILL_S96_RESTORE;
1681 return AMDGPU::SI_SPILL_S128_RESTORE;
1683 return AMDGPU::SI_SPILL_S160_RESTORE;
1685 return AMDGPU::SI_SPILL_S192_RESTORE;
1687 return AMDGPU::SI_SPILL_S224_RESTORE;
1689 return AMDGPU::SI_SPILL_S256_RESTORE;
1691 return AMDGPU::SI_SPILL_S288_RESTORE;
1693 return AMDGPU::SI_SPILL_S320_RESTORE;
1695 return AMDGPU::SI_SPILL_S352_RESTORE;
1697 return AMDGPU::SI_SPILL_S384_RESTORE;
1699 return AMDGPU::SI_SPILL_S512_RESTORE;
1701 return AMDGPU::SI_SPILL_S1024_RESTORE;
1710 return AMDGPU::SI_SPILL_V16_RESTORE;
1712 return AMDGPU::SI_SPILL_V32_RESTORE;
1714 return AMDGPU::SI_SPILL_V64_RESTORE;
1716 return AMDGPU::SI_SPILL_V96_RESTORE;
1718 return AMDGPU::SI_SPILL_V128_RESTORE;
1720 return AMDGPU::SI_SPILL_V160_RESTORE;
1722 return AMDGPU::SI_SPILL_V192_RESTORE;
1724 return AMDGPU::SI_SPILL_V224_RESTORE;
1726 return AMDGPU::SI_SPILL_V256_RESTORE;
1728 return AMDGPU::SI_SPILL_V288_RESTORE;
1730 return AMDGPU::SI_SPILL_V320_RESTORE;
1732 return AMDGPU::SI_SPILL_V352_RESTORE;
1734 return AMDGPU::SI_SPILL_V384_RESTORE;
1736 return AMDGPU::SI_SPILL_V512_RESTORE;
1738 return AMDGPU::SI_SPILL_V1024_RESTORE;
1747 return AMDGPU::SI_SPILL_AV32_RESTORE;
1749 return AMDGPU::SI_SPILL_AV64_RESTORE;
1751 return AMDGPU::SI_SPILL_AV96_RESTORE;
1753 return AMDGPU::SI_SPILL_AV128_RESTORE;
1755 return AMDGPU::SI_SPILL_AV160_RESTORE;
1757 return AMDGPU::SI_SPILL_AV192_RESTORE;
1759 return AMDGPU::SI_SPILL_AV224_RESTORE;
1761 return AMDGPU::SI_SPILL_AV256_RESTORE;
1763 return AMDGPU::SI_SPILL_AV288_RESTORE;
1765 return AMDGPU::SI_SPILL_AV320_RESTORE;
1767 return AMDGPU::SI_SPILL_AV352_RESTORE;
1769 return AMDGPU::SI_SPILL_AV384_RESTORE;
1771 return AMDGPU::SI_SPILL_AV512_RESTORE;
1773 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1780 bool IsVectorSuperClass) {
1785 if (IsVectorSuperClass)
1786 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1788 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1794 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1801 if (ST.hasMAIInsts())
1804 assert(!RI.isAGPRClass(RC));
1818 unsigned SpillSize = RI.getSpillSize(*RC);
1825 FrameInfo.getObjectAlign(FrameIndex));
1827 if (RI.isSGPRClass(RC)) {
1830 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1831 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1832 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1837 if (DestReg.
isVirtual() && SpillSize == 4) {
1866 unsigned Quantity)
const {
1868 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1869 while (Quantity > 0) {
1870 unsigned Arg = std::min(Quantity, MaxSNopCount);
1881 constexpr unsigned DoorbellIDMask = 0x3ff;
1882 constexpr unsigned ECQueueWaveAbort = 0x400;
1887 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1888 MBB.splitAt(
MI,
false);
1892 MBB.addSuccessor(TrapBB);
1902 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1906 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1911 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1912 .
addUse(DoorbellRegMasked)
1913 .
addImm(ECQueueWaveAbort);
1914 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1915 .
addUse(SetWaveAbortBit);
1918 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1929 return MBB.getNextNode();
1933 switch (
MI.getOpcode()) {
1935 if (
MI.isMetaInstruction())
1940 return MI.getOperand(0).getImm() + 1;
1951 switch (
MI.getOpcode()) {
1953 case AMDGPU::S_MOV_B64_term:
1956 MI.setDesc(
get(AMDGPU::S_MOV_B64));
1959 case AMDGPU::S_MOV_B32_term:
1962 MI.setDesc(
get(AMDGPU::S_MOV_B32));
1965 case AMDGPU::S_XOR_B64_term:
1968 MI.setDesc(
get(AMDGPU::S_XOR_B64));
1971 case AMDGPU::S_XOR_B32_term:
1974 MI.setDesc(
get(AMDGPU::S_XOR_B32));
1976 case AMDGPU::S_OR_B64_term:
1979 MI.setDesc(
get(AMDGPU::S_OR_B64));
1981 case AMDGPU::S_OR_B32_term:
1984 MI.setDesc(
get(AMDGPU::S_OR_B32));
1987 case AMDGPU::S_ANDN2_B64_term:
1990 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
1993 case AMDGPU::S_ANDN2_B32_term:
1996 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
1999 case AMDGPU::S_AND_B64_term:
2002 MI.setDesc(
get(AMDGPU::S_AND_B64));
2005 case AMDGPU::S_AND_B32_term:
2008 MI.setDesc(
get(AMDGPU::S_AND_B32));
2011 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2014 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2017 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2020 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2023 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2024 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2026 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2027 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2030 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2031 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2034 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2035 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2037 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2041 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2044 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2047 int64_t Imm =
MI.getOperand(1).getImm();
2049 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2050 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2055 MI.eraseFromParent();
2061 case AMDGPU::V_MOV_B64_PSEUDO: {
2063 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2064 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2072 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2073 MI.setDesc(Mov64Desc);
2077 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2080 if (
SrcOp.isGlobal()) {
2085 unsigned BaseFlags, LoReloc, HiReloc;
2086 std::tie(BaseFlags, LoReloc, HiReloc) =
2093 }
else if (
SrcOp.isImm()) {
2095 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2096 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2120 if (ST.hasPkMovB32() &&
2139 MI.eraseFromParent();
2142 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2146 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2150 if (ST.has64BitLiterals()) {
2151 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2155 if (
SrcOp.isGlobal()) {
2157 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2158 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2161 unsigned BaseFlags, LoReloc, HiReloc;
2162 std::tie(BaseFlags, LoReloc, HiReloc) =
2169 MI.eraseFromParent();
2176 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2181 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2182 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2184 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2185 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2190 MI.eraseFromParent();
2193 case AMDGPU::V_SET_INACTIVE_B32: {
2197 .
add(
MI.getOperand(3))
2198 .
add(
MI.getOperand(4))
2199 .
add(
MI.getOperand(1))
2200 .
add(
MI.getOperand(2))
2201 .
add(
MI.getOperand(5));
2202 MI.eraseFromParent();
2205 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2206 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2207 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2208 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2209 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2210 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2211 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2212 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2213 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2214 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2215 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2216 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2217 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2218 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2219 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2220 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2221 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2222 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2223 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2224 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2225 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2226 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2227 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2228 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2229 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2230 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2231 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2232 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2233 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2234 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2235 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2236 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2237 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2241 if (RI.hasVGPRs(EltRC)) {
2242 Opc = AMDGPU::V_MOVRELD_B32_e32;
2244 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2245 : AMDGPU::S_MOVRELD_B32;
2250 bool IsUndef =
MI.getOperand(1).isUndef();
2251 unsigned SubReg =
MI.getOperand(3).getImm();
2252 assert(VecReg ==
MI.getOperand(1).getReg());
2257 .
add(
MI.getOperand(2))
2261 const int ImpDefIdx =
2263 const int ImpUseIdx = ImpDefIdx + 1;
2265 MI.eraseFromParent();
2268 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2269 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2270 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2271 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2272 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2273 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2274 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2275 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2276 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2277 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2278 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2279 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2280 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2281 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2282 assert(ST.useVGPRIndexMode());
2284 bool IsUndef =
MI.getOperand(1).isUndef();
2293 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2297 .
add(
MI.getOperand(2))
2301 const int ImpDefIdx =
2303 const int ImpUseIdx = ImpDefIdx + 1;
2310 MI.eraseFromParent();
2313 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2314 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2315 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2316 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2317 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2318 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2319 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2320 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2321 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2322 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2323 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2324 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2325 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2326 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2327 assert(ST.useVGPRIndexMode());
2330 bool IsUndef =
MI.getOperand(1).isUndef();
2334 .
add(
MI.getOperand(2))
2347 MI.eraseFromParent();
2350 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2353 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2354 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2373 if (ST.hasGetPCZeroExtension()) {
2377 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2384 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2394 MI.eraseFromParent();
2397 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2407 Op.setOffset(
Op.getOffset() + 4);
2409 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2413 MI.eraseFromParent();
2416 case AMDGPU::ENTER_STRICT_WWM: {
2422 case AMDGPU::ENTER_STRICT_WQM: {
2429 MI.eraseFromParent();
2432 case AMDGPU::EXIT_STRICT_WWM:
2433 case AMDGPU::EXIT_STRICT_WQM: {
2439 case AMDGPU::SI_RETURN: {
2453 MI.eraseFromParent();
2457 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2458 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2459 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2462 case AMDGPU::S_GETPC_B64_pseudo:
2463 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2464 if (ST.hasGetPCZeroExtension()) {
2466 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2475 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2476 assert(ST.hasBF16PackedInsts());
2477 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2488 case AMDGPU::GET_STACK_BASE:
2491 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2498 Register DestReg =
MI.getOperand(0).getReg();
2508 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2509 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2510 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2513 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2516 MI.getNumExplicitOperands());
2534 case AMDGPU::S_MOV_B64:
2535 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2544 if (UsedLanes.
all())
2549 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2550 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2552 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2553 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2555 if (NeedLo && NeedHi)
2559 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2561 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2570 case AMDGPU::S_LOAD_DWORDX16_IMM:
2571 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2584 for (
auto &CandMO :
I->operands()) {
2585 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2593 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2597 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2603 unsigned NewOpcode = -1;
2604 if (SubregSize == 256)
2605 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2606 else if (SubregSize == 128)
2607 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2617 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2622 MI->getOperand(0).setReg(DestReg);
2623 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2627 OffsetMO->
setImm(FinalOffset);
2633 MI->setMemRefs(*MF, NewMMOs);
2646std::pair<MachineInstr*, MachineInstr*>
2648 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2650 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2653 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2654 return std::pair(&
MI,
nullptr);
2665 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2667 if (Dst.isPhysical()) {
2668 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2675 for (
unsigned I = 1;
I <= 2; ++
I) {
2678 if (
SrcOp.isImm()) {
2680 Imm.ashrInPlace(Part * 32);
2681 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2685 if (Src.isPhysical())
2686 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2693 MovDPP.addImm(MO.getImm());
2695 Split[Part] = MovDPP;
2699 if (Dst.isVirtual())
2706 MI.eraseFromParent();
2707 return std::pair(Split[0], Split[1]);
2710std::optional<DestSourcePair>
2712 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2715 return std::nullopt;
2719 AMDGPU::OpName Src0OpName,
2721 AMDGPU::OpName Src1OpName)
const {
2728 "All commutable instructions have both src0 and src1 modifiers");
2730 int Src0ModsVal = Src0Mods->
getImm();
2731 int Src1ModsVal = Src1Mods->
getImm();
2733 Src1Mods->
setImm(Src0ModsVal);
2734 Src0Mods->
setImm(Src1ModsVal);
2743 bool IsKill = RegOp.
isKill();
2745 bool IsUndef = RegOp.
isUndef();
2746 bool IsDebug = RegOp.
isDebug();
2748 if (NonRegOp.
isImm())
2750 else if (NonRegOp.
isFI())
2771 int64_t NonRegVal = NonRegOp1.
getImm();
2774 NonRegOp2.
setImm(NonRegVal);
2781 unsigned OpIdx1)
const {
2786 unsigned Opc =
MI.getOpcode();
2787 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2797 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2800 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2805 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2811 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2826 unsigned Src1Idx)
const {
2827 assert(!NewMI &&
"this should never be used");
2829 unsigned Opc =
MI.getOpcode();
2831 if (CommutedOpcode == -1)
2834 if (Src0Idx > Src1Idx)
2837 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2838 static_cast<int>(Src0Idx) &&
2839 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2840 static_cast<int>(Src1Idx) &&
2841 "inconsistency with findCommutedOpIndices");
2866 Src1, AMDGPU::OpName::src1_modifiers);
2869 AMDGPU::OpName::src1_sel);
2881 unsigned &SrcOpIdx0,
2882 unsigned &SrcOpIdx1)
const {
2887 unsigned &SrcOpIdx0,
2888 unsigned &SrcOpIdx1)
const {
2889 if (!
Desc.isCommutable())
2892 unsigned Opc =
Desc.getOpcode();
2893 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2897 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2901 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2905 int64_t BrOffset)
const {
2922 return MI.getOperand(0).getMBB();
2927 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
2928 MI.getOpcode() == AMDGPU::SI_LOOP)
2940 "new block should be inserted for expanding unconditional branch");
2943 "restore block should be inserted for restoring clobbered registers");
2951 if (ST.useAddPC64Inst()) {
2953 MCCtx.createTempSymbol(
"offset",
true);
2957 MCCtx.createTempSymbol(
"post_addpc",
true);
2958 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
2962 Offset->setVariableValue(OffsetExpr);
2966 assert(RS &&
"RegScavenger required for long branching");
2974 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
2975 ST.hasVALUReadSGPRHazard();
2976 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
2977 if (FlushSGPRWrites)
2985 ApplyHazardWorkarounds();
2988 MCCtx.createTempSymbol(
"post_getpc",
true);
2992 MCCtx.createTempSymbol(
"offset_lo",
true);
2994 MCCtx.createTempSymbol(
"offset_hi",
true);
2997 .
addReg(PCReg, {}, AMDGPU::sub0)
3001 .
addReg(PCReg, {}, AMDGPU::sub1)
3003 ApplyHazardWorkarounds();
3044 if (LongBranchReservedReg) {
3045 RS->enterBasicBlock(
MBB);
3046 Scav = LongBranchReservedReg;
3048 RS->enterBasicBlockEnd(
MBB);
3049 Scav = RS->scavengeRegisterBackwards(
3054 RS->setRegUsed(Scav);
3062 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3079unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3081 case SIInstrInfo::SCC_TRUE:
3082 return AMDGPU::S_CBRANCH_SCC1;
3083 case SIInstrInfo::SCC_FALSE:
3084 return AMDGPU::S_CBRANCH_SCC0;
3085 case SIInstrInfo::VCCNZ:
3086 return AMDGPU::S_CBRANCH_VCCNZ;
3087 case SIInstrInfo::VCCZ:
3088 return AMDGPU::S_CBRANCH_VCCZ;
3089 case SIInstrInfo::EXECNZ:
3090 return AMDGPU::S_CBRANCH_EXECNZ;
3091 case SIInstrInfo::EXECZ:
3092 return AMDGPU::S_CBRANCH_EXECZ;
3098SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3100 case AMDGPU::S_CBRANCH_SCC0:
3102 case AMDGPU::S_CBRANCH_SCC1:
3104 case AMDGPU::S_CBRANCH_VCCNZ:
3106 case AMDGPU::S_CBRANCH_VCCZ:
3108 case AMDGPU::S_CBRANCH_EXECNZ:
3110 case AMDGPU::S_CBRANCH_EXECZ:
3122 bool AllowModify)
const {
3123 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3125 TBB =
I->getOperand(0).getMBB();
3129 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3130 if (Pred == INVALID_BR)
3135 Cond.push_back(
I->getOperand(1));
3139 if (
I ==
MBB.end()) {
3145 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3147 FBB =
I->getOperand(0).getMBB();
3157 bool AllowModify)
const {
3165 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3166 switch (
I->getOpcode()) {
3167 case AMDGPU::S_MOV_B64_term:
3168 case AMDGPU::S_XOR_B64_term:
3169 case AMDGPU::S_OR_B64_term:
3170 case AMDGPU::S_ANDN2_B64_term:
3171 case AMDGPU::S_AND_B64_term:
3172 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3173 case AMDGPU::S_MOV_B32_term:
3174 case AMDGPU::S_XOR_B32_term:
3175 case AMDGPU::S_OR_B32_term:
3176 case AMDGPU::S_ANDN2_B32_term:
3177 case AMDGPU::S_AND_B32_term:
3178 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3179 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3180 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3183 case AMDGPU::SI_ELSE:
3184 case AMDGPU::SI_KILL_I1_TERMINATOR:
3185 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3202 int *BytesRemoved)
const {
3204 unsigned RemovedSize = 0;
3207 if (
MI.isBranch() ||
MI.isReturn()) {
3209 MI.eraseFromParent();
3215 *BytesRemoved = RemovedSize;
3232 int *BytesAdded)
const {
3233 if (!FBB &&
Cond.empty()) {
3237 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3244 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3256 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3274 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3281 if (
Cond.size() != 2) {
3285 if (
Cond[0].isImm()) {
3296 Register FalseReg,
int &CondCycles,
3297 int &TrueCycles,
int &FalseCycles)
const {
3307 CondCycles = TrueCycles = FalseCycles = NumInsts;
3310 return RI.hasVGPRs(RC) && NumInsts <= 6;
3324 if (NumInsts % 2 == 0)
3327 CondCycles = TrueCycles = FalseCycles = NumInsts;
3328 return RI.isSGPRClass(RC);
3339 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3340 if (Pred == VCCZ || Pred == SCC_FALSE) {
3341 Pred =
static_cast<BranchPredicate
>(-Pred);
3347 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3349 if (DstSize == 32) {
3351 if (Pred == SCC_TRUE) {
3366 if (DstSize == 64 && Pred == SCC_TRUE) {
3376 static const int16_t Sub0_15[] = {
3377 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3378 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3379 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3380 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3383 static const int16_t Sub0_15_64[] = {
3384 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3385 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3386 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3387 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3390 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3392 const int16_t *SubIndices = Sub0_15;
3393 int NElts = DstSize / 32;
3397 if (Pred == SCC_TRUE) {
3399 SelOp = AMDGPU::S_CSELECT_B32;
3400 EltRC = &AMDGPU::SGPR_32RegClass;
3402 SelOp = AMDGPU::S_CSELECT_B64;
3403 EltRC = &AMDGPU::SGPR_64RegClass;
3404 SubIndices = Sub0_15_64;
3410 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3415 for (
int Idx = 0; Idx != NElts; ++Idx) {
3419 unsigned SubIdx = SubIndices[Idx];
3422 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3424 .
addReg(FalseReg, {}, SubIdx)
3425 .addReg(TrueReg, {}, SubIdx);
3428 .
addReg(TrueReg, {}, SubIdx)
3429 .addReg(FalseReg, {}, SubIdx);
3442 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3445 switch (
MI.getOpcode()) {
3446 case AMDGPU::S_ENDPGM:
3447 case AMDGPU::S_ENDPGM_SAVED:
3448 case AMDGPU::S_TRAP:
3449 case AMDGPU::S_GETREG_B32:
3450 case AMDGPU::S_SETREG_B32:
3451 case AMDGPU::S_SETREG_B32_mode:
3452 case AMDGPU::S_SETREG_IMM32_B32:
3453 case AMDGPU::S_SETREG_IMM32_B32_mode:
3454 case AMDGPU::S_SENDMSG:
3455 case AMDGPU::S_SENDMSGHALT:
3456 case AMDGPU::S_SENDMSG_RTN_B32:
3457 case AMDGPU::S_SENDMSG_RTN_B64:
3458 case AMDGPU::S_BARRIER_WAIT:
3459 case AMDGPU::S_BARRIER_SIGNAL_M0:
3460 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3461 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3462 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3470 switch (
MI.getOpcode()) {
3471 case AMDGPU::V_MOV_B16_t16_e32:
3472 case AMDGPU::V_MOV_B16_t16_e64:
3473 case AMDGPU::V_MOV_B32_e32:
3474 case AMDGPU::V_MOV_B32_e64:
3475 case AMDGPU::V_MOV_B64_PSEUDO:
3476 case AMDGPU::V_MOV_B64_e32:
3477 case AMDGPU::V_MOV_B64_e64:
3478 case AMDGPU::S_MOV_B32:
3479 case AMDGPU::S_MOV_B64:
3480 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3482 case AMDGPU::WWM_COPY:
3483 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3484 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3485 case AMDGPU::V_ACCVGPR_MOV_B32:
3486 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3487 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3495 switch (
MI.getOpcode()) {
3496 case AMDGPU::V_MOV_B16_t16_e32:
3497 case AMDGPU::V_MOV_B16_t16_e64:
3499 case AMDGPU::V_MOV_B32_e32:
3500 case AMDGPU::V_MOV_B32_e64:
3501 case AMDGPU::V_MOV_B64_PSEUDO:
3502 case AMDGPU::V_MOV_B64_e32:
3503 case AMDGPU::V_MOV_B64_e64:
3504 case AMDGPU::S_MOV_B32:
3505 case AMDGPU::S_MOV_B64:
3506 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3508 case AMDGPU::WWM_COPY:
3509 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3510 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3511 case AMDGPU::V_ACCVGPR_MOV_B32:
3512 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3513 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3521 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3522 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3523 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3526 unsigned Opc =
MI.getOpcode();
3528 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3530 MI.removeOperand(Idx);
3536 MI.setDesc(NewDesc);
3542 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3543 Desc.implicit_defs().size();
3545 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3546 MI.removeOperand(
I);
3550 unsigned SubRegIndex) {
3551 switch (SubRegIndex) {
3552 case AMDGPU::NoSubRegister:
3562 case AMDGPU::sub1_lo16:
3564 case AMDGPU::sub1_hi16:
3567 return std::nullopt;
3575 case AMDGPU::V_MAC_F16_e32:
3576 case AMDGPU::V_MAC_F16_e64:
3577 case AMDGPU::V_MAD_F16_e64:
3578 return AMDGPU::V_MADAK_F16;
3579 case AMDGPU::V_MAC_F32_e32:
3580 case AMDGPU::V_MAC_F32_e64:
3581 case AMDGPU::V_MAD_F32_e64:
3582 return AMDGPU::V_MADAK_F32;
3583 case AMDGPU::V_FMAC_F32_e32:
3584 case AMDGPU::V_FMAC_F32_e64:
3585 case AMDGPU::V_FMA_F32_e64:
3586 return AMDGPU::V_FMAAK_F32;
3587 case AMDGPU::V_FMAC_F16_e32:
3588 case AMDGPU::V_FMAC_F16_e64:
3589 case AMDGPU::V_FMAC_F16_t16_e64:
3590 case AMDGPU::V_FMAC_F16_fake16_e64:
3591 case AMDGPU::V_FMAC_F16_t16_e32:
3592 case AMDGPU::V_FMAC_F16_fake16_e32:
3593 case AMDGPU::V_FMA_F16_e64:
3594 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3595 ? AMDGPU::V_FMAAK_F16_t16
3596 : AMDGPU::V_FMAAK_F16_fake16
3597 : AMDGPU::V_FMAAK_F16;
3598 case AMDGPU::V_FMAC_F64_e32:
3599 case AMDGPU::V_FMAC_F64_e64:
3600 case AMDGPU::V_FMA_F64_e64:
3601 return AMDGPU::V_FMAAK_F64;
3609 case AMDGPU::V_MAC_F16_e32:
3610 case AMDGPU::V_MAC_F16_e64:
3611 case AMDGPU::V_MAD_F16_e64:
3612 return AMDGPU::V_MADMK_F16;
3613 case AMDGPU::V_MAC_F32_e32:
3614 case AMDGPU::V_MAC_F32_e64:
3615 case AMDGPU::V_MAD_F32_e64:
3616 return AMDGPU::V_MADMK_F32;
3617 case AMDGPU::V_FMAC_F32_e32:
3618 case AMDGPU::V_FMAC_F32_e64:
3619 case AMDGPU::V_FMA_F32_e64:
3620 return AMDGPU::V_FMAMK_F32;
3621 case AMDGPU::V_FMAC_F16_e32:
3622 case AMDGPU::V_FMAC_F16_e64:
3623 case AMDGPU::V_FMAC_F16_t16_e64:
3624 case AMDGPU::V_FMAC_F16_fake16_e64:
3625 case AMDGPU::V_FMAC_F16_t16_e32:
3626 case AMDGPU::V_FMAC_F16_fake16_e32:
3627 case AMDGPU::V_FMA_F16_e64:
3628 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3629 ? AMDGPU::V_FMAMK_F16_t16
3630 : AMDGPU::V_FMAMK_F16_fake16
3631 : AMDGPU::V_FMAMK_F16;
3632 case AMDGPU::V_FMAC_F64_e32:
3633 case AMDGPU::V_FMAC_F64_e64:
3634 case AMDGPU::V_FMA_F64_e64:
3635 return AMDGPU::V_FMAMK_F64;
3649 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3652 if (
Opc == AMDGPU::COPY) {
3653 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3660 if (HasMultipleUses) {
3663 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3666 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3674 if (ImmDefSize == 32 &&
3679 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3680 RI.getSubRegIdxSize(UseSubReg) == 16;
3683 if (RI.hasVGPRs(DstRC))
3686 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3692 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3699 for (
unsigned MovOp :
3700 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3701 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3709 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3713 if (MovDstPhysReg) {
3717 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3724 if (MovDstPhysReg) {
3725 if (!MovDstRC->
contains(MovDstPhysReg))
3741 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3749 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3753 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3755 UseMI.getOperand(0).setReg(MovDstPhysReg);
3760 UseMI.setDesc(NewMCID);
3761 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3762 UseMI.addImplicitDefUseOperands(*MF);
3766 if (HasMultipleUses)
3769 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3770 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3771 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3772 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3773 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3774 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3775 Opc == AMDGPU::V_FMAC_F64_e64) {
3784 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3795 auto CopyRegOperandToNarrowerRC =
3798 if (!
MI.getOperand(OpNo).isReg())
3802 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3805 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3806 get(AMDGPU::COPY), Tmp)
3808 MI.getOperand(OpNo).setReg(Tmp);
3809 MI.getOperand(OpNo).setIsKill();
3816 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3817 if (!RegSrc->
isReg())
3820 ST.getConstantBusLimit(
Opc) < 2)
3835 if (Def && Def->isMoveImmediate() &&
3850 unsigned SrcSubReg = RegSrc->
getSubReg();
3855 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3856 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3857 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3858 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3859 UseMI.untieRegOperand(
3860 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3867 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3868 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3872 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3873 UseMI.getOperand(0).getReg())
3875 UseMI.getOperand(0).setReg(Tmp);
3876 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3877 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
3882 DefMI.eraseFromParent();
3889 if (ST.getConstantBusLimit(
Opc) < 2) {
3892 bool Src0Inlined =
false;
3893 if (Src0->
isReg()) {
3898 if (Def && Def->isMoveImmediate() &&
3903 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
3904 RI.isSGPRReg(*MRI, Src0->
getReg())) {
3910 if (Src1->
isReg() && !Src0Inlined) {
3913 if (Def && Def->isMoveImmediate() &&
3917 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
3930 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3931 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3932 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3933 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3934 UseMI.untieRegOperand(
3935 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3937 const std::optional<int64_t> SubRegImm =
3947 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
3948 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
3952 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3953 UseMI.getOperand(0).getReg())
3955 UseMI.getOperand(0).setReg(Tmp);
3956 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3957 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
3967 DefMI.eraseFromParent();
3979 if (BaseOps1.
size() != BaseOps2.
size())
3981 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
3982 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
3990 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
3991 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
3992 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3994 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
3997bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4000 int64_t Offset0, Offset1;
4003 bool Offset0IsScalable, Offset1IsScalable;
4017 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4018 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4025 "MIa must load from or modify a memory location");
4027 "MIb must load from or modify a memory location");
4049 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4056 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4066 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4080 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4091 if (
Reg.isPhysical())
4095 Imm = Def->getOperand(1).getImm();
4115 unsigned NumOps =
MI.getNumOperands();
4118 if (
Op.isReg() &&
Op.isKill())
4126 case AMDGPU::V_MAC_F16_e32:
4127 case AMDGPU::V_MAC_F16_e64:
4128 return AMDGPU::V_MAD_F16_e64;
4129 case AMDGPU::V_MAC_F32_e32:
4130 case AMDGPU::V_MAC_F32_e64:
4131 return AMDGPU::V_MAD_F32_e64;
4132 case AMDGPU::V_MAC_LEGACY_F32_e32:
4133 case AMDGPU::V_MAC_LEGACY_F32_e64:
4134 return AMDGPU::V_MAD_LEGACY_F32_e64;
4135 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4136 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4137 return AMDGPU::V_FMA_LEGACY_F32_e64;
4138 case AMDGPU::V_FMAC_F16_e32:
4139 case AMDGPU::V_FMAC_F16_e64:
4140 case AMDGPU::V_FMAC_F16_t16_e64:
4141 case AMDGPU::V_FMAC_F16_fake16_e64:
4142 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4143 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4144 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4145 : AMDGPU::V_FMA_F16_gfx9_e64;
4146 case AMDGPU::V_FMAC_F32_e32:
4147 case AMDGPU::V_FMAC_F32_e64:
4148 return AMDGPU::V_FMA_F32_e64;
4149 case AMDGPU::V_FMAC_F64_e32:
4150 case AMDGPU::V_FMAC_F64_e64:
4151 return AMDGPU::V_FMA_F64_e64;
4171 if (
MI.isBundle()) {
4174 if (
MI.getBundleSize() != 1)
4176 CandidateMI =
MI.getNextNode();
4180 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4184 if (
MI.isBundle()) {
4189 MI.untieRegOperand(MO.getOperandNo());
4197 if (Def.isEarlyClobber() && Def.isReg() &&
4202 auto UpdateDefIndex = [&](
LiveRange &LR) {
4203 auto *S = LR.find(OldIndex);
4204 if (S != LR.end() && S->start == OldIndex) {
4205 assert(S->valno && S->valno->def == OldIndex);
4206 S->start = NewIndex;
4207 S->valno->def = NewIndex;
4211 for (
auto &SR : LI.subranges())
4217 if (U.RemoveMIUse) {
4220 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4224 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4225 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4226 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4227 U.RemoveMIUse->removeOperand(
I);
4232 if (
MI.isBundle()) {
4236 if (MO.isReg() && MO.getReg() == DefReg) {
4237 assert(MO.getSubReg() == 0 &&
4238 "tied sub-registers in bundles currently not supported");
4239 MI.removeOperand(MO.getOperandNo());
4256 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4257 MIOp.setIsUndef(
true);
4258 MIOp.setReg(DummyReg);
4262 if (
MI.isBundle()) {
4266 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4267 MIOp.setIsUndef(
true);
4268 MIOp.setReg(DummyReg);
4281 return MI.isBundle() ? &
MI : NewMI;
4286 ThreeAddressUpdates &U)
const {
4288 unsigned Opc =
MI.getOpcode();
4292 if (NewMFMAOpc != -1) {
4295 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4296 MIB.
add(
MI.getOperand(
I));
4304 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4309 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4310 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4311 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4315 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4316 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4317 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4318 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4319 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4320 bool Src0Literal =
false;
4325 case AMDGPU::V_MAC_F16_e64:
4326 case AMDGPU::V_FMAC_F16_e64:
4327 case AMDGPU::V_FMAC_F16_t16_e64:
4328 case AMDGPU::V_FMAC_F16_fake16_e64:
4329 case AMDGPU::V_MAC_F32_e64:
4330 case AMDGPU::V_MAC_LEGACY_F32_e64:
4331 case AMDGPU::V_FMAC_F32_e64:
4332 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4333 case AMDGPU::V_FMAC_F64_e64:
4335 case AMDGPU::V_MAC_F16_e32:
4336 case AMDGPU::V_FMAC_F16_e32:
4337 case AMDGPU::V_MAC_F32_e32:
4338 case AMDGPU::V_MAC_LEGACY_F32_e32:
4339 case AMDGPU::V_FMAC_F32_e32:
4340 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4341 case AMDGPU::V_FMAC_F64_e32: {
4342 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4343 AMDGPU::OpName::src0);
4344 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4355 MachineInstrBuilder MIB;
4358 const MachineOperand *Src0Mods =
4361 const MachineOperand *Src1Mods =
4364 const MachineOperand *Src2Mods =
4370 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4371 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4373 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4375 MachineInstr *
DefMI =
nullptr;
4411 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4427 if (Src0Literal && !ST.hasVOP3Literal())
4455 switch (
MI.getOpcode()) {
4456 case AMDGPU::S_SET_GPR_IDX_ON:
4457 case AMDGPU::S_SET_GPR_IDX_MODE:
4458 case AMDGPU::S_SET_GPR_IDX_OFF:
4476 if (
MI.isTerminator() ||
MI.isPosition())
4480 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4483 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4489 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4490 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4491 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4492 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4493 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4498 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4499 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4500 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4514 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4519 if (
MI.memoperands_empty())
4524 unsigned AS = Memop->getAddrSpace();
4525 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4526 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4527 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4528 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4543 if (
MI.memoperands_empty())
4552 unsigned AS = Memop->getAddrSpace();
4562 bool TgSplit)
const {
4575 if (
MI.memoperands_empty())
4580 unsigned AS = Memop->getAddrSpace();
4596 unsigned Opcode =
MI.getOpcode();
4611 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4612 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4613 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4614 Opcode == AMDGPU::S_SETHALT)
4617 if (
MI.isCall() ||
MI.isInlineAsm())
4633 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4634 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4635 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4636 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4644 if (
MI.isMetaInstruction())
4648 if (
MI.isCopyLike()) {
4649 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4653 return MI.readsRegister(AMDGPU::EXEC, &RI);
4664 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4668 switch (Imm.getBitWidth()) {
4674 ST.hasInv2PiInlineImm());
4677 ST.hasInv2PiInlineImm());
4679 return ST.has16BitInsts() &&
4681 ST.hasInv2PiInlineImm());
4688 APInt IntImm = Imm.bitcastToAPInt();
4690 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4698 return ST.has16BitInsts() &&
4701 return ST.has16BitInsts() &&
4711 switch (OperandType) {
4721 int32_t Trunc =
static_cast<int32_t
>(Imm);
4765 int16_t Trunc =
static_cast<int16_t
>(Imm);
4766 return ST.has16BitInsts() &&
4775 int16_t Trunc =
static_cast<int16_t
>(Imm);
4776 return ST.has16BitInsts() &&
4827 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4833 return ST.hasVOP3Literal();
4837 int64_t ImmVal)
const {
4839 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4840 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4841 OpNo ==
static_cast<unsigned>(Src1Idx))
4846 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4847 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4848 AMDGPU::OpName::src2))
4850 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4862 "unexpected imm-like operand kind");
4875 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4893 AMDGPU::OpName
OpName)
const {
4895 return Mods && Mods->
getImm();
4908 switch (
MI.getOpcode()) {
4909 default:
return false;
4911 case AMDGPU::V_ADDC_U32_e64:
4912 case AMDGPU::V_SUBB_U32_e64:
4913 case AMDGPU::V_SUBBREV_U32_e64: {
4916 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
4921 case AMDGPU::V_MAC_F16_e64:
4922 case AMDGPU::V_MAC_F32_e64:
4923 case AMDGPU::V_MAC_LEGACY_F32_e64:
4924 case AMDGPU::V_FMAC_F16_e64:
4925 case AMDGPU::V_FMAC_F16_t16_e64:
4926 case AMDGPU::V_FMAC_F16_fake16_e64:
4927 case AMDGPU::V_FMAC_F32_e64:
4928 case AMDGPU::V_FMAC_F64_e64:
4929 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4930 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
4935 case AMDGPU::V_CNDMASK_B32_e64:
4941 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
4971 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
4980 unsigned Op32)
const {
4994 Inst32.
add(
MI.getOperand(
I));
4998 int Idx =
MI.getNumExplicitDefs();
5000 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5005 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5027 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5035 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5038 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5039 AMDGPU::SReg_64RegClass.contains(Reg);
5067 switch (MO.getReg()) {
5069 case AMDGPU::VCC_LO:
5070 case AMDGPU::VCC_HI:
5072 case AMDGPU::FLAT_SCR:
5085 switch (
MI.getOpcode()) {
5086 case AMDGPU::V_READLANE_B32:
5087 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5088 case AMDGPU::V_WRITELANE_B32:
5089 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5096 if (
MI.isPreISelOpcode() ||
5097 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5115 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5126 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5127 ErrInfo =
"illegal copy from vector register to SGPR";
5145 if (!MRI.
isSSA() &&
MI.isCopy())
5146 return verifyCopy(
MI, MRI, ErrInfo);
5148 if (SIInstrInfo::isGenericOpcode(Opcode))
5151 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5152 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5153 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5155 if (Src0Idx == -1) {
5157 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5158 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5159 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5160 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5165 if (!
Desc.isVariadic() &&
5166 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5167 ErrInfo =
"Instruction has wrong number of operands.";
5171 if (
MI.isInlineAsm()) {
5184 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5185 ErrInfo =
"inlineasm operand has incorrect register class.";
5193 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5194 ErrInfo =
"missing memory operand from image instruction.";
5199 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5202 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5203 "all fp values to integers.";
5208 int16_t RegClass = getOpRegClassID(OpInfo);
5210 switch (OpInfo.OperandType) {
5212 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5213 ErrInfo =
"Illegal immediate value for operand.";
5246 ErrInfo =
"Illegal immediate value for operand.";
5255 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5258 OpInfo.OperandType ==
5260 ErrInfo =
"illegal 64-bit immediate value for operand.";
5267 ErrInfo =
"Expected inline constant for operand.";
5281 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5282 ErrInfo =
"Expected immediate, but got non-immediate";
5291 if (OpInfo.isGenericType())
5306 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5307 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5309 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5311 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5312 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5319 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5320 ErrInfo =
"Subtarget requires even aligned vector registers";
5325 if (RegClass != -1) {
5326 if (Reg.isVirtual())
5331 ErrInfo =
"Operand has incorrect register class.";
5339 if (!ST.hasSDWA()) {
5340 ErrInfo =
"SDWA is not supported on this target";
5344 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5345 AMDGPU::OpName::dst_sel}) {
5349 int64_t Imm = MO->
getImm();
5351 ErrInfo =
"Invalid SDWA selection";
5356 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5358 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5363 if (!ST.hasSDWAScalar()) {
5365 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5366 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5373 "Only reg allowed as operands in SDWA instructions on GFX9+";
5379 if (!ST.hasSDWAOmod()) {
5382 if (OMod !=
nullptr &&
5384 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5389 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5390 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5391 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5392 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5395 unsigned Mods = Src0ModsMO->
getImm();
5398 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5404 if (
isVOPC(BasicOpcode)) {
5405 if (!ST.hasSDWASdst() && DstIdx != -1) {
5408 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5409 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5412 }
else if (!ST.hasSDWAOutModsVOPC()) {
5415 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5416 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5422 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5423 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5430 if (DstUnused && DstUnused->isImm() &&
5433 if (!Dst.isReg() || !Dst.isTied()) {
5434 ErrInfo =
"Dst register should have tied register";
5439 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5442 "Dst register should be tied to implicit use of preserved register";
5446 ErrInfo =
"Dst register should use same physical register as preserved";
5452 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5454 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5455 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5458 if (Src1MO.
isImm()) {
5459 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5465 if (
isImage(Opcode) && !
MI.mayStore()) {
5477 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5485 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5489 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5490 if (RegCount > DstSize) {
5491 ErrInfo =
"Image instruction returns too many registers for dst "
5501 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5502 unsigned ConstantBusCount = 0;
5503 bool UsesLiteral =
false;
5506 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5510 LiteralVal = &
MI.getOperand(ImmIdx);
5519 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5530 }
else if (!MO.
isFI()) {
5537 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5547 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5548 return !RI.regsOverlap(SGPRUsed, SGPR);
5557 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5558 Opcode != AMDGPU::V_WRITELANE_B32) {
5559 ErrInfo =
"VOP* instruction violates constant bus restriction";
5563 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5564 ErrInfo =
"VOP3 instruction uses literal";
5571 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5572 unsigned SGPRCount = 0;
5575 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5583 if (MO.
getReg() != SGPRUsed)
5588 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5589 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5596 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5597 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5604 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5614 ErrInfo =
"ABS not allowed in VOP3B instructions";
5627 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5634 if (
Desc.isBranch()) {
5636 ErrInfo =
"invalid branch target for SOPK instruction";
5643 ErrInfo =
"invalid immediate for SOPK instruction";
5648 ErrInfo =
"invalid immediate for SOPK instruction";
5655 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5656 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5657 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5658 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5659 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5660 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5662 const unsigned StaticNumOps =
5663 Desc.getNumOperands() +
Desc.implicit_uses().size();
5664 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5670 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5671 ErrInfo =
"missing implicit register operands";
5677 if (!Dst->isUse()) {
5678 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5683 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5684 UseOpIdx != StaticNumOps + 1) {
5685 ErrInfo =
"movrel implicit operands should be tied";
5692 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5694 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5695 ErrInfo =
"src0 should be subreg of implicit vector use";
5703 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5704 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5710 if (
MI.mayStore() &&
5715 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5716 ErrInfo =
"scalar stores must use m0 as offset register";
5722 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5724 if (
Offset->getImm() != 0) {
5725 ErrInfo =
"subtarget does not support offsets in flat instructions";
5730 if (
isDS(
MI) && !ST.hasGDS()) {
5732 if (GDSOp && GDSOp->
getImm() != 0) {
5733 ErrInfo =
"GDS is not supported on this subtarget";
5741 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5742 AMDGPU::OpName::vaddr0);
5743 AMDGPU::OpName RSrcOpName =
5744 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5745 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5753 ErrInfo =
"dim is out of range";
5758 if (ST.hasR128A16()) {
5760 IsA16 = R128A16->
getImm() != 0;
5761 }
else if (ST.hasA16()) {
5763 IsA16 = A16->
getImm() != 0;
5766 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5768 unsigned AddrWords =
5771 unsigned VAddrWords;
5773 VAddrWords = RsrcIdx - VAddr0Idx;
5774 if (ST.hasPartialNSAEncoding() &&
5776 unsigned LastVAddrIdx = RsrcIdx - 1;
5777 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5785 if (VAddrWords != AddrWords) {
5787 <<
" but got " << VAddrWords <<
"\n");
5788 ErrInfo =
"bad vaddr size";
5798 unsigned DC = DppCt->
getImm();
5799 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5800 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5801 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5802 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5803 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5804 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5805 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5806 ErrInfo =
"Invalid dpp_ctrl value";
5809 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5810 !ST.hasDPPWavefrontShifts()) {
5811 ErrInfo =
"Invalid dpp_ctrl value: "
5812 "wavefront shifts are not supported on GFX10+";
5815 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5816 !ST.hasDPPBroadcasts()) {
5817 ErrInfo =
"Invalid dpp_ctrl value: "
5818 "broadcasts are not supported on GFX10+";
5821 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5823 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5824 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5825 !ST.hasGFX90AInsts()) {
5826 ErrInfo =
"Invalid dpp_ctrl value: "
5827 "row_newbroadcast/row_share is not supported before "
5831 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5832 ErrInfo =
"Invalid dpp_ctrl value: "
5833 "row_share and row_xmask are not supported before GFX10";
5838 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5841 ErrInfo =
"Invalid dpp_ctrl value: "
5842 "DP ALU dpp only support row_newbcast";
5849 AMDGPU::OpName DataName =
5850 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5856 if (!ST.hasGFX90AInsts()) {
5857 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5858 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
5859 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
5860 ErrInfo =
"Invalid register class: "
5861 "agpr loads and stores not supported on this GPU";
5867 if (ST.needsAlignedVGPRs()) {
5868 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
5873 if (Reg.isPhysical())
5874 return !(RI.getHWRegIndex(Reg) & 1);
5876 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5877 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
5880 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5881 Opcode == AMDGPU::DS_GWS_BARRIER) {
5883 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5884 ErrInfo =
"Subtarget requires even aligned vector registers "
5885 "for DS_GWS instructions";
5891 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5892 ErrInfo =
"Subtarget requires even aligned vector registers "
5893 "for vaddr operand of image instructions";
5899 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5901 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5902 ErrInfo =
"Invalid register class: "
5903 "v_accvgpr_write with an SGPR is not supported on this GPU";
5908 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5911 ErrInfo =
"pseudo expects only physical SGPRs";
5918 if (!ST.hasScaleOffset()) {
5919 ErrInfo =
"Subtarget does not support offset scaling";
5923 ErrInfo =
"Instruction does not support offset scaling";
5931 for (
unsigned I = 0;
I < 3; ++
I) {
5937 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
5938 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
5940 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
5941 &AMDGPU::SReg_64RegClass) ||
5942 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
5943 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
5952 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
5954 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
5956 : AMDGPU::V_MOV_B32_e32;
5966 default:
return AMDGPU::INSTRUCTION_LIST_END;
5967 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
5968 case AMDGPU::COPY:
return AMDGPU::COPY;
5969 case AMDGPU::PHI:
return AMDGPU::PHI;
5970 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
5971 case AMDGPU::WQM:
return AMDGPU::WQM;
5972 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
5973 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
5974 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
5975 case AMDGPU::S_ADD_I32:
5976 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
5977 case AMDGPU::S_ADDC_U32:
5978 return AMDGPU::V_ADDC_U32_e32;
5979 case AMDGPU::S_SUB_I32:
5980 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
5983 case AMDGPU::S_ADD_U32:
5984 return AMDGPU::V_ADD_CO_U32_e32;
5985 case AMDGPU::S_SUB_U32:
5986 return AMDGPU::V_SUB_CO_U32_e32;
5987 case AMDGPU::S_ADD_U64_PSEUDO:
5988 return AMDGPU::V_ADD_U64_PSEUDO;
5989 case AMDGPU::S_SUB_U64_PSEUDO:
5990 return AMDGPU::V_SUB_U64_PSEUDO;
5991 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
5992 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
5993 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
5994 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
5995 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
5996 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
5997 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
5998 case AMDGPU::S_XNOR_B32:
5999 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6000 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6001 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6002 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6003 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6004 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6005 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6006 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6007 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6008 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6009 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6010 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6011 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6012 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6013 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6014 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6015 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6016 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6017 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6018 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6019 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6020 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6021 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6022 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6023 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6024 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6025 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6026 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6027 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6028 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6029 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6030 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6031 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6032 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6033 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6034 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6035 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6036 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6037 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6038 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6039 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6040 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6041 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6042 case AMDGPU::S_CVT_F32_F16:
6043 case AMDGPU::S_CVT_HI_F32_F16:
6044 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6045 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6046 case AMDGPU::S_CVT_F16_F32:
6047 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6048 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6049 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6050 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6051 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6052 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6053 case AMDGPU::S_CEIL_F16:
6054 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6055 : AMDGPU::V_CEIL_F16_fake16_e64;
6056 case AMDGPU::S_FLOOR_F16:
6057 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6058 : AMDGPU::V_FLOOR_F16_fake16_e64;
6059 case AMDGPU::S_TRUNC_F16:
6060 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6061 : AMDGPU::V_TRUNC_F16_fake16_e64;
6062 case AMDGPU::S_RNDNE_F16:
6063 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6064 : AMDGPU::V_RNDNE_F16_fake16_e64;
6065 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6066 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6067 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6068 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6069 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6070 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6071 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6072 case AMDGPU::S_ADD_F16:
6073 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6074 : AMDGPU::V_ADD_F16_fake16_e64;
6075 case AMDGPU::S_SUB_F16:
6076 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6077 : AMDGPU::V_SUB_F16_fake16_e64;
6078 case AMDGPU::S_MIN_F16:
6079 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6080 : AMDGPU::V_MIN_F16_fake16_e64;
6081 case AMDGPU::S_MAX_F16:
6082 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6083 : AMDGPU::V_MAX_F16_fake16_e64;
6084 case AMDGPU::S_MINIMUM_F16:
6085 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6086 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6087 case AMDGPU::S_MAXIMUM_F16:
6088 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6089 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6090 case AMDGPU::S_MUL_F16:
6091 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6092 : AMDGPU::V_MUL_F16_fake16_e64;
6093 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6094 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6095 case AMDGPU::S_FMAC_F16:
6096 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6097 : AMDGPU::V_FMAC_F16_fake16_e64;
6098 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6099 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6100 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6101 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6102 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6103 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6104 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6105 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6106 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6107 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6108 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6109 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6110 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6111 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6112 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6113 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6114 case AMDGPU::S_CMP_LT_F16:
6115 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6116 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6117 case AMDGPU::S_CMP_EQ_F16:
6118 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6119 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6120 case AMDGPU::S_CMP_LE_F16:
6121 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6122 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6123 case AMDGPU::S_CMP_GT_F16:
6124 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6125 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6126 case AMDGPU::S_CMP_LG_F16:
6127 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6128 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6129 case AMDGPU::S_CMP_GE_F16:
6130 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6131 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6132 case AMDGPU::S_CMP_O_F16:
6133 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6134 : AMDGPU::V_CMP_O_F16_fake16_e64;
6135 case AMDGPU::S_CMP_U_F16:
6136 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6137 : AMDGPU::V_CMP_U_F16_fake16_e64;
6138 case AMDGPU::S_CMP_NGE_F16:
6139 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6140 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6141 case AMDGPU::S_CMP_NLG_F16:
6142 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6143 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6144 case AMDGPU::S_CMP_NGT_F16:
6145 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6146 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6147 case AMDGPU::S_CMP_NLE_F16:
6148 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6149 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6150 case AMDGPU::S_CMP_NEQ_F16:
6151 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6152 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6153 case AMDGPU::S_CMP_NLT_F16:
6154 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6155 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6156 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6157 case AMDGPU::V_S_EXP_F16_e64:
6158 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6159 : AMDGPU::V_EXP_F16_fake16_e64;
6160 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6161 case AMDGPU::V_S_LOG_F16_e64:
6162 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6163 : AMDGPU::V_LOG_F16_fake16_e64;
6164 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6165 case AMDGPU::V_S_RCP_F16_e64:
6166 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6167 : AMDGPU::V_RCP_F16_fake16_e64;
6168 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6169 case AMDGPU::V_S_RSQ_F16_e64:
6170 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6171 : AMDGPU::V_RSQ_F16_fake16_e64;
6172 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6173 case AMDGPU::V_S_SQRT_F16_e64:
6174 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6175 : AMDGPU::V_SQRT_F16_fake16_e64;
6178 "Unexpected scalar opcode without corresponding vector one!");
6227 "Not a whole wave func");
6230 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6231 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6238 unsigned OpNo)
const {
6240 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6241 Desc.operands()[OpNo].RegClass == -1) {
6244 if (Reg.isVirtual()) {
6248 return RI.getPhysRegBaseClass(Reg);
6251 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6252 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6257 constexpr AMDGPU::OpName OpNames[] = {
6258 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6261 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6262 if (
static_cast<unsigned>(SrcIdx) ==
OpIdx)
6274 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[
OpIdx]);
6276 unsigned Size = RI.getRegSizeInBits(*RC);
6277 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6278 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6279 : AMDGPU::V_MOV_B32_e32;
6281 Opcode = AMDGPU::COPY;
6282 else if (RI.isSGPRClass(RC))
6283 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6308 .
addImm(AMDGPU::sub0_sub1)
6310 .
addImm(AMDGPU::sub2_sub3);
6323 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6329 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6340 if (SubIdx == AMDGPU::sub0)
6342 if (SubIdx == AMDGPU::sub1)
6354void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6370 if (Reg.isPhysical())
6380 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6383 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6390 unsigned Opc =
MI.getOpcode();
6393 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6403 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6404 if (IsAGPR && !ST.hasMAIInsts())
6410 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6411 const int DataIdx = AMDGPU::getNamedOperandIdx(
6412 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6413 if ((
int)
OpIdx == VDstIdx && DataIdx != -1 &&
6414 MI.getOperand(DataIdx).isReg() &&
6415 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6417 if ((
int)
OpIdx == DataIdx) {
6418 if (VDstIdx != -1 &&
6419 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6422 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6423 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6424 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6429 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6430 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6431 RI.isSGPRReg(MRI, MO.
getReg()))
6434 if (ST.hasFlatScratchHiInB64InstHazard() &&
6441 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6444 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6445 (
int)
OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6465 constexpr unsigned NumOps = 3;
6466 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6467 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6468 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6469 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6474 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6477 MO = &
MI.getOperand(SrcIdx);
6480 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6484 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6488 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6492 return !OpSel && !OpSelHi;
6501 int64_t RegClass = getOpRegClassID(OpInfo);
6503 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6509 if (
isVALU(
MI,
true) && !IsInlineConst &&
6513 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6514 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6518 if (!LiteralLimit--)
6528 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6536 if (--ConstantBusLimit <= 0)
6548 if (!LiteralLimit--)
6550 if (--ConstantBusLimit <= 0)
6556 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6560 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6562 !
Op.isIdenticalTo(*MO))
6572 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6587 bool Is64BitOp = Is64BitFPOp ||
6595 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6604 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6622 bool IsGFX950Only = ST.hasGFX950Insts();
6623 bool IsGFX940Only = ST.hasGFX940Insts();
6625 if (!IsGFX950Only && !IsGFX940Only)
6643 unsigned Opcode =
MI.getOpcode();
6645 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6646 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6647 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6648 case AMDGPU::V_MQSAD_U32_U8_e64:
6649 case AMDGPU::V_PK_ADD_F16:
6650 case AMDGPU::V_PK_ADD_F32:
6651 case AMDGPU::V_PK_ADD_I16:
6652 case AMDGPU::V_PK_ADD_U16:
6653 case AMDGPU::V_PK_ASHRREV_I16:
6654 case AMDGPU::V_PK_FMA_F16:
6655 case AMDGPU::V_PK_FMA_F32:
6656 case AMDGPU::V_PK_FMAC_F16_e32:
6657 case AMDGPU::V_PK_FMAC_F16_e64:
6658 case AMDGPU::V_PK_LSHLREV_B16:
6659 case AMDGPU::V_PK_LSHRREV_B16:
6660 case AMDGPU::V_PK_MAD_I16:
6661 case AMDGPU::V_PK_MAD_U16:
6662 case AMDGPU::V_PK_MAX_F16:
6663 case AMDGPU::V_PK_MAX_I16:
6664 case AMDGPU::V_PK_MAX_U16:
6665 case AMDGPU::V_PK_MIN_F16:
6666 case AMDGPU::V_PK_MIN_I16:
6667 case AMDGPU::V_PK_MIN_U16:
6668 case AMDGPU::V_PK_MOV_B32:
6669 case AMDGPU::V_PK_MUL_F16:
6670 case AMDGPU::V_PK_MUL_F32:
6671 case AMDGPU::V_PK_MUL_LO_U16:
6672 case AMDGPU::V_PK_SUB_I16:
6673 case AMDGPU::V_PK_SUB_U16:
6674 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6683 unsigned Opc =
MI.getOpcode();
6686 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6689 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6695 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6696 RI.isSGPRReg(MRI, Src0.
getReg()))
6702 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6704 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6710 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6721 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6722 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6723 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6735 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6736 RI.isVGPR(MRI, Src1.
getReg())) {
6749 if (HasImplicitSGPR || !
MI.isCommutable()) {
6766 if (CommutedOpc == -1) {
6771 MI.setDesc(
get(CommutedOpc));
6775 bool Src0Kill = Src0.
isKill();
6779 else if (Src1.
isReg()) {
6794 unsigned Opc =
MI.getOpcode();
6797 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6798 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6799 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6802 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6803 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6804 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6805 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6806 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6807 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6808 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6818 if (VOP3Idx[2] != -1) {
6830 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6831 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6833 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6835 SGPRsUsed.
insert(SGPRReg);
6839 for (
int Idx : VOP3Idx) {
6848 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6860 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
6867 if (ConstantBusLimit > 0) {
6879 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
6880 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
6886 for (
unsigned I = 0;
I < 3; ++
I) {
6899 SRC = RI.getCommonSubClass(SRC, DstRC);
6902 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6904 if (RI.hasAGPRs(VRC)) {
6905 VRC = RI.getEquivalentVGPRClass(VRC);
6908 get(TargetOpcode::COPY), NewSrcReg)
6915 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6921 for (
unsigned i = 0; i < SubRegs; ++i) {
6924 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6925 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6931 get(AMDGPU::REG_SEQUENCE), DstReg);
6932 for (
unsigned i = 0; i < SubRegs; ++i) {
6934 MIB.
addImm(RI.getSubRegFromChannel(i));
6947 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
6949 SBase->setReg(SGPR);
6952 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
6960 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
6961 if (OldSAddrIdx < 0)
6974 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
6977 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
6978 if (NewVAddrIdx < 0)
6981 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
6985 if (OldVAddrIdx >= 0) {
6999 if (OldVAddrIdx == NewVAddrIdx) {
7010 assert(OldSAddrIdx == NewVAddrIdx);
7012 if (OldVAddrIdx >= 0) {
7013 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7014 AMDGPU::OpName::vdst_in);
7018 if (NewVDstIn != -1) {
7019 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7025 if (NewVDstIn != -1) {
7026 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7067 unsigned OpSubReg =
Op.getSubReg();
7070 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7077 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7078 .
addReg(OpReg, {}, OpSubReg);
7080 Op.setSubReg(AMDGPU::NoSubRegister);
7087 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7090 bool ImpDef = Def->isImplicitDef();
7091 while (!ImpDef && Def && Def->isCopy()) {
7092 if (Def->getOperand(1).getReg().isPhysical())
7095 ImpDef = Def && Def->isImplicitDef();
7097 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7113 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7118 bool UseNewExecInstructions =
7127 if (UseNewExecInstructions) {
7162 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7163 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7164 unsigned NumSubRegs =
RegSize / 32;
7165 Register VScalarOp = ScalarOp->getReg();
7168 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7170 if (NumSubRegs == 1) {
7173 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7174 Common != VScalarOpRC) {
7181 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7184 if (UseNewExecInstructions) {
7186 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7189 if (
I == LoopBB.
end())
7194 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7200 CondReg = NewCondReg;
7211 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7212 ScalarOp->setReg(CurReg);
7215 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7216 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7218 ScalarOp->setReg(PhySGPRs[Idx]);
7220 ScalarOp->setIsKill();
7224 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7225 "Unhandled register size");
7227 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7234 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7235 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7238 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7239 .
addReg(VScalarOp, VScalarOpUndef,
7240 TRI->getSubRegFromChannel(Idx + 1));
7247 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7254 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7256 if (UseNewExecInstructions) {
7258 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7260 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7261 if (
I == LoopBB.
end())
7265 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7267 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7271 CondReg = NewCondReg;
7282 const auto *SScalarOpRC =
7288 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7289 unsigned Channel = 0;
7290 for (
Register Piece : ReadlanePieces) {
7291 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7295 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7296 ScalarOp->setReg(SScalarOp);
7298 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7299 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7301 ScalarOp->setReg(PhySGPRs[Idx]);
7303 ScalarOp->setIsKill();
7311 if (!UseNewExecInstructions) {
7323 if (UseNewExecInstructions) {
7347 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7348 "Physical SGPRs must be empty or match the number of scalar operands");
7354 if (!Begin.isValid())
7356 if (!End.isValid()) {
7362 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7371 std::numeric_limits<unsigned>::max()) !=
7389 for (
auto I = Begin;
I != AfterMI;
I++) {
7390 for (
auto &MO :
I->all_uses())
7426 for (
auto &Succ : RemainderBB->
successors()) {
7451static std::tuple<unsigned, unsigned>
7459 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7460 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7467 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7484 .
addImm(AMDGPU::sub0_sub1)
7490 return std::tuple(RsrcPtr, NewSRsrc);
7501 if (ST.useRealTrue16Insts())
7531 if (
MI.getOpcode() == AMDGPU::PHI) {
7533 assert(!RI.isSGPRClass(VRC));
7536 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7538 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7554 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7557 if (RI.hasVGPRs(DstRC)) {
7561 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7563 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7581 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7586 if (DstRC != Src0RC) {
7595 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7597 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7603 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7604 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7605 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7606 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7607 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7608 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7609 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7611 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7624 ? AMDGPU::OpName::rsrc
7625 : AMDGPU::OpName::srsrc;
7630 AMDGPU::OpName SampOpName =
7631 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7640 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7648 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7652 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7662 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7663 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7664 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7665 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7667 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7674 bool isSoffsetLegal =
true;
7676 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7677 if (SoffsetIdx != -1) {
7681 isSoffsetLegal =
false;
7685 bool isRsrcLegal =
true;
7687 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7688 if (RsrcIdx != -1) {
7690 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7691 isRsrcLegal =
false;
7695 if (isRsrcLegal && isSoffsetLegal)
7723 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7727 unsigned RsrcPtr, NewSRsrc;
7734 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7735 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7741 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7742 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7755 }
else if (!VAddr && ST.hasAddr64()) {
7759 "FIXME: Need to emit flat atomics here");
7761 unsigned RsrcPtr, NewSRsrc;
7787 MIB.
addImm(CPol->getImm());
7792 MIB.
addImm(TFE->getImm());
7812 MI.removeFromParent();
7817 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7818 .addImm(AMDGPU::sub0)
7819 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7820 .addImm(AMDGPU::sub1);
7823 if (!isSoffsetLegal) {
7834 if (!isSoffsetLegal) {
7843 if (InSet.insert(
MI).second)
7847 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
7848 if (RsrcIdx != -1) {
7849 DeferredList.insert(
MI);
7854 return DeferredList.contains(
MI);
7864 if (!ST.useRealTrue16Insts())
7867 unsigned Opcode =
MI.getOpcode();
7870 if (
OpIdx >=
MI.getNumExplicitOperands() ||
7871 OpIdx >=
get(Opcode).getNumOperands() ||
7872 get(Opcode).operands()[
OpIdx].RegClass == -1)
7876 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
7880 if (!RI.isVGPRClass(CurrRC))
7883 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[
OpIdx]);
7885 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7887 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
7888 Op.setSubReg(AMDGPU::lo16);
7893 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
7894 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7904 Op.setReg(NewDstReg);
7905 Op.setSubReg(AMDGPU::NoSubRegister);
7918 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7919 "This only handle waterfall for SI_CALL_ISEL");
7926 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7929 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7934 while (End !=
MBB.end() && End->isCopy() &&
7935 MI->definesRegister(End->getOperand(1).getReg(), &RI))
7945 while (!Worklist.
empty()) {
7951 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
7957 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
7959 "Deferred MachineInstr are not supposed to re-populate worklist");
7962 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
7963 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
7965 Entry.second.SGPRs);
7968 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
7970 Entry.first->eraseFromParent();
7978 if (SubRegIndices.
size() <= 1) {
7981 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7988 for (int16_t Indice : SubRegIndices) {
7991 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7998 get(AMDGPU::REG_SEQUENCE), DstReg);
7999 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8001 MIB.
addImm(RI.getSubRegFromChannel(i));
8011 if (DstReg == AMDGPU::M0) {
8024 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8026 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8027 if (
UseMI->getOperand(i).isReg() &&
8028 UseMI->getOperand(i).getReg() == DstReg) {
8032 V2SCopyInfo.MOs.push_back(MO);
8033 V2SCopyInfo.SGPRs.push_back(DstReg);
8037 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8038 I->getOperand(0).isReg() &&
8039 I->getOperand(0).getReg() == DstReg) {
8042 }
else if (
I->readsRegister(DstReg, &RI)) {
8044 V2SPhyCopiesToErase[&Inst] =
false;
8046 if (
I->findRegisterDefOperand(DstReg, &RI))
8068 case AMDGPU::S_ADD_I32:
8069 case AMDGPU::S_SUB_I32: {
8073 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8081 case AMDGPU::S_MUL_U64:
8082 if (ST.hasVMulU64Inst()) {
8083 NewOpcode = AMDGPU::V_MUL_U64_e64;
8087 splitScalarSMulU64(Worklist, Inst, MDT);
8091 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8092 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8095 splitScalarSMulPseudo(Worklist, Inst, MDT);
8099 case AMDGPU::S_AND_B64:
8100 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8104 case AMDGPU::S_OR_B64:
8105 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8109 case AMDGPU::S_XOR_B64:
8110 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8114 case AMDGPU::S_NAND_B64:
8115 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8119 case AMDGPU::S_NOR_B64:
8120 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8124 case AMDGPU::S_XNOR_B64:
8125 if (ST.hasDLInsts())
8126 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8128 splitScalar64BitXnor(Worklist, Inst, MDT);
8132 case AMDGPU::S_ANDN2_B64:
8133 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8137 case AMDGPU::S_ORN2_B64:
8138 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8142 case AMDGPU::S_BREV_B64:
8143 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8147 case AMDGPU::S_NOT_B64:
8148 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8152 case AMDGPU::S_BCNT1_I32_B64:
8153 splitScalar64BitBCNT(Worklist, Inst);
8157 case AMDGPU::S_BFE_I64:
8158 splitScalar64BitBFE(Worklist, Inst);
8162 case AMDGPU::S_FLBIT_I32_B64:
8163 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8166 case AMDGPU::S_FF1_I32_B64:
8167 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8171 case AMDGPU::S_LSHL_B32:
8172 if (ST.hasOnlyRevVALUShifts()) {
8173 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8177 case AMDGPU::S_ASHR_I32:
8178 if (ST.hasOnlyRevVALUShifts()) {
8179 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8183 case AMDGPU::S_LSHR_B32:
8184 if (ST.hasOnlyRevVALUShifts()) {
8185 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8189 case AMDGPU::S_LSHL_B64:
8190 if (ST.hasOnlyRevVALUShifts()) {
8192 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8193 : AMDGPU::V_LSHLREV_B64_e64;
8197 case AMDGPU::S_ASHR_I64:
8198 if (ST.hasOnlyRevVALUShifts()) {
8199 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8203 case AMDGPU::S_LSHR_B64:
8204 if (ST.hasOnlyRevVALUShifts()) {
8205 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8210 case AMDGPU::S_ABS_I32:
8211 lowerScalarAbs(Worklist, Inst);
8215 case AMDGPU::S_ABSDIFF_I32:
8216 lowerScalarAbsDiff(Worklist, Inst);
8220 case AMDGPU::S_CBRANCH_SCC0:
8221 case AMDGPU::S_CBRANCH_SCC1: {
8224 bool IsSCC = CondReg == AMDGPU::SCC;
8232 case AMDGPU::S_BFE_U64:
8233 case AMDGPU::S_BFM_B64:
8236 case AMDGPU::S_PACK_LL_B32_B16:
8237 case AMDGPU::S_PACK_LH_B32_B16:
8238 case AMDGPU::S_PACK_HL_B32_B16:
8239 case AMDGPU::S_PACK_HH_B32_B16:
8240 movePackToVALU(Worklist, MRI, Inst);
8244 case AMDGPU::S_XNOR_B32:
8245 lowerScalarXnor(Worklist, Inst);
8249 case AMDGPU::S_NAND_B32:
8250 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8254 case AMDGPU::S_NOR_B32:
8255 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8259 case AMDGPU::S_ANDN2_B32:
8260 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8264 case AMDGPU::S_ORN2_B32:
8265 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8273 case AMDGPU::S_ADD_CO_PSEUDO:
8274 case AMDGPU::S_SUB_CO_PSEUDO: {
8275 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8276 ? AMDGPU::V_ADDC_U32_e64
8277 : AMDGPU::V_SUBB_U32_e64;
8278 const auto *CarryRC = RI.getWaveMaskRegClass();
8300 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8304 case AMDGPU::S_UADDO_PSEUDO:
8305 case AMDGPU::S_USUBO_PSEUDO: {
8311 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8312 ? AMDGPU::V_ADD_CO_U32_e64
8313 : AMDGPU::V_SUB_CO_U32_e64;
8325 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8329 case AMDGPU::S_LSHL1_ADD_U32:
8330 case AMDGPU::S_LSHL2_ADD_U32:
8331 case AMDGPU::S_LSHL3_ADD_U32:
8332 case AMDGPU::S_LSHL4_ADD_U32: {
8336 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8337 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8338 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8352 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8356 case AMDGPU::S_CSELECT_B32:
8357 case AMDGPU::S_CSELECT_B64:
8358 lowerSelect(Worklist, Inst, MDT);
8361 case AMDGPU::S_CMP_EQ_I32:
8362 case AMDGPU::S_CMP_LG_I32:
8363 case AMDGPU::S_CMP_GT_I32:
8364 case AMDGPU::S_CMP_GE_I32:
8365 case AMDGPU::S_CMP_LT_I32:
8366 case AMDGPU::S_CMP_LE_I32:
8367 case AMDGPU::S_CMP_EQ_U32:
8368 case AMDGPU::S_CMP_LG_U32:
8369 case AMDGPU::S_CMP_GT_U32:
8370 case AMDGPU::S_CMP_GE_U32:
8371 case AMDGPU::S_CMP_LT_U32:
8372 case AMDGPU::S_CMP_LE_U32:
8373 case AMDGPU::S_CMP_EQ_U64:
8374 case AMDGPU::S_CMP_LG_U64:
8375 case AMDGPU::S_CMP_LT_F32:
8376 case AMDGPU::S_CMP_EQ_F32:
8377 case AMDGPU::S_CMP_LE_F32:
8378 case AMDGPU::S_CMP_GT_F32:
8379 case AMDGPU::S_CMP_LG_F32:
8380 case AMDGPU::S_CMP_GE_F32:
8381 case AMDGPU::S_CMP_O_F32:
8382 case AMDGPU::S_CMP_U_F32:
8383 case AMDGPU::S_CMP_NGE_F32:
8384 case AMDGPU::S_CMP_NLG_F32:
8385 case AMDGPU::S_CMP_NGT_F32:
8386 case AMDGPU::S_CMP_NLE_F32:
8387 case AMDGPU::S_CMP_NEQ_F32:
8388 case AMDGPU::S_CMP_NLT_F32: {
8393 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8407 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8411 case AMDGPU::S_CMP_LT_F16:
8412 case AMDGPU::S_CMP_EQ_F16:
8413 case AMDGPU::S_CMP_LE_F16:
8414 case AMDGPU::S_CMP_GT_F16:
8415 case AMDGPU::S_CMP_LG_F16:
8416 case AMDGPU::S_CMP_GE_F16:
8417 case AMDGPU::S_CMP_O_F16:
8418 case AMDGPU::S_CMP_U_F16:
8419 case AMDGPU::S_CMP_NGE_F16:
8420 case AMDGPU::S_CMP_NLG_F16:
8421 case AMDGPU::S_CMP_NGT_F16:
8422 case AMDGPU::S_CMP_NLE_F16:
8423 case AMDGPU::S_CMP_NEQ_F16:
8424 case AMDGPU::S_CMP_NLT_F16: {
8446 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8450 case AMDGPU::S_CVT_HI_F32_F16: {
8453 if (ST.useRealTrue16Insts()) {
8458 .
addReg(TmpReg, {}, AMDGPU::hi16)
8474 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8478 case AMDGPU::S_MINIMUM_F32:
8479 case AMDGPU::S_MAXIMUM_F32: {
8491 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8495 case AMDGPU::S_MINIMUM_F16:
8496 case AMDGPU::S_MAXIMUM_F16: {
8498 ? &AMDGPU::VGPR_16RegClass
8499 : &AMDGPU::VGPR_32RegClass);
8510 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8514 case AMDGPU::V_S_EXP_F16_e64:
8515 case AMDGPU::V_S_LOG_F16_e64:
8516 case AMDGPU::V_S_RCP_F16_e64:
8517 case AMDGPU::V_S_RSQ_F16_e64:
8518 case AMDGPU::V_S_SQRT_F16_e64: {
8520 ? &AMDGPU::VGPR_16RegClass
8521 : &AMDGPU::VGPR_32RegClass);
8532 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8538 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8546 if (NewOpcode == Opcode) {
8553 V2SPhyCopiesToErase);
8561 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8568 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8573 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8574 UseMO.setReg(NewDstReg);
8604 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8608 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8614 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8621 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8623 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8628 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8636 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8646 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8647 AMDGPU::OpName::src0_modifiers) >= 0)
8651 NewInstr->addOperand(Src);
8654 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8657 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8659 NewInstr.addImm(
Size);
8660 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8664 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8669 "Scalar BFE is only implemented for constant width and offset");
8677 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8678 AMDGPU::OpName::src1_modifiers) >= 0)
8680 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8682 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8683 AMDGPU::OpName::src2_modifiers) >= 0)
8685 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8687 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8689 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8691 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8697 NewInstr->addOperand(
Op);
8704 if (
Op.getReg() == AMDGPU::SCC) {
8706 if (
Op.isDef() && !
Op.isDead())
8707 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8709 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8714 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8715 Register DstReg = NewInstr->getOperand(0).getReg();
8728 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8732std::pair<bool, MachineBasicBlock *>
8735 if (ST.hasAddNoCarryInsts()) {
8747 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8749 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8750 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8761 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8762 return std::pair(
true, NewBB);
8765 return std::pair(
false,
nullptr);
8782 bool IsSCC = (CondReg == AMDGPU::SCC);
8790 for (MachineOperand &UseMO :
8792 MachineInstr &
UseMI = *UseMO.getParent();
8793 switch (
UseMI.getOpcode()) {
8794 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8795 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8796 case AMDGPU::V_CNDMASK_B16_t16_e32:
8797 case AMDGPU::V_CNDMASK_B16_t16_e64:
8798 case AMDGPU::V_CNDMASK_B32_e32:
8799 case AMDGPU::V_CNDMASK_B32_e64:
8800 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8801 if (UseMO.isImplicit() ||
8803 UseMO.setReg(CondReg);
8817 bool CopyFound =
false;
8818 for (MachineInstr &CandI :
8821 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8823 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8825 .
addReg(CandI.getOperand(1).getReg());
8837 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8846 MachineInstr *NewInst;
8847 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
8848 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8863 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8878 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8879 : AMDGPU::V_SUB_CO_U32_e32;
8890 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8907 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8908 : AMDGPU::V_SUB_CO_U32_e32;
8921 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8935 if (ST.hasDLInsts()) {
8945 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8951 bool Src0IsSGPR = Src0.
isReg() &&
8953 bool Src1IsSGPR = Src1.
isReg() &&
8967 }
else if (Src1IsSGPR) {
8985 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8991 unsigned Opcode)
const {
9015 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9020 unsigned Opcode)
const {
9044 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9059 const MCInstrDesc &InstDesc =
get(Opcode);
9062 &AMDGPU::SGPR_32RegClass;
9065 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9068 AMDGPU::sub0, Src0SubRC);
9073 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9076 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9079 AMDGPU::sub1, Src0SubRC);
9082 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9096 Worklist.
insert(&LoHalf);
9097 Worklist.
insert(&HiHalf);
9103 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9127 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9128 if (RI.isSGPRClass(Src0SubRC))
9129 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9131 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9132 if (RI.isSGPRClass(Src1SubRC))
9133 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9137 MachineOperand Op0L =
9139 MachineOperand Op1L =
9141 MachineOperand Op0H =
9143 MachineOperand Op1H =
9162 MachineInstr *Op1L_Op0H =
9168 MachineInstr *Op1H_Op0L =
9174 MachineInstr *Carry =
9179 MachineInstr *LoHalf =
9189 MachineInstr *HiHalf =
9212 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9236 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9237 if (RI.isSGPRClass(Src0SubRC))
9238 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9240 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9241 if (RI.isSGPRClass(Src1SubRC))
9242 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9246 MachineOperand Op0L =
9248 MachineOperand Op1L =
9252 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9253 ? AMDGPU::V_MUL_HI_U32_e64
9254 : AMDGPU::V_MUL_HI_I32_e64;
9255 MachineInstr *HiHalf =
9258 MachineInstr *LoHalf =
9277 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9293 const MCInstrDesc &InstDesc =
get(Opcode);
9296 &AMDGPU::SGPR_32RegClass;
9299 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9302 &AMDGPU::SGPR_32RegClass;
9305 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9308 AMDGPU::sub0, Src0SubRC);
9310 AMDGPU::sub0, Src1SubRC);
9312 AMDGPU::sub1, Src0SubRC);
9314 AMDGPU::sub1, Src1SubRC);
9319 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9322 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9327 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9340 Worklist.
insert(&LoHalf);
9341 Worklist.
insert(&HiHalf);
9344 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9364 MachineOperand* Op0;
9365 MachineOperand* Op1;
9367 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9400 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9403 &AMDGPU::SGPR_32RegClass;
9409 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9412 AMDGPU::sub0, SrcSubRC);
9414 AMDGPU::sub1, SrcSubRC);
9424 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9443 Offset == 0 &&
"Not implemented");
9466 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9476 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9479 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9485 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9504 const MCInstrDesc &InstDesc =
get(Opcode);
9506 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9507 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9508 : AMDGPU::V_ADD_CO_U32_e32;
9511 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9513 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9515 MachineOperand SrcRegSub0 =
9517 MachineOperand SrcRegSub1 =
9530 .
addReg(IsCtlz ? MidReg1 : MidReg2)
9536 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9540 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9543void SIInstrInfo::addUsersToMoveToVALUWorklist(
9547 MachineInstr &
UseMI = *MO.getParent();
9551 switch (
UseMI.getOpcode()) {
9554 case AMDGPU::SOFT_WQM:
9555 case AMDGPU::STRICT_WWM:
9556 case AMDGPU::STRICT_WQM:
9557 case AMDGPU::REG_SEQUENCE:
9559 case AMDGPU::INSERT_SUBREG:
9562 OpNo = MO.getOperandNo();
9569 if (!RI.hasVectorRegisters(OpRC))
9586 if (ST.useRealTrue16Insts()) {
9588 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9591 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9597 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9600 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9609 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9611 case AMDGPU::S_PACK_LL_B32_B16:
9613 .addReg(SrcReg0, {},
9614 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9615 .addImm(AMDGPU::lo16)
9616 .addReg(SrcReg1, {},
9617 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9618 .addImm(AMDGPU::hi16);
9620 case AMDGPU::S_PACK_LH_B32_B16:
9622 .addReg(SrcReg0, {},
9623 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9624 .addImm(AMDGPU::lo16)
9625 .addReg(SrcReg1, {}, AMDGPU::hi16)
9626 .addImm(AMDGPU::hi16);
9628 case AMDGPU::S_PACK_HL_B32_B16:
9629 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9630 .addImm(AMDGPU::lo16)
9631 .addReg(SrcReg1, {},
9632 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9633 .addImm(AMDGPU::hi16);
9635 case AMDGPU::S_PACK_HH_B32_B16:
9636 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9637 .addImm(AMDGPU::lo16)
9638 .addReg(SrcReg1, {}, AMDGPU::hi16)
9639 .addImm(AMDGPU::hi16);
9647 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9652 case AMDGPU::S_PACK_LL_B32_B16: {
9671 case AMDGPU::S_PACK_LH_B32_B16: {
9681 case AMDGPU::S_PACK_HL_B32_B16: {
9692 case AMDGPU::S_PACK_HH_B32_B16: {
9712 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9721 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9722 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9723 SmallVector<MachineInstr *, 4> CopyToDelete;
9726 for (MachineInstr &
MI :
9730 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9733 MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9734 Register DestReg =
MI.getOperand(0).getReg();
9741 MI.getOperand(SCCIdx).setReg(NewCond);
9747 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9750 for (
auto &Copy : CopyToDelete)
9751 Copy->eraseFromParent();
9759void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9765 for (MachineInstr &
MI :
9768 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9770 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9787 case AMDGPU::REG_SEQUENCE:
9788 case AMDGPU::INSERT_SUBREG:
9790 case AMDGPU::SOFT_WQM:
9791 case AMDGPU::STRICT_WWM:
9792 case AMDGPU::STRICT_WQM: {
9794 if (RI.isAGPRClass(SrcRC)) {
9795 if (RI.isAGPRClass(NewDstRC))
9800 case AMDGPU::REG_SEQUENCE:
9801 case AMDGPU::INSERT_SUBREG:
9802 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9805 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9811 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9814 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9828 int OpIndices[3])
const {
9829 const MCInstrDesc &
Desc =
MI.getDesc();
9845 const MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9847 for (
unsigned i = 0; i < 3; ++i) {
9848 int Idx = OpIndices[i];
9852 const MachineOperand &MO =
MI.getOperand(Idx);
9859 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
9860 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9867 if (RI.isSGPRClass(RegRC))
9885 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9886 SGPRReg = UsedSGPRs[0];
9889 if (!SGPRReg && UsedSGPRs[1]) {
9890 if (UsedSGPRs[1] == UsedSGPRs[2])
9891 SGPRReg = UsedSGPRs[1];
9898 AMDGPU::OpName OperandName)
const {
9899 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9902 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
9906 return &
MI.getOperand(Idx);
9920 if (ST.isAmdHsaOS()) {
9923 RsrcDataFormat |= (1ULL << 56);
9928 RsrcDataFormat |= (2ULL << 59);
9931 return RsrcDataFormat;
9941 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
9946 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
9953 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
9959 unsigned Opc =
MI.getOpcode();
9965 return get(
Opc).mayLoad() &&
9972 if (!Addr || !Addr->
isFI())
9981 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
9983 return MI.getOperand(VDataIdx).getReg();
9993 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
9995 return MI.getOperand(DataIdx).getReg();
10016 if (!
MI.mayStore())
10029 unsigned Opc =
MI.getOpcode();
10031 unsigned DescSize =
Desc.getSize();
10036 unsigned Size = DescSize;
10040 if (
MI.isBranch() && ST.hasOffset3fBug())
10051 bool HasLiteral =
false;
10052 unsigned LiteralSize = 4;
10053 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10058 if (ST.has64BitLiterals()) {
10059 switch (OpInfo.OperandType) {
10084 return HasLiteral ? DescSize + LiteralSize : DescSize;
10089 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10093 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10094 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10098 case TargetOpcode::BUNDLE:
10099 return getInstBundleSize(
MI);
10100 case TargetOpcode::INLINEASM:
10101 case TargetOpcode::INLINEASM_BR: {
10103 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10107 if (
MI.isMetaInstruction())
10111 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10114 unsigned LoInstOpcode = D16Info->LoOp;
10116 DescSize =
Desc.getSize();
10120 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10123 DescSize =
Desc.getSize();
10132 if (
MI.isBranch() && ST.hasOffset3fBug())
10133 return InstSizeVerifyMode::NoVerify;
10134 return InstSizeVerifyMode::ExactSize;
10141 if (
MI.memoperands_empty())
10153 static const std::pair<int, const char *> TargetIndices[] = {
10192std::pair<unsigned, unsigned>
10199 static const std::pair<unsigned, const char *> TargetFlags[] = {
10217 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10233 return AMDGPU::WWM_COPY;
10235 return AMDGPU::COPY;
10252 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10256 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10257 return IsLRSplitInst;
10270 bool IsNullOrVectorRegister =
true;
10274 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10277 return IsNullOrVectorRegister &&
10279 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10280 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10288 if (ST.hasAddNoCarryInsts())
10304 if (ST.hasAddNoCarryInsts())
10308 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10310 : RS.scavengeRegisterBackwards(
10311 *RI.getBoolRC(),
I,
false,
10324 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10325 case AMDGPU::SI_KILL_I1_TERMINATOR:
10334 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10335 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10336 case AMDGPU::SI_KILL_I1_PSEUDO:
10337 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10349 const unsigned OffsetBits =
10351 return (1 << OffsetBits) - 1;
10355 if (!ST.isWave32())
10358 if (
MI.isInlineAsm())
10361 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10364 for (
auto &
Op :
MI.implicit_operands()) {
10365 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10366 Op.setReg(AMDGPU::VCC_LO);
10375 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10379 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10380 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10396 if (Imm > MaxImm) {
10397 if (Imm <= MaxImm + 64) {
10399 Overflow = Imm - MaxImm;
10418 if (Overflow > 0) {
10426 if (ST.hasRestrictedSOffset())
10431 SOffset = Overflow;
10469 if (!ST.hasFlatInstOffsets())
10473 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10478 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10479 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10490std::pair<int64_t, int64_t>
10493 int64_t RemainderOffset = COffsetVal;
10494 int64_t ImmField = 0;
10499 if (AllowNegative) {
10501 int64_t
D = 1LL << NumBits;
10502 RemainderOffset = (COffsetVal /
D) *
D;
10503 ImmField = COffsetVal - RemainderOffset;
10505 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10507 (ImmField % 4) != 0) {
10509 RemainderOffset += ImmField % 4;
10510 ImmField -= ImmField % 4;
10512 }
else if (COffsetVal >= 0) {
10514 RemainderOffset = COffsetVal - ImmField;
10518 assert(RemainderOffset + ImmField == COffsetVal);
10519 return {ImmField, RemainderOffset};
10524 if (ST.hasNegativeScratchOffsetBug() &&
10532 switch (ST.getGeneration()) {
10561 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10562 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10563 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10564 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10565 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10566 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10567 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10568 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10575#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10576 case OPCODE##_dpp: \
10577 case OPCODE##_e32: \
10578 case OPCODE##_e64: \
10579 case OPCODE##_e64_dpp: \
10580 case OPCODE##_sdwa:
10594 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10595 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10596 case AMDGPU::V_FMA_F16_gfx9_e64:
10597 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10598 case AMDGPU::V_INTERP_P2_F16:
10599 case AMDGPU::V_MAD_F16_e64:
10600 case AMDGPU::V_MAD_U16_e64:
10601 case AMDGPU::V_MAD_I16_e64:
10610 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10624 switch (ST.getGeneration()) {
10637 if (
isMAI(Opcode)) {
10645 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10648 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10655 if (ST.hasGFX90AInsts()) {
10656 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10657 if (ST.hasGFX940Insts())
10659 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10661 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10663 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10669 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10688 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10689 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10690 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10702 switch (
MI.getOpcode()) {
10704 case AMDGPU::REG_SEQUENCE:
10708 case AMDGPU::INSERT_SUBREG:
10709 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10726 if (!
P.Reg.isVirtual())
10731 while (
auto *
MI = DefInst) {
10733 switch (
MI->getOpcode()) {
10735 case AMDGPU::V_MOV_B32_e32: {
10736 auto &Op1 =
MI->getOperand(1);
10765 auto *DefBB =
DefMI.getParent();
10769 if (
UseMI.getParent() != DefBB)
10772 const int MaxInstScan = 20;
10776 auto E =
UseMI.getIterator();
10777 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10778 if (
I->isDebugInstr())
10781 if (++NumInst > MaxInstScan)
10784 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10797 auto *DefBB =
DefMI.getParent();
10799 const int MaxUseScan = 10;
10803 auto &UseInst = *
Use.getParent();
10806 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10809 if (++NumUse > MaxUseScan)
10816 const int MaxInstScan = 20;
10820 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10823 if (
I->isDebugInstr())
10826 if (++NumInst > MaxInstScan)
10839 if (Reg == VReg && --NumUse == 0)
10841 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
10850 auto Cur =
MBB.begin();
10851 if (Cur !=
MBB.end())
10853 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
10856 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
10865 if (InsPt !=
MBB.end() &&
10866 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10867 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10868 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10869 InsPt->definesRegister(Src,
nullptr)) {
10873 .
addReg(Src, {}, SrcSubReg)
10916 if (isFullCopyInstr(
MI)) {
10917 Register DstReg =
MI.getOperand(0).getReg();
10918 Register SrcReg =
MI.getOperand(1).getReg();
10940 unsigned *PredCost)
const {
10941 if (
MI.isBundle()) {
10944 unsigned Lat = 0,
Count = 0;
10945 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
10947 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
10949 return Lat +
Count - 1;
10952 return SchedModel.computeInstrLatency(&
MI);
10959 return *CallAddrOp;
10966 unsigned Opcode =
MI.getOpcode();
10968 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
10971 :
MI.getOperand(1).getReg();
10975 unsigned SrcAS = SrcTy.getAddressSpace();
10978 ST.hasGloballyAddressableScratch()
10986 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
10987 return HandleAddrSpaceCast(
MI);
10990 auto IID = GI->getIntrinsicID();
10997 case Intrinsic::amdgcn_addrspacecast_nonnull:
10998 return HandleAddrSpaceCast(
MI);
10999 case Intrinsic::amdgcn_if:
11000 case Intrinsic::amdgcn_else:
11014 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11015 Opcode == AMDGPU::G_SEXTLOAD) {
11016 if (
MI.memoperands_empty())
11020 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11021 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11029 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11030 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11031 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11037 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11040 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11048 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11049 return Formatter.get();
11057 unsigned opcode =
MI.getOpcode();
11058 if (opcode == AMDGPU::V_READLANE_B32 ||
11059 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11060 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11065 if (
MI.isInlineAsm()) {
11071 if (!RC || !RI.isSGPRClass(RC))
11076 if (isCopyInstr(
MI)) {
11080 RI.getPhysRegBaseClass(srcOp.
getReg());
11088 if (
MI.isPreISelOpcode())
11103 if (
MI.memoperands_empty())
11107 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11108 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11123 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11125 if (!
SrcOp.isReg())
11129 if (!Reg || !
SrcOp.readsReg())
11135 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11162 F,
"ds_ordered_count unsupported for this calling conv"));
11176 Register &SrcReg2, int64_t &CmpMask,
11177 int64_t &CmpValue)
const {
11178 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11181 switch (
MI.getOpcode()) {
11184 case AMDGPU::S_CMP_EQ_U32:
11185 case AMDGPU::S_CMP_EQ_I32:
11186 case AMDGPU::S_CMP_LG_U32:
11187 case AMDGPU::S_CMP_LG_I32:
11188 case AMDGPU::S_CMP_LT_U32:
11189 case AMDGPU::S_CMP_LT_I32:
11190 case AMDGPU::S_CMP_GT_U32:
11191 case AMDGPU::S_CMP_GT_I32:
11192 case AMDGPU::S_CMP_LE_U32:
11193 case AMDGPU::S_CMP_LE_I32:
11194 case AMDGPU::S_CMP_GE_U32:
11195 case AMDGPU::S_CMP_GE_I32:
11196 case AMDGPU::S_CMP_EQ_U64:
11197 case AMDGPU::S_CMP_LG_U64:
11198 SrcReg =
MI.getOperand(0).getReg();
11199 if (
MI.getOperand(1).isReg()) {
11200 if (
MI.getOperand(1).getSubReg())
11202 SrcReg2 =
MI.getOperand(1).getReg();
11204 }
else if (
MI.getOperand(1).isImm()) {
11206 CmpValue =
MI.getOperand(1).getImm();
11212 case AMDGPU::S_CMPK_EQ_U32:
11213 case AMDGPU::S_CMPK_EQ_I32:
11214 case AMDGPU::S_CMPK_LG_U32:
11215 case AMDGPU::S_CMPK_LG_I32:
11216 case AMDGPU::S_CMPK_LT_U32:
11217 case AMDGPU::S_CMPK_LT_I32:
11218 case AMDGPU::S_CMPK_GT_U32:
11219 case AMDGPU::S_CMPK_GT_I32:
11220 case AMDGPU::S_CMPK_LE_U32:
11221 case AMDGPU::S_CMPK_LE_I32:
11222 case AMDGPU::S_CMPK_GE_U32:
11223 case AMDGPU::S_CMPK_GE_I32:
11224 SrcReg =
MI.getOperand(0).getReg();
11226 CmpValue =
MI.getOperand(1).getImm();
11236 if (S->isLiveIn(AMDGPU::SCC))
11245bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11248 bool SCCIsDead =
false;
11251 constexpr unsigned ScanLimit = 12;
11252 unsigned Count = 0;
11253 for (MachineInstr &
MI :
11255 if (++
Count > ScanLimit)
11257 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11258 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11259 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11260 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11261 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11266 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11279 for (MachineInstr *
MI : InvertInstr) {
11280 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11281 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11283 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11284 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11285 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11286 ? AMDGPU::S_CBRANCH_SCC1
11287 : AMDGPU::S_CBRANCH_SCC0));
11300 bool NeedInversion)
const {
11301 MachineInstr *KillsSCC =
nullptr;
11306 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11308 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11311 if (NeedInversion && !invertSCCUse(SCCRedefine))
11313 if (MachineOperand *SccDef =
11315 SccDef->setIsDead(
false);
11323 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11324 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11326 bool Op1IsNonZeroImm =
11327 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11328 bool Op2IsZeroImm =
11329 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11330 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11336 unsigned &NewDefOpc) {
11339 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11340 Def.getOpcode() != AMDGPU::S_ADD_U32)
11346 if ((!AddSrc1.
isImm() || AddSrc1.
getImm() != 1) &&
11352 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11354 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11357 NewDefOpc = AMDGPU::S_ADD_U32;
11359 NeedInversion = !NeedInversion;
11364 Register SrcReg2, int64_t CmpMask,
11373 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11374 this](
bool NeedInversion) ->
bool {
11398 unsigned NewDefOpc = Def->getOpcode();
11404 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11407 if (NewDefOpc != Def->getOpcode())
11408 Def->setDesc(
get(NewDefOpc));
11417 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11424 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11432 optimizeSCC(
Select, Def,
false);
11439 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11440 this](int64_t ExpectedValue,
unsigned SrcSize,
11441 bool IsReversible,
bool IsSigned) ->
bool {
11469 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11470 Def->getOpcode() != AMDGPU::S_AND_B64)
11474 const auto isMask = [&Mask, SrcSize](
const MachineOperand *MO) ->
bool {
11485 SrcOp = &Def->getOperand(2);
11486 else if (isMask(&Def->getOperand(2)))
11487 SrcOp = &Def->getOperand(1);
11495 if (IsSigned && BitNo == SrcSize - 1)
11498 ExpectedValue <<= BitNo;
11500 bool IsReversedCC =
false;
11501 if (CmpValue != ExpectedValue) {
11504 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11509 Register DefReg = Def->getOperand(0).getReg();
11513 if (!optimizeSCC(Def, &CmpInstr,
false))
11524 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11525 : AMDGPU::S_BITCMP1_B32
11526 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11527 : AMDGPU::S_BITCMP1_B64;
11532 Def->eraseFromParent();
11540 case AMDGPU::S_CMP_EQ_U32:
11541 case AMDGPU::S_CMP_EQ_I32:
11542 case AMDGPU::S_CMPK_EQ_U32:
11543 case AMDGPU::S_CMPK_EQ_I32:
11544 return optimizeCmpAnd(1, 32,
true,
false) ||
11545 optimizeCmpSelect(
true);
11546 case AMDGPU::S_CMP_GE_U32:
11547 case AMDGPU::S_CMPK_GE_U32:
11548 return optimizeCmpAnd(1, 32,
false,
false);
11549 case AMDGPU::S_CMP_GE_I32:
11550 case AMDGPU::S_CMPK_GE_I32:
11551 return optimizeCmpAnd(1, 32,
false,
true);
11552 case AMDGPU::S_CMP_EQ_U64:
11553 return optimizeCmpAnd(1, 64,
true,
false);
11554 case AMDGPU::S_CMP_LG_U32:
11555 case AMDGPU::S_CMP_LG_I32:
11556 case AMDGPU::S_CMPK_LG_U32:
11557 case AMDGPU::S_CMPK_LG_I32:
11558 return optimizeCmpAnd(0, 32,
true,
false) ||
11559 optimizeCmpSelect(
false);
11560 case AMDGPU::S_CMP_GT_U32:
11561 case AMDGPU::S_CMPK_GT_U32:
11562 return optimizeCmpAnd(0, 32,
false,
false);
11563 case AMDGPU::S_CMP_GT_I32:
11564 case AMDGPU::S_CMPK_GT_I32:
11565 return optimizeCmpAnd(0, 32,
false,
true);
11566 case AMDGPU::S_CMP_LG_U64:
11567 return optimizeCmpAnd(0, 64,
true,
false) ||
11568 optimizeCmpSelect(
false);
11575 AMDGPU::OpName
OpName)
const {
11576 if (!ST.needsAlignedVGPRs())
11579 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11591 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11593 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11597 : &AMDGPU::VReg_64_Align2RegClass);
11599 .
addReg(DataReg, {},
Op.getSubReg())
11604 Op.setSubReg(AMDGPU::sub0);
11619 if (ST.hasGFX1250Insts())
11626 unsigned Opcode =
MI.getOpcode();
11632 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11633 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11636 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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & 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 Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool 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 bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
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.
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.