34#include "llvm/IR/IntrinsicsAMDGPU.h"
42#define DEBUG_TYPE "si-instr-info"
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
48#define GET_D16ImageDimIntrinsics_IMPL
49#define GET_ImageDimIntrinsicTable_IMPL
50#define GET_RsrcIntrinsics_IMPL
51#include "AMDGPUGenSearchableTables.inc"
59 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
62 "amdgpu-fix-16-bit-physreg-copies",
63 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
79 unsigned N =
Node->getNumOperands();
80 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
92 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
93 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
95 if (Op0Idx == -1 && Op1Idx == -1)
99 if ((Op0Idx == -1 && Op1Idx != -1) ||
100 (Op1Idx == -1 && Op0Idx != -1))
121 return !
MI.memoperands_empty() &&
123 return MMO->isLoad() && MMO->isInvariant();
132static std::tuple<unsigned, unsigned, unsigned>
135 unsigned SrcFlags =
SrcOp.getTargetFlags();
160 return std::make_tuple(BaseFlags, LoReloc, HiReloc);
178 if (!
MI.hasImplicitDef() &&
179 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
180 !
MI.mayRaiseFPException())
189 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
204 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
205 MI.hasUnmodeledSideEffects())
210 if (
MI.isInlineAsm())
214 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
229 if (Reg.isPhysical()) {
245 if (MO.isDef() && Reg != DefReg)
253bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
257 if (
MI.isConvergent())
285 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
290 for (
auto Op :
MI.uses()) {
291 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
303 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
323 int64_t &Offset1)
const {
331 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
335 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
351 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
352 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
353 if (Offset0Idx == -1 || Offset1Idx == -1)
360 Offset0Idx -=
get(Opc0).NumDefs;
361 Offset1Idx -=
get(Opc1).NumDefs;
391 if (!Load0Offset || !Load1Offset)
408 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
409 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
411 if (OffIdx0 == -1 || OffIdx1 == -1)
417 OffIdx0 -=
get(Opc0).NumDefs;
418 OffIdx1 -=
get(Opc1).NumDefs;
437 case AMDGPU::DS_READ2ST64_B32:
438 case AMDGPU::DS_READ2ST64_B64:
439 case AMDGPU::DS_WRITE2ST64_B32:
440 case AMDGPU::DS_WRITE2ST64_B64:
455 OffsetIsScalable =
false;
472 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
474 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
475 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
488 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
489 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
490 if (Offset0 + 1 != Offset1)
501 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
509 Offset = EltSize * Offset0;
511 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
512 if (DataOpIdx == -1) {
513 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
515 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
531 if (BaseOp && !BaseOp->
isFI())
539 if (SOffset->
isReg())
545 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
547 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
556 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
557 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
559 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
560 if (VAddr0Idx >= 0) {
562 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
569 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
584 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
601 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
603 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
620 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
628 if (MO1->getAddrSpace() != MO2->getAddrSpace())
631 const auto *Base1 = MO1->getValue();
632 const auto *Base2 = MO2->getValue();
633 if (!Base1 || !Base2)
641 return Base1 == Base2;
645 int64_t Offset1,
bool OffsetIsScalable1,
647 int64_t Offset2,
bool OffsetIsScalable2,
648 unsigned ClusterSize,
649 unsigned NumBytes)
const {
662 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
681 const unsigned LoadSize = NumBytes / ClusterSize;
682 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
683 return NumDWords <= MaxMemoryClusterDWords;
697 int64_t Offset0, int64_t Offset1,
698 unsigned NumLoads)
const {
699 assert(Offset1 > Offset0 &&
700 "Second offset should be larger than first offset!");
705 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
712 const char *
Msg =
"illegal VGPR to SGPR copy") {
731 assert((
TII.getSubtarget().hasMAIInsts() &&
732 !
TII.getSubtarget().hasGFX90AInsts()) &&
733 "Expected GFX908 subtarget.");
736 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
737 "Source register of the copy should be either an SGPR or an AGPR.");
740 "Destination register of the copy should be an AGPR.");
749 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
752 if (!Def->modifiesRegister(SrcReg, &RI))
755 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
756 Def->getOperand(0).getReg() != SrcReg)
763 bool SafeToPropagate =
true;
766 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
767 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
768 SafeToPropagate =
false;
770 if (!SafeToPropagate)
773 for (
auto I = Def;
I !=
MI; ++
I)
774 I->clearRegisterKills(DefOp.
getReg(), &RI);
782 if (ImpUseSuperReg) {
783 Builder.addReg(ImpUseSuperReg,
791 RS.enterBasicBlockEnd(
MBB);
792 RS.backward(std::next(
MI));
801 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
804 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
805 "VGPR used for an intermediate copy should have been reserved.");
810 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
820 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
821 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
822 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
829 if (ImpUseSuperReg) {
830 UseBuilder.
addReg(ImpUseSuperReg,
847 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
848 int16_t SubIdx = BaseIndices[Idx];
849 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
850 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
851 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
852 unsigned Opcode = AMDGPU::S_MOV_B32;
855 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
856 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
857 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
861 DestSubReg = RI.getSubReg(DestReg, SubIdx);
862 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
863 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
864 Opcode = AMDGPU::S_MOV_B64;
879 assert(FirstMI && LastMI);
884 LastMI->addRegisterKilled(SrcReg, &RI);
890 Register SrcReg,
bool KillSrc,
bool RenamableDest,
891 bool RenamableSrc)
const {
893 unsigned Size = RI.getRegSizeInBits(*RC);
895 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
901 if (((
Size == 16) != (SrcSize == 16))) {
903 assert(ST.useRealTrue16Insts());
905 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
908 if (DestReg == SrcReg) {
914 RC = RI.getPhysRegBaseClass(DestReg);
915 Size = RI.getRegSizeInBits(*RC);
916 SrcRC = RI.getPhysRegBaseClass(SrcReg);
917 SrcSize = RI.getRegSizeInBits(*SrcRC);
921 if (RC == &AMDGPU::VGPR_32RegClass) {
923 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
924 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
925 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
926 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
932 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
933 RC == &AMDGPU::SReg_32RegClass) {
934 if (SrcReg == AMDGPU::SCC) {
941 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
942 if (DestReg == AMDGPU::VCC_LO) {
960 if (RC == &AMDGPU::SReg_64RegClass) {
961 if (SrcReg == AMDGPU::SCC) {
968 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
969 if (DestReg == AMDGPU::VCC) {
987 if (DestReg == AMDGPU::SCC) {
990 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
994 assert(ST.hasScalarCompareEq64());
1008 if (RC == &AMDGPU::AGPR_32RegClass) {
1009 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1010 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1016 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1025 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1032 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1033 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1035 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1036 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1037 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1038 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1041 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1042 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1055 if (IsAGPRDst || IsAGPRSrc) {
1056 if (!DstLow || !SrcLow) {
1058 "Cannot use hi16 subreg with an AGPR!");
1065 if (ST.useRealTrue16Insts()) {
1071 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1072 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1084 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1085 if (!DstLow || !SrcLow) {
1087 "Cannot use hi16 subreg on VI!");
1110 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1111 if (ST.hasVMovB64Inst()) {
1116 if (ST.hasPkMovB32()) {
1132 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1133 if (RI.isSGPRClass(RC)) {
1134 if (!RI.isSGPRClass(SrcRC)) {
1138 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1144 unsigned EltSize = 4;
1145 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1146 if (RI.isAGPRClass(RC)) {
1147 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1148 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1149 else if (RI.hasVGPRs(SrcRC) ||
1150 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1151 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1153 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1154 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1155 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1156 }
else if ((
Size % 64 == 0) && RI.hasVGPRs(RC) &&
1157 (RI.isProperlyAlignedRC(*RC) &&
1158 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1160 if (ST.hasVMovB64Inst()) {
1161 Opcode = AMDGPU::V_MOV_B64_e32;
1163 }
else if (ST.hasPkMovB32()) {
1164 Opcode = AMDGPU::V_PK_MOV_B32;
1174 std::unique_ptr<RegScavenger> RS;
1175 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1176 RS = std::make_unique<RegScavenger>();
1182 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1183 const bool CanKillSuperReg = KillSrc && !Overlap;
1185 for (
unsigned Idx = 0; Idx < SubIndices.
size(); ++Idx) {
1188 SubIdx = SubIndices[Idx];
1190 SubIdx = SubIndices[SubIndices.
size() - Idx - 1];
1191 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1192 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1193 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1195 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size() - 1;
1197 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1200 *RS, Overlap, ImpUseSuper);
1201 }
else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1242 int64_t &ImmVal)
const {
1243 switch (
MI.getOpcode()) {
1244 case AMDGPU::V_MOV_B32_e32:
1245 case AMDGPU::S_MOV_B32:
1246 case AMDGPU::S_MOVK_I32:
1247 case AMDGPU::S_MOV_B64:
1248 case AMDGPU::V_MOV_B64_e32:
1249 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1250 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1251 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1252 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1253 case AMDGPU::V_MOV_B64_PSEUDO:
1254 case AMDGPU::V_MOV_B16_t16_e32: {
1258 return MI.getOperand(0).getReg() == Reg;
1263 case AMDGPU::V_MOV_B16_t16_e64: {
1265 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1267 return MI.getOperand(0).getReg() == Reg;
1272 case AMDGPU::S_BREV_B32:
1273 case AMDGPU::V_BFREV_B32_e32:
1274 case AMDGPU::V_BFREV_B32_e64: {
1278 return MI.getOperand(0).getReg() == Reg;
1283 case AMDGPU::S_NOT_B32:
1284 case AMDGPU::V_NOT_B32_e32:
1285 case AMDGPU::V_NOT_B32_e64: {
1288 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1289 return MI.getOperand(0).getReg() == Reg;
1299std::optional<int64_t>
1304 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1305 return std::nullopt;
1308 if (Def && Def->isMoveImmediate()) {
1314 return std::nullopt;
1319 if (RI.isAGPRClass(DstRC))
1320 return AMDGPU::COPY;
1321 if (RI.getRegSizeInBits(*DstRC) == 16) {
1324 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1326 if (RI.getRegSizeInBits(*DstRC) == 32)
1327 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1328 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1329 return AMDGPU::S_MOV_B64;
1330 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1331 return AMDGPU::V_MOV_B64_PSEUDO;
1332 return AMDGPU::COPY;
1337 bool IsIndirectSrc)
const {
1338 if (IsIndirectSrc) {
1340 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1342 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1344 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1346 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1348 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1350 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1352 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1354 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1356 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1358 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1360 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1362 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1364 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1365 if (VecSize <= 1024)
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1372 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1374 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1376 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1378 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1380 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1382 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1384 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1386 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1388 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1390 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1392 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1394 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1396 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1397 if (VecSize <= 1024)
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1405 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1407 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1409 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1411 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1413 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1415 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1417 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1419 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1421 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1423 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1425 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1427 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1429 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1430 if (VecSize <= 1024)
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1438 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1440 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1442 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1444 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1446 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1448 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1450 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1452 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1454 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1456 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1458 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1460 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1462 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1463 if (VecSize <= 1024)
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1471 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1473 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1475 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1477 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1478 if (VecSize <= 1024)
1479 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1486 bool IsSGPR)
const {
1498 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1505 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1507 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1509 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1511 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1512 : AMDGPU::SI_SPILL_S128_SAVE;
1514 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1515 : AMDGPU::SI_SPILL_S160_SAVE;
1517 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1518 : AMDGPU::SI_SPILL_S192_SAVE;
1520 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1521 : AMDGPU::SI_SPILL_S224_SAVE;
1523 return AMDGPU::SI_SPILL_S256_SAVE;
1525 return AMDGPU::SI_SPILL_S288_SAVE;
1527 return AMDGPU::SI_SPILL_S320_SAVE;
1529 return AMDGPU::SI_SPILL_S352_SAVE;
1531 return AMDGPU::SI_SPILL_S384_SAVE;
1533 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1534 : AMDGPU::SI_SPILL_S512_SAVE;
1536 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1537 : AMDGPU::SI_SPILL_S1024_SAVE;
1546 return AMDGPU::SI_SPILL_V16_SAVE;
1548 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1550 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1552 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1554 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1555 : AMDGPU::SI_SPILL_V128_SAVE;
1557 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1558 : AMDGPU::SI_SPILL_V160_SAVE;
1560 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1561 : AMDGPU::SI_SPILL_V192_SAVE;
1563 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1564 : AMDGPU::SI_SPILL_V224_SAVE;
1566 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1567 : AMDGPU::SI_SPILL_V256_SAVE;
1569 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1570 : AMDGPU::SI_SPILL_V288_SAVE;
1572 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1573 : AMDGPU::SI_SPILL_V320_SAVE;
1575 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1576 : AMDGPU::SI_SPILL_V352_SAVE;
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1579 : AMDGPU::SI_SPILL_V384_SAVE;
1581 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1582 : AMDGPU::SI_SPILL_V512_SAVE;
1584 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1585 : AMDGPU::SI_SPILL_V1024_SAVE;
1594 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1595 : AMDGPU::SI_SPILL_AV32_SAVE;
1597 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1598 : AMDGPU::SI_SPILL_AV64_SAVE;
1600 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1601 : AMDGPU::SI_SPILL_AV96_SAVE;
1603 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1604 : AMDGPU::SI_SPILL_AV128_SAVE;
1606 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1607 : AMDGPU::SI_SPILL_AV160_SAVE;
1609 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1610 : AMDGPU::SI_SPILL_AV192_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1613 : AMDGPU::SI_SPILL_AV224_SAVE;
1615 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1616 : AMDGPU::SI_SPILL_AV256_SAVE;
1618 return AMDGPU::SI_SPILL_AV288_SAVE;
1620 return AMDGPU::SI_SPILL_AV320_SAVE;
1622 return AMDGPU::SI_SPILL_AV352_SAVE;
1624 return AMDGPU::SI_SPILL_AV384_SAVE;
1626 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1627 : AMDGPU::SI_SPILL_AV512_SAVE;
1629 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1630 : AMDGPU::SI_SPILL_AV1024_SAVE;
1637 bool IsVectorSuperClass) {
1642 if (IsVectorSuperClass)
1643 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1645 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1651 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1658 if (ST.hasMAIInsts())
1664void SIInstrInfo::storeRegToStackSlotImpl(
1677 FrameInfo.getObjectAlign(FrameIndex));
1678 unsigned SpillSize = RI.getSpillSize(*RC);
1684 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1685 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1686 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1695 if (SrcReg.
isVirtual() && SpillSize == 4) {
1709 SpillSize, *MFI, NeedsCFI);
1724 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1733 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1740 return AMDGPU::SI_SPILL_S32_RESTORE;
1742 return AMDGPU::SI_SPILL_S64_RESTORE;
1744 return AMDGPU::SI_SPILL_S96_RESTORE;
1746 return AMDGPU::SI_SPILL_S128_RESTORE;
1748 return AMDGPU::SI_SPILL_S160_RESTORE;
1750 return AMDGPU::SI_SPILL_S192_RESTORE;
1752 return AMDGPU::SI_SPILL_S224_RESTORE;
1754 return AMDGPU::SI_SPILL_S256_RESTORE;
1756 return AMDGPU::SI_SPILL_S288_RESTORE;
1758 return AMDGPU::SI_SPILL_S320_RESTORE;
1760 return AMDGPU::SI_SPILL_S352_RESTORE;
1762 return AMDGPU::SI_SPILL_S384_RESTORE;
1764 return AMDGPU::SI_SPILL_S512_RESTORE;
1766 return AMDGPU::SI_SPILL_S1024_RESTORE;
1775 return AMDGPU::SI_SPILL_V16_RESTORE;
1777 return AMDGPU::SI_SPILL_V32_RESTORE;
1779 return AMDGPU::SI_SPILL_V64_RESTORE;
1781 return AMDGPU::SI_SPILL_V96_RESTORE;
1783 return AMDGPU::SI_SPILL_V128_RESTORE;
1785 return AMDGPU::SI_SPILL_V160_RESTORE;
1787 return AMDGPU::SI_SPILL_V192_RESTORE;
1789 return AMDGPU::SI_SPILL_V224_RESTORE;
1791 return AMDGPU::SI_SPILL_V256_RESTORE;
1793 return AMDGPU::SI_SPILL_V288_RESTORE;
1795 return AMDGPU::SI_SPILL_V320_RESTORE;
1797 return AMDGPU::SI_SPILL_V352_RESTORE;
1799 return AMDGPU::SI_SPILL_V384_RESTORE;
1801 return AMDGPU::SI_SPILL_V512_RESTORE;
1803 return AMDGPU::SI_SPILL_V1024_RESTORE;
1812 return AMDGPU::SI_SPILL_AV32_RESTORE;
1814 return AMDGPU::SI_SPILL_AV64_RESTORE;
1816 return AMDGPU::SI_SPILL_AV96_RESTORE;
1818 return AMDGPU::SI_SPILL_AV128_RESTORE;
1820 return AMDGPU::SI_SPILL_AV160_RESTORE;
1822 return AMDGPU::SI_SPILL_AV192_RESTORE;
1824 return AMDGPU::SI_SPILL_AV224_RESTORE;
1826 return AMDGPU::SI_SPILL_AV256_RESTORE;
1828 return AMDGPU::SI_SPILL_AV288_RESTORE;
1830 return AMDGPU::SI_SPILL_AV320_RESTORE;
1832 return AMDGPU::SI_SPILL_AV352_RESTORE;
1834 return AMDGPU::SI_SPILL_AV384_RESTORE;
1836 return AMDGPU::SI_SPILL_AV512_RESTORE;
1838 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1845 bool IsVectorSuperClass) {
1850 if (IsVectorSuperClass)
1851 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1853 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1859 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1866 if (ST.hasMAIInsts())
1869 assert(!RI.isAGPRClass(RC));
1883 unsigned SpillSize = RI.getSpillSize(*RC);
1890 FrameInfo.getObjectAlign(FrameIndex));
1892 if (RI.isSGPRClass(RC)) {
1895 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1896 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1897 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1902 if (DestReg.
isVirtual() && SpillSize == 4) {
1931 unsigned Quantity)
const {
1933 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1934 while (Quantity > 0) {
1935 unsigned Arg = std::min(Quantity, MaxSNopCount);
1946 constexpr unsigned DoorbellIDMask = 0x3ff;
1947 constexpr unsigned ECQueueWaveAbort = 0x400;
1952 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1953 MBB.splitAt(
MI,
false);
1957 MBB.addSuccessor(TrapBB);
1967 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1971 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1976 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1977 .
addUse(DoorbellRegMasked)
1978 .
addImm(ECQueueWaveAbort);
1979 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1980 .
addUse(SetWaveAbortBit);
1983 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1994 return MBB.getNextNode();
1998 switch (
MI.getOpcode()) {
2000 if (
MI.isMetaInstruction())
2005 return MI.getOperand(0).getImm() + 1;
2016 switch (
MI.getOpcode()) {
2018 case AMDGPU::S_MOV_B64_term:
2021 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2024 case AMDGPU::S_MOV_B32_term:
2027 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2030 case AMDGPU::S_XOR_B64_term:
2033 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2036 case AMDGPU::S_XOR_B32_term:
2039 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2041 case AMDGPU::S_OR_B64_term:
2044 MI.setDesc(
get(AMDGPU::S_OR_B64));
2046 case AMDGPU::S_OR_B32_term:
2049 MI.setDesc(
get(AMDGPU::S_OR_B32));
2052 case AMDGPU::S_ANDN2_B64_term:
2055 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2058 case AMDGPU::S_ANDN2_B32_term:
2061 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2064 case AMDGPU::S_AND_B64_term:
2067 MI.setDesc(
get(AMDGPU::S_AND_B64));
2070 case AMDGPU::S_AND_B32_term:
2073 MI.setDesc(
get(AMDGPU::S_AND_B32));
2076 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2079 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2082 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2085 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2088 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2089 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2091 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2092 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2095 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2096 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2099 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2100 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2102 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2106 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2109 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2112 int64_t Imm =
MI.getOperand(1).getImm();
2114 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2115 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2120 MI.eraseFromParent();
2126 case AMDGPU::V_MOV_B64_PSEUDO: {
2128 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2129 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2137 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2138 MI.setDesc(Mov64Desc);
2142 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2145 if (
SrcOp.isGlobal()) {
2150 unsigned BaseFlags, LoReloc, HiReloc;
2151 std::tie(BaseFlags, LoReloc, HiReloc) =
2158 }
else if (
SrcOp.isImm()) {
2160 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2161 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2185 if (ST.hasPkMovB32() &&
2204 MI.eraseFromParent();
2207 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2211 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2215 if (ST.has64BitLiterals()) {
2216 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2220 if (
SrcOp.isGlobal()) {
2222 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2223 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2226 unsigned BaseFlags, LoReloc, HiReloc;
2227 std::tie(BaseFlags, LoReloc, HiReloc) =
2234 MI.eraseFromParent();
2241 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2246 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2247 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2249 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2250 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2255 MI.eraseFromParent();
2258 case AMDGPU::V_SET_INACTIVE_B32: {
2262 .
add(
MI.getOperand(3))
2263 .
add(
MI.getOperand(4))
2264 .
add(
MI.getOperand(1))
2265 .
add(
MI.getOperand(2))
2266 .
add(
MI.getOperand(5));
2267 MI.eraseFromParent();
2270 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2271 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2272 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2273 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2274 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2275 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2276 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2277 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2278 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2279 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2280 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2281 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2282 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2283 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2284 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2285 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2286 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2287 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2288 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2289 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2290 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2291 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2292 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2293 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2294 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2295 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2296 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2297 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2298 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2299 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2300 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2301 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2302 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2306 if (RI.hasVGPRs(EltRC)) {
2307 Opc = AMDGPU::V_MOVRELD_B32_e32;
2309 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2310 : AMDGPU::S_MOVRELD_B32;
2315 bool IsUndef =
MI.getOperand(1).isUndef();
2316 unsigned SubReg =
MI.getOperand(3).getImm();
2317 assert(VecReg ==
MI.getOperand(1).getReg());
2322 .
add(
MI.getOperand(2))
2326 const int ImpDefIdx =
2328 const int ImpUseIdx = ImpDefIdx + 1;
2330 MI.eraseFromParent();
2333 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2334 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2335 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2336 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2337 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2338 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2339 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2340 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2341 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2342 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2343 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2344 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2345 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2346 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2347 assert(ST.useVGPRIndexMode());
2349 bool IsUndef =
MI.getOperand(1).isUndef();
2358 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2362 .
add(
MI.getOperand(2))
2366 const int ImpDefIdx =
2368 const int ImpUseIdx = ImpDefIdx + 1;
2375 MI.eraseFromParent();
2378 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2379 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2380 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2381 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2382 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2383 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2384 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2385 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2386 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2387 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2388 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2389 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2390 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2391 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2392 assert(ST.useVGPRIndexMode());
2395 bool IsUndef =
MI.getOperand(1).isUndef();
2399 .
add(
MI.getOperand(2))
2412 MI.eraseFromParent();
2415 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2418 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2419 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2438 if (ST.hasGetPCZeroExtension()) {
2442 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2449 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2459 MI.eraseFromParent();
2462 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2472 Op.setOffset(
Op.getOffset() + 4);
2474 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2478 MI.eraseFromParent();
2481 case AMDGPU::ENTER_STRICT_WWM: {
2487 case AMDGPU::ENTER_STRICT_WQM: {
2494 MI.eraseFromParent();
2497 case AMDGPU::EXIT_STRICT_WWM:
2498 case AMDGPU::EXIT_STRICT_WQM: {
2504 case AMDGPU::SI_RETURN: {
2518 MI.eraseFromParent();
2522 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2523 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2524 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2527 case AMDGPU::S_GETPC_B64_pseudo:
2528 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2529 if (ST.hasGetPCZeroExtension()) {
2531 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2540 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2541 assert(ST.hasBF16PackedInsts());
2542 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2553 case AMDGPU::GET_STACK_BASE:
2556 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2563 Register DestReg =
MI.getOperand(0).getReg();
2573 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2574 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2575 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2578 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2581 MI.getNumExplicitOperands());
2599 case AMDGPU::S_MOV_B64:
2600 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2609 if (UsedLanes.
all())
2614 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2615 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2617 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2618 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2620 if (NeedLo && NeedHi)
2624 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2626 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2635 case AMDGPU::S_LOAD_DWORDX16_IMM:
2636 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2649 for (
auto &CandMO :
I->operands()) {
2650 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2658 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2662 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2668 unsigned NewOpcode = -1;
2669 if (SubregSize == 256)
2670 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2671 else if (SubregSize == 128)
2672 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2682 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2687 MI->getOperand(0).setReg(DestReg);
2688 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2692 OffsetMO->
setImm(FinalOffset);
2698 MI->setMemRefs(*MF, NewMMOs);
2711std::pair<MachineInstr*, MachineInstr*>
2713 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2715 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2718 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2719 return std::pair(&
MI,
nullptr);
2730 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2732 if (Dst.isPhysical()) {
2733 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2740 for (
unsigned I = 1;
I <= 2; ++
I) {
2743 if (
SrcOp.isImm()) {
2745 Imm.ashrInPlace(Part * 32);
2746 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2750 if (Src.isPhysical())
2751 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2758 MovDPP.addImm(MO.getImm());
2760 Split[Part] = MovDPP;
2764 if (Dst.isVirtual())
2771 MI.eraseFromParent();
2772 return std::pair(Split[0], Split[1]);
2775std::optional<DestSourcePair>
2777 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2780 return std::nullopt;
2784 AMDGPU::OpName Src0OpName,
2786 AMDGPU::OpName Src1OpName)
const {
2793 "All commutable instructions have both src0 and src1 modifiers");
2795 int Src0ModsVal = Src0Mods->
getImm();
2796 int Src1ModsVal = Src1Mods->
getImm();
2798 Src1Mods->
setImm(Src0ModsVal);
2799 Src0Mods->
setImm(Src1ModsVal);
2808 bool IsKill = RegOp.
isKill();
2810 bool IsUndef = RegOp.
isUndef();
2811 bool IsDebug = RegOp.
isDebug();
2813 if (NonRegOp.
isImm())
2815 else if (NonRegOp.
isFI())
2836 int64_t NonRegVal = NonRegOp1.
getImm();
2839 NonRegOp2.
setImm(NonRegVal);
2846 unsigned OpIdx1)
const {
2851 unsigned Opc =
MI.getOpcode();
2852 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2862 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2865 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2870 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2876 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2891 unsigned Src1Idx)
const {
2892 assert(!NewMI &&
"this should never be used");
2894 unsigned Opc =
MI.getOpcode();
2896 if (CommutedOpcode == -1)
2899 if (Src0Idx > Src1Idx)
2902 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2903 static_cast<int>(Src0Idx) &&
2904 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2905 static_cast<int>(Src1Idx) &&
2906 "inconsistency with findCommutedOpIndices");
2931 Src1, AMDGPU::OpName::src1_modifiers);
2934 AMDGPU::OpName::src1_sel);
2946 unsigned &SrcOpIdx0,
2947 unsigned &SrcOpIdx1)
const {
2952 unsigned &SrcOpIdx0,
2953 unsigned &SrcOpIdx1)
const {
2954 if (!
Desc.isCommutable())
2957 unsigned Opc =
Desc.getOpcode();
2958 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2962 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2966 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2970 int64_t BrOffset)
const {
2987 return MI.getOperand(0).getMBB();
2992 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
2993 MI.getOpcode() == AMDGPU::SI_LOOP)
3005 "new block should be inserted for expanding unconditional branch");
3008 "restore block should be inserted for restoring clobbered registers");
3016 if (ST.useAddPC64Inst()) {
3018 MCCtx.createTempSymbol(
"offset",
true);
3022 MCCtx.createTempSymbol(
"post_addpc",
true);
3023 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3027 Offset->setVariableValue(OffsetExpr);
3031 assert(RS &&
"RegScavenger required for long branching");
3039 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3040 ST.hasVALUReadSGPRHazard();
3041 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3042 if (FlushSGPRWrites)
3050 ApplyHazardWorkarounds();
3053 MCCtx.createTempSymbol(
"post_getpc",
true);
3057 MCCtx.createTempSymbol(
"offset_lo",
true);
3059 MCCtx.createTempSymbol(
"offset_hi",
true);
3062 .
addReg(PCReg, {}, AMDGPU::sub0)
3066 .
addReg(PCReg, {}, AMDGPU::sub1)
3068 ApplyHazardWorkarounds();
3109 if (LongBranchReservedReg) {
3110 RS->enterBasicBlock(
MBB);
3111 Scav = LongBranchReservedReg;
3113 RS->enterBasicBlockEnd(
MBB);
3114 Scav = RS->scavengeRegisterBackwards(
3119 RS->setRegUsed(Scav);
3127 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3144unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3146 case SIInstrInfo::SCC_TRUE:
3147 return AMDGPU::S_CBRANCH_SCC1;
3148 case SIInstrInfo::SCC_FALSE:
3149 return AMDGPU::S_CBRANCH_SCC0;
3150 case SIInstrInfo::VCCNZ:
3151 return AMDGPU::S_CBRANCH_VCCNZ;
3152 case SIInstrInfo::VCCZ:
3153 return AMDGPU::S_CBRANCH_VCCZ;
3154 case SIInstrInfo::EXECNZ:
3155 return AMDGPU::S_CBRANCH_EXECNZ;
3156 case SIInstrInfo::EXECZ:
3157 return AMDGPU::S_CBRANCH_EXECZ;
3163SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3165 case AMDGPU::S_CBRANCH_SCC0:
3167 case AMDGPU::S_CBRANCH_SCC1:
3169 case AMDGPU::S_CBRANCH_VCCNZ:
3171 case AMDGPU::S_CBRANCH_VCCZ:
3173 case AMDGPU::S_CBRANCH_EXECNZ:
3175 case AMDGPU::S_CBRANCH_EXECZ:
3187 bool AllowModify)
const {
3188 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3190 TBB =
I->getOperand(0).getMBB();
3194 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3195 if (Pred == INVALID_BR)
3200 Cond.push_back(
I->getOperand(1));
3204 if (
I ==
MBB.end()) {
3210 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3212 FBB =
I->getOperand(0).getMBB();
3222 bool AllowModify)
const {
3230 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3231 switch (
I->getOpcode()) {
3232 case AMDGPU::S_MOV_B64_term:
3233 case AMDGPU::S_XOR_B64_term:
3234 case AMDGPU::S_OR_B64_term:
3235 case AMDGPU::S_ANDN2_B64_term:
3236 case AMDGPU::S_AND_B64_term:
3237 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3238 case AMDGPU::S_MOV_B32_term:
3239 case AMDGPU::S_XOR_B32_term:
3240 case AMDGPU::S_OR_B32_term:
3241 case AMDGPU::S_ANDN2_B32_term:
3242 case AMDGPU::S_AND_B32_term:
3243 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3244 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3245 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3248 case AMDGPU::SI_ELSE:
3249 case AMDGPU::SI_KILL_I1_TERMINATOR:
3250 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3267 int *BytesRemoved)
const {
3269 unsigned RemovedSize = 0;
3272 if (
MI.isBranch() ||
MI.isReturn()) {
3274 MI.eraseFromParent();
3280 *BytesRemoved = RemovedSize;
3297 int *BytesAdded)
const {
3298 if (!FBB &&
Cond.empty()) {
3302 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3309 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3321 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3339 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3346 if (
Cond.size() != 2) {
3350 if (
Cond[0].isImm()) {
3361 Register FalseReg,
int &CondCycles,
3362 int &TrueCycles,
int &FalseCycles)
const {
3372 CondCycles = TrueCycles = FalseCycles = NumInsts;
3375 return RI.hasVGPRs(RC) && NumInsts <= 6;
3389 if (NumInsts % 2 == 0)
3392 CondCycles = TrueCycles = FalseCycles = NumInsts;
3393 return RI.isSGPRClass(RC);
3404 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3405 if (Pred == VCCZ || Pred == SCC_FALSE) {
3406 Pred =
static_cast<BranchPredicate
>(-Pred);
3412 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3414 if (DstSize == 32) {
3416 if (Pred == SCC_TRUE) {
3431 if (DstSize == 64 && Pred == SCC_TRUE) {
3441 static const int16_t Sub0_15[] = {
3442 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3443 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3444 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3445 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3448 static const int16_t Sub0_15_64[] = {
3449 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3450 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3451 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3452 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3455 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3457 const int16_t *SubIndices = Sub0_15;
3458 int NElts = DstSize / 32;
3462 if (Pred == SCC_TRUE) {
3464 SelOp = AMDGPU::S_CSELECT_B32;
3465 EltRC = &AMDGPU::SGPR_32RegClass;
3467 SelOp = AMDGPU::S_CSELECT_B64;
3468 EltRC = &AMDGPU::SGPR_64RegClass;
3469 SubIndices = Sub0_15_64;
3475 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3480 for (
int Idx = 0; Idx != NElts; ++Idx) {
3484 unsigned SubIdx = SubIndices[Idx];
3487 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3489 .
addReg(FalseReg, {}, SubIdx)
3490 .addReg(TrueReg, {}, SubIdx);
3493 .
addReg(TrueReg, {}, SubIdx)
3494 .addReg(FalseReg, {}, SubIdx);
3507 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3510 switch (
MI.getOpcode()) {
3511 case AMDGPU::S_ENDPGM:
3512 case AMDGPU::S_ENDPGM_SAVED:
3513 case AMDGPU::S_TRAP:
3514 case AMDGPU::S_GETREG_B32:
3515 case AMDGPU::S_SETREG_B32:
3516 case AMDGPU::S_SETREG_B32_mode:
3517 case AMDGPU::S_SETREG_IMM32_B32:
3518 case AMDGPU::S_SETREG_IMM32_B32_mode:
3519 case AMDGPU::S_SENDMSG:
3520 case AMDGPU::S_SENDMSGHALT:
3521 case AMDGPU::S_SENDMSG_RTN_B32:
3522 case AMDGPU::S_SENDMSG_RTN_B64:
3523 case AMDGPU::S_BARRIER_WAIT:
3524 case AMDGPU::S_BARRIER_SIGNAL_M0:
3525 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3526 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3527 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3535 switch (
MI.getOpcode()) {
3536 case AMDGPU::V_MOV_B16_t16_e32:
3537 case AMDGPU::V_MOV_B16_t16_e64:
3538 case AMDGPU::V_MOV_B32_e32:
3539 case AMDGPU::V_MOV_B32_e64:
3540 case AMDGPU::V_MOV_B64_PSEUDO:
3541 case AMDGPU::V_MOV_B64_e32:
3542 case AMDGPU::V_MOV_B64_e64:
3543 case AMDGPU::S_MOV_B32:
3544 case AMDGPU::S_MOV_B64:
3545 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3547 case AMDGPU::WWM_COPY:
3548 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3549 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3550 case AMDGPU::V_ACCVGPR_MOV_B32:
3551 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3552 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3560 switch (
MI.getOpcode()) {
3561 case AMDGPU::V_MOV_B16_t16_e32:
3562 case AMDGPU::V_MOV_B16_t16_e64:
3564 case AMDGPU::V_MOV_B32_e32:
3565 case AMDGPU::V_MOV_B32_e64:
3566 case AMDGPU::V_MOV_B64_PSEUDO:
3567 case AMDGPU::V_MOV_B64_e32:
3568 case AMDGPU::V_MOV_B64_e64:
3569 case AMDGPU::S_MOV_B32:
3570 case AMDGPU::S_MOV_B64:
3571 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3573 case AMDGPU::WWM_COPY:
3574 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3575 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3576 case AMDGPU::V_ACCVGPR_MOV_B32:
3577 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3578 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3586 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3587 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3588 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3591 unsigned Opc =
MI.getOpcode();
3593 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3595 MI.removeOperand(Idx);
3601 MI.setDesc(NewDesc);
3607 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3608 Desc.implicit_defs().size();
3610 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3611 MI.removeOperand(
I);
3615 unsigned SubRegIndex) {
3616 switch (SubRegIndex) {
3617 case AMDGPU::NoSubRegister:
3627 case AMDGPU::sub1_lo16:
3629 case AMDGPU::sub1_hi16:
3632 return std::nullopt;
3640 case AMDGPU::V_MAC_F16_e32:
3641 case AMDGPU::V_MAC_F16_e64:
3642 case AMDGPU::V_MAD_F16_e64:
3643 return AMDGPU::V_MADAK_F16;
3644 case AMDGPU::V_MAC_F32_e32:
3645 case AMDGPU::V_MAC_F32_e64:
3646 case AMDGPU::V_MAD_F32_e64:
3647 return AMDGPU::V_MADAK_F32;
3648 case AMDGPU::V_FMAC_F32_e32:
3649 case AMDGPU::V_FMAC_F32_e64:
3650 case AMDGPU::V_FMA_F32_e64:
3651 return AMDGPU::V_FMAAK_F32;
3652 case AMDGPU::V_FMAC_F16_e32:
3653 case AMDGPU::V_FMAC_F16_e64:
3654 case AMDGPU::V_FMAC_F16_t16_e64:
3655 case AMDGPU::V_FMAC_F16_fake16_e64:
3656 case AMDGPU::V_FMAC_F16_t16_e32:
3657 case AMDGPU::V_FMAC_F16_fake16_e32:
3658 case AMDGPU::V_FMA_F16_e64:
3659 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3660 ? AMDGPU::V_FMAAK_F16_t16
3661 : AMDGPU::V_FMAAK_F16_fake16
3662 : AMDGPU::V_FMAAK_F16;
3663 case AMDGPU::V_FMAC_F64_e32:
3664 case AMDGPU::V_FMAC_F64_e64:
3665 case AMDGPU::V_FMA_F64_e64:
3666 return AMDGPU::V_FMAAK_F64;
3674 case AMDGPU::V_MAC_F16_e32:
3675 case AMDGPU::V_MAC_F16_e64:
3676 case AMDGPU::V_MAD_F16_e64:
3677 return AMDGPU::V_MADMK_F16;
3678 case AMDGPU::V_MAC_F32_e32:
3679 case AMDGPU::V_MAC_F32_e64:
3680 case AMDGPU::V_MAD_F32_e64:
3681 return AMDGPU::V_MADMK_F32;
3682 case AMDGPU::V_FMAC_F32_e32:
3683 case AMDGPU::V_FMAC_F32_e64:
3684 case AMDGPU::V_FMA_F32_e64:
3685 return AMDGPU::V_FMAMK_F32;
3686 case AMDGPU::V_FMAC_F16_e32:
3687 case AMDGPU::V_FMAC_F16_e64:
3688 case AMDGPU::V_FMAC_F16_t16_e64:
3689 case AMDGPU::V_FMAC_F16_fake16_e64:
3690 case AMDGPU::V_FMAC_F16_t16_e32:
3691 case AMDGPU::V_FMAC_F16_fake16_e32:
3692 case AMDGPU::V_FMA_F16_e64:
3693 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3694 ? AMDGPU::V_FMAMK_F16_t16
3695 : AMDGPU::V_FMAMK_F16_fake16
3696 : AMDGPU::V_FMAMK_F16;
3697 case AMDGPU::V_FMAC_F64_e32:
3698 case AMDGPU::V_FMAC_F64_e64:
3699 case AMDGPU::V_FMA_F64_e64:
3700 return AMDGPU::V_FMAMK_F64;
3714 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3717 if (
Opc == AMDGPU::COPY) {
3718 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3725 if (HasMultipleUses) {
3728 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3731 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3739 if (ImmDefSize == 32 &&
3744 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3745 RI.getSubRegIdxSize(UseSubReg) == 16;
3748 if (RI.hasVGPRs(DstRC))
3751 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3757 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3764 for (
unsigned MovOp :
3765 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3766 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3774 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3778 if (MovDstPhysReg) {
3782 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3789 if (MovDstPhysReg) {
3790 if (!MovDstRC->
contains(MovDstPhysReg))
3806 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3814 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3818 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3820 UseMI.getOperand(0).setReg(MovDstPhysReg);
3825 UseMI.setDesc(NewMCID);
3826 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3827 UseMI.addImplicitDefUseOperands(*MF);
3831 if (HasMultipleUses)
3834 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3835 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3836 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3837 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3838 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3839 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3840 Opc == AMDGPU::V_FMAC_F64_e64) {
3849 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3860 auto CopyRegOperandToNarrowerRC =
3863 if (!
MI.getOperand(OpNo).isReg())
3867 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3870 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3871 get(AMDGPU::COPY), Tmp)
3873 MI.getOperand(OpNo).setReg(Tmp);
3874 MI.getOperand(OpNo).setIsKill();
3881 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3882 if (!RegSrc->
isReg())
3885 ST.getConstantBusLimit(
Opc) < 2)
3900 if (Def && Def->isMoveImmediate() &&
3915 unsigned SrcSubReg = RegSrc->
getSubReg();
3920 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3921 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3922 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3923 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3924 UseMI.untieRegOperand(
3925 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3932 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3933 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3937 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3938 UseMI.getOperand(0).getReg())
3940 UseMI.getOperand(0).setReg(Tmp);
3941 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3942 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
3947 DefMI.eraseFromParent();
3954 if (ST.getConstantBusLimit(
Opc) < 2) {
3957 bool Src0Inlined =
false;
3958 if (Src0->
isReg()) {
3963 if (Def && Def->isMoveImmediate() &&
3968 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
3969 RI.isSGPRReg(*MRI, Src0->
getReg())) {
3975 if (Src1->
isReg() && !Src0Inlined) {
3978 if (Def && Def->isMoveImmediate() &&
3982 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
3995 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3996 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3997 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3998 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3999 UseMI.untieRegOperand(
4000 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4002 const std::optional<int64_t> SubRegImm =
4012 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4013 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4017 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4018 UseMI.getOperand(0).getReg())
4020 UseMI.getOperand(0).setReg(Tmp);
4021 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4022 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4032 DefMI.eraseFromParent();
4044 if (BaseOps1.
size() != BaseOps2.
size())
4046 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4047 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4055 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4056 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4057 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4059 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4062bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4065 int64_t Offset0, Offset1;
4068 bool Offset0IsScalable, Offset1IsScalable;
4082 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4083 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4090 "MIa must load from or modify a memory location");
4092 "MIb must load from or modify a memory location");
4114 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4121 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4131 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4145 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4156 if (
Reg.isPhysical())
4160 Imm = Def->getOperand(1).getImm();
4180 unsigned NumOps =
MI.getNumOperands();
4183 if (
Op.isReg() &&
Op.isKill())
4191 case AMDGPU::V_MAC_F16_e32:
4192 case AMDGPU::V_MAC_F16_e64:
4193 return AMDGPU::V_MAD_F16_e64;
4194 case AMDGPU::V_MAC_F32_e32:
4195 case AMDGPU::V_MAC_F32_e64:
4196 return AMDGPU::V_MAD_F32_e64;
4197 case AMDGPU::V_MAC_LEGACY_F32_e32:
4198 case AMDGPU::V_MAC_LEGACY_F32_e64:
4199 return AMDGPU::V_MAD_LEGACY_F32_e64;
4200 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4201 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4202 return AMDGPU::V_FMA_LEGACY_F32_e64;
4203 case AMDGPU::V_FMAC_F16_e32:
4204 case AMDGPU::V_FMAC_F16_e64:
4205 case AMDGPU::V_FMAC_F16_t16_e64:
4206 case AMDGPU::V_FMAC_F16_fake16_e64:
4207 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4208 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4209 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4210 : AMDGPU::V_FMA_F16_gfx9_e64;
4211 case AMDGPU::V_FMAC_F32_e32:
4212 case AMDGPU::V_FMAC_F32_e64:
4213 return AMDGPU::V_FMA_F32_e64;
4214 case AMDGPU::V_FMAC_F64_e32:
4215 case AMDGPU::V_FMAC_F64_e64:
4216 return AMDGPU::V_FMA_F64_e64;
4236 if (
MI.isBundle()) {
4239 if (
MI.getBundleSize() != 1)
4241 CandidateMI =
MI.getNextNode();
4245 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4249 if (
MI.isBundle()) {
4254 MI.untieRegOperand(MO.getOperandNo());
4262 if (Def.isEarlyClobber() && Def.isReg() &&
4267 auto UpdateDefIndex = [&](
LiveRange &LR) {
4268 auto *S = LR.find(OldIndex);
4269 if (S != LR.end() && S->start == OldIndex) {
4270 assert(S->valno && S->valno->def == OldIndex);
4271 S->start = NewIndex;
4272 S->valno->def = NewIndex;
4276 for (
auto &SR : LI.subranges())
4282 if (U.RemoveMIUse) {
4285 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4289 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4290 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4291 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4292 U.RemoveMIUse->removeOperand(
I);
4297 if (
MI.isBundle()) {
4301 if (MO.isReg() && MO.getReg() == DefReg) {
4302 assert(MO.getSubReg() == 0 &&
4303 "tied sub-registers in bundles currently not supported");
4304 MI.removeOperand(MO.getOperandNo());
4321 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4322 MIOp.setIsUndef(
true);
4323 MIOp.setReg(DummyReg);
4327 if (
MI.isBundle()) {
4331 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4332 MIOp.setIsUndef(
true);
4333 MIOp.setReg(DummyReg);
4346 return MI.isBundle() ? &
MI : NewMI;
4351 ThreeAddressUpdates &U)
const {
4353 unsigned Opc =
MI.getOpcode();
4357 if (NewMFMAOpc != -1) {
4360 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4361 MIB.
add(
MI.getOperand(
I));
4369 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4374 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4375 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4376 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4380 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4381 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4382 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4383 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4384 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4385 bool Src0Literal =
false;
4390 case AMDGPU::V_MAC_F16_e64:
4391 case AMDGPU::V_FMAC_F16_e64:
4392 case AMDGPU::V_FMAC_F16_t16_e64:
4393 case AMDGPU::V_FMAC_F16_fake16_e64:
4394 case AMDGPU::V_MAC_F32_e64:
4395 case AMDGPU::V_MAC_LEGACY_F32_e64:
4396 case AMDGPU::V_FMAC_F32_e64:
4397 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4398 case AMDGPU::V_FMAC_F64_e64:
4400 case AMDGPU::V_MAC_F16_e32:
4401 case AMDGPU::V_FMAC_F16_e32:
4402 case AMDGPU::V_MAC_F32_e32:
4403 case AMDGPU::V_MAC_LEGACY_F32_e32:
4404 case AMDGPU::V_FMAC_F32_e32:
4405 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4406 case AMDGPU::V_FMAC_F64_e32: {
4407 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4408 AMDGPU::OpName::src0);
4409 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4420 MachineInstrBuilder MIB;
4423 const MachineOperand *Src0Mods =
4426 const MachineOperand *Src1Mods =
4429 const MachineOperand *Src2Mods =
4435 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4436 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4438 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4440 MachineInstr *
DefMI =
nullptr;
4476 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4492 if (Src0Literal && !ST.hasVOP3Literal())
4520 switch (
MI.getOpcode()) {
4521 case AMDGPU::S_SET_GPR_IDX_ON:
4522 case AMDGPU::S_SET_GPR_IDX_MODE:
4523 case AMDGPU::S_SET_GPR_IDX_OFF:
4541 if (
MI.isTerminator() ||
MI.isPosition())
4545 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4548 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4554 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4555 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4556 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4557 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4558 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4563 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4564 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4565 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4579 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4584 if (
MI.memoperands_empty())
4589 unsigned AS = Memop->getAddrSpace();
4590 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4591 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4592 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4593 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4608 if (
MI.memoperands_empty())
4617 unsigned AS = Memop->getAddrSpace();
4627 bool TgSplit)
const {
4640 if (
MI.memoperands_empty())
4645 unsigned AS = Memop->getAddrSpace();
4661 unsigned Opcode =
MI.getOpcode();
4676 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4677 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4678 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4679 Opcode == AMDGPU::S_SETHALT)
4682 if (
MI.isCall() ||
MI.isInlineAsm())
4698 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4699 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4700 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4701 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4709 if (
MI.isMetaInstruction())
4713 if (
MI.isCopyLike()) {
4714 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4718 return MI.readsRegister(AMDGPU::EXEC, &RI);
4729 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4733 switch (Imm.getBitWidth()) {
4739 ST.hasInv2PiInlineImm());
4742 ST.hasInv2PiInlineImm());
4744 return ST.has16BitInsts() &&
4746 ST.hasInv2PiInlineImm());
4753 APInt IntImm = Imm.bitcastToAPInt();
4755 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4763 return ST.has16BitInsts() &&
4766 return ST.has16BitInsts() &&
4776 switch (OperandType) {
4786 int32_t Trunc =
static_cast<int32_t
>(Imm);
4830 int16_t Trunc =
static_cast<int16_t
>(Imm);
4831 return ST.has16BitInsts() &&
4840 int16_t Trunc =
static_cast<int16_t
>(Imm);
4841 return ST.has16BitInsts() &&
4892 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4898 return ST.hasVOP3Literal();
4902 int64_t ImmVal)
const {
4904 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4905 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4906 OpNo ==
static_cast<unsigned>(Src1Idx))
4911 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4912 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4913 AMDGPU::OpName::src2))
4916 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
4923 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4935 "unexpected imm-like operand kind");
4948 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4966 AMDGPU::OpName
OpName)
const {
4968 return Mods && Mods->
getImm();
4981 switch (
MI.getOpcode()) {
4982 default:
return false;
4984 case AMDGPU::V_ADDC_U32_e64:
4985 case AMDGPU::V_SUBB_U32_e64:
4986 case AMDGPU::V_SUBBREV_U32_e64: {
4989 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
4994 case AMDGPU::V_MAC_F16_e64:
4995 case AMDGPU::V_MAC_F32_e64:
4996 case AMDGPU::V_MAC_LEGACY_F32_e64:
4997 case AMDGPU::V_FMAC_F16_e64:
4998 case AMDGPU::V_FMAC_F16_t16_e64:
4999 case AMDGPU::V_FMAC_F16_fake16_e64:
5000 case AMDGPU::V_FMAC_F32_e64:
5001 case AMDGPU::V_FMAC_F64_e64:
5002 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5003 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5008 case AMDGPU::V_CNDMASK_B32_e64:
5014 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5027 if (Src0 && Src0->
isImm()) {
5030 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5052 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5061 unsigned Op32)
const {
5075 Inst32.
add(
MI.getOperand(
I));
5079 int Idx =
MI.getNumExplicitDefs();
5081 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5086 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5108 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5116 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5119 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5120 AMDGPU::SReg_64RegClass.contains(Reg);
5148 switch (MO.getReg()) {
5150 case AMDGPU::VCC_LO:
5151 case AMDGPU::VCC_HI:
5153 case AMDGPU::FLAT_SCR:
5166 switch (
MI.getOpcode()) {
5167 case AMDGPU::V_READLANE_B32:
5168 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5169 case AMDGPU::V_WRITELANE_B32:
5170 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5177 if (
MI.isPreISelOpcode() ||
5178 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5196 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5207 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5208 ErrInfo =
"illegal copy from vector register to SGPR";
5226 if (!MRI.
isSSA() &&
MI.isCopy())
5227 return verifyCopy(
MI, MRI, ErrInfo);
5229 if (SIInstrInfo::isGenericOpcode(Opcode))
5232 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5233 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5234 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5236 if (Src0Idx == -1) {
5238 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5239 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5240 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5241 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5246 if (!
Desc.isVariadic() &&
5247 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5248 ErrInfo =
"Instruction has wrong number of operands.";
5252 if (
MI.isInlineAsm()) {
5265 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5266 ErrInfo =
"inlineasm operand has incorrect register class.";
5274 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5275 ErrInfo =
"missing memory operand from image instruction.";
5280 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5283 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5284 "all fp values to integers.";
5289 int16_t RegClass = getOpRegClassID(OpInfo);
5291 switch (OpInfo.OperandType) {
5293 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5294 ErrInfo =
"Illegal immediate value for operand.";
5327 ErrInfo =
"Illegal immediate value for operand.";
5336 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5339 OpInfo.OperandType ==
5341 ErrInfo =
"illegal 64-bit immediate value for operand.";
5348 ErrInfo =
"Expected inline constant for operand.";
5362 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5363 ErrInfo =
"Expected immediate, but got non-immediate";
5372 if (OpInfo.isGenericType())
5387 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5388 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5390 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5392 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5393 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5400 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5401 ErrInfo =
"Subtarget requires even aligned vector registers";
5406 if (RegClass != -1) {
5407 if (Reg.isVirtual())
5412 ErrInfo =
"Operand has incorrect register class.";
5420 if (!ST.hasSDWA()) {
5421 ErrInfo =
"SDWA is not supported on this target";
5425 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5426 AMDGPU::OpName::dst_sel}) {
5430 int64_t Imm = MO->
getImm();
5432 ErrInfo =
"Invalid SDWA selection";
5437 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5439 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5444 if (!ST.hasSDWAScalar()) {
5446 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5447 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5454 "Only reg allowed as operands in SDWA instructions on GFX9+";
5460 if (!ST.hasSDWAOmod()) {
5463 if (OMod !=
nullptr &&
5465 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5470 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5471 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5472 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5473 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5476 unsigned Mods = Src0ModsMO->
getImm();
5479 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5485 if (
isVOPC(BasicOpcode)) {
5486 if (!ST.hasSDWASdst() && DstIdx != -1) {
5489 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5490 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5493 }
else if (!ST.hasSDWAOutModsVOPC()) {
5496 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5497 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5503 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5504 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5511 if (DstUnused && DstUnused->isImm() &&
5514 if (!Dst.isReg() || !Dst.isTied()) {
5515 ErrInfo =
"Dst register should have tied register";
5520 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5523 "Dst register should be tied to implicit use of preserved register";
5527 ErrInfo =
"Dst register should use same physical register as preserved";
5533 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5535 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5536 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5539 if (Src1MO.
isImm()) {
5540 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5546 if (
isImage(Opcode) && !
MI.mayStore()) {
5558 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5566 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5570 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5571 if (RegCount > DstSize) {
5572 ErrInfo =
"Image instruction returns too many registers for dst "
5582 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5583 unsigned ConstantBusCount = 0;
5584 bool UsesLiteral =
false;
5587 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5591 LiteralVal = &
MI.getOperand(ImmIdx);
5600 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5611 }
else if (!MO.
isFI()) {
5618 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5628 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5629 return !RI.regsOverlap(SGPRUsed, SGPR);
5638 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5639 Opcode != AMDGPU::V_WRITELANE_B32) {
5640 ErrInfo =
"VOP* instruction violates constant bus restriction";
5644 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5645 ErrInfo =
"VOP3 instruction uses literal";
5652 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5653 unsigned SGPRCount = 0;
5656 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5664 if (MO.
getReg() != SGPRUsed)
5669 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5670 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5677 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5678 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5685 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5695 ErrInfo =
"ABS not allowed in VOP3B instructions";
5708 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5715 if (
Desc.isBranch()) {
5717 ErrInfo =
"invalid branch target for SOPK instruction";
5724 ErrInfo =
"invalid immediate for SOPK instruction";
5729 ErrInfo =
"invalid immediate for SOPK instruction";
5736 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5737 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5738 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5739 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5740 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5741 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5743 const unsigned StaticNumOps =
5744 Desc.getNumOperands() +
Desc.implicit_uses().size();
5745 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5751 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5752 ErrInfo =
"missing implicit register operands";
5758 if (!Dst->isUse()) {
5759 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5764 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5765 UseOpIdx != StaticNumOps + 1) {
5766 ErrInfo =
"movrel implicit operands should be tied";
5773 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5775 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5776 ErrInfo =
"src0 should be subreg of implicit vector use";
5784 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5785 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5791 if (
MI.mayStore() &&
5796 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5797 ErrInfo =
"scalar stores must use m0 as offset register";
5803 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5805 if (
Offset->getImm() != 0) {
5806 ErrInfo =
"subtarget does not support offsets in flat instructions";
5811 if (
isDS(
MI) && !ST.hasGDS()) {
5813 if (GDSOp && GDSOp->
getImm() != 0) {
5814 ErrInfo =
"GDS is not supported on this subtarget";
5822 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5823 AMDGPU::OpName::vaddr0);
5824 AMDGPU::OpName RSrcOpName =
5825 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5826 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5834 ErrInfo =
"dim is out of range";
5839 if (ST.hasR128A16()) {
5841 IsA16 = R128A16->
getImm() != 0;
5842 }
else if (ST.hasA16()) {
5844 IsA16 = A16->
getImm() != 0;
5847 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5849 unsigned AddrWords =
5852 unsigned VAddrWords;
5854 VAddrWords = RsrcIdx - VAddr0Idx;
5855 if (ST.hasPartialNSAEncoding() &&
5857 unsigned LastVAddrIdx = RsrcIdx - 1;
5858 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5866 if (VAddrWords != AddrWords) {
5868 <<
" but got " << VAddrWords <<
"\n");
5869 ErrInfo =
"bad vaddr size";
5879 unsigned DC = DppCt->
getImm();
5880 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5881 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5882 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5883 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5884 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5885 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5886 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5887 ErrInfo =
"Invalid dpp_ctrl value";
5890 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5891 !ST.hasDPPWavefrontShifts()) {
5892 ErrInfo =
"Invalid dpp_ctrl value: "
5893 "wavefront shifts are not supported on GFX10+";
5896 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5897 !ST.hasDPPBroadcasts()) {
5898 ErrInfo =
"Invalid dpp_ctrl value: "
5899 "broadcasts are not supported on GFX10+";
5902 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5904 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5905 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5906 !ST.hasGFX90AInsts()) {
5907 ErrInfo =
"Invalid dpp_ctrl value: "
5908 "row_newbroadcast/row_share is not supported before "
5912 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5913 ErrInfo =
"Invalid dpp_ctrl value: "
5914 "row_share and row_xmask are not supported before GFX10";
5919 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5922 ErrInfo =
"Invalid dpp_ctrl value: "
5923 "DP ALU dpp only support row_newbcast";
5930 AMDGPU::OpName DataName =
5931 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5937 if (!ST.hasGFX90AInsts()) {
5938 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5939 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
5940 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
5941 ErrInfo =
"Invalid register class: "
5942 "agpr loads and stores not supported on this GPU";
5948 if (ST.needsAlignedVGPRs()) {
5949 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
5954 if (Reg.isPhysical())
5955 return !(RI.getHWRegIndex(Reg) & 1);
5957 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5958 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
5961 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5962 Opcode == AMDGPU::DS_GWS_BARRIER) {
5964 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5965 ErrInfo =
"Subtarget requires even aligned vector registers "
5966 "for DS_GWS instructions";
5972 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5973 ErrInfo =
"Subtarget requires even aligned vector registers "
5974 "for vaddr operand of image instructions";
5980 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5982 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5983 ErrInfo =
"Invalid register class: "
5984 "v_accvgpr_write with an SGPR is not supported on this GPU";
5989 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5992 ErrInfo =
"pseudo expects only physical SGPRs";
5999 if (!ST.hasScaleOffset()) {
6000 ErrInfo =
"Subtarget does not support offset scaling";
6004 ErrInfo =
"Instruction does not support offset scaling";
6012 for (
unsigned I = 0;
I < 3; ++
I) {
6018 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6019 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6021 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6022 &AMDGPU::SReg_64RegClass) ||
6023 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6024 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6033 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6035 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6037 : AMDGPU::V_MOV_B32_e32;
6047 default:
return AMDGPU::INSTRUCTION_LIST_END;
6048 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6049 case AMDGPU::COPY:
return AMDGPU::COPY;
6050 case AMDGPU::PHI:
return AMDGPU::PHI;
6051 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6052 case AMDGPU::WQM:
return AMDGPU::WQM;
6053 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6054 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6055 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6056 case AMDGPU::S_ADD_I32:
6057 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6058 case AMDGPU::S_ADDC_U32:
6059 return AMDGPU::V_ADDC_U32_e32;
6060 case AMDGPU::S_SUB_I32:
6061 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6064 case AMDGPU::S_ADD_U32:
6065 return AMDGPU::V_ADD_CO_U32_e32;
6066 case AMDGPU::S_SUB_U32:
6067 return AMDGPU::V_SUB_CO_U32_e32;
6068 case AMDGPU::S_ADD_U64_PSEUDO:
6069 return AMDGPU::V_ADD_U64_PSEUDO;
6070 case AMDGPU::S_SUB_U64_PSEUDO:
6071 return AMDGPU::V_SUB_U64_PSEUDO;
6072 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6073 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6074 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6075 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6076 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6077 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6078 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6079 case AMDGPU::S_XNOR_B32:
6080 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6081 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6082 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6083 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6084 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6085 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6086 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6087 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6088 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6089 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6090 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6091 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6092 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6093 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6094 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6095 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6096 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6097 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6098 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6099 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6100 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6101 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6102 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6103 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6104 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6105 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6106 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6107 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6108 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6109 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6110 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6111 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6112 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6113 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6114 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6115 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6116 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6117 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6118 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6119 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6120 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6121 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6122 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6123 case AMDGPU::S_CVT_F32_F16:
6124 case AMDGPU::S_CVT_HI_F32_F16:
6125 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6126 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6127 case AMDGPU::S_CVT_F16_F32:
6128 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6129 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6130 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6131 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6132 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6133 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6134 case AMDGPU::S_CEIL_F16:
6135 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6136 : AMDGPU::V_CEIL_F16_fake16_e64;
6137 case AMDGPU::S_FLOOR_F16:
6138 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6139 : AMDGPU::V_FLOOR_F16_fake16_e64;
6140 case AMDGPU::S_TRUNC_F16:
6141 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6142 : AMDGPU::V_TRUNC_F16_fake16_e64;
6143 case AMDGPU::S_RNDNE_F16:
6144 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6145 : AMDGPU::V_RNDNE_F16_fake16_e64;
6146 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6147 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6148 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6149 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6150 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6151 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6152 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6153 case AMDGPU::S_ADD_F16:
6154 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6155 : AMDGPU::V_ADD_F16_fake16_e64;
6156 case AMDGPU::S_SUB_F16:
6157 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6158 : AMDGPU::V_SUB_F16_fake16_e64;
6159 case AMDGPU::S_MIN_F16:
6160 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6161 : AMDGPU::V_MIN_F16_fake16_e64;
6162 case AMDGPU::S_MAX_F16:
6163 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6164 : AMDGPU::V_MAX_F16_fake16_e64;
6165 case AMDGPU::S_MINIMUM_F16:
6166 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6167 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6168 case AMDGPU::S_MAXIMUM_F16:
6169 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6170 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6171 case AMDGPU::S_MUL_F16:
6172 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6173 : AMDGPU::V_MUL_F16_fake16_e64;
6174 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6175 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6176 case AMDGPU::S_FMAC_F16:
6177 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6178 : AMDGPU::V_FMAC_F16_fake16_e64;
6179 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6180 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6181 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6182 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6183 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6184 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6185 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6186 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6187 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6188 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6189 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6190 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6191 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6192 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6193 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6194 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6195 case AMDGPU::S_CMP_LT_F16:
6196 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6197 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6198 case AMDGPU::S_CMP_EQ_F16:
6199 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6200 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6201 case AMDGPU::S_CMP_LE_F16:
6202 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6203 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6204 case AMDGPU::S_CMP_GT_F16:
6205 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6206 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6207 case AMDGPU::S_CMP_LG_F16:
6208 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6209 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6210 case AMDGPU::S_CMP_GE_F16:
6211 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6212 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6213 case AMDGPU::S_CMP_O_F16:
6214 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6215 : AMDGPU::V_CMP_O_F16_fake16_e64;
6216 case AMDGPU::S_CMP_U_F16:
6217 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6218 : AMDGPU::V_CMP_U_F16_fake16_e64;
6219 case AMDGPU::S_CMP_NGE_F16:
6220 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6221 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6222 case AMDGPU::S_CMP_NLG_F16:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6224 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6225 case AMDGPU::S_CMP_NGT_F16:
6226 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6227 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6228 case AMDGPU::S_CMP_NLE_F16:
6229 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6230 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6231 case AMDGPU::S_CMP_NEQ_F16:
6232 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6233 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6234 case AMDGPU::S_CMP_NLT_F16:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6236 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6237 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6238 case AMDGPU::V_S_EXP_F16_e64:
6239 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6240 : AMDGPU::V_EXP_F16_fake16_e64;
6241 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6242 case AMDGPU::V_S_LOG_F16_e64:
6243 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6244 : AMDGPU::V_LOG_F16_fake16_e64;
6245 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6246 case AMDGPU::V_S_RCP_F16_e64:
6247 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6248 : AMDGPU::V_RCP_F16_fake16_e64;
6249 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6250 case AMDGPU::V_S_RSQ_F16_e64:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6252 : AMDGPU::V_RSQ_F16_fake16_e64;
6253 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6254 case AMDGPU::V_S_SQRT_F16_e64:
6255 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6256 : AMDGPU::V_SQRT_F16_fake16_e64;
6259 "Unexpected scalar opcode without corresponding vector one!");
6308 "Not a whole wave func");
6311 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6312 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6319 unsigned OpNo)
const {
6321 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6322 Desc.operands()[OpNo].RegClass == -1) {
6325 if (Reg.isVirtual()) {
6329 return RI.getPhysRegBaseClass(Reg);
6332 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6333 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6338 constexpr AMDGPU::OpName OpNames[] = {
6339 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6342 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6343 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6355 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6357 unsigned Size = RI.getRegSizeInBits(*RC);
6358 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6359 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6360 : AMDGPU::V_MOV_B32_e32;
6362 Opcode = AMDGPU::COPY;
6363 else if (RI.isSGPRClass(RC))
6364 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6389 .
addImm(AMDGPU::sub0_sub1)
6391 .
addImm(AMDGPU::sub2_sub3);
6404 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6410 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6421 if (SubIdx == AMDGPU::sub0)
6423 if (SubIdx == AMDGPU::sub1)
6435void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6451 if (Reg.isPhysical())
6461 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6464 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6471 unsigned Opc =
MI.getOpcode();
6474 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6484 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6485 if (IsAGPR && !ST.hasMAIInsts())
6491 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6492 const int DataIdx = AMDGPU::getNamedOperandIdx(
6493 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6494 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6495 MI.getOperand(DataIdx).isReg() &&
6496 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6498 if ((
int)OpIdx == DataIdx) {
6499 if (VDstIdx != -1 &&
6500 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6503 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6504 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6505 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6510 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6511 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6512 RI.isSGPRReg(MRI, MO.
getReg()))
6515 if (ST.hasFlatScratchHiInB64InstHazard() &&
6522 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6525 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6526 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6546 constexpr unsigned NumOps = 3;
6547 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6548 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6549 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6550 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6555 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6558 MO = &
MI.getOperand(SrcIdx);
6561 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6565 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6569 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6573 return !OpSel && !OpSelHi;
6582 int64_t RegClass = getOpRegClassID(OpInfo);
6584 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6586 MO = &
MI.getOperand(OpIdx);
6590 if (
isVALU(
MI,
true) && !IsInlineConst &&
6594 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6595 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6599 if (!LiteralLimit--)
6609 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6617 if (--ConstantBusLimit <= 0)
6629 if (!LiteralLimit--)
6631 if (--ConstantBusLimit <= 0)
6637 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6641 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6643 !
Op.isIdenticalTo(*MO))
6653 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6668 bool Is64BitOp = Is64BitFPOp ||
6676 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6685 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6703 bool IsGFX950Only = ST.hasGFX950Insts();
6704 bool IsGFX940Only = ST.hasGFX940Insts();
6706 if (!IsGFX950Only && !IsGFX940Only)
6724 unsigned Opcode =
MI.getOpcode();
6726 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6727 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6728 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6729 case AMDGPU::V_MQSAD_U32_U8_e64:
6730 case AMDGPU::V_PK_ADD_F16:
6731 case AMDGPU::V_PK_ADD_F32:
6732 case AMDGPU::V_PK_ADD_I16:
6733 case AMDGPU::V_PK_ADD_U16:
6734 case AMDGPU::V_PK_ASHRREV_I16:
6735 case AMDGPU::V_PK_FMA_F16:
6736 case AMDGPU::V_PK_FMA_F32:
6737 case AMDGPU::V_PK_FMAC_F16_e32:
6738 case AMDGPU::V_PK_FMAC_F16_e64:
6739 case AMDGPU::V_PK_LSHLREV_B16:
6740 case AMDGPU::V_PK_LSHRREV_B16:
6741 case AMDGPU::V_PK_MAD_I16:
6742 case AMDGPU::V_PK_MAD_U16:
6743 case AMDGPU::V_PK_MAX_F16:
6744 case AMDGPU::V_PK_MAX_I16:
6745 case AMDGPU::V_PK_MAX_U16:
6746 case AMDGPU::V_PK_MIN_F16:
6747 case AMDGPU::V_PK_MIN_I16:
6748 case AMDGPU::V_PK_MIN_U16:
6749 case AMDGPU::V_PK_MOV_B32:
6750 case AMDGPU::V_PK_MUL_F16:
6751 case AMDGPU::V_PK_MUL_F32:
6752 case AMDGPU::V_PK_MUL_LO_U16:
6753 case AMDGPU::V_PK_SUB_I16:
6754 case AMDGPU::V_PK_SUB_U16:
6755 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6764 unsigned Opc =
MI.getOpcode();
6767 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6770 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6776 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6777 RI.isSGPRReg(MRI, Src0.
getReg()))
6783 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6785 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6791 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6802 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6803 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6804 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6816 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6817 RI.isVGPR(MRI, Src1.
getReg())) {
6830 if (HasImplicitSGPR || !
MI.isCommutable()) {
6847 if (CommutedOpc == -1) {
6852 MI.setDesc(
get(CommutedOpc));
6856 bool Src0Kill = Src0.
isKill();
6860 else if (Src1.
isReg()) {
6875 unsigned Opc =
MI.getOpcode();
6878 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6879 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6880 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6883 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6884 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6885 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6886 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6887 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6888 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6889 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6899 if (VOP3Idx[2] != -1) {
6911 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6912 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6914 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6916 SGPRsUsed.
insert(SGPRReg);
6920 for (
int Idx : VOP3Idx) {
6929 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6941 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
6948 if (ConstantBusLimit > 0) {
6960 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
6961 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
6967 for (
unsigned I = 0;
I < 3; ++
I) {
6980 SRC = RI.getCommonSubClass(SRC, DstRC);
6983 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6985 if (RI.hasAGPRs(VRC)) {
6986 VRC = RI.getEquivalentVGPRClass(VRC);
6989 get(TargetOpcode::COPY), NewSrcReg)
6996 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7002 for (
unsigned i = 0; i < SubRegs; ++i) {
7005 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7006 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7012 get(AMDGPU::REG_SEQUENCE), DstReg);
7013 for (
unsigned i = 0; i < SubRegs; ++i) {
7015 MIB.
addImm(RI.getSubRegFromChannel(i));
7028 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7030 SBase->setReg(SGPR);
7033 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7041 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7042 if (OldSAddrIdx < 0)
7055 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7058 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7059 if (NewVAddrIdx < 0)
7062 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7066 if (OldVAddrIdx >= 0) {
7080 if (OldVAddrIdx == NewVAddrIdx) {
7091 assert(OldSAddrIdx == NewVAddrIdx);
7093 if (OldVAddrIdx >= 0) {
7094 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7095 AMDGPU::OpName::vdst_in);
7099 if (NewVDstIn != -1) {
7100 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7106 if (NewVDstIn != -1) {
7107 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7148 unsigned OpSubReg =
Op.getSubReg();
7151 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7158 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7159 .
addReg(OpReg, {}, OpSubReg);
7161 Op.setSubReg(AMDGPU::NoSubRegister);
7168 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7171 bool ImpDef = Def->isImplicitDef();
7172 while (!ImpDef && Def && Def->isCopy()) {
7173 if (Def->getOperand(1).getReg().isPhysical())
7176 ImpDef = Def && Def->isImplicitDef();
7178 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7194 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7199 bool UseNewExecInstructions =
7208 if (UseNewExecInstructions) {
7243 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7244 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7245 unsigned NumSubRegs =
RegSize / 32;
7246 Register VScalarOp = ScalarOp->getReg();
7249 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7251 if (NumSubRegs == 1) {
7254 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7255 Common != VScalarOpRC) {
7262 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7265 if (UseNewExecInstructions) {
7267 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7270 if (
I == LoopBB.
end())
7275 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7281 CondReg = NewCondReg;
7292 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7293 ScalarOp->setReg(CurReg);
7296 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7297 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7299 ScalarOp->setReg(PhySGPRs[Idx]);
7301 ScalarOp->setIsKill();
7305 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7306 "Unhandled register size");
7308 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7315 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7316 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7319 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7320 .
addReg(VScalarOp, VScalarOpUndef,
7321 TRI->getSubRegFromChannel(Idx + 1));
7328 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7335 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7337 if (UseNewExecInstructions) {
7339 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7341 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7342 if (
I == LoopBB.
end())
7346 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7348 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7352 CondReg = NewCondReg;
7363 const auto *SScalarOpRC =
7369 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7370 unsigned Channel = 0;
7371 for (
Register Piece : ReadlanePieces) {
7372 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7376 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7377 ScalarOp->setReg(SScalarOp);
7379 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7380 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7382 ScalarOp->setReg(PhySGPRs[Idx]);
7384 ScalarOp->setIsKill();
7392 if (!UseNewExecInstructions) {
7404 if (UseNewExecInstructions) {
7428 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7429 "Physical SGPRs must be empty or match the number of scalar operands");
7435 if (!Begin.isValid())
7437 if (!End.isValid()) {
7443 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7452 std::numeric_limits<unsigned>::max()) !=
7470 for (
auto I = Begin;
I != AfterMI;
I++) {
7471 for (
auto &MO :
I->all_uses())
7507 for (
auto &Succ : RemainderBB->
successors()) {
7532static std::tuple<unsigned, unsigned>
7540 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7541 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7548 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7565 .
addImm(AMDGPU::sub0_sub1)
7571 return std::tuple(RsrcPtr, NewSRsrc);
7582 if (ST.useRealTrue16Insts())
7612 if (
MI.getOpcode() == AMDGPU::PHI) {
7614 assert(!RI.isSGPRClass(VRC));
7617 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7619 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7635 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7638 if (RI.hasVGPRs(DstRC)) {
7642 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7644 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7662 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7667 if (DstRC != Src0RC) {
7676 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7678 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7684 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7685 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7686 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7687 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7688 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7689 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7690 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7692 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7705 ? AMDGPU::OpName::rsrc
7706 : AMDGPU::OpName::srsrc;
7711 AMDGPU::OpName SampOpName =
7712 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7721 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7729 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7733 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7743 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7744 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7745 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7746 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7748 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7755 bool isSoffsetLegal =
true;
7757 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7758 if (SoffsetIdx != -1) {
7762 isSoffsetLegal =
false;
7766 bool isRsrcLegal =
true;
7768 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7769 if (RsrcIdx != -1) {
7771 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7772 isRsrcLegal =
false;
7776 if (isRsrcLegal && isSoffsetLegal)
7804 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7808 unsigned RsrcPtr, NewSRsrc;
7815 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7816 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7822 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7823 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7836 }
else if (!VAddr && ST.hasAddr64()) {
7840 "FIXME: Need to emit flat atomics here");
7842 unsigned RsrcPtr, NewSRsrc;
7868 MIB.
addImm(CPol->getImm());
7873 MIB.
addImm(TFE->getImm());
7893 MI.removeFromParent();
7898 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7899 .addImm(AMDGPU::sub0)
7900 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7901 .addImm(AMDGPU::sub1);
7904 if (!isSoffsetLegal) {
7915 if (!isSoffsetLegal) {
7924 if (InSet.insert(
MI).second)
7928 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
7929 if (RsrcIdx != -1) {
7930 DeferredList.insert(
MI);
7935 return DeferredList.contains(
MI);
7945 if (!ST.useRealTrue16Insts())
7948 unsigned Opcode =
MI.getOpcode();
7951 if (OpIdx >=
MI.getNumExplicitOperands() ||
7952 OpIdx >=
get(Opcode).getNumOperands() ||
7953 get(Opcode).operands()[OpIdx].RegClass == -1)
7957 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
7961 if (!RI.isVGPRClass(CurrRC))
7964 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
7966 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7968 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
7969 Op.setSubReg(AMDGPU::lo16);
7974 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
7975 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7985 Op.setReg(NewDstReg);
7986 Op.setSubReg(AMDGPU::NoSubRegister);
7991 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
7999 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8000 "This only handle waterfall for SI_CALL_ISEL");
8007 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8010 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8015 while (End !=
MBB.end() && End->isCopy() &&
8016 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8026 while (!Worklist.
empty()) {
8032 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8038 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8040 "Deferred MachineInstr are not supposed to re-populate worklist");
8043 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8044 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8046 Entry.second.SGPRs);
8049 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8051 Entry.first->eraseFromParent();
8059 if (SubRegIndices.
size() <= 1) {
8062 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8069 for (int16_t Indice : SubRegIndices) {
8072 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8079 get(AMDGPU::REG_SEQUENCE), DstReg);
8080 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8082 MIB.
addImm(RI.getSubRegFromChannel(i));
8092 if (DstReg == AMDGPU::M0) {
8105 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8107 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8108 if (
UseMI->getOperand(i).isReg() &&
8109 UseMI->getOperand(i).getReg() == DstReg) {
8113 V2SCopyInfo.MOs.push_back(MO);
8114 V2SCopyInfo.SGPRs.push_back(DstReg);
8118 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8119 I->getOperand(0).isReg() &&
8120 I->getOperand(0).getReg() == DstReg) {
8123 }
else if (
I->readsRegister(DstReg, &RI)) {
8125 V2SPhyCopiesToErase[&Inst] =
false;
8127 if (
I->findRegisterDefOperand(DstReg, &RI))
8149 case AMDGPU::S_ADD_I32:
8150 case AMDGPU::S_SUB_I32: {
8154 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8162 case AMDGPU::S_MUL_U64:
8163 if (ST.hasVMulU64Inst()) {
8164 NewOpcode = AMDGPU::V_MUL_U64_e64;
8168 splitScalarSMulU64(Worklist, Inst, MDT);
8172 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8173 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8176 splitScalarSMulPseudo(Worklist, Inst, MDT);
8180 case AMDGPU::S_AND_B64:
8181 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8185 case AMDGPU::S_OR_B64:
8186 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8190 case AMDGPU::S_XOR_B64:
8191 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8195 case AMDGPU::S_NAND_B64:
8196 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8200 case AMDGPU::S_NOR_B64:
8201 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8205 case AMDGPU::S_XNOR_B64:
8206 if (ST.hasDLInsts())
8207 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8209 splitScalar64BitXnor(Worklist, Inst, MDT);
8213 case AMDGPU::S_ANDN2_B64:
8214 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8218 case AMDGPU::S_ORN2_B64:
8219 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8223 case AMDGPU::S_BREV_B64:
8224 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8228 case AMDGPU::S_NOT_B64:
8229 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8233 case AMDGPU::S_BCNT1_I32_B64:
8234 splitScalar64BitBCNT(Worklist, Inst);
8238 case AMDGPU::S_BFE_I64:
8239 splitScalar64BitBFE(Worklist, Inst);
8243 case AMDGPU::S_FLBIT_I32_B64:
8244 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8247 case AMDGPU::S_FF1_I32_B64:
8248 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8252 case AMDGPU::S_LSHL_B32:
8253 if (ST.hasOnlyRevVALUShifts()) {
8254 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8258 case AMDGPU::S_ASHR_I32:
8259 if (ST.hasOnlyRevVALUShifts()) {
8260 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8264 case AMDGPU::S_LSHR_B32:
8265 if (ST.hasOnlyRevVALUShifts()) {
8266 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8270 case AMDGPU::S_LSHL_B64:
8271 if (ST.hasOnlyRevVALUShifts()) {
8273 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8274 : AMDGPU::V_LSHLREV_B64_e64;
8278 case AMDGPU::S_ASHR_I64:
8279 if (ST.hasOnlyRevVALUShifts()) {
8280 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8284 case AMDGPU::S_LSHR_B64:
8285 if (ST.hasOnlyRevVALUShifts()) {
8286 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8291 case AMDGPU::S_ABS_I32:
8292 lowerScalarAbs(Worklist, Inst);
8296 case AMDGPU::S_ABSDIFF_I32:
8297 lowerScalarAbsDiff(Worklist, Inst);
8301 case AMDGPU::S_CBRANCH_SCC0:
8302 case AMDGPU::S_CBRANCH_SCC1: {
8305 bool IsSCC = CondReg == AMDGPU::SCC;
8313 case AMDGPU::S_BFE_U64:
8314 case AMDGPU::S_BFM_B64:
8317 case AMDGPU::S_PACK_LL_B32_B16:
8318 case AMDGPU::S_PACK_LH_B32_B16:
8319 case AMDGPU::S_PACK_HL_B32_B16:
8320 case AMDGPU::S_PACK_HH_B32_B16:
8321 movePackToVALU(Worklist, MRI, Inst);
8325 case AMDGPU::S_XNOR_B32:
8326 lowerScalarXnor(Worklist, Inst);
8330 case AMDGPU::S_NAND_B32:
8331 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8335 case AMDGPU::S_NOR_B32:
8336 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8340 case AMDGPU::S_ANDN2_B32:
8341 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8345 case AMDGPU::S_ORN2_B32:
8346 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8354 case AMDGPU::S_ADD_CO_PSEUDO:
8355 case AMDGPU::S_SUB_CO_PSEUDO: {
8356 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8357 ? AMDGPU::V_ADDC_U32_e64
8358 : AMDGPU::V_SUBB_U32_e64;
8359 const auto *CarryRC = RI.getWaveMaskRegClass();
8381 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8385 case AMDGPU::S_UADDO_PSEUDO:
8386 case AMDGPU::S_USUBO_PSEUDO: {
8392 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8393 ? AMDGPU::V_ADD_CO_U32_e64
8394 : AMDGPU::V_SUB_CO_U32_e64;
8406 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8410 case AMDGPU::S_LSHL1_ADD_U32:
8411 case AMDGPU::S_LSHL2_ADD_U32:
8412 case AMDGPU::S_LSHL3_ADD_U32:
8413 case AMDGPU::S_LSHL4_ADD_U32: {
8417 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8418 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8419 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8433 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8437 case AMDGPU::S_CSELECT_B32:
8438 case AMDGPU::S_CSELECT_B64:
8439 lowerSelect(Worklist, Inst, MDT);
8442 case AMDGPU::S_CMP_EQ_I32:
8443 case AMDGPU::S_CMP_LG_I32:
8444 case AMDGPU::S_CMP_GT_I32:
8445 case AMDGPU::S_CMP_GE_I32:
8446 case AMDGPU::S_CMP_LT_I32:
8447 case AMDGPU::S_CMP_LE_I32:
8448 case AMDGPU::S_CMP_EQ_U32:
8449 case AMDGPU::S_CMP_LG_U32:
8450 case AMDGPU::S_CMP_GT_U32:
8451 case AMDGPU::S_CMP_GE_U32:
8452 case AMDGPU::S_CMP_LT_U32:
8453 case AMDGPU::S_CMP_LE_U32:
8454 case AMDGPU::S_CMP_EQ_U64:
8455 case AMDGPU::S_CMP_LG_U64:
8456 case AMDGPU::S_CMP_LT_F32:
8457 case AMDGPU::S_CMP_EQ_F32:
8458 case AMDGPU::S_CMP_LE_F32:
8459 case AMDGPU::S_CMP_GT_F32:
8460 case AMDGPU::S_CMP_LG_F32:
8461 case AMDGPU::S_CMP_GE_F32:
8462 case AMDGPU::S_CMP_O_F32:
8463 case AMDGPU::S_CMP_U_F32:
8464 case AMDGPU::S_CMP_NGE_F32:
8465 case AMDGPU::S_CMP_NLG_F32:
8466 case AMDGPU::S_CMP_NGT_F32:
8467 case AMDGPU::S_CMP_NLE_F32:
8468 case AMDGPU::S_CMP_NEQ_F32:
8469 case AMDGPU::S_CMP_NLT_F32: {
8474 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8488 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8492 case AMDGPU::S_CMP_LT_F16:
8493 case AMDGPU::S_CMP_EQ_F16:
8494 case AMDGPU::S_CMP_LE_F16:
8495 case AMDGPU::S_CMP_GT_F16:
8496 case AMDGPU::S_CMP_LG_F16:
8497 case AMDGPU::S_CMP_GE_F16:
8498 case AMDGPU::S_CMP_O_F16:
8499 case AMDGPU::S_CMP_U_F16:
8500 case AMDGPU::S_CMP_NGE_F16:
8501 case AMDGPU::S_CMP_NLG_F16:
8502 case AMDGPU::S_CMP_NGT_F16:
8503 case AMDGPU::S_CMP_NLE_F16:
8504 case AMDGPU::S_CMP_NEQ_F16:
8505 case AMDGPU::S_CMP_NLT_F16: {
8527 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8531 case AMDGPU::S_CVT_HI_F32_F16: {
8534 if (ST.useRealTrue16Insts()) {
8539 .
addReg(TmpReg, {}, AMDGPU::hi16)
8555 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8559 case AMDGPU::S_MINIMUM_F32:
8560 case AMDGPU::S_MAXIMUM_F32: {
8572 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8576 case AMDGPU::S_MINIMUM_F16:
8577 case AMDGPU::S_MAXIMUM_F16: {
8579 ? &AMDGPU::VGPR_16RegClass
8580 : &AMDGPU::VGPR_32RegClass);
8591 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8595 case AMDGPU::V_S_EXP_F16_e64:
8596 case AMDGPU::V_S_LOG_F16_e64:
8597 case AMDGPU::V_S_RCP_F16_e64:
8598 case AMDGPU::V_S_RSQ_F16_e64:
8599 case AMDGPU::V_S_SQRT_F16_e64: {
8601 ? &AMDGPU::VGPR_16RegClass
8602 : &AMDGPU::VGPR_32RegClass);
8613 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8619 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8627 if (NewOpcode == Opcode) {
8634 V2SPhyCopiesToErase);
8642 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8649 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8654 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8655 UseMO.setReg(NewDstReg);
8672 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8685 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8689 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8695 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8702 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8704 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8709 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8717 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8727 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8728 AMDGPU::OpName::src0_modifiers) >= 0)
8732 NewInstr->addOperand(Src);
8735 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8738 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8740 NewInstr.addImm(
Size);
8741 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8745 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8750 "Scalar BFE is only implemented for constant width and offset");
8758 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8759 AMDGPU::OpName::src1_modifiers) >= 0)
8761 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8763 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8764 AMDGPU::OpName::src2_modifiers) >= 0)
8766 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8768 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8770 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8772 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8778 NewInstr->addOperand(
Op);
8785 if (
Op.getReg() == AMDGPU::SCC) {
8787 if (
Op.isDef() && !
Op.isDead())
8788 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8790 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8795 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8796 Register DstReg = NewInstr->getOperand(0).getReg();
8809 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8813std::pair<bool, MachineBasicBlock *>
8816 if (ST.hasAddNoCarryInsts()) {
8828 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8830 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8831 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8842 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8843 return std::pair(
true, NewBB);
8846 return std::pair(
false,
nullptr);
8863 bool IsSCC = (CondReg == AMDGPU::SCC);
8871 for (MachineOperand &UseMO :
8873 MachineInstr &
UseMI = *UseMO.getParent();
8874 switch (
UseMI.getOpcode()) {
8875 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8876 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8877 case AMDGPU::V_CNDMASK_B16_t16_e32:
8878 case AMDGPU::V_CNDMASK_B16_t16_e64:
8879 case AMDGPU::V_CNDMASK_B32_e32:
8880 case AMDGPU::V_CNDMASK_B32_e64:
8881 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8882 if (UseMO.isImplicit() ||
8884 UseMO.setReg(CondReg);
8898 bool CopyFound =
false;
8899 for (MachineInstr &CandI :
8902 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8904 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8906 .
addReg(CandI.getOperand(1).getReg());
8918 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8927 MachineInstr *NewInst;
8928 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
8929 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8944 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8959 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8960 : AMDGPU::V_SUB_CO_U32_e32;
8971 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8988 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8989 : AMDGPU::V_SUB_CO_U32_e32;
9002 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9016 if (ST.hasDLInsts()) {
9026 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9032 bool Src0IsSGPR = Src0.
isReg() &&
9034 bool Src1IsSGPR = Src1.
isReg() &&
9048 }
else if (Src1IsSGPR) {
9066 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9072 unsigned Opcode)
const {
9096 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9101 unsigned Opcode)
const {
9125 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9140 const MCInstrDesc &InstDesc =
get(Opcode);
9143 &AMDGPU::SGPR_32RegClass;
9146 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9149 AMDGPU::sub0, Src0SubRC);
9154 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9157 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9160 AMDGPU::sub1, Src0SubRC);
9163 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9177 Worklist.
insert(&LoHalf);
9178 Worklist.
insert(&HiHalf);
9184 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9208 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9209 if (RI.isSGPRClass(Src0SubRC))
9210 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9212 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9213 if (RI.isSGPRClass(Src1SubRC))
9214 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9218 MachineOperand Op0L =
9220 MachineOperand Op1L =
9222 MachineOperand Op0H =
9224 MachineOperand Op1H =
9243 MachineInstr *Op1L_Op0H =
9249 MachineInstr *Op1H_Op0L =
9255 MachineInstr *Carry =
9260 MachineInstr *LoHalf =
9270 MachineInstr *HiHalf =
9293 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9317 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9318 if (RI.isSGPRClass(Src0SubRC))
9319 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9321 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9322 if (RI.isSGPRClass(Src1SubRC))
9323 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9327 MachineOperand Op0L =
9329 MachineOperand Op1L =
9333 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9334 ? AMDGPU::V_MUL_HI_U32_e64
9335 : AMDGPU::V_MUL_HI_I32_e64;
9336 MachineInstr *HiHalf =
9339 MachineInstr *LoHalf =
9358 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9374 const MCInstrDesc &InstDesc =
get(Opcode);
9377 &AMDGPU::SGPR_32RegClass;
9380 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9383 &AMDGPU::SGPR_32RegClass;
9386 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9389 AMDGPU::sub0, Src0SubRC);
9391 AMDGPU::sub0, Src1SubRC);
9393 AMDGPU::sub1, Src0SubRC);
9395 AMDGPU::sub1, Src1SubRC);
9400 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9403 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9408 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9421 Worklist.
insert(&LoHalf);
9422 Worklist.
insert(&HiHalf);
9425 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9445 MachineOperand* Op0;
9446 MachineOperand* Op1;
9448 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9481 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9484 &AMDGPU::SGPR_32RegClass;
9490 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9493 AMDGPU::sub0, SrcSubRC);
9495 AMDGPU::sub1, SrcSubRC);
9505 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9524 Offset == 0 &&
"Not implemented");
9547 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9557 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9560 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9566 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9585 const MCInstrDesc &InstDesc =
get(Opcode);
9587 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9588 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9589 : AMDGPU::V_ADD_CO_U32_e32;
9592 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9594 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9596 MachineOperand SrcRegSub0 =
9598 MachineOperand SrcRegSub1 =
9611 .
addReg(IsCtlz ? MidReg1 : MidReg2)
9617 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9621 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9624void SIInstrInfo::addUsersToMoveToVALUWorklist(
9628 MachineInstr &
UseMI = *MO.getParent();
9632 switch (
UseMI.getOpcode()) {
9635 case AMDGPU::SOFT_WQM:
9636 case AMDGPU::STRICT_WWM:
9637 case AMDGPU::STRICT_WQM:
9638 case AMDGPU::REG_SEQUENCE:
9640 case AMDGPU::INSERT_SUBREG:
9643 OpNo = MO.getOperandNo();
9650 if (!RI.hasVectorRegisters(OpRC))
9667 if (ST.useRealTrue16Insts()) {
9669 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9672 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9678 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9681 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9690 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9692 case AMDGPU::S_PACK_LL_B32_B16:
9694 .addReg(SrcReg0, {},
9695 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9696 .addImm(AMDGPU::lo16)
9697 .addReg(SrcReg1, {},
9698 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9699 .addImm(AMDGPU::hi16);
9701 case AMDGPU::S_PACK_LH_B32_B16:
9703 .addReg(SrcReg0, {},
9704 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9705 .addImm(AMDGPU::lo16)
9706 .addReg(SrcReg1, {}, AMDGPU::hi16)
9707 .addImm(AMDGPU::hi16);
9709 case AMDGPU::S_PACK_HL_B32_B16:
9710 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9711 .addImm(AMDGPU::lo16)
9712 .addReg(SrcReg1, {},
9713 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9714 .addImm(AMDGPU::hi16);
9716 case AMDGPU::S_PACK_HH_B32_B16:
9717 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9718 .addImm(AMDGPU::lo16)
9719 .addReg(SrcReg1, {}, AMDGPU::hi16)
9720 .addImm(AMDGPU::hi16);
9728 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9733 case AMDGPU::S_PACK_LL_B32_B16: {
9752 case AMDGPU::S_PACK_LH_B32_B16: {
9762 case AMDGPU::S_PACK_HL_B32_B16: {
9773 case AMDGPU::S_PACK_HH_B32_B16: {
9793 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9802 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9803 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9804 SmallVector<MachineInstr *, 4> CopyToDelete;
9807 for (MachineInstr &
MI :
9811 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9814 MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9815 Register DestReg =
MI.getOperand(0).getReg();
9822 MI.getOperand(SCCIdx).setReg(NewCond);
9828 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9831 for (
auto &Copy : CopyToDelete)
9832 Copy->eraseFromParent();
9840void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9846 for (MachineInstr &
MI :
9849 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9851 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9868 case AMDGPU::REG_SEQUENCE:
9869 case AMDGPU::INSERT_SUBREG:
9871 case AMDGPU::SOFT_WQM:
9872 case AMDGPU::STRICT_WWM:
9873 case AMDGPU::STRICT_WQM: {
9875 if (RI.isAGPRClass(SrcRC)) {
9876 if (RI.isAGPRClass(NewDstRC))
9881 case AMDGPU::REG_SEQUENCE:
9882 case AMDGPU::INSERT_SUBREG:
9883 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9886 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9892 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9895 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9909 int OpIndices[3])
const {
9910 const MCInstrDesc &
Desc =
MI.getDesc();
9926 const MachineRegisterInfo &MRI =
MI.getMF()->getRegInfo();
9928 for (
unsigned i = 0; i < 3; ++i) {
9929 int Idx = OpIndices[i];
9933 const MachineOperand &MO =
MI.getOperand(Idx);
9940 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
9941 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9948 if (RI.isSGPRClass(RegRC))
9966 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9967 SGPRReg = UsedSGPRs[0];
9970 if (!SGPRReg && UsedSGPRs[1]) {
9971 if (UsedSGPRs[1] == UsedSGPRs[2])
9972 SGPRReg = UsedSGPRs[1];
9979 AMDGPU::OpName OperandName)
const {
9980 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9983 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
9987 return &
MI.getOperand(Idx);
10001 if (ST.isAmdHsaOS()) {
10004 RsrcDataFormat |= (1ULL << 56);
10009 RsrcDataFormat |= (2ULL << 59);
10012 return RsrcDataFormat;
10022 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10027 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10034 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10040 unsigned Opc =
MI.getOpcode();
10046 return get(
Opc).mayLoad() &&
10053 if (!Addr || !Addr->
isFI())
10062 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10064 return MI.getOperand(VDataIdx).getReg();
10074 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10076 return MI.getOperand(DataIdx).getReg();
10097 if (!
MI.mayStore())
10110 unsigned Opc =
MI.getOpcode();
10112 unsigned DescSize =
Desc.getSize();
10117 unsigned Size = DescSize;
10121 if (
MI.isBranch() && ST.hasOffset3fBug())
10132 bool HasLiteral =
false;
10133 unsigned LiteralSize = 4;
10134 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10139 if (ST.has64BitLiterals()) {
10140 switch (OpInfo.OperandType) {
10165 return HasLiteral ? DescSize + LiteralSize : DescSize;
10170 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10174 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10175 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10179 case TargetOpcode::BUNDLE:
10180 return getInstBundleSize(
MI);
10181 case TargetOpcode::INLINEASM:
10182 case TargetOpcode::INLINEASM_BR: {
10184 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10188 if (
MI.isMetaInstruction())
10192 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10195 unsigned LoInstOpcode = D16Info->LoOp;
10197 DescSize =
Desc.getSize();
10201 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10204 DescSize =
Desc.getSize();
10213 if (
MI.isBranch() && ST.hasOffset3fBug())
10214 return InstSizeVerifyMode::NoVerify;
10215 return InstSizeVerifyMode::ExactSize;
10222 if (
MI.memoperands_empty())
10234 static const std::pair<int, const char *> TargetIndices[] = {
10274std::pair<unsigned, unsigned>
10281 static const std::pair<unsigned, const char *> TargetFlags[] = {
10299 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10315 return AMDGPU::WWM_COPY;
10317 return AMDGPU::COPY;
10334 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10338 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10339 return IsLRSplitInst;
10352 bool IsNullOrVectorRegister =
true;
10356 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10359 return IsNullOrVectorRegister &&
10361 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10362 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10370 if (ST.hasAddNoCarryInsts())
10386 if (ST.hasAddNoCarryInsts())
10390 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10392 : RS.scavengeRegisterBackwards(
10393 *RI.getBoolRC(),
I,
false,
10406 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10407 case AMDGPU::SI_KILL_I1_TERMINATOR:
10416 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10417 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10418 case AMDGPU::SI_KILL_I1_PSEUDO:
10419 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10431 const unsigned OffsetBits =
10433 return (1 << OffsetBits) - 1;
10437 if (!ST.isWave32())
10440 if (
MI.isInlineAsm())
10443 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10446 for (
auto &
Op :
MI.implicit_operands()) {
10447 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10448 Op.setReg(AMDGPU::VCC_LO);
10457 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10461 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10462 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10478 if (Imm > MaxImm) {
10479 if (Imm <= MaxImm + 64) {
10481 Overflow = Imm - MaxImm;
10500 if (Overflow > 0) {
10508 if (ST.hasRestrictedSOffset())
10513 SOffset = Overflow;
10551 if (!ST.hasFlatInstOffsets())
10555 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10560 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10561 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10572std::pair<int64_t, int64_t>
10575 int64_t RemainderOffset = COffsetVal;
10576 int64_t ImmField = 0;
10581 if (AllowNegative) {
10583 int64_t
D = 1LL << NumBits;
10584 RemainderOffset = (COffsetVal /
D) *
D;
10585 ImmField = COffsetVal - RemainderOffset;
10587 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10589 (ImmField % 4) != 0) {
10591 RemainderOffset += ImmField % 4;
10592 ImmField -= ImmField % 4;
10594 }
else if (COffsetVal >= 0) {
10596 RemainderOffset = COffsetVal - ImmField;
10600 assert(RemainderOffset + ImmField == COffsetVal);
10601 return {ImmField, RemainderOffset};
10606 if (ST.hasNegativeScratchOffsetBug() &&
10614 switch (ST.getGeneration()) {
10643 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10644 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10645 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10646 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10647 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10648 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10649 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10650 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10657#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10658 case OPCODE##_dpp: \
10659 case OPCODE##_e32: \
10660 case OPCODE##_e64: \
10661 case OPCODE##_e64_dpp: \
10662 case OPCODE##_sdwa:
10676 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10677 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10678 case AMDGPU::V_FMA_F16_gfx9_e64:
10679 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10680 case AMDGPU::V_INTERP_P2_F16:
10681 case AMDGPU::V_MAD_F16_e64:
10682 case AMDGPU::V_MAD_U16_e64:
10683 case AMDGPU::V_MAD_I16_e64:
10692 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10706 switch (ST.getGeneration()) {
10719 if (
isMAI(Opcode)) {
10727 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10730 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10737 if (ST.hasGFX90AInsts()) {
10738 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10739 if (ST.hasGFX940Insts())
10741 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10743 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10745 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10751 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10770 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10771 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10772 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10784 switch (
MI.getOpcode()) {
10786 case AMDGPU::REG_SEQUENCE:
10790 case AMDGPU::INSERT_SUBREG:
10791 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10808 if (!
P.Reg.isVirtual())
10813 while (
auto *
MI = DefInst) {
10815 switch (
MI->getOpcode()) {
10817 case AMDGPU::V_MOV_B32_e32: {
10818 auto &Op1 =
MI->getOperand(1);
10847 auto *DefBB =
DefMI.getParent();
10851 if (
UseMI.getParent() != DefBB)
10854 const int MaxInstScan = 20;
10858 auto E =
UseMI.getIterator();
10859 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10860 if (
I->isDebugInstr())
10863 if (++NumInst > MaxInstScan)
10866 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10879 auto *DefBB =
DefMI.getParent();
10881 const int MaxUseScan = 10;
10885 auto &UseInst = *
Use.getParent();
10888 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10891 if (++NumUse > MaxUseScan)
10898 const int MaxInstScan = 20;
10902 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10905 if (
I->isDebugInstr())
10908 if (++NumInst > MaxInstScan)
10921 if (Reg == VReg && --NumUse == 0)
10923 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
10932 auto Cur =
MBB.begin();
10933 if (Cur !=
MBB.end())
10935 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
10938 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
10947 if (InsPt !=
MBB.end() &&
10948 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10949 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10950 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10951 InsPt->definesRegister(Src,
nullptr)) {
10955 .
addReg(Src, {}, SrcSubReg)
10998 if (isFullCopyInstr(
MI)) {
10999 Register DstReg =
MI.getOperand(0).getReg();
11000 Register SrcReg =
MI.getOperand(1).getReg();
11022 unsigned *PredCost)
const {
11023 if (
MI.isBundle()) {
11026 unsigned Lat = 0,
Count = 0;
11027 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11029 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11031 return Lat +
Count - 1;
11034 return SchedModel.computeInstrLatency(&
MI);
11041 return *CallAddrOp;
11048 unsigned Opcode =
MI.getOpcode();
11050 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11053 :
MI.getOperand(1).getReg();
11057 unsigned SrcAS = SrcTy.getAddressSpace();
11060 ST.hasGloballyAddressableScratch()
11068 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11069 return HandleAddrSpaceCast(
MI);
11072 auto IID = GI->getIntrinsicID();
11079 case Intrinsic::amdgcn_addrspacecast_nonnull:
11080 return HandleAddrSpaceCast(
MI);
11081 case Intrinsic::amdgcn_if:
11082 case Intrinsic::amdgcn_else:
11096 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11097 Opcode == AMDGPU::G_SEXTLOAD) {
11098 if (
MI.memoperands_empty())
11102 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11103 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11111 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11112 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11113 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11119 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11122 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11130 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11131 return Formatter.get();
11139 unsigned opcode =
MI.getOpcode();
11140 if (opcode == AMDGPU::V_READLANE_B32 ||
11141 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11142 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11147 if (
MI.isInlineAsm()) {
11153 if (!RC || !RI.isSGPRClass(RC))
11158 if (isCopyInstr(
MI)) {
11162 RI.getPhysRegBaseClass(srcOp.
getReg());
11170 if (
MI.isPreISelOpcode())
11185 if (
MI.memoperands_empty())
11189 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11190 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11205 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11207 if (!
SrcOp.isReg())
11211 if (!Reg || !
SrcOp.readsReg())
11217 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11244 F,
"ds_ordered_count unsupported for this calling conv"));
11258 Register &SrcReg2, int64_t &CmpMask,
11259 int64_t &CmpValue)
const {
11260 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11263 switch (
MI.getOpcode()) {
11266 case AMDGPU::S_CMP_EQ_U32:
11267 case AMDGPU::S_CMP_EQ_I32:
11268 case AMDGPU::S_CMP_LG_U32:
11269 case AMDGPU::S_CMP_LG_I32:
11270 case AMDGPU::S_CMP_LT_U32:
11271 case AMDGPU::S_CMP_LT_I32:
11272 case AMDGPU::S_CMP_GT_U32:
11273 case AMDGPU::S_CMP_GT_I32:
11274 case AMDGPU::S_CMP_LE_U32:
11275 case AMDGPU::S_CMP_LE_I32:
11276 case AMDGPU::S_CMP_GE_U32:
11277 case AMDGPU::S_CMP_GE_I32:
11278 case AMDGPU::S_CMP_EQ_U64:
11279 case AMDGPU::S_CMP_LG_U64:
11280 SrcReg =
MI.getOperand(0).getReg();
11281 if (
MI.getOperand(1).isReg()) {
11282 if (
MI.getOperand(1).getSubReg())
11284 SrcReg2 =
MI.getOperand(1).getReg();
11286 }
else if (
MI.getOperand(1).isImm()) {
11288 CmpValue =
MI.getOperand(1).getImm();
11294 case AMDGPU::S_CMPK_EQ_U32:
11295 case AMDGPU::S_CMPK_EQ_I32:
11296 case AMDGPU::S_CMPK_LG_U32:
11297 case AMDGPU::S_CMPK_LG_I32:
11298 case AMDGPU::S_CMPK_LT_U32:
11299 case AMDGPU::S_CMPK_LT_I32:
11300 case AMDGPU::S_CMPK_GT_U32:
11301 case AMDGPU::S_CMPK_GT_I32:
11302 case AMDGPU::S_CMPK_LE_U32:
11303 case AMDGPU::S_CMPK_LE_I32:
11304 case AMDGPU::S_CMPK_GE_U32:
11305 case AMDGPU::S_CMPK_GE_I32:
11306 SrcReg =
MI.getOperand(0).getReg();
11308 CmpValue =
MI.getOperand(1).getImm();
11318 if (S->isLiveIn(AMDGPU::SCC))
11327bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11330 bool SCCIsDead =
false;
11333 constexpr unsigned ScanLimit = 12;
11334 unsigned Count = 0;
11335 for (MachineInstr &
MI :
11337 if (++
Count > ScanLimit)
11339 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11340 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11341 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11342 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11343 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11348 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11361 for (MachineInstr *
MI : InvertInstr) {
11362 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11363 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11365 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11366 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11367 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11368 ? AMDGPU::S_CBRANCH_SCC1
11369 : AMDGPU::S_CBRANCH_SCC0));
11382 bool NeedInversion)
const {
11383 MachineInstr *KillsSCC =
nullptr;
11388 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11390 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11393 if (NeedInversion && !invertSCCUse(SCCRedefine))
11395 if (MachineOperand *SccDef =
11397 SccDef->setIsDead(
false);
11405 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11406 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11408 bool Op1IsNonZeroImm =
11409 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11410 bool Op2IsZeroImm =
11411 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11412 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11418 unsigned &NewDefOpc) {
11421 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11422 Def.getOpcode() != AMDGPU::S_ADD_U32)
11428 if ((!AddSrc1.
isImm() || AddSrc1.
getImm() != 1) &&
11434 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11436 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11439 NewDefOpc = AMDGPU::S_ADD_U32;
11441 NeedInversion = !NeedInversion;
11446 Register SrcReg2, int64_t CmpMask,
11455 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11456 this](
bool NeedInversion) ->
bool {
11480 unsigned NewDefOpc = Def->getOpcode();
11486 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11489 if (NewDefOpc != Def->getOpcode())
11490 Def->setDesc(
get(NewDefOpc));
11499 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11506 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11514 optimizeSCC(
Select, Def,
false);
11521 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11522 this](int64_t ExpectedValue,
unsigned SrcSize,
11523 bool IsReversible,
bool IsSigned) ->
bool {
11551 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11552 Def->getOpcode() != AMDGPU::S_AND_B64)
11556 const auto isMask = [&Mask, SrcSize](
const MachineOperand *MO) ->
bool {
11567 SrcOp = &Def->getOperand(2);
11568 else if (isMask(&Def->getOperand(2)))
11569 SrcOp = &Def->getOperand(1);
11577 if (IsSigned && BitNo == SrcSize - 1)
11580 ExpectedValue <<= BitNo;
11582 bool IsReversedCC =
false;
11583 if (CmpValue != ExpectedValue) {
11586 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11591 Register DefReg = Def->getOperand(0).getReg();
11595 if (!optimizeSCC(Def, &CmpInstr,
false))
11606 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11607 : AMDGPU::S_BITCMP1_B32
11608 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11609 : AMDGPU::S_BITCMP1_B64;
11614 Def->eraseFromParent();
11622 case AMDGPU::S_CMP_EQ_U32:
11623 case AMDGPU::S_CMP_EQ_I32:
11624 case AMDGPU::S_CMPK_EQ_U32:
11625 case AMDGPU::S_CMPK_EQ_I32:
11626 return optimizeCmpAnd(1, 32,
true,
false) ||
11627 optimizeCmpSelect(
true);
11628 case AMDGPU::S_CMP_GE_U32:
11629 case AMDGPU::S_CMPK_GE_U32:
11630 return optimizeCmpAnd(1, 32,
false,
false);
11631 case AMDGPU::S_CMP_GE_I32:
11632 case AMDGPU::S_CMPK_GE_I32:
11633 return optimizeCmpAnd(1, 32,
false,
true);
11634 case AMDGPU::S_CMP_EQ_U64:
11635 return optimizeCmpAnd(1, 64,
true,
false);
11636 case AMDGPU::S_CMP_LG_U32:
11637 case AMDGPU::S_CMP_LG_I32:
11638 case AMDGPU::S_CMPK_LG_U32:
11639 case AMDGPU::S_CMPK_LG_I32:
11640 return optimizeCmpAnd(0, 32,
true,
false) ||
11641 optimizeCmpSelect(
false);
11642 case AMDGPU::S_CMP_GT_U32:
11643 case AMDGPU::S_CMPK_GT_U32:
11644 return optimizeCmpAnd(0, 32,
false,
false);
11645 case AMDGPU::S_CMP_GT_I32:
11646 case AMDGPU::S_CMPK_GT_I32:
11647 return optimizeCmpAnd(0, 32,
false,
true);
11648 case AMDGPU::S_CMP_LG_U64:
11649 return optimizeCmpAnd(0, 64,
true,
false) ||
11650 optimizeCmpSelect(
false);
11657 AMDGPU::OpName
OpName)
const {
11658 if (!ST.needsAlignedVGPRs())
11661 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11673 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11675 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11679 : &AMDGPU::VReg_64_Align2RegClass);
11681 .
addReg(DataReg, {},
Op.getSubReg())
11686 Op.setSubReg(AMDGPU::sub0);
11691 if (!SchedModel.hasInstrSchedModel())
11697 unsigned RepeatRate = 0;
11699 PI = SchedModel.getWriteProcResBegin(SCDesc),
11700 PE = SchedModel.getWriteProcResEnd(SCDesc);
11702 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11719 if (ST.hasGFX1250Insts())
11726 unsigned Opcode =
MI.getOpcode();
11732 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11733 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11736 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)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI, int64_t &Imm, MachineInstr **DefMI=nullptr)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const unsigned AndN2WrExecOpc
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned OrSaveExecOpc
const unsigned AndSaveExecOpc
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void setVariableValue(const MCExpr *Value)
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
bool isIgnorableUse(const MachineOperand &MO) const override
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
static bool isF16PseudoScalarTrans(unsigned Opcode)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Register getLongBranchReservedReg() const
bool isWholeWaveFunction() const
Register getStackPtrOffsetReg() const
unsigned getMaxMemoryClusterDWords() const
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool isD16Buf(const T &...O)
constexpr bool isSDWA(const T &...O)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
constexpr unsigned BitWidth
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
@ AlwaysUniform
The result value is always uniform.
@ NeverUniform
The result value can never be assumed to be uniform.
@ Default
The result value is uniform if and only if all operands are uniform.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
constexpr bool all() const
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
MachineInstr * top() const
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.