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>
140 unsigned LoReloc, HiReloc;
170 return {BaseFlags, LoReloc, HiReloc};
188 if (!
MI.hasImplicitDef() &&
189 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
190 !
MI.mayRaiseFPException())
199 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
214 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
215 MI.hasUnmodeledSideEffects())
220 if (
MI.isInlineAsm())
224 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
239 if (Reg.isPhysical()) {
255 if (MO.isDef() && Reg != DefReg)
263bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
267 if (
MI.isConvergent())
295 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
300 for (
auto Op :
MI.uses()) {
301 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
315 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
335 int64_t &Offset1)
const {
343 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
347 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
363 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
364 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
365 if (Offset0Idx == -1 || Offset1Idx == -1)
372 Offset0Idx -=
get(Opc0).NumDefs;
373 Offset1Idx -=
get(Opc1).NumDefs;
403 if (!Load0Offset || !Load1Offset)
420 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
421 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
423 if (OffIdx0 == -1 || OffIdx1 == -1)
429 OffIdx0 -=
get(Opc0).NumDefs;
430 OffIdx1 -=
get(Opc1).NumDefs;
449 case AMDGPU::DS_READ2ST64_B32:
450 case AMDGPU::DS_READ2ST64_B64:
451 case AMDGPU::DS_WRITE2ST64_B32:
452 case AMDGPU::DS_WRITE2ST64_B64:
467 OffsetIsScalable =
false;
484 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
486 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
487 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
500 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
501 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
502 if (Offset0 + 1 != Offset1)
513 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
521 Offset = EltSize * Offset0;
523 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
524 if (DataOpIdx == -1) {
525 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
527 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
543 if (BaseOp && !BaseOp->
isFI())
551 if (SOffset->
isReg())
557 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
559 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
568 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
569 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
571 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
572 if (VAddr0Idx >= 0) {
574 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
581 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
596 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
613 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
615 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
632 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
640 if (MO1->getAddrSpace() != MO2->getAddrSpace())
643 const auto *Base1 = MO1->getValue();
644 const auto *Base2 = MO2->getValue();
645 if (!Base1 || !Base2)
653 return Base1 == Base2;
657 int64_t Offset1,
bool OffsetIsScalable1,
659 int64_t Offset2,
bool OffsetIsScalable2,
660 unsigned ClusterSize,
661 unsigned NumBytes)
const {
674 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
693 const unsigned LoadSize = NumBytes / ClusterSize;
694 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
695 return NumDWords <= MaxMemoryClusterDWords;
709 int64_t Offset0, int64_t Offset1,
710 unsigned NumLoads)
const {
711 assert(Offset1 > Offset0 &&
712 "Second offset should be larger than first offset!");
717 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
724 const char *
Msg =
"illegal VGPR to SGPR copy") {
743 assert((
TII.getSubtarget().hasMAIInsts() &&
744 !
TII.getSubtarget().hasGFX90AInsts()) &&
745 "Expected GFX908 subtarget.");
748 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
749 "Source register of the copy should be either an SGPR or an AGPR.");
752 "Destination register of the copy should be an AGPR.");
761 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
764 if (!Def->modifiesRegister(SrcReg, &RI))
767 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
768 Def->getOperand(0).getReg() != SrcReg)
775 bool SafeToPropagate =
true;
778 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
779 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
780 SafeToPropagate =
false;
782 if (!SafeToPropagate)
785 for (
auto I = Def;
I !=
MI; ++
I)
786 I->clearRegisterKills(DefOp.
getReg(), &RI);
794 if (ImpUseSuperReg) {
795 Builder.addReg(ImpUseSuperReg,
803 RS.enterBasicBlockEnd(
MBB);
804 RS.backward(std::next(
MI));
813 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
816 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
817 "VGPR used for an intermediate copy should have been reserved.");
822 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
832 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
833 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
834 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
841 if (ImpUseSuperReg) {
842 UseBuilder.
addReg(ImpUseSuperReg,
859 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
860 int16_t SubIdx = BaseIndices[Idx];
861 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
862 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
863 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
864 unsigned Opcode = AMDGPU::S_MOV_B32;
867 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
868 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
869 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
873 DestSubReg = RI.getSubReg(DestReg, SubIdx);
874 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
875 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
876 Opcode = AMDGPU::S_MOV_B64;
891 assert(FirstMI && LastMI);
896 LastMI->addRegisterKilled(SrcReg, &RI);
902 Register SrcReg,
bool KillSrc,
bool RenamableDest,
903 bool RenamableSrc)
const {
905 unsigned Size = RI.getRegSizeInBits(*RC);
907 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
913 if (((
Size == 16) != (SrcSize == 16))) {
915 assert(ST.useRealTrue16Insts());
917 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
920 if (DestReg == SrcReg) {
926 RC = RI.getPhysRegBaseClass(DestReg);
927 Size = RI.getRegSizeInBits(*RC);
928 SrcRC = RI.getPhysRegBaseClass(SrcReg);
929 SrcSize = RI.getRegSizeInBits(*SrcRC);
933 if (RC == &AMDGPU::VGPR_32RegClass) {
935 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
936 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
937 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
938 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
944 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
945 RC == &AMDGPU::SReg_32RegClass) {
946 if (SrcReg == AMDGPU::SCC) {
953 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
954 if (DestReg == AMDGPU::VCC_LO) {
972 if (RC == &AMDGPU::SReg_64RegClass) {
973 if (SrcReg == AMDGPU::SCC) {
980 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
981 if (DestReg == AMDGPU::VCC) {
999 if (DestReg == AMDGPU::SCC) {
1002 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1006 assert(ST.hasScalarCompareEq64());
1020 if (RC == &AMDGPU::AGPR_32RegClass) {
1021 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1022 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1028 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1037 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1044 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1045 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1047 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1048 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1049 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1050 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1053 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1054 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1067 if (IsAGPRDst || IsAGPRSrc) {
1068 if (!DstLow || !SrcLow) {
1070 "Cannot use hi16 subreg with an AGPR!");
1077 if (ST.useRealTrue16Insts()) {
1083 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1084 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1096 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1097 if (!DstLow || !SrcLow) {
1099 "Cannot use hi16 subreg on VI!");
1122 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1123 if (ST.hasVMovB64Inst()) {
1128 if (ST.hasPkMovB32()) {
1144 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1145 if (RI.isSGPRClass(RC)) {
1146 if (!RI.isSGPRClass(SrcRC)) {
1150 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1156 unsigned EltSize = 4;
1157 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1158 if (RI.isAGPRClass(RC)) {
1159 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1160 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1161 else if (RI.hasVGPRs(SrcRC) ||
1162 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1163 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1165 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1166 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1167 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1168 }
else if ((
Size % 64 == 0) && RI.hasVGPRs(RC) &&
1169 (RI.isProperlyAlignedRC(*RC) &&
1170 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1172 if (ST.hasVMovB64Inst()) {
1173 Opcode = AMDGPU::V_MOV_B64_e32;
1175 }
else if (ST.hasPkMovB32()) {
1176 Opcode = AMDGPU::V_PK_MOV_B32;
1186 std::unique_ptr<RegScavenger> RS;
1187 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1188 RS = std::make_unique<RegScavenger>();
1194 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1195 const bool CanKillSuperReg = KillSrc && !Overlap;
1197 for (
unsigned Idx = 0; Idx < SubIndices.
size(); ++Idx) {
1200 SubIdx = SubIndices[Idx];
1202 SubIdx = SubIndices[SubIndices.
size() - Idx - 1];
1203 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1204 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1205 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1207 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size() - 1;
1209 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1212 *RS, Overlap, ImpUseSuper);
1213 }
else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1254 int64_t &ImmVal)
const {
1255 switch (
MI.getOpcode()) {
1256 case AMDGPU::V_MOV_B32_e32:
1257 case AMDGPU::S_MOV_B32:
1258 case AMDGPU::S_MOVK_I32:
1259 case AMDGPU::S_MOV_B64:
1260 case AMDGPU::V_MOV_B64_e32:
1261 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1262 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1263 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1264 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1265 case AMDGPU::V_MOV_B64_PSEUDO:
1266 case AMDGPU::V_MOV_B16_t16_e32: {
1270 return MI.getOperand(0).getReg() == Reg;
1275 case AMDGPU::V_MOV_B16_t16_e64: {
1277 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1279 return MI.getOperand(0).getReg() == Reg;
1284 case AMDGPU::S_BREV_B32:
1285 case AMDGPU::V_BFREV_B32_e32:
1286 case AMDGPU::V_BFREV_B32_e64: {
1290 return MI.getOperand(0).getReg() == Reg;
1295 case AMDGPU::S_NOT_B32:
1296 case AMDGPU::V_NOT_B32_e32:
1297 case AMDGPU::V_NOT_B32_e64: {
1300 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1301 return MI.getOperand(0).getReg() == Reg;
1311std::optional<int64_t>
1316 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1317 return std::nullopt;
1320 if (Def && Def->isMoveImmediate()) {
1326 return std::nullopt;
1331 if (RI.isAGPRClass(DstRC))
1332 return AMDGPU::COPY;
1333 if (RI.getRegSizeInBits(*DstRC) == 16) {
1336 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1338 if (RI.getRegSizeInBits(*DstRC) == 32)
1339 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1340 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1341 return AMDGPU::S_MOV_B64;
1342 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1343 return AMDGPU::V_MOV_B64_PSEUDO;
1344 return AMDGPU::COPY;
1349 bool IsIndirectSrc)
const {
1350 if (IsIndirectSrc) {
1352 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1354 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1356 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1358 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1360 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1362 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1364 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1368 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1370 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1372 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1374 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1376 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1377 if (VecSize <= 1024)
1378 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1384 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1386 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1388 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1390 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1392 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1394 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1396 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1400 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1402 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1404 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1406 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1408 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1409 if (VecSize <= 1024)
1410 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1417 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1419 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1421 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1423 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1425 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1427 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1429 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1433 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1435 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1437 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1439 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1441 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1442 if (VecSize <= 1024)
1443 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1450 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1452 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1454 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1456 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1458 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1460 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1462 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1466 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1468 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1470 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1472 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1474 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1475 if (VecSize <= 1024)
1476 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1483 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1485 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1487 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1489 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1490 if (VecSize <= 1024)
1491 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1498 bool IsSGPR)
const {
1510 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1517 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1519 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1521 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1523 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1524 : AMDGPU::SI_SPILL_S128_SAVE;
1526 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1527 : AMDGPU::SI_SPILL_S160_SAVE;
1529 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1530 : AMDGPU::SI_SPILL_S192_SAVE;
1532 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1533 : AMDGPU::SI_SPILL_S224_SAVE;
1535 return AMDGPU::SI_SPILL_S256_SAVE;
1537 return AMDGPU::SI_SPILL_S288_SAVE;
1539 return AMDGPU::SI_SPILL_S320_SAVE;
1541 return AMDGPU::SI_SPILL_S352_SAVE;
1543 return AMDGPU::SI_SPILL_S384_SAVE;
1545 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1546 : AMDGPU::SI_SPILL_S512_SAVE;
1548 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1549 : AMDGPU::SI_SPILL_S1024_SAVE;
1558 return AMDGPU::SI_SPILL_V16_SAVE;
1560 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1562 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1564 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1566 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1567 : AMDGPU::SI_SPILL_V128_SAVE;
1569 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1570 : AMDGPU::SI_SPILL_V160_SAVE;
1572 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1573 : AMDGPU::SI_SPILL_V192_SAVE;
1575 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1576 : AMDGPU::SI_SPILL_V224_SAVE;
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1579 : AMDGPU::SI_SPILL_V256_SAVE;
1581 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1582 : AMDGPU::SI_SPILL_V288_SAVE;
1584 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1585 : AMDGPU::SI_SPILL_V320_SAVE;
1587 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1588 : AMDGPU::SI_SPILL_V352_SAVE;
1590 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1591 : AMDGPU::SI_SPILL_V384_SAVE;
1593 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1594 : AMDGPU::SI_SPILL_V512_SAVE;
1596 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1597 : AMDGPU::SI_SPILL_V1024_SAVE;
1606 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1607 : AMDGPU::SI_SPILL_AV32_SAVE;
1609 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1610 : AMDGPU::SI_SPILL_AV64_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1613 : AMDGPU::SI_SPILL_AV96_SAVE;
1615 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1616 : AMDGPU::SI_SPILL_AV128_SAVE;
1618 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1619 : AMDGPU::SI_SPILL_AV160_SAVE;
1621 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1622 : AMDGPU::SI_SPILL_AV192_SAVE;
1624 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1625 : AMDGPU::SI_SPILL_AV224_SAVE;
1627 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1628 : AMDGPU::SI_SPILL_AV256_SAVE;
1630 return AMDGPU::SI_SPILL_AV288_SAVE;
1632 return AMDGPU::SI_SPILL_AV320_SAVE;
1634 return AMDGPU::SI_SPILL_AV352_SAVE;
1636 return AMDGPU::SI_SPILL_AV384_SAVE;
1638 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1639 : AMDGPU::SI_SPILL_AV512_SAVE;
1641 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1642 : AMDGPU::SI_SPILL_AV1024_SAVE;
1649 bool IsVectorSuperClass) {
1654 if (IsVectorSuperClass)
1655 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1657 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1663 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1670 if (ST.hasMAIInsts())
1676void SIInstrInfo::storeRegToStackSlotImpl(
1689 FrameInfo.getObjectAlign(FrameIndex));
1690 unsigned SpillSize = RI.getSpillSize(*RC);
1696 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1697 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1698 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1707 if (SrcReg.
isVirtual() && SpillSize == 4) {
1721 SpillSize, *MFI, NeedsCFI);
1736 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1745 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1752 return AMDGPU::SI_SPILL_S32_RESTORE;
1754 return AMDGPU::SI_SPILL_S64_RESTORE;
1756 return AMDGPU::SI_SPILL_S96_RESTORE;
1758 return AMDGPU::SI_SPILL_S128_RESTORE;
1760 return AMDGPU::SI_SPILL_S160_RESTORE;
1762 return AMDGPU::SI_SPILL_S192_RESTORE;
1764 return AMDGPU::SI_SPILL_S224_RESTORE;
1766 return AMDGPU::SI_SPILL_S256_RESTORE;
1768 return AMDGPU::SI_SPILL_S288_RESTORE;
1770 return AMDGPU::SI_SPILL_S320_RESTORE;
1772 return AMDGPU::SI_SPILL_S352_RESTORE;
1774 return AMDGPU::SI_SPILL_S384_RESTORE;
1776 return AMDGPU::SI_SPILL_S512_RESTORE;
1778 return AMDGPU::SI_SPILL_S1024_RESTORE;
1787 return AMDGPU::SI_SPILL_V16_RESTORE;
1789 return AMDGPU::SI_SPILL_V32_RESTORE;
1791 return AMDGPU::SI_SPILL_V64_RESTORE;
1793 return AMDGPU::SI_SPILL_V96_RESTORE;
1795 return AMDGPU::SI_SPILL_V128_RESTORE;
1797 return AMDGPU::SI_SPILL_V160_RESTORE;
1799 return AMDGPU::SI_SPILL_V192_RESTORE;
1801 return AMDGPU::SI_SPILL_V224_RESTORE;
1803 return AMDGPU::SI_SPILL_V256_RESTORE;
1805 return AMDGPU::SI_SPILL_V288_RESTORE;
1807 return AMDGPU::SI_SPILL_V320_RESTORE;
1809 return AMDGPU::SI_SPILL_V352_RESTORE;
1811 return AMDGPU::SI_SPILL_V384_RESTORE;
1813 return AMDGPU::SI_SPILL_V512_RESTORE;
1815 return AMDGPU::SI_SPILL_V1024_RESTORE;
1824 return AMDGPU::SI_SPILL_AV32_RESTORE;
1826 return AMDGPU::SI_SPILL_AV64_RESTORE;
1828 return AMDGPU::SI_SPILL_AV96_RESTORE;
1830 return AMDGPU::SI_SPILL_AV128_RESTORE;
1832 return AMDGPU::SI_SPILL_AV160_RESTORE;
1834 return AMDGPU::SI_SPILL_AV192_RESTORE;
1836 return AMDGPU::SI_SPILL_AV224_RESTORE;
1838 return AMDGPU::SI_SPILL_AV256_RESTORE;
1840 return AMDGPU::SI_SPILL_AV288_RESTORE;
1842 return AMDGPU::SI_SPILL_AV320_RESTORE;
1844 return AMDGPU::SI_SPILL_AV352_RESTORE;
1846 return AMDGPU::SI_SPILL_AV384_RESTORE;
1848 return AMDGPU::SI_SPILL_AV512_RESTORE;
1850 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1857 bool IsVectorSuperClass) {
1862 if (IsVectorSuperClass)
1863 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1865 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1871 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1878 if (ST.hasMAIInsts())
1881 assert(!RI.isAGPRClass(RC));
1895 unsigned SpillSize = RI.getSpillSize(*RC);
1902 FrameInfo.getObjectAlign(FrameIndex));
1904 if (RI.isSGPRClass(RC)) {
1907 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1908 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1909 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1914 if (DestReg.
isVirtual() && SpillSize == 4) {
1943 unsigned Quantity)
const {
1945 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1946 while (Quantity > 0) {
1947 unsigned Arg = std::min(Quantity, MaxSNopCount);
1958 constexpr unsigned DoorbellIDMask = 0x3ff;
1959 constexpr unsigned ECQueueWaveAbort = 0x400;
1964 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1965 MBB.splitAt(
MI,
false);
1969 MBB.addSuccessor(TrapBB);
1979 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1983 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1988 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1989 .
addUse(DoorbellRegMasked)
1990 .
addImm(ECQueueWaveAbort);
1991 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1992 .
addUse(SetWaveAbortBit);
1995 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2006 return MBB.getNextNode();
2010 switch (
MI.getOpcode()) {
2012 if (
MI.isMetaInstruction())
2017 return MI.getOperand(0).getImm() + 1;
2028 switch (
MI.getOpcode()) {
2030 case AMDGPU::S_MOV_B64_term:
2033 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2036 case AMDGPU::S_MOV_B32_term:
2039 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2042 case AMDGPU::S_XOR_B64_term:
2045 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2048 case AMDGPU::S_XOR_B32_term:
2051 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2053 case AMDGPU::S_OR_B64_term:
2056 MI.setDesc(
get(AMDGPU::S_OR_B64));
2058 case AMDGPU::S_OR_B32_term:
2061 MI.setDesc(
get(AMDGPU::S_OR_B32));
2064 case AMDGPU::S_ANDN2_B64_term:
2067 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2070 case AMDGPU::S_ANDN2_B32_term:
2073 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2076 case AMDGPU::S_AND_B64_term:
2079 MI.setDesc(
get(AMDGPU::S_AND_B64));
2082 case AMDGPU::S_AND_B32_term:
2085 MI.setDesc(
get(AMDGPU::S_AND_B32));
2088 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2091 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2094 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2097 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2100 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2101 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2103 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2104 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2107 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2108 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2111 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2112 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2114 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2118 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2121 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2124 int64_t
Imm =
MI.getOperand(1).getImm();
2126 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2127 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2132 MI.eraseFromParent();
2138 case AMDGPU::V_MOV_B64_PSEUDO: {
2140 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2141 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2149 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2150 MI.setDesc(Mov64Desc);
2154 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2157 if (
SrcOp.isGlobal()) {
2162 unsigned BaseFlags, LoReloc, HiReloc;
2163 std::tie(BaseFlags, LoReloc, HiReloc) =
2170 }
else if (
SrcOp.isImm()) {
2172 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2173 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2197 if (ST.hasPkMovB32() &&
2216 MI.eraseFromParent();
2219 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2223 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2227 if (ST.has64BitLiterals()) {
2228 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2232 if (
SrcOp.isGlobal()) {
2234 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2235 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2238 unsigned BaseFlags, LoReloc, HiReloc;
2239 std::tie(BaseFlags, LoReloc, HiReloc) =
2246 MI.eraseFromParent();
2253 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2258 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2259 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2261 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2262 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2267 MI.eraseFromParent();
2270 case AMDGPU::V_SET_INACTIVE_B32: {
2274 .
add(
MI.getOperand(3))
2275 .
add(
MI.getOperand(4))
2276 .
add(
MI.getOperand(1))
2277 .
add(
MI.getOperand(2))
2278 .
add(
MI.getOperand(5));
2279 MI.eraseFromParent();
2282 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2283 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2284 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2285 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2286 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2287 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2288 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2289 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2290 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2291 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2292 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2293 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2294 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2295 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2296 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2297 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2298 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2299 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2300 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2301 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2302 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2303 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2304 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2305 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2306 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2307 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2308 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2309 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2310 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2311 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2312 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2313 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2314 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2318 if (RI.hasVGPRs(EltRC)) {
2319 Opc = AMDGPU::V_MOVRELD_B32_e32;
2321 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2322 : AMDGPU::S_MOVRELD_B32;
2327 bool IsUndef =
MI.getOperand(1).isUndef();
2328 unsigned SubReg =
MI.getOperand(3).getImm();
2329 assert(VecReg ==
MI.getOperand(1).getReg());
2334 .
add(
MI.getOperand(2))
2338 const int ImpDefIdx =
2340 const int ImpUseIdx = ImpDefIdx + 1;
2342 MI.eraseFromParent();
2345 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2346 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2347 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2348 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2349 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2350 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2351 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2352 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2353 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2354 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2355 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2356 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2357 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2358 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2359 assert(ST.useVGPRIndexMode());
2361 bool IsUndef =
MI.getOperand(1).isUndef();
2370 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2374 .
add(
MI.getOperand(2))
2378 const int ImpDefIdx =
2380 const int ImpUseIdx = ImpDefIdx + 1;
2387 MI.eraseFromParent();
2390 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2391 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2392 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2393 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2394 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2395 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2396 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2397 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2398 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2399 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2400 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2401 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2402 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2403 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2404 assert(ST.useVGPRIndexMode());
2407 bool IsUndef =
MI.getOperand(1).isUndef();
2411 .
add(
MI.getOperand(2))
2424 MI.eraseFromParent();
2427 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2430 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2431 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2450 if (ST.hasGetPCZeroExtension()) {
2454 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2461 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2471 MI.eraseFromParent();
2474 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2484 Op.setOffset(
Op.getOffset() + 4);
2486 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2490 MI.eraseFromParent();
2493 case AMDGPU::ENTER_STRICT_WWM: {
2499 case AMDGPU::ENTER_STRICT_WQM: {
2506 MI.eraseFromParent();
2509 case AMDGPU::EXIT_STRICT_WWM:
2510 case AMDGPU::EXIT_STRICT_WQM: {
2516 case AMDGPU::SI_RETURN: {
2530 MI.eraseFromParent();
2534 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2535 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2536 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2539 case AMDGPU::S_GETPC_B64_pseudo:
2540 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2541 if (ST.hasGetPCZeroExtension()) {
2543 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2552 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2553 assert(ST.hasBF16PackedInsts());
2554 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2565 case AMDGPU::GET_STACK_BASE:
2568 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2575 Register DestReg =
MI.getOperand(0).getReg();
2585 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2586 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2587 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2590 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2593 MI.getNumExplicitOperands());
2611 case AMDGPU::S_MOV_B64:
2612 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2621 if (UsedLanes.
all())
2626 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2627 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2629 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2630 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2632 if (NeedLo && NeedHi)
2636 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2638 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2647 case AMDGPU::S_LOAD_DWORDX16_IMM:
2648 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2661 for (
auto &CandMO :
I->operands()) {
2662 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2670 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2674 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2680 unsigned NewOpcode = -1;
2681 if (SubregSize == 256)
2682 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2683 else if (SubregSize == 128)
2684 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2694 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2699 MI->getOperand(0).setReg(DestReg);
2700 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2704 OffsetMO->
setImm(FinalOffset);
2710 MI->setMemRefs(*MF, NewMMOs);
2723std::pair<MachineInstr*, MachineInstr*>
2725 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2727 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2730 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2731 return std::pair(&
MI,
nullptr);
2742 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2744 if (Dst.isPhysical()) {
2745 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2752 for (
unsigned I = 1;
I <= 2; ++
I) {
2755 if (
SrcOp.isImm()) {
2757 Imm.ashrInPlace(Part * 32);
2758 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2762 if (Src.isPhysical())
2763 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2770 MovDPP.addImm(MO.getImm());
2772 Split[Part] = MovDPP;
2776 if (Dst.isVirtual())
2783 MI.eraseFromParent();
2784 return std::pair(Split[0], Split[1]);
2787std::optional<DestSourcePair>
2789 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2792 return std::nullopt;
2796 AMDGPU::OpName Src0OpName,
2798 AMDGPU::OpName Src1OpName)
const {
2805 "All commutable instructions have both src0 and src1 modifiers");
2807 int Src0ModsVal = Src0Mods->
getImm();
2808 int Src1ModsVal = Src1Mods->
getImm();
2810 Src1Mods->
setImm(Src0ModsVal);
2811 Src0Mods->
setImm(Src1ModsVal);
2820 bool IsKill = RegOp.
isKill();
2822 bool IsUndef = RegOp.
isUndef();
2823 bool IsDebug = RegOp.
isDebug();
2825 if (NonRegOp.
isImm())
2827 else if (NonRegOp.
isFI())
2848 int64_t NonRegVal = NonRegOp1.
getImm();
2851 NonRegOp2.
setImm(NonRegVal);
2858 unsigned OpIdx1)
const {
2863 unsigned Opc =
MI.getOpcode();
2864 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2874 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2877 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2882 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2888 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2903 unsigned Src1Idx)
const {
2904 assert(!NewMI &&
"this should never be used");
2906 unsigned Opc =
MI.getOpcode();
2908 if (CommutedOpcode == -1)
2911 if (Src0Idx > Src1Idx)
2914 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2915 static_cast<int>(Src0Idx) &&
2916 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2917 static_cast<int>(Src1Idx) &&
2918 "inconsistency with findCommutedOpIndices");
2943 Src1, AMDGPU::OpName::src1_modifiers);
2946 AMDGPU::OpName::src1_sel);
2958 unsigned &SrcOpIdx0,
2959 unsigned &SrcOpIdx1)
const {
2964 unsigned &SrcOpIdx0,
2965 unsigned &SrcOpIdx1)
const {
2966 if (!
Desc.isCommutable())
2969 unsigned Opc =
Desc.getOpcode();
2970 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2974 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2978 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2982 int64_t BrOffset)
const {
2999 return MI.getOperand(0).getMBB();
3004 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3005 MI.getOpcode() == AMDGPU::SI_LOOP)
3017 "new block should be inserted for expanding unconditional branch");
3020 "restore block should be inserted for restoring clobbered registers");
3028 if (ST.useAddPC64Inst()) {
3030 MCCtx.createTempSymbol(
"offset",
true);
3034 MCCtx.createTempSymbol(
"post_addpc",
true);
3035 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3039 Offset->setVariableValue(OffsetExpr);
3043 assert(RS &&
"RegScavenger required for long branching");
3051 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3052 ST.hasVALUReadSGPRHazard();
3053 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3054 if (FlushSGPRWrites)
3062 ApplyHazardWorkarounds();
3065 MCCtx.createTempSymbol(
"post_getpc",
true);
3069 MCCtx.createTempSymbol(
"offset_lo",
true);
3071 MCCtx.createTempSymbol(
"offset_hi",
true);
3074 .
addReg(PCReg, {}, AMDGPU::sub0)
3078 .
addReg(PCReg, {}, AMDGPU::sub1)
3080 ApplyHazardWorkarounds();
3121 if (LongBranchReservedReg) {
3122 RS->enterBasicBlock(
MBB);
3123 Scav = LongBranchReservedReg;
3125 RS->enterBasicBlockEnd(
MBB);
3126 Scav = RS->scavengeRegisterBackwards(
3131 RS->setRegUsed(Scav);
3139 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3156unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3158 case SIInstrInfo::SCC_TRUE:
3159 return AMDGPU::S_CBRANCH_SCC1;
3160 case SIInstrInfo::SCC_FALSE:
3161 return AMDGPU::S_CBRANCH_SCC0;
3162 case SIInstrInfo::VCCNZ:
3163 return AMDGPU::S_CBRANCH_VCCNZ;
3164 case SIInstrInfo::VCCZ:
3165 return AMDGPU::S_CBRANCH_VCCZ;
3166 case SIInstrInfo::EXECNZ:
3167 return AMDGPU::S_CBRANCH_EXECNZ;
3168 case SIInstrInfo::EXECZ:
3169 return AMDGPU::S_CBRANCH_EXECZ;
3175SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3177 case AMDGPU::S_CBRANCH_SCC0:
3179 case AMDGPU::S_CBRANCH_SCC1:
3181 case AMDGPU::S_CBRANCH_VCCNZ:
3183 case AMDGPU::S_CBRANCH_VCCZ:
3185 case AMDGPU::S_CBRANCH_EXECNZ:
3187 case AMDGPU::S_CBRANCH_EXECZ:
3199 bool AllowModify)
const {
3200 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3202 TBB =
I->getOperand(0).getMBB();
3206 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3207 if (Pred == INVALID_BR)
3212 Cond.push_back(
I->getOperand(1));
3216 if (
I ==
MBB.end()) {
3222 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3224 FBB =
I->getOperand(0).getMBB();
3234 bool AllowModify)
const {
3242 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3243 switch (
I->getOpcode()) {
3244 case AMDGPU::S_MOV_B64_term:
3245 case AMDGPU::S_XOR_B64_term:
3246 case AMDGPU::S_OR_B64_term:
3247 case AMDGPU::S_ANDN2_B64_term:
3248 case AMDGPU::S_AND_B64_term:
3249 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3250 case AMDGPU::S_MOV_B32_term:
3251 case AMDGPU::S_XOR_B32_term:
3252 case AMDGPU::S_OR_B32_term:
3253 case AMDGPU::S_ANDN2_B32_term:
3254 case AMDGPU::S_AND_B32_term:
3255 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3256 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3257 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3260 case AMDGPU::SI_ELSE:
3261 case AMDGPU::SI_KILL_I1_TERMINATOR:
3262 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3279 int *BytesRemoved)
const {
3281 unsigned RemovedSize = 0;
3284 if (
MI.isBranch() ||
MI.isReturn()) {
3286 MI.eraseFromParent();
3292 *BytesRemoved = RemovedSize;
3309 int *BytesAdded)
const {
3310 if (!FBB &&
Cond.empty()) {
3314 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3321 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3333 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3351 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3358 if (
Cond.size() != 2) {
3362 if (
Cond[0].isImm()) {
3373 Register FalseReg,
int &CondCycles,
3374 int &TrueCycles,
int &FalseCycles)
const {
3384 CondCycles = TrueCycles = FalseCycles = NumInsts;
3387 return RI.hasVGPRs(RC) && NumInsts <= 6;
3401 if (NumInsts % 2 == 0)
3404 CondCycles = TrueCycles = FalseCycles = NumInsts;
3405 return RI.isSGPRClass(RC);
3416 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3417 if (Pred == VCCZ || Pred == SCC_FALSE) {
3418 Pred =
static_cast<BranchPredicate
>(-Pred);
3424 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3426 if (DstSize == 32) {
3428 if (Pred == SCC_TRUE) {
3443 if (DstSize == 64 && Pred == SCC_TRUE) {
3453 static const int16_t Sub0_15[] = {
3454 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3455 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3456 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3457 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3460 static const int16_t Sub0_15_64[] = {
3461 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3462 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3463 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3464 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3467 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3469 const int16_t *SubIndices = Sub0_15;
3470 int NElts = DstSize / 32;
3474 if (Pred == SCC_TRUE) {
3476 SelOp = AMDGPU::S_CSELECT_B32;
3477 EltRC = &AMDGPU::SGPR_32RegClass;
3479 SelOp = AMDGPU::S_CSELECT_B64;
3480 EltRC = &AMDGPU::SGPR_64RegClass;
3481 SubIndices = Sub0_15_64;
3487 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3492 for (
int Idx = 0; Idx != NElts; ++Idx) {
3496 unsigned SubIdx = SubIndices[Idx];
3499 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3501 .
addReg(FalseReg, {}, SubIdx)
3502 .addReg(TrueReg, {}, SubIdx);
3505 .
addReg(TrueReg, {}, SubIdx)
3506 .addReg(FalseReg, {}, SubIdx);
3519 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3522 switch (
MI.getOpcode()) {
3523 case AMDGPU::S_ENDPGM:
3524 case AMDGPU::S_ENDPGM_SAVED:
3525 case AMDGPU::S_TRAP:
3526 case AMDGPU::S_GETREG_B32:
3527 case AMDGPU::S_SETREG_B32:
3528 case AMDGPU::S_SETREG_B32_mode:
3529 case AMDGPU::S_SETREG_IMM32_B32:
3530 case AMDGPU::S_SETREG_IMM32_B32_mode:
3531 case AMDGPU::S_SENDMSG:
3532 case AMDGPU::S_SENDMSGHALT:
3533 case AMDGPU::S_SENDMSG_RTN_B32:
3534 case AMDGPU::S_SENDMSG_RTN_B64:
3535 case AMDGPU::S_BARRIER_WAIT:
3536 case AMDGPU::S_BARRIER_SIGNAL_M0:
3537 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3538 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3539 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3547 switch (
MI.getOpcode()) {
3548 case AMDGPU::V_MOV_B16_t16_e32:
3549 case AMDGPU::V_MOV_B16_t16_e64:
3550 case AMDGPU::V_MOV_B32_e32:
3551 case AMDGPU::V_MOV_B32_e64:
3552 case AMDGPU::V_MOV_B64_PSEUDO:
3553 case AMDGPU::V_MOV_B64_e32:
3554 case AMDGPU::V_MOV_B64_e64:
3555 case AMDGPU::S_MOV_B32:
3556 case AMDGPU::S_MOV_B64:
3557 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3559 case AMDGPU::WWM_COPY:
3560 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3561 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3562 case AMDGPU::V_ACCVGPR_MOV_B32:
3563 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3564 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3572 switch (
MI.getOpcode()) {
3573 case AMDGPU::V_MOV_B16_t16_e32:
3574 case AMDGPU::V_MOV_B16_t16_e64:
3576 case AMDGPU::V_MOV_B32_e32:
3577 case AMDGPU::V_MOV_B32_e64:
3578 case AMDGPU::V_MOV_B64_PSEUDO:
3579 case AMDGPU::V_MOV_B64_e32:
3580 case AMDGPU::V_MOV_B64_e64:
3581 case AMDGPU::S_MOV_B32:
3582 case AMDGPU::S_MOV_B64:
3583 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3585 case AMDGPU::WWM_COPY:
3586 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3587 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3588 case AMDGPU::V_ACCVGPR_MOV_B32:
3589 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3590 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3598 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3599 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3600 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3603 unsigned Opc =
MI.getOpcode();
3605 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3607 MI.removeOperand(Idx);
3613 MI.setDesc(NewDesc);
3619 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3620 Desc.implicit_defs().size();
3622 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3623 MI.removeOperand(
I);
3627 unsigned SubRegIndex) {
3628 switch (SubRegIndex) {
3629 case AMDGPU::NoSubRegister:
3639 case AMDGPU::sub1_lo16:
3641 case AMDGPU::sub1_hi16:
3644 return std::nullopt;
3652 case AMDGPU::V_MAC_F16_e32:
3653 case AMDGPU::V_MAC_F16_e64:
3654 case AMDGPU::V_MAD_F16_e64:
3655 return AMDGPU::V_MADAK_F16;
3656 case AMDGPU::V_MAC_F32_e32:
3657 case AMDGPU::V_MAC_F32_e64:
3658 case AMDGPU::V_MAD_F32_e64:
3659 return AMDGPU::V_MADAK_F32;
3660 case AMDGPU::V_FMAC_F32_e32:
3661 case AMDGPU::V_FMAC_F32_e64:
3662 case AMDGPU::V_FMA_F32_e64:
3663 return AMDGPU::V_FMAAK_F32;
3664 case AMDGPU::V_FMAC_F16_e32:
3665 case AMDGPU::V_FMAC_F16_e64:
3666 case AMDGPU::V_FMAC_F16_t16_e64:
3667 case AMDGPU::V_FMAC_F16_fake16_e64:
3668 case AMDGPU::V_FMAC_F16_t16_e32:
3669 case AMDGPU::V_FMAC_F16_fake16_e32:
3670 case AMDGPU::V_FMA_F16_e64:
3671 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3672 ? AMDGPU::V_FMAAK_F16_t16
3673 : AMDGPU::V_FMAAK_F16_fake16
3674 : AMDGPU::V_FMAAK_F16;
3675 case AMDGPU::V_FMAC_F64_e32:
3676 case AMDGPU::V_FMAC_F64_e64:
3677 case AMDGPU::V_FMA_F64_e64:
3678 return AMDGPU::V_FMAAK_F64;
3686 case AMDGPU::V_MAC_F16_e32:
3687 case AMDGPU::V_MAC_F16_e64:
3688 case AMDGPU::V_MAD_F16_e64:
3689 return AMDGPU::V_MADMK_F16;
3690 case AMDGPU::V_MAC_F32_e32:
3691 case AMDGPU::V_MAC_F32_e64:
3692 case AMDGPU::V_MAD_F32_e64:
3693 return AMDGPU::V_MADMK_F32;
3694 case AMDGPU::V_FMAC_F32_e32:
3695 case AMDGPU::V_FMAC_F32_e64:
3696 case AMDGPU::V_FMA_F32_e64:
3697 return AMDGPU::V_FMAMK_F32;
3698 case AMDGPU::V_FMAC_F16_e32:
3699 case AMDGPU::V_FMAC_F16_e64:
3700 case AMDGPU::V_FMAC_F16_t16_e64:
3701 case AMDGPU::V_FMAC_F16_fake16_e64:
3702 case AMDGPU::V_FMAC_F16_t16_e32:
3703 case AMDGPU::V_FMAC_F16_fake16_e32:
3704 case AMDGPU::V_FMA_F16_e64:
3705 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3706 ? AMDGPU::V_FMAMK_F16_t16
3707 : AMDGPU::V_FMAMK_F16_fake16
3708 : AMDGPU::V_FMAMK_F16;
3709 case AMDGPU::V_FMAC_F64_e32:
3710 case AMDGPU::V_FMAC_F64_e64:
3711 case AMDGPU::V_FMA_F64_e64:
3712 return AMDGPU::V_FMAMK_F64;
3726 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3729 if (
Opc == AMDGPU::COPY) {
3730 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3737 if (HasMultipleUses) {
3740 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3743 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3751 if (ImmDefSize == 32 &&
3756 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3757 RI.getSubRegIdxSize(UseSubReg) == 16;
3760 if (RI.hasVGPRs(DstRC))
3763 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3769 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3776 for (
unsigned MovOp :
3777 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3778 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3786 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3790 if (MovDstPhysReg) {
3794 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3801 if (MovDstPhysReg) {
3802 if (!MovDstRC->
contains(MovDstPhysReg))
3818 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3826 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3830 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3832 UseMI.getOperand(0).setReg(MovDstPhysReg);
3837 UseMI.setDesc(NewMCID);
3838 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3839 UseMI.addImplicitDefUseOperands(*MF);
3843 if (HasMultipleUses)
3846 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3847 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3848 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3849 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3850 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3851 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3852 Opc == AMDGPU::V_FMAC_F64_e64) {
3861 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3872 auto CopyRegOperandToNarrowerRC =
3875 if (!
MI.getOperand(OpNo).isReg())
3879 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3882 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3883 get(AMDGPU::COPY), Tmp)
3885 MI.getOperand(OpNo).setReg(Tmp);
3886 MI.getOperand(OpNo).setIsKill();
3893 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3894 if (!RegSrc->
isReg())
3897 ST.getConstantBusLimit(
Opc) < 2)
3912 if (Def && Def->isMoveImmediate() &&
3927 unsigned SrcSubReg = RegSrc->
getSubReg();
3932 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3933 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3934 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3935 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
3936 UseMI.untieRegOperand(
3937 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
3944 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3945 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3949 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
3950 UseMI.getOperand(0).getReg())
3952 UseMI.getOperand(0).setReg(Tmp);
3953 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
3954 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
3959 DefMI.eraseFromParent();
3966 if (ST.getConstantBusLimit(
Opc) < 2) {
3969 bool Src0Inlined =
false;
3970 if (Src0->
isReg()) {
3975 if (Def && Def->isMoveImmediate() &&
3980 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
3981 RI.isSGPRReg(*MRI, Src0->
getReg())) {
3987 if (Src1->
isReg() && !Src0Inlined) {
3990 if (Def && Def->isMoveImmediate() &&
3994 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
4007 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4008 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4009 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4010 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4011 UseMI.untieRegOperand(
4012 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4014 const std::optional<int64_t> SubRegImm =
4024 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4025 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4029 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4030 UseMI.getOperand(0).getReg())
4032 UseMI.getOperand(0).setReg(Tmp);
4033 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4034 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4044 DefMI.eraseFromParent();
4056 if (BaseOps1.
size() != BaseOps2.
size())
4058 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4059 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4067 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4068 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4069 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4071 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4074bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4077 int64_t Offset0, Offset1;
4080 bool Offset0IsScalable, Offset1IsScalable;
4094 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4095 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4102 "MIa must load from or modify a memory location");
4104 "MIb must load from or modify a memory location");
4126 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4133 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4143 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4157 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4168 if (
Reg.isPhysical())
4172 Imm = Def->getOperand(1).getImm();
4192 unsigned NumOps =
MI.getNumOperands();
4195 if (
Op.isReg() &&
Op.isKill())
4203 case AMDGPU::V_MAC_F16_e32:
4204 case AMDGPU::V_MAC_F16_e64:
4205 return AMDGPU::V_MAD_F16_e64;
4206 case AMDGPU::V_MAC_F32_e32:
4207 case AMDGPU::V_MAC_F32_e64:
4208 return AMDGPU::V_MAD_F32_e64;
4209 case AMDGPU::V_MAC_LEGACY_F32_e32:
4210 case AMDGPU::V_MAC_LEGACY_F32_e64:
4211 return AMDGPU::V_MAD_LEGACY_F32_e64;
4212 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4213 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4214 return AMDGPU::V_FMA_LEGACY_F32_e64;
4215 case AMDGPU::V_FMAC_F16_e32:
4216 case AMDGPU::V_FMAC_F16_e64:
4217 case AMDGPU::V_FMAC_F16_t16_e64:
4218 case AMDGPU::V_FMAC_F16_fake16_e64:
4219 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4220 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4221 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4222 : AMDGPU::V_FMA_F16_gfx9_e64;
4223 case AMDGPU::V_FMAC_F32_e32:
4224 case AMDGPU::V_FMAC_F32_e64:
4225 return AMDGPU::V_FMA_F32_e64;
4226 case AMDGPU::V_FMAC_F64_e32:
4227 case AMDGPU::V_FMAC_F64_e64:
4228 return AMDGPU::V_FMA_F64_e64;
4248 if (
MI.isBundle()) {
4251 if (
MI.getBundleSize() != 1)
4253 CandidateMI =
MI.getNextNode();
4257 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4261 if (
MI.isBundle()) {
4266 MI.untieRegOperand(MO.getOperandNo());
4274 if (Def.isEarlyClobber() && Def.isReg() &&
4279 auto UpdateDefIndex = [&](
LiveRange &LR) {
4280 auto *S = LR.find(OldIndex);
4281 if (S != LR.end() && S->start == OldIndex) {
4282 assert(S->valno && S->valno->def == OldIndex);
4283 S->start = NewIndex;
4284 S->valno->def = NewIndex;
4288 for (
auto &SR : LI.subranges())
4294 if (U.RemoveMIUse) {
4297 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4301 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4302 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4303 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4304 U.RemoveMIUse->removeOperand(
I);
4309 if (
MI.isBundle()) {
4313 if (MO.isReg() && MO.getReg() == DefReg) {
4314 assert(MO.getSubReg() == 0 &&
4315 "tied sub-registers in bundles currently not supported");
4316 MI.removeOperand(MO.getOperandNo());
4333 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4334 MIOp.setIsUndef(
true);
4335 MIOp.setReg(DummyReg);
4339 if (
MI.isBundle()) {
4343 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4344 MIOp.setIsUndef(
true);
4345 MIOp.setReg(DummyReg);
4358 return MI.isBundle() ? &
MI : NewMI;
4363 ThreeAddressUpdates &U)
const {
4365 unsigned Opc =
MI.getOpcode();
4369 if (NewMFMAOpc != -1) {
4372 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4373 MIB.
add(
MI.getOperand(
I));
4381 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4386 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4387 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4388 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4392 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4393 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4394 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4395 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4396 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4397 bool Src0Literal =
false;
4402 case AMDGPU::V_MAC_F16_e64:
4403 case AMDGPU::V_FMAC_F16_e64:
4404 case AMDGPU::V_FMAC_F16_t16_e64:
4405 case AMDGPU::V_FMAC_F16_fake16_e64:
4406 case AMDGPU::V_MAC_F32_e64:
4407 case AMDGPU::V_MAC_LEGACY_F32_e64:
4408 case AMDGPU::V_FMAC_F32_e64:
4409 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4410 case AMDGPU::V_FMAC_F64_e64:
4412 case AMDGPU::V_MAC_F16_e32:
4413 case AMDGPU::V_FMAC_F16_e32:
4414 case AMDGPU::V_MAC_F32_e32:
4415 case AMDGPU::V_MAC_LEGACY_F32_e32:
4416 case AMDGPU::V_FMAC_F32_e32:
4417 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4418 case AMDGPU::V_FMAC_F64_e32: {
4419 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4420 AMDGPU::OpName::src0);
4421 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4432 MachineInstrBuilder MIB;
4435 const MachineOperand *Src0Mods =
4438 const MachineOperand *Src1Mods =
4441 const MachineOperand *Src2Mods =
4447 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4448 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4450 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4452 MachineInstr *
DefMI =
nullptr;
4488 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4504 if (Src0Literal && !ST.hasVOP3Literal())
4532 switch (
MI.getOpcode()) {
4533 case AMDGPU::S_SET_GPR_IDX_ON:
4534 case AMDGPU::S_SET_GPR_IDX_MODE:
4535 case AMDGPU::S_SET_GPR_IDX_OFF:
4553 if (
MI.isTerminator() ||
MI.isPosition())
4557 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4560 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4566 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4567 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4568 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4569 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4570 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4575 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4576 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4577 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4591 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4596 if (
MI.memoperands_empty())
4601 unsigned AS = Memop->getAddrSpace();
4602 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4603 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4604 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4605 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4620 if (
MI.memoperands_empty())
4629 unsigned AS = Memop->getAddrSpace();
4639 bool TgSplit)
const {
4652 if (
MI.memoperands_empty())
4657 unsigned AS = Memop->getAddrSpace();
4673 unsigned Opcode =
MI.getOpcode();
4688 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4689 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4690 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4691 Opcode == AMDGPU::S_SETHALT)
4694 if (
MI.isCall() ||
MI.isInlineAsm())
4710 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4711 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4712 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4713 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4721 if (
MI.isMetaInstruction())
4725 if (
MI.isCopyLike()) {
4726 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4730 return MI.readsRegister(AMDGPU::EXEC, &RI);
4741 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4745 switch (
Imm.getBitWidth()) {
4751 ST.hasInv2PiInlineImm());
4754 ST.hasInv2PiInlineImm());
4756 return ST.has16BitInsts() &&
4758 ST.hasInv2PiInlineImm());
4765 APInt IntImm =
Imm.bitcastToAPInt();
4767 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4775 return ST.has16BitInsts() &&
4778 return ST.has16BitInsts() &&
4788 switch (OperandType) {
4798 int32_t Trunc =
static_cast<int32_t
>(
Imm);
4842 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4843 return ST.has16BitInsts() &&
4852 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4853 return ST.has16BitInsts() &&
4904 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4910 return ST.hasVOP3Literal();
4914 int64_t ImmVal)
const {
4916 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4917 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4918 OpNo ==
static_cast<unsigned>(Src1Idx))
4923 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4924 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4925 AMDGPU::OpName::src2))
4928 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
4935 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4947 "unexpected imm-like operand kind");
4960 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4978 AMDGPU::OpName
OpName)
const {
4980 return Mods && Mods->
getImm();
4993 switch (
MI.getOpcode()) {
4994 default:
return false;
4996 case AMDGPU::V_ADDC_U32_e64:
4997 case AMDGPU::V_SUBB_U32_e64:
4998 case AMDGPU::V_SUBBREV_U32_e64: {
5001 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
5006 case AMDGPU::V_MAC_F16_e64:
5007 case AMDGPU::V_MAC_F32_e64:
5008 case AMDGPU::V_MAC_LEGACY_F32_e64:
5009 case AMDGPU::V_FMAC_F16_e64:
5010 case AMDGPU::V_FMAC_F16_t16_e64:
5011 case AMDGPU::V_FMAC_F16_fake16_e64:
5012 case AMDGPU::V_FMAC_F32_e64:
5013 case AMDGPU::V_FMAC_F64_e64:
5014 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5015 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5020 case AMDGPU::V_CNDMASK_B32_e64:
5026 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5039 if (Src0 && Src0->
isImm()) {
5042 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5064 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5073 unsigned Op32)
const {
5087 Inst32.
add(
MI.getOperand(
I));
5091 int Idx =
MI.getNumExplicitDefs();
5093 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5098 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5120 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5128 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5131 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5132 AMDGPU::SReg_64RegClass.contains(Reg);
5160 switch (MO.getReg()) {
5162 case AMDGPU::VCC_LO:
5163 case AMDGPU::VCC_HI:
5165 case AMDGPU::FLAT_SCR:
5178 switch (
MI.getOpcode()) {
5179 case AMDGPU::V_READLANE_B32:
5180 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5181 case AMDGPU::V_WRITELANE_B32:
5182 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5189 if (
MI.isPreISelOpcode() ||
5190 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5208 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5219 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5220 ErrInfo =
"illegal copy from vector register to SGPR";
5238 if (!MRI.
isSSA() &&
MI.isCopy())
5239 return verifyCopy(
MI, MRI, ErrInfo);
5241 if (SIInstrInfo::isGenericOpcode(Opcode))
5244 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5245 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5246 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5248 if (Src0Idx == -1) {
5250 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5251 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5252 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5253 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5258 if (!
Desc.isVariadic() &&
5259 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5260 ErrInfo =
"Instruction has wrong number of operands.";
5264 if (
MI.isInlineAsm()) {
5277 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5278 ErrInfo =
"inlineasm operand has incorrect register class.";
5286 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5287 ErrInfo =
"missing memory operand from image instruction.";
5292 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5295 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5296 "all fp values to integers.";
5301 int16_t RegClass = getOpRegClassID(OpInfo);
5303 switch (OpInfo.OperandType) {
5305 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5306 ErrInfo =
"Illegal immediate value for operand.";
5339 ErrInfo =
"Illegal immediate value for operand.";
5348 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5351 OpInfo.OperandType ==
5353 ErrInfo =
"illegal 64-bit immediate value for operand.";
5360 ErrInfo =
"Expected inline constant for operand.";
5374 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5375 ErrInfo =
"Expected immediate, but got non-immediate";
5384 if (OpInfo.isGenericType())
5399 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5400 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5402 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5404 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5405 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5412 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5413 ErrInfo =
"Subtarget requires even aligned vector registers";
5418 if (RegClass != -1) {
5419 if (Reg.isVirtual())
5424 ErrInfo =
"Operand has incorrect register class.";
5432 if (!ST.hasSDWA()) {
5433 ErrInfo =
"SDWA is not supported on this target";
5437 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5438 AMDGPU::OpName::dst_sel}) {
5444 ErrInfo =
"Invalid SDWA selection";
5449 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5451 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5456 if (!ST.hasSDWAScalar()) {
5458 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5459 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5466 "Only reg allowed as operands in SDWA instructions on GFX9+";
5472 if (!ST.hasSDWAOmod()) {
5475 if (OMod !=
nullptr &&
5477 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5482 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5483 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5484 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5485 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5488 unsigned Mods = Src0ModsMO->
getImm();
5491 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5497 if (
isVOPC(BasicOpcode)) {
5498 if (!ST.hasSDWASdst() && DstIdx != -1) {
5501 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5502 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5505 }
else if (!ST.hasSDWAOutModsVOPC()) {
5508 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5509 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5515 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5516 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5523 if (DstUnused && DstUnused->isImm() &&
5526 if (!Dst.isReg() || !Dst.isTied()) {
5527 ErrInfo =
"Dst register should have tied register";
5532 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5535 "Dst register should be tied to implicit use of preserved register";
5539 ErrInfo =
"Dst register should use same physical register as preserved";
5545 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5547 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5548 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5551 if (Src1MO.
isImm()) {
5552 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5558 if (
isImage(Opcode) && !
MI.mayStore()) {
5563 uint64_t DMaskImm = DMask->
getImm();
5570 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5578 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5582 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5583 if (RegCount > DstSize) {
5584 ErrInfo =
"Image instruction returns too many registers for dst "
5594 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5595 unsigned ConstantBusCount = 0;
5596 bool UsesLiteral =
false;
5599 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5603 LiteralVal = &
MI.getOperand(ImmIdx);
5612 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5623 }
else if (!MO.
isFI()) {
5630 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5640 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5641 return !RI.regsOverlap(SGPRUsed, SGPR);
5650 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5651 Opcode != AMDGPU::V_WRITELANE_B32) {
5652 ErrInfo =
"VOP* instruction violates constant bus restriction";
5656 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5657 ErrInfo =
"VOP3 instruction uses literal";
5664 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5665 unsigned SGPRCount = 0;
5668 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5676 if (MO.
getReg() != SGPRUsed)
5681 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5682 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5689 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5690 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5697 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5707 ErrInfo =
"ABS not allowed in VOP3B instructions";
5720 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5727 if (
Desc.isBranch()) {
5729 ErrInfo =
"invalid branch target for SOPK instruction";
5733 uint64_t
Imm =
Op->getImm();
5736 ErrInfo =
"invalid immediate for SOPK instruction";
5741 ErrInfo =
"invalid immediate for SOPK instruction";
5748 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5749 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5750 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5751 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5752 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5753 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5755 const unsigned StaticNumOps =
5756 Desc.getNumOperands() +
Desc.implicit_uses().size();
5757 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5763 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5764 ErrInfo =
"missing implicit register operands";
5770 if (!Dst->isUse()) {
5771 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5776 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5777 UseOpIdx != StaticNumOps + 1) {
5778 ErrInfo =
"movrel implicit operands should be tied";
5785 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5787 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5788 ErrInfo =
"src0 should be subreg of implicit vector use";
5796 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5797 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5803 if (
MI.mayStore() &&
5808 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5809 ErrInfo =
"scalar stores must use m0 as offset register";
5815 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5817 if (
Offset->getImm() != 0) {
5818 ErrInfo =
"subtarget does not support offsets in flat instructions";
5823 if (
isDS(
MI) && !ST.hasGDS()) {
5825 if (GDSOp && GDSOp->
getImm() != 0) {
5826 ErrInfo =
"GDS is not supported on this subtarget";
5834 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5835 AMDGPU::OpName::vaddr0);
5836 AMDGPU::OpName RSrcOpName =
5837 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5838 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5846 ErrInfo =
"dim is out of range";
5851 if (ST.hasR128A16()) {
5853 IsA16 = R128A16->
getImm() != 0;
5854 }
else if (ST.hasA16()) {
5856 IsA16 = A16->
getImm() != 0;
5859 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5861 unsigned AddrWords =
5864 unsigned VAddrWords;
5866 VAddrWords = RsrcIdx - VAddr0Idx;
5867 if (ST.hasPartialNSAEncoding() &&
5869 unsigned LastVAddrIdx = RsrcIdx - 1;
5870 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5878 if (VAddrWords != AddrWords) {
5880 <<
" but got " << VAddrWords <<
"\n");
5881 ErrInfo =
"bad vaddr size";
5891 unsigned DC = DppCt->
getImm();
5892 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5893 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5894 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5895 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5896 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5897 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5898 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5899 ErrInfo =
"Invalid dpp_ctrl value";
5902 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5903 !ST.hasDPPWavefrontShifts()) {
5904 ErrInfo =
"Invalid dpp_ctrl value: "
5905 "wavefront shifts are not supported on GFX10+";
5908 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5909 !ST.hasDPPBroadcasts()) {
5910 ErrInfo =
"Invalid dpp_ctrl value: "
5911 "broadcasts are not supported on GFX10+";
5914 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5916 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5917 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5918 !ST.hasGFX90AInsts()) {
5919 ErrInfo =
"Invalid dpp_ctrl value: "
5920 "row_newbroadcast/row_share is not supported before "
5924 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5925 ErrInfo =
"Invalid dpp_ctrl value: "
5926 "row_share and row_xmask are not supported before GFX10";
5931 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5934 ErrInfo =
"Invalid dpp_ctrl value: "
5935 "DP ALU dpp only support row_newbcast";
5942 AMDGPU::OpName DataName =
5943 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5949 if (!ST.hasGFX90AInsts()) {
5950 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5951 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
5952 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
5953 ErrInfo =
"Invalid register class: "
5954 "agpr loads and stores not supported on this GPU";
5960 if (ST.needsAlignedVGPRs()) {
5961 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
5966 if (Reg.isPhysical())
5967 return !(RI.getHWRegIndex(Reg) & 1);
5969 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5970 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
5973 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5974 Opcode == AMDGPU::DS_GWS_BARRIER) {
5976 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5977 ErrInfo =
"Subtarget requires even aligned vector registers "
5978 "for DS_GWS instructions";
5984 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5985 ErrInfo =
"Subtarget requires even aligned vector registers "
5986 "for vaddr operand of image instructions";
5992 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5994 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5995 ErrInfo =
"Invalid register class: "
5996 "v_accvgpr_write with an SGPR is not supported on this GPU";
6001 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6004 ErrInfo =
"pseudo expects only physical SGPRs";
6011 if (!ST.hasScaleOffset()) {
6012 ErrInfo =
"Subtarget does not support offset scaling";
6016 ErrInfo =
"Instruction does not support offset scaling";
6024 for (
unsigned I = 0;
I < 3; ++
I) {
6030 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6031 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6033 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6034 &AMDGPU::SReg_64RegClass) ||
6035 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6036 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6045 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6047 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6049 : AMDGPU::V_MOV_B32_e32;
6059 default:
return AMDGPU::INSTRUCTION_LIST_END;
6060 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6061 case AMDGPU::COPY:
return AMDGPU::COPY;
6062 case AMDGPU::PHI:
return AMDGPU::PHI;
6063 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6064 case AMDGPU::WQM:
return AMDGPU::WQM;
6065 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6066 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6067 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6068 case AMDGPU::S_ADD_I32:
6069 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6070 case AMDGPU::S_ADDC_U32:
6071 return AMDGPU::V_ADDC_U32_e32;
6072 case AMDGPU::S_SUB_I32:
6073 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6076 case AMDGPU::S_ADD_U32:
6077 return AMDGPU::V_ADD_CO_U32_e32;
6078 case AMDGPU::S_SUB_U32:
6079 return AMDGPU::V_SUB_CO_U32_e32;
6080 case AMDGPU::S_ADD_U64_PSEUDO:
6081 return AMDGPU::V_ADD_U64_PSEUDO;
6082 case AMDGPU::S_SUB_U64_PSEUDO:
6083 return AMDGPU::V_SUB_U64_PSEUDO;
6084 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6085 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6086 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6087 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6088 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6089 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6090 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6091 case AMDGPU::S_XNOR_B32:
6092 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6093 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6094 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6095 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6096 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6097 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6098 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6099 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6100 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6101 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6102 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6103 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6104 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6105 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6106 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6107 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6108 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6109 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6110 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6111 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6112 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6113 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6114 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6115 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6116 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6117 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6118 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6119 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6120 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6121 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6122 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6123 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6124 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6125 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6126 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6127 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6128 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6129 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6130 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6131 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6132 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6133 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6134 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6135 case AMDGPU::S_CVT_F32_F16:
6136 case AMDGPU::S_CVT_HI_F32_F16:
6137 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6138 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6139 case AMDGPU::S_CVT_F16_F32:
6140 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6141 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6142 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6143 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6144 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6145 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6146 case AMDGPU::S_CEIL_F16:
6147 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6148 : AMDGPU::V_CEIL_F16_fake16_e64;
6149 case AMDGPU::S_FLOOR_F16:
6150 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6151 : AMDGPU::V_FLOOR_F16_fake16_e64;
6152 case AMDGPU::S_TRUNC_F16:
6153 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6154 : AMDGPU::V_TRUNC_F16_fake16_e64;
6155 case AMDGPU::S_RNDNE_F16:
6156 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6157 : AMDGPU::V_RNDNE_F16_fake16_e64;
6158 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6159 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6160 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6161 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6162 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6163 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6164 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6165 case AMDGPU::S_ADD_F16:
6166 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6167 : AMDGPU::V_ADD_F16_fake16_e64;
6168 case AMDGPU::S_SUB_F16:
6169 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6170 : AMDGPU::V_SUB_F16_fake16_e64;
6171 case AMDGPU::S_MIN_F16:
6172 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6173 : AMDGPU::V_MIN_F16_fake16_e64;
6174 case AMDGPU::S_MAX_F16:
6175 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6176 : AMDGPU::V_MAX_F16_fake16_e64;
6177 case AMDGPU::S_MINIMUM_F16:
6178 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6179 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6180 case AMDGPU::S_MAXIMUM_F16:
6181 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6182 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6183 case AMDGPU::S_MUL_F16:
6184 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6185 : AMDGPU::V_MUL_F16_fake16_e64;
6186 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6187 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6188 case AMDGPU::S_FMAC_F16:
6189 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6190 : AMDGPU::V_FMAC_F16_fake16_e64;
6191 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6192 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6193 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6194 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6195 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6196 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6197 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6198 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6199 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6200 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6201 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6202 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6203 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6204 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6205 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6206 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6207 case AMDGPU::S_CMP_LT_F16:
6208 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6209 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6210 case AMDGPU::S_CMP_EQ_F16:
6211 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6212 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6213 case AMDGPU::S_CMP_LE_F16:
6214 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6215 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6216 case AMDGPU::S_CMP_GT_F16:
6217 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6218 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6219 case AMDGPU::S_CMP_LG_F16:
6220 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6221 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6222 case AMDGPU::S_CMP_GE_F16:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6224 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6225 case AMDGPU::S_CMP_O_F16:
6226 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6227 : AMDGPU::V_CMP_O_F16_fake16_e64;
6228 case AMDGPU::S_CMP_U_F16:
6229 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6230 : AMDGPU::V_CMP_U_F16_fake16_e64;
6231 case AMDGPU::S_CMP_NGE_F16:
6232 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6233 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6234 case AMDGPU::S_CMP_NLG_F16:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6236 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6237 case AMDGPU::S_CMP_NGT_F16:
6238 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6239 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6240 case AMDGPU::S_CMP_NLE_F16:
6241 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6242 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6243 case AMDGPU::S_CMP_NEQ_F16:
6244 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6245 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6246 case AMDGPU::S_CMP_NLT_F16:
6247 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6248 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6249 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6250 case AMDGPU::V_S_EXP_F16_e64:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6252 : AMDGPU::V_EXP_F16_fake16_e64;
6253 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6254 case AMDGPU::V_S_LOG_F16_e64:
6255 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6256 : AMDGPU::V_LOG_F16_fake16_e64;
6257 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6258 case AMDGPU::V_S_RCP_F16_e64:
6259 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6260 : AMDGPU::V_RCP_F16_fake16_e64;
6261 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6262 case AMDGPU::V_S_RSQ_F16_e64:
6263 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6264 : AMDGPU::V_RSQ_F16_fake16_e64;
6265 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6266 case AMDGPU::V_S_SQRT_F16_e64:
6267 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6268 : AMDGPU::V_SQRT_F16_fake16_e64;
6271 "Unexpected scalar opcode without corresponding vector one!");
6320 "Not a whole wave func");
6323 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6324 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6331 unsigned OpNo)
const {
6333 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6334 Desc.operands()[OpNo].RegClass == -1) {
6337 if (Reg.isVirtual()) {
6341 return RI.getPhysRegBaseClass(Reg);
6344 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6345 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6350 constexpr AMDGPU::OpName OpNames[] = {
6351 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6354 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6355 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6367 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6369 unsigned Size = RI.getRegSizeInBits(*RC);
6370 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6371 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6372 : AMDGPU::V_MOV_B32_e32;
6374 Opcode = AMDGPU::COPY;
6375 else if (RI.isSGPRClass(RC))
6376 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6401 .
addImm(AMDGPU::sub0_sub1)
6403 .
addImm(AMDGPU::sub2_sub3);
6416 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6422 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6433 if (SubIdx == AMDGPU::sub0)
6435 if (SubIdx == AMDGPU::sub1)
6447void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6463 if (Reg.isPhysical())
6473 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6476 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6483 unsigned Opc =
MI.getOpcode();
6486 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6496 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6497 if (IsAGPR && !ST.hasMAIInsts())
6503 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6504 const int DataIdx = AMDGPU::getNamedOperandIdx(
6505 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6506 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6507 MI.getOperand(DataIdx).isReg() &&
6508 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6510 if ((
int)OpIdx == DataIdx) {
6511 if (VDstIdx != -1 &&
6512 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6515 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6516 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6517 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6522 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6523 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6524 RI.isSGPRReg(MRI, MO.
getReg()))
6527 if (ST.hasFlatScratchHiInB64InstHazard() &&
6534 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6537 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6538 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6558 constexpr unsigned NumOps = 3;
6559 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6560 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6561 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6562 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6567 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6570 MO = &
MI.getOperand(SrcIdx);
6573 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6577 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6581 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6585 return !OpSel && !OpSelHi;
6594 int64_t RegClass = getOpRegClassID(OpInfo);
6596 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6598 MO = &
MI.getOperand(OpIdx);
6602 if (
isVALU(
MI,
true) && !IsInlineConst &&
6606 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6607 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6611 if (!LiteralLimit--)
6621 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6629 if (--ConstantBusLimit <= 0)
6641 if (!LiteralLimit--)
6643 if (--ConstantBusLimit <= 0)
6649 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6653 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6655 !
Op.isIdenticalTo(*MO))
6665 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6680 bool Is64BitOp = Is64BitFPOp ||
6688 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6697 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6715 bool IsGFX950Only = ST.hasGFX950Insts();
6716 bool IsGFX940Only = ST.hasGFX940Insts();
6718 if (!IsGFX950Only && !IsGFX940Only)
6736 unsigned Opcode =
MI.getOpcode();
6738 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6739 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6740 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6741 case AMDGPU::V_MQSAD_U32_U8_e64:
6742 case AMDGPU::V_PK_ADD_F16:
6743 case AMDGPU::V_PK_ADD_F32:
6744 case AMDGPU::V_PK_ADD_I16:
6745 case AMDGPU::V_PK_ADD_U16:
6746 case AMDGPU::V_PK_ASHRREV_I16:
6747 case AMDGPU::V_PK_FMA_F16:
6748 case AMDGPU::V_PK_FMA_F32:
6749 case AMDGPU::V_PK_FMAC_F16_e32:
6750 case AMDGPU::V_PK_FMAC_F16_e64:
6751 case AMDGPU::V_PK_LSHLREV_B16:
6752 case AMDGPU::V_PK_LSHRREV_B16:
6753 case AMDGPU::V_PK_MAD_I16:
6754 case AMDGPU::V_PK_MAD_U16:
6755 case AMDGPU::V_PK_MAX_F16:
6756 case AMDGPU::V_PK_MAX_I16:
6757 case AMDGPU::V_PK_MAX_U16:
6758 case AMDGPU::V_PK_MIN_F16:
6759 case AMDGPU::V_PK_MIN_I16:
6760 case AMDGPU::V_PK_MIN_U16:
6761 case AMDGPU::V_PK_MOV_B32:
6762 case AMDGPU::V_PK_MUL_F16:
6763 case AMDGPU::V_PK_MUL_F32:
6764 case AMDGPU::V_PK_MUL_LO_U16:
6765 case AMDGPU::V_PK_SUB_I16:
6766 case AMDGPU::V_PK_SUB_U16:
6767 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6776 unsigned Opc =
MI.getOpcode();
6779 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6782 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6788 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6789 RI.isSGPRReg(MRI, Src0.
getReg()))
6795 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6797 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6803 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6814 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6815 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6816 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6828 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6829 RI.isVGPR(MRI, Src1.
getReg())) {
6842 if (HasImplicitSGPR || !
MI.isCommutable()) {
6859 if (CommutedOpc == -1) {
6864 MI.setDesc(
get(CommutedOpc));
6868 bool Src0Kill = Src0.
isKill();
6872 else if (Src1.
isReg()) {
6887 unsigned Opc =
MI.getOpcode();
6890 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6891 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6892 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6895 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6896 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6897 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6898 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6899 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6900 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6901 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6911 if (VOP3Idx[2] != -1) {
6923 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6924 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6926 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6928 SGPRsUsed.
insert(SGPRReg);
6932 for (
int Idx : VOP3Idx) {
6941 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6953 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
6960 if (ConstantBusLimit > 0) {
6972 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
6973 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
6979 for (
unsigned I = 0;
I < 3; ++
I) {
6992 SRC = RI.getCommonSubClass(SRC, DstRC);
6995 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6997 if (RI.hasAGPRs(VRC)) {
6998 VRC = RI.getEquivalentVGPRClass(VRC);
7001 get(TargetOpcode::COPY), NewSrcReg)
7008 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7014 for (
unsigned i = 0; i < SubRegs; ++i) {
7017 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7018 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7024 get(AMDGPU::REG_SEQUENCE), DstReg);
7025 for (
unsigned i = 0; i < SubRegs; ++i) {
7027 MIB.
addImm(RI.getSubRegFromChannel(i));
7040 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7042 SBase->setReg(SGPR);
7045 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7053 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7054 if (OldSAddrIdx < 0)
7067 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7070 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7071 if (NewVAddrIdx < 0)
7074 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7078 if (OldVAddrIdx >= 0) {
7092 if (OldVAddrIdx == NewVAddrIdx) {
7103 assert(OldSAddrIdx == NewVAddrIdx);
7105 if (OldVAddrIdx >= 0) {
7106 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7107 AMDGPU::OpName::vdst_in);
7111 if (NewVDstIn != -1) {
7112 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7118 if (NewVDstIn != -1) {
7119 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7160 unsigned OpSubReg =
Op.getSubReg();
7163 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7170 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7171 .
addReg(OpReg, {}, OpSubReg);
7173 Op.setSubReg(AMDGPU::NoSubRegister);
7180 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7183 bool ImpDef = Def->isImplicitDef();
7184 while (!ImpDef && Def && Def->isCopy()) {
7185 if (Def->getOperand(1).getReg().isPhysical())
7188 ImpDef = Def && Def->isImplicitDef();
7190 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7206 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7211 bool UseNewExecInstructions =
7220 if (UseNewExecInstructions) {
7255 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7256 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7257 unsigned NumSubRegs =
RegSize / 32;
7258 Register VScalarOp = ScalarOp->getReg();
7261 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7263 if (NumSubRegs == 1) {
7266 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7267 Common != VScalarOpRC) {
7274 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7277 if (UseNewExecInstructions) {
7279 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7282 if (
I == LoopBB.
end())
7287 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7293 CondReg = NewCondReg;
7304 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7305 ScalarOp->setReg(CurReg);
7308 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7309 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7311 ScalarOp->setReg(PhySGPRs[Idx]);
7313 ScalarOp->setIsKill();
7317 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7318 "Unhandled register size");
7320 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7327 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7328 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7331 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7332 .
addReg(VScalarOp, VScalarOpUndef,
7333 TRI->getSubRegFromChannel(Idx + 1));
7340 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7347 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7349 if (UseNewExecInstructions) {
7351 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7353 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7354 if (
I == LoopBB.
end())
7358 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7360 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7364 CondReg = NewCondReg;
7375 const auto *SScalarOpRC =
7381 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7382 unsigned Channel = 0;
7383 for (
Register Piece : ReadlanePieces) {
7384 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7388 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7389 ScalarOp->setReg(SScalarOp);
7391 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7392 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7394 ScalarOp->setReg(PhySGPRs[Idx]);
7396 ScalarOp->setIsKill();
7404 if (!UseNewExecInstructions) {
7416 if (UseNewExecInstructions) {
7440 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7441 "Physical SGPRs must be empty or match the number of scalar operands");
7447 if (!Begin.isValid())
7449 if (!End.isValid()) {
7455 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7464 std::numeric_limits<unsigned>::max()) !=
7482 for (
auto I = Begin;
I != AfterMI;
I++) {
7483 for (
auto &MO :
I->all_uses())
7519 for (
auto &Succ : RemainderBB->
successors()) {
7544static std::tuple<unsigned, unsigned>
7552 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7553 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7560 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7577 .
addImm(AMDGPU::sub0_sub1)
7583 return std::tuple(RsrcPtr, NewSRsrc);
7594 if (ST.useRealTrue16Insts())
7624 if (
MI.getOpcode() == AMDGPU::PHI) {
7626 assert(!RI.isSGPRClass(VRC));
7629 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7631 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7647 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7650 if (RI.hasVGPRs(DstRC)) {
7654 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7656 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7674 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7679 if (DstRC != Src0RC) {
7688 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7690 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7696 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7697 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7698 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7699 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7700 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7701 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7702 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7704 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7717 ? AMDGPU::OpName::rsrc
7718 : AMDGPU::OpName::srsrc;
7723 AMDGPU::OpName SampOpName =
7724 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7733 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7741 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7745 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7755 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7756 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7757 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7758 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7760 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7767 bool isSoffsetLegal =
true;
7769 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7770 if (SoffsetIdx != -1) {
7774 isSoffsetLegal =
false;
7778 bool isRsrcLegal =
true;
7780 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7781 if (RsrcIdx != -1) {
7783 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7784 isRsrcLegal =
false;
7788 if (isRsrcLegal && isSoffsetLegal)
7816 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7820 unsigned RsrcPtr, NewSRsrc;
7827 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7828 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7834 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7835 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7848 }
else if (!VAddr && ST.hasAddr64()) {
7852 "FIXME: Need to emit flat atomics here");
7854 unsigned RsrcPtr, NewSRsrc;
7880 MIB.
addImm(CPol->getImm());
7885 MIB.
addImm(TFE->getImm());
7905 MI.removeFromParent();
7910 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7911 .addImm(AMDGPU::sub0)
7912 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7913 .addImm(AMDGPU::sub1);
7916 if (!isSoffsetLegal) {
7927 if (!isSoffsetLegal) {
7936 if (InSet.insert(
MI).second)
7940 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
7941 if (RsrcIdx != -1) {
7942 DeferredList.insert(
MI);
7947 return DeferredList.contains(
MI);
7957 if (!ST.useRealTrue16Insts())
7960 unsigned Opcode =
MI.getOpcode();
7963 if (OpIdx >=
MI.getNumExplicitOperands() ||
7964 OpIdx >=
get(Opcode).getNumOperands() ||
7965 get(Opcode).operands()[OpIdx].RegClass == -1)
7969 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
7973 if (!RI.isVGPRClass(CurrRC))
7976 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
7978 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7980 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
7981 Op.setSubReg(AMDGPU::lo16);
7986 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
7987 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7997 Op.setReg(NewDstReg);
7998 Op.setSubReg(AMDGPU::NoSubRegister);
8003 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8011 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8012 "This only handle waterfall for SI_CALL_ISEL");
8019 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8022 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8027 while (End !=
MBB.end() && End->isCopy() &&
8028 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8038 while (!Worklist.
empty()) {
8044 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8050 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8052 "Deferred MachineInstr are not supposed to re-populate worklist");
8055 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8056 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8058 Entry.second.SGPRs);
8061 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8063 Entry.first->eraseFromParent();
8071 if (SubRegIndices.
size() <= 1) {
8074 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8081 for (int16_t Indice : SubRegIndices) {
8084 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8091 get(AMDGPU::REG_SEQUENCE), DstReg);
8092 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8094 MIB.
addImm(RI.getSubRegFromChannel(i));
8104 if (DstReg == AMDGPU::M0) {
8117 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8119 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8120 if (
UseMI->getOperand(i).isReg() &&
8121 UseMI->getOperand(i).getReg() == DstReg) {
8125 V2SCopyInfo.MOs.push_back(MO);
8126 V2SCopyInfo.SGPRs.push_back(DstReg);
8130 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8131 I->getOperand(0).isReg() &&
8132 I->getOperand(0).getReg() == DstReg) {
8135 }
else if (
I->readsRegister(DstReg, &RI)) {
8137 V2SPhyCopiesToErase[&Inst] =
false;
8139 if (
I->findRegisterDefOperand(DstReg, &RI))
8161 case AMDGPU::S_ADD_I32:
8162 case AMDGPU::S_SUB_I32: {
8166 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8174 case AMDGPU::S_MUL_U64:
8175 if (ST.hasVMulU64Inst()) {
8176 NewOpcode = AMDGPU::V_MUL_U64_e64;
8180 splitScalarSMulU64(Worklist, Inst, MDT);
8184 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8185 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8188 splitScalarSMulPseudo(Worklist, Inst, MDT);
8192 case AMDGPU::S_AND_B64:
8193 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8197 case AMDGPU::S_OR_B64:
8198 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8202 case AMDGPU::S_XOR_B64:
8203 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8207 case AMDGPU::S_NAND_B64:
8208 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8212 case AMDGPU::S_NOR_B64:
8213 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8217 case AMDGPU::S_XNOR_B64:
8218 if (ST.hasDLInsts())
8219 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8221 splitScalar64BitXnor(Worklist, Inst, MDT);
8225 case AMDGPU::S_ANDN2_B64:
8226 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8230 case AMDGPU::S_ORN2_B64:
8231 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8235 case AMDGPU::S_BREV_B64:
8236 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8240 case AMDGPU::S_NOT_B64:
8241 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8245 case AMDGPU::S_BCNT1_I32_B64:
8246 splitScalar64BitBCNT(Worklist, Inst);
8250 case AMDGPU::S_BFE_I64:
8251 splitScalar64BitBFE(Worklist, Inst);
8255 case AMDGPU::S_FLBIT_I32_B64:
8256 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8259 case AMDGPU::S_FF1_I32_B64:
8260 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8264 case AMDGPU::S_LSHL_B32:
8265 if (ST.hasOnlyRevVALUShifts()) {
8266 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8270 case AMDGPU::S_ASHR_I32:
8271 if (ST.hasOnlyRevVALUShifts()) {
8272 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8276 case AMDGPU::S_LSHR_B32:
8277 if (ST.hasOnlyRevVALUShifts()) {
8278 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8282 case AMDGPU::S_LSHL_B64:
8283 if (ST.hasOnlyRevVALUShifts()) {
8285 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8286 : AMDGPU::V_LSHLREV_B64_e64;
8290 case AMDGPU::S_ASHR_I64:
8291 if (ST.hasOnlyRevVALUShifts()) {
8292 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8296 case AMDGPU::S_LSHR_B64:
8297 if (ST.hasOnlyRevVALUShifts()) {
8298 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8303 case AMDGPU::S_ABS_I32:
8304 lowerScalarAbs(Worklist, Inst);
8308 case AMDGPU::S_ABSDIFF_I32:
8309 lowerScalarAbsDiff(Worklist, Inst);
8313 case AMDGPU::S_CBRANCH_SCC0:
8314 case AMDGPU::S_CBRANCH_SCC1: {
8317 bool IsSCC = CondReg == AMDGPU::SCC;
8325 case AMDGPU::S_BFE_U64:
8326 case AMDGPU::S_BFM_B64:
8329 case AMDGPU::S_PACK_LL_B32_B16:
8330 case AMDGPU::S_PACK_LH_B32_B16:
8331 case AMDGPU::S_PACK_HL_B32_B16:
8332 case AMDGPU::S_PACK_HH_B32_B16:
8333 movePackToVALU(Worklist, MRI, Inst);
8337 case AMDGPU::S_XNOR_B32:
8338 lowerScalarXnor(Worklist, Inst);
8342 case AMDGPU::S_NAND_B32:
8343 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8347 case AMDGPU::S_NOR_B32:
8348 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8352 case AMDGPU::S_ANDN2_B32:
8353 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8357 case AMDGPU::S_ORN2_B32:
8358 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8366 case AMDGPU::S_ADD_CO_PSEUDO:
8367 case AMDGPU::S_SUB_CO_PSEUDO: {
8368 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8369 ? AMDGPU::V_ADDC_U32_e64
8370 : AMDGPU::V_SUBB_U32_e64;
8371 const auto *CarryRC = RI.getWaveMaskRegClass();
8393 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8397 case AMDGPU::S_UADDO_PSEUDO:
8398 case AMDGPU::S_USUBO_PSEUDO: {
8404 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8405 ? AMDGPU::V_ADD_CO_U32_e64
8406 : AMDGPU::V_SUB_CO_U32_e64;
8418 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8422 case AMDGPU::S_LSHL1_ADD_U32:
8423 case AMDGPU::S_LSHL2_ADD_U32:
8424 case AMDGPU::S_LSHL3_ADD_U32:
8425 case AMDGPU::S_LSHL4_ADD_U32: {
8429 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8430 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8431 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8445 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8449 case AMDGPU::S_CSELECT_B32:
8450 case AMDGPU::S_CSELECT_B64:
8451 lowerSelect(Worklist, Inst, MDT);
8454 case AMDGPU::S_CMP_EQ_I32:
8455 case AMDGPU::S_CMP_LG_I32:
8456 case AMDGPU::S_CMP_GT_I32:
8457 case AMDGPU::S_CMP_GE_I32:
8458 case AMDGPU::S_CMP_LT_I32:
8459 case AMDGPU::S_CMP_LE_I32:
8460 case AMDGPU::S_CMP_EQ_U32:
8461 case AMDGPU::S_CMP_LG_U32:
8462 case AMDGPU::S_CMP_GT_U32:
8463 case AMDGPU::S_CMP_GE_U32:
8464 case AMDGPU::S_CMP_LT_U32:
8465 case AMDGPU::S_CMP_LE_U32:
8466 case AMDGPU::S_CMP_EQ_U64:
8467 case AMDGPU::S_CMP_LG_U64:
8468 case AMDGPU::S_CMP_LT_F32:
8469 case AMDGPU::S_CMP_EQ_F32:
8470 case AMDGPU::S_CMP_LE_F32:
8471 case AMDGPU::S_CMP_GT_F32:
8472 case AMDGPU::S_CMP_LG_F32:
8473 case AMDGPU::S_CMP_GE_F32:
8474 case AMDGPU::S_CMP_O_F32:
8475 case AMDGPU::S_CMP_U_F32:
8476 case AMDGPU::S_CMP_NGE_F32:
8477 case AMDGPU::S_CMP_NLG_F32:
8478 case AMDGPU::S_CMP_NGT_F32:
8479 case AMDGPU::S_CMP_NLE_F32:
8480 case AMDGPU::S_CMP_NEQ_F32:
8481 case AMDGPU::S_CMP_NLT_F32: {
8486 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8500 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8504 case AMDGPU::S_CMP_LT_F16:
8505 case AMDGPU::S_CMP_EQ_F16:
8506 case AMDGPU::S_CMP_LE_F16:
8507 case AMDGPU::S_CMP_GT_F16:
8508 case AMDGPU::S_CMP_LG_F16:
8509 case AMDGPU::S_CMP_GE_F16:
8510 case AMDGPU::S_CMP_O_F16:
8511 case AMDGPU::S_CMP_U_F16:
8512 case AMDGPU::S_CMP_NGE_F16:
8513 case AMDGPU::S_CMP_NLG_F16:
8514 case AMDGPU::S_CMP_NGT_F16:
8515 case AMDGPU::S_CMP_NLE_F16:
8516 case AMDGPU::S_CMP_NEQ_F16:
8517 case AMDGPU::S_CMP_NLT_F16: {
8539 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8543 case AMDGPU::S_CVT_HI_F32_F16: {
8546 if (ST.useRealTrue16Insts()) {
8551 .
addReg(TmpReg, {}, AMDGPU::hi16)
8567 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8571 case AMDGPU::S_MINIMUM_F32:
8572 case AMDGPU::S_MAXIMUM_F32: {
8584 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8588 case AMDGPU::S_MINIMUM_F16:
8589 case AMDGPU::S_MAXIMUM_F16: {
8591 ? &AMDGPU::VGPR_16RegClass
8592 : &AMDGPU::VGPR_32RegClass);
8603 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8607 case AMDGPU::V_S_EXP_F16_e64:
8608 case AMDGPU::V_S_LOG_F16_e64:
8609 case AMDGPU::V_S_RCP_F16_e64:
8610 case AMDGPU::V_S_RSQ_F16_e64:
8611 case AMDGPU::V_S_SQRT_F16_e64: {
8613 ? &AMDGPU::VGPR_16RegClass
8614 : &AMDGPU::VGPR_32RegClass);
8625 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8631 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8639 if (NewOpcode == Opcode) {
8646 V2SPhyCopiesToErase);
8654 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8661 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8667 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8668 UseMO.setReg(NewDstReg);
8687 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8700 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8704 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8710 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8717 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8719 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8724 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8732 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8742 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8743 AMDGPU::OpName::src0_modifiers) >= 0)
8747 NewInstr->addOperand(Src);
8750 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8753 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8755 NewInstr.addImm(
Size);
8756 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8760 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8765 "Scalar BFE is only implemented for constant width and offset");
8773 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8774 AMDGPU::OpName::src1_modifiers) >= 0)
8776 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8778 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8779 AMDGPU::OpName::src2_modifiers) >= 0)
8781 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8783 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8785 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8787 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8793 NewInstr->addOperand(
Op);
8800 if (
Op.getReg() == AMDGPU::SCC) {
8802 if (
Op.isDef() && !
Op.isDead())
8803 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8805 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8810 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8811 Register DstReg = NewInstr->getOperand(0).getReg();
8824 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8828std::pair<bool, MachineBasicBlock *>
8831 if (ST.hasAddNoCarryInsts()) {
8843 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8845 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8846 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8857 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8858 return std::pair(
true, NewBB);
8861 return std::pair(
false,
nullptr);
8878 bool IsSCC = (CondReg == AMDGPU::SCC);
8886 for (MachineOperand &UseMO :
8888 MachineInstr &
UseMI = *UseMO.getParent();
8889 switch (
UseMI.getOpcode()) {
8890 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8891 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8892 case AMDGPU::V_CNDMASK_B16_t16_e32:
8893 case AMDGPU::V_CNDMASK_B16_t16_e64:
8894 case AMDGPU::V_CNDMASK_B32_e32:
8895 case AMDGPU::V_CNDMASK_B32_e64:
8896 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8897 if (UseMO.isImplicit() ||
8899 UseMO.setReg(CondReg);
8913 bool CopyFound =
false;
8914 for (MachineInstr &CandI :
8917 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8919 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8921 .
addReg(CandI.getOperand(1).getReg());
8933 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8942 MachineInstr *NewInst;
8943 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
8944 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8959 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8974 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8975 : AMDGPU::V_SUB_CO_U32_e32;
8986 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9003 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9004 : AMDGPU::V_SUB_CO_U32_e32;
9017 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9031 if (ST.hasDLInsts()) {
9041 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9047 bool Src0IsSGPR = Src0.
isReg() &&
9049 bool Src1IsSGPR = Src1.
isReg() &&
9063 }
else if (Src1IsSGPR) {
9081 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9087 unsigned Opcode)
const {
9111 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9116 unsigned Opcode)
const {
9140 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9155 const MCInstrDesc &InstDesc =
get(Opcode);
9158 &AMDGPU::SGPR_32RegClass;
9161 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9164 AMDGPU::sub0, Src0SubRC);
9169 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9172 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9175 AMDGPU::sub1, Src0SubRC);
9178 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9192 Worklist.
insert(&LoHalf);
9193 Worklist.
insert(&HiHalf);
9199 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9223 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9224 if (RI.isSGPRClass(Src0SubRC))
9225 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9227 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9228 if (RI.isSGPRClass(Src1SubRC))
9229 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9233 MachineOperand Op0L =
9235 MachineOperand Op1L =
9237 MachineOperand Op0H =
9239 MachineOperand Op1H =
9258 MachineInstr *Op1L_Op0H =
9264 MachineInstr *Op1H_Op0L =
9270 MachineInstr *Carry =
9275 MachineInstr *LoHalf =
9285 MachineInstr *HiHalf =
9308 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9332 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9333 if (RI.isSGPRClass(Src0SubRC))
9334 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9336 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9337 if (RI.isSGPRClass(Src1SubRC))
9338 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9342 MachineOperand Op0L =
9344 MachineOperand Op1L =
9348 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9349 ? AMDGPU::V_MUL_HI_U32_e64
9350 : AMDGPU::V_MUL_HI_I32_e64;
9351 MachineInstr *HiHalf =
9354 MachineInstr *LoHalf =
9373 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9389 const MCInstrDesc &InstDesc =
get(Opcode);
9392 &AMDGPU::SGPR_32RegClass;
9395 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9398 &AMDGPU::SGPR_32RegClass;
9401 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9404 AMDGPU::sub0, Src0SubRC);
9406 AMDGPU::sub0, Src1SubRC);
9408 AMDGPU::sub1, Src0SubRC);
9410 AMDGPU::sub1, Src1SubRC);
9415 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9418 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9423 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9436 Worklist.
insert(&LoHalf);
9437 Worklist.
insert(&HiHalf);
9440 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9460 MachineOperand* Op0;
9461 MachineOperand* Op1;
9463 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9496 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9499 &AMDGPU::SGPR_32RegClass;
9505 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9508 AMDGPU::sub0, SrcSubRC);
9510 AMDGPU::sub1, SrcSubRC);
9520 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9539 Offset == 0 &&
"Not implemented");
9562 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9572 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9575 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9581 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9600 const MCInstrDesc &InstDesc =
get(Opcode);
9602 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9603 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9604 : AMDGPU::V_ADD_CO_U32_e32;
9607 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9609 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9611 MachineOperand SrcRegSub0 =
9613 MachineOperand SrcRegSub1 =
9626 .
addReg(IsCtlz ? MidReg1 : MidReg2)
9632 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9636 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9639void SIInstrInfo::addUsersToMoveToVALUWorklist(
9643 MachineInstr &
UseMI = *MO.getParent();
9647 switch (
UseMI.getOpcode()) {
9650 case AMDGPU::SOFT_WQM:
9651 case AMDGPU::STRICT_WWM:
9652 case AMDGPU::STRICT_WQM:
9653 case AMDGPU::REG_SEQUENCE:
9655 case AMDGPU::INSERT_SUBREG:
9658 OpNo = MO.getOperandNo();
9665 if (!RI.hasVectorRegisters(OpRC))
9682 if (ST.useRealTrue16Insts()) {
9684 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9687 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9693 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9696 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9705 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9707 case AMDGPU::S_PACK_LL_B32_B16:
9709 .addReg(SrcReg0, {},
9710 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9711 .addImm(AMDGPU::lo16)
9712 .addReg(SrcReg1, {},
9713 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9714 .addImm(AMDGPU::hi16);
9716 case AMDGPU::S_PACK_LH_B32_B16:
9718 .addReg(SrcReg0, {},
9719 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9720 .addImm(AMDGPU::lo16)
9721 .addReg(SrcReg1, {}, AMDGPU::hi16)
9722 .addImm(AMDGPU::hi16);
9724 case AMDGPU::S_PACK_HL_B32_B16:
9725 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9726 .addImm(AMDGPU::lo16)
9727 .addReg(SrcReg1, {},
9728 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9729 .addImm(AMDGPU::hi16);
9731 case AMDGPU::S_PACK_HH_B32_B16:
9732 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9733 .addImm(AMDGPU::lo16)
9734 .addReg(SrcReg1, {}, AMDGPU::hi16)
9735 .addImm(AMDGPU::hi16);
9743 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9748 case AMDGPU::S_PACK_LL_B32_B16: {
9767 case AMDGPU::S_PACK_LH_B32_B16: {
9777 case AMDGPU::S_PACK_HL_B32_B16: {
9788 case AMDGPU::S_PACK_HH_B32_B16: {
9808 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9817 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9818 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9819 SmallVector<MachineInstr *, 4> CopyToDelete;
9822 for (MachineInstr &
MI :
9826 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9830 Register DestReg =
MI.getOperand(0).getReg();
9837 MI.getOperand(SCCIdx).setReg(NewCond);
9843 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9846 for (
auto &Copy : CopyToDelete)
9847 Copy->eraseFromParent();
9855void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9861 for (MachineInstr &
MI :
9864 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9866 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9883 case AMDGPU::REG_SEQUENCE:
9884 case AMDGPU::INSERT_SUBREG:
9886 case AMDGPU::SOFT_WQM:
9887 case AMDGPU::STRICT_WWM:
9888 case AMDGPU::STRICT_WQM: {
9890 if (RI.isAGPRClass(SrcRC)) {
9891 if (RI.isAGPRClass(NewDstRC))
9896 case AMDGPU::REG_SEQUENCE:
9897 case AMDGPU::INSERT_SUBREG:
9898 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9901 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9907 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9910 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9924 int OpIndices[3])
const {
9925 const MCInstrDesc &
Desc =
MI.getDesc();
9943 for (
unsigned i = 0; i < 3; ++i) {
9944 int Idx = OpIndices[i];
9948 const MachineOperand &MO =
MI.getOperand(Idx);
9955 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
9956 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9963 if (RI.isSGPRClass(RegRC))
9981 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9982 SGPRReg = UsedSGPRs[0];
9985 if (!SGPRReg && UsedSGPRs[1]) {
9986 if (UsedSGPRs[1] == UsedSGPRs[2])
9987 SGPRReg = UsedSGPRs[1];
9994 AMDGPU::OpName OperandName)
const {
9995 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9998 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10002 return &
MI.getOperand(Idx);
10016 if (ST.isAmdHsaOS()) {
10019 RsrcDataFormat |= (1ULL << 56);
10024 RsrcDataFormat |= (2ULL << 59);
10027 return RsrcDataFormat;
10037 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10042 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10049 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10055 unsigned Opc =
MI.getOpcode();
10061 return get(
Opc).mayLoad() &&
10068 if (!Addr || !Addr->
isFI())
10077 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10079 return MI.getOperand(VDataIdx).getReg();
10089 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10091 return MI.getOperand(DataIdx).getReg();
10112 if (!
MI.mayStore())
10125 unsigned Opc =
MI.getOpcode();
10127 unsigned DescSize =
Desc.getSize();
10132 unsigned Size = DescSize;
10136 if (
MI.isBranch() && ST.hasOffset3fBug())
10147 bool HasLiteral =
false;
10148 unsigned LiteralSize = 4;
10149 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10154 if (ST.has64BitLiterals()) {
10155 switch (OpInfo.OperandType) {
10180 return HasLiteral ? DescSize + LiteralSize : DescSize;
10185 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10189 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10190 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10194 case TargetOpcode::BUNDLE:
10195 return getInstBundleSize(
MI);
10196 case TargetOpcode::INLINEASM:
10197 case TargetOpcode::INLINEASM_BR: {
10199 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10203 if (
MI.isMetaInstruction())
10207 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10210 unsigned LoInstOpcode = D16Info->LoOp;
10212 DescSize =
Desc.getSize();
10216 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10219 DescSize =
Desc.getSize();
10228 if (
MI.isBranch() && ST.hasOffset3fBug())
10229 return InstSizeVerifyMode::NoVerify;
10230 return InstSizeVerifyMode::ExactSize;
10237 if (
MI.memoperands_empty())
10249 static const std::pair<int, const char *> TargetIndices[] = {
10289std::pair<unsigned, unsigned>
10296 static const std::pair<unsigned, const char *> TargetFlags[] = {
10314 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10330 return AMDGPU::WWM_COPY;
10332 return AMDGPU::COPY;
10349 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10353 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10354 return IsLRSplitInst;
10367 bool IsNullOrVectorRegister =
true;
10371 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10374 return IsNullOrVectorRegister &&
10376 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10377 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10385 if (ST.hasAddNoCarryInsts())
10401 if (ST.hasAddNoCarryInsts())
10405 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10407 : RS.scavengeRegisterBackwards(
10408 *RI.getBoolRC(),
I,
false,
10421 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10422 case AMDGPU::SI_KILL_I1_TERMINATOR:
10431 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10432 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10433 case AMDGPU::SI_KILL_I1_PSEUDO:
10434 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10446 const unsigned OffsetBits =
10448 return (1 << OffsetBits) - 1;
10452 if (!ST.isWave32())
10455 if (
MI.isInlineAsm())
10458 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10461 for (
auto &
Op :
MI.implicit_operands()) {
10462 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10463 Op.setReg(AMDGPU::VCC_LO);
10472 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10476 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10477 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10493 if (
Imm > MaxImm) {
10494 if (
Imm <= MaxImm + 64) {
10496 Overflow =
Imm - MaxImm;
10515 if (Overflow > 0) {
10523 if (ST.hasRestrictedSOffset())
10528 SOffset = Overflow;
10566 if (!ST.hasFlatInstOffsets())
10570 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10575 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10576 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10587std::pair<int64_t, int64_t>
10590 int64_t RemainderOffset = COffsetVal;
10591 int64_t ImmField = 0;
10596 if (AllowNegative) {
10598 int64_t
D = 1LL << NumBits;
10599 RemainderOffset = (COffsetVal /
D) *
D;
10600 ImmField = COffsetVal - RemainderOffset;
10602 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10604 (ImmField % 4) != 0) {
10606 RemainderOffset += ImmField % 4;
10607 ImmField -= ImmField % 4;
10609 }
else if (COffsetVal >= 0) {
10611 RemainderOffset = COffsetVal - ImmField;
10615 assert(RemainderOffset + ImmField == COffsetVal);
10616 return {ImmField, RemainderOffset};
10621 if (ST.hasNegativeScratchOffsetBug() &&
10629 switch (ST.getGeneration()) {
10658 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10659 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10660 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10661 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10662 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10663 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10664 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10665 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10672#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10673 case OPCODE##_dpp: \
10674 case OPCODE##_e32: \
10675 case OPCODE##_e64: \
10676 case OPCODE##_e64_dpp: \
10677 case OPCODE##_sdwa:
10691 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10692 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10693 case AMDGPU::V_FMA_F16_gfx9_e64:
10694 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10695 case AMDGPU::V_INTERP_P2_F16:
10696 case AMDGPU::V_MAD_F16_e64:
10697 case AMDGPU::V_MAD_U16_e64:
10698 case AMDGPU::V_MAD_I16_e64:
10707 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10721 switch (ST.getGeneration()) {
10734 if (
isMAI(Opcode)) {
10742 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10745 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10752 if (ST.hasGFX90AInsts()) {
10753 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10754 if (ST.hasGFX940Insts())
10756 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10758 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10760 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10766 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10785 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10786 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10787 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10799 switch (
MI.getOpcode()) {
10801 case AMDGPU::REG_SEQUENCE:
10805 case AMDGPU::INSERT_SUBREG:
10806 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10823 if (!
P.Reg.isVirtual())
10828 while (
auto *
MI = DefInst) {
10830 switch (
MI->getOpcode()) {
10832 case AMDGPU::V_MOV_B32_e32: {
10833 auto &Op1 =
MI->getOperand(1);
10862 auto *DefBB =
DefMI.getParent();
10866 if (
UseMI.getParent() != DefBB)
10869 const int MaxInstScan = 20;
10873 auto E =
UseMI.getIterator();
10874 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10875 if (
I->isDebugInstr())
10878 if (++NumInst > MaxInstScan)
10881 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10894 auto *DefBB =
DefMI.getParent();
10896 const int MaxUseScan = 10;
10900 auto &UseInst = *
Use.getParent();
10903 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10906 if (++NumUse > MaxUseScan)
10913 const int MaxInstScan = 20;
10917 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10920 if (
I->isDebugInstr())
10923 if (++NumInst > MaxInstScan)
10936 if (Reg == VReg && --NumUse == 0)
10938 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
10947 auto Cur =
MBB.begin();
10948 if (Cur !=
MBB.end())
10950 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
10953 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
10962 if (InsPt !=
MBB.end() &&
10963 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10964 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10965 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10966 InsPt->definesRegister(Src,
nullptr)) {
10970 .
addReg(Src, {}, SrcSubReg)
11013 if (isFullCopyInstr(
MI)) {
11014 Register DstReg =
MI.getOperand(0).getReg();
11015 Register SrcReg =
MI.getOperand(1).getReg();
11037 unsigned *PredCost)
const {
11038 if (
MI.isBundle()) {
11041 unsigned Lat = 0,
Count = 0;
11042 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11044 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11046 return Lat +
Count - 1;
11049 return SchedModel.computeInstrLatency(&
MI);
11056 return *CallAddrOp;
11063 unsigned Opcode =
MI.getOpcode();
11065 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11068 :
MI.getOperand(1).getReg();
11072 unsigned SrcAS = SrcTy.getAddressSpace();
11075 ST.hasGloballyAddressableScratch()
11083 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11084 return HandleAddrSpaceCast(
MI);
11087 auto IID = GI->getIntrinsicID();
11094 case Intrinsic::amdgcn_addrspacecast_nonnull:
11095 return HandleAddrSpaceCast(
MI);
11096 case Intrinsic::amdgcn_if:
11097 case Intrinsic::amdgcn_else:
11111 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11112 Opcode == AMDGPU::G_SEXTLOAD) {
11113 if (
MI.memoperands_empty())
11117 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11118 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11126 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11127 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11128 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11134 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11137 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11145 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11146 return Formatter.get();
11154 unsigned opcode =
MI.getOpcode();
11155 if (opcode == AMDGPU::V_READLANE_B32 ||
11156 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11157 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11162 if (
MI.isInlineAsm()) {
11168 if (!RC || !RI.isSGPRClass(RC))
11173 if (isCopyInstr(
MI)) {
11177 RI.getPhysRegBaseClass(srcOp.
getReg());
11185 if (
MI.isPreISelOpcode())
11200 if (
MI.memoperands_empty())
11204 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11205 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11220 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11222 if (!
SrcOp.isReg())
11226 if (!Reg || !
SrcOp.readsReg())
11232 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11259 F,
"ds_ordered_count unsupported for this calling conv"));
11273 Register &SrcReg2, int64_t &CmpMask,
11274 int64_t &CmpValue)
const {
11275 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11278 switch (
MI.getOpcode()) {
11281 case AMDGPU::S_CMP_EQ_U32:
11282 case AMDGPU::S_CMP_EQ_I32:
11283 case AMDGPU::S_CMP_LG_U32:
11284 case AMDGPU::S_CMP_LG_I32:
11285 case AMDGPU::S_CMP_LT_U32:
11286 case AMDGPU::S_CMP_LT_I32:
11287 case AMDGPU::S_CMP_GT_U32:
11288 case AMDGPU::S_CMP_GT_I32:
11289 case AMDGPU::S_CMP_LE_U32:
11290 case AMDGPU::S_CMP_LE_I32:
11291 case AMDGPU::S_CMP_GE_U32:
11292 case AMDGPU::S_CMP_GE_I32:
11293 case AMDGPU::S_CMP_EQ_U64:
11294 case AMDGPU::S_CMP_LG_U64:
11295 SrcReg =
MI.getOperand(0).getReg();
11296 if (
MI.getOperand(1).isReg()) {
11297 if (
MI.getOperand(1).getSubReg())
11299 SrcReg2 =
MI.getOperand(1).getReg();
11301 }
else if (
MI.getOperand(1).isImm()) {
11303 CmpValue =
MI.getOperand(1).getImm();
11309 case AMDGPU::S_CMPK_EQ_U32:
11310 case AMDGPU::S_CMPK_EQ_I32:
11311 case AMDGPU::S_CMPK_LG_U32:
11312 case AMDGPU::S_CMPK_LG_I32:
11313 case AMDGPU::S_CMPK_LT_U32:
11314 case AMDGPU::S_CMPK_LT_I32:
11315 case AMDGPU::S_CMPK_GT_U32:
11316 case AMDGPU::S_CMPK_GT_I32:
11317 case AMDGPU::S_CMPK_LE_U32:
11318 case AMDGPU::S_CMPK_LE_I32:
11319 case AMDGPU::S_CMPK_GE_U32:
11320 case AMDGPU::S_CMPK_GE_I32:
11321 SrcReg =
MI.getOperand(0).getReg();
11323 CmpValue =
MI.getOperand(1).getImm();
11333 if (S->isLiveIn(AMDGPU::SCC))
11342bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11345 bool SCCIsDead =
false;
11348 constexpr unsigned ScanLimit = 12;
11349 unsigned Count = 0;
11350 for (MachineInstr &
MI :
11352 if (++
Count > ScanLimit)
11354 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11355 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11356 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11357 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11358 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11363 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11376 for (MachineInstr *
MI : InvertInstr) {
11377 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11378 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11380 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11381 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11382 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11383 ? AMDGPU::S_CBRANCH_SCC1
11384 : AMDGPU::S_CBRANCH_SCC0));
11397 bool NeedInversion)
const {
11398 MachineInstr *KillsSCC =
nullptr;
11403 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11405 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11408 if (NeedInversion && !invertSCCUse(SCCRedefine))
11410 if (MachineOperand *SccDef =
11412 SccDef->setIsDead(
false);
11420 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11421 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11423 bool Op1IsNonZeroImm =
11424 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11425 bool Op2IsZeroImm =
11426 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11427 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11433 unsigned &NewDefOpc) {
11436 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11437 Def.getOpcode() != AMDGPU::S_ADD_U32)
11443 if ((!AddSrc1.
isImm() || AddSrc1.
getImm() != 1) &&
11449 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11451 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11454 NewDefOpc = AMDGPU::S_ADD_U32;
11456 NeedInversion = !NeedInversion;
11461 Register SrcReg2, int64_t CmpMask,
11470 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11471 this](
bool NeedInversion) ->
bool {
11495 unsigned NewDefOpc = Def->getOpcode();
11501 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11504 if (NewDefOpc != Def->getOpcode())
11505 Def->setDesc(
get(NewDefOpc));
11514 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11521 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11529 optimizeSCC(
Select, Def,
false);
11536 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11537 this](int64_t ExpectedValue,
unsigned SrcSize,
11538 bool IsReversible,
bool IsSigned) ->
bool {
11566 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11567 Def->getOpcode() != AMDGPU::S_AND_B64)
11571 const auto isMask = [&Mask, SrcSize](
const MachineOperand *MO) ->
bool {
11582 SrcOp = &Def->getOperand(2);
11583 else if (isMask(&Def->getOperand(2)))
11584 SrcOp = &Def->getOperand(1);
11592 if (IsSigned && BitNo == SrcSize - 1)
11595 ExpectedValue <<= BitNo;
11597 bool IsReversedCC =
false;
11598 if (CmpValue != ExpectedValue) {
11601 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11606 Register DefReg = Def->getOperand(0).getReg();
11610 if (!optimizeSCC(Def, &CmpInstr,
false))
11621 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11622 : AMDGPU::S_BITCMP1_B32
11623 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11624 : AMDGPU::S_BITCMP1_B64;
11629 Def->eraseFromParent();
11637 case AMDGPU::S_CMP_EQ_U32:
11638 case AMDGPU::S_CMP_EQ_I32:
11639 case AMDGPU::S_CMPK_EQ_U32:
11640 case AMDGPU::S_CMPK_EQ_I32:
11641 return optimizeCmpAnd(1, 32,
true,
false) ||
11642 optimizeCmpSelect(
true);
11643 case AMDGPU::S_CMP_GE_U32:
11644 case AMDGPU::S_CMPK_GE_U32:
11645 return optimizeCmpAnd(1, 32,
false,
false);
11646 case AMDGPU::S_CMP_GE_I32:
11647 case AMDGPU::S_CMPK_GE_I32:
11648 return optimizeCmpAnd(1, 32,
false,
true);
11649 case AMDGPU::S_CMP_EQ_U64:
11650 return optimizeCmpAnd(1, 64,
true,
false);
11651 case AMDGPU::S_CMP_LG_U32:
11652 case AMDGPU::S_CMP_LG_I32:
11653 case AMDGPU::S_CMPK_LG_U32:
11654 case AMDGPU::S_CMPK_LG_I32:
11655 return optimizeCmpAnd(0, 32,
true,
false) ||
11656 optimizeCmpSelect(
false);
11657 case AMDGPU::S_CMP_GT_U32:
11658 case AMDGPU::S_CMPK_GT_U32:
11659 return optimizeCmpAnd(0, 32,
false,
false);
11660 case AMDGPU::S_CMP_GT_I32:
11661 case AMDGPU::S_CMPK_GT_I32:
11662 return optimizeCmpAnd(0, 32,
false,
true);
11663 case AMDGPU::S_CMP_LG_U64:
11664 return optimizeCmpAnd(0, 64,
true,
false) ||
11665 optimizeCmpSelect(
false);
11672 AMDGPU::OpName
OpName)
const {
11673 if (!ST.needsAlignedVGPRs())
11676 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11688 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11690 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11694 : &AMDGPU::VReg_64_Align2RegClass);
11696 .
addReg(DataReg, {},
Op.getSubReg())
11701 Op.setSubReg(AMDGPU::sub0);
11706 if (!SchedModel.hasInstrSchedModel())
11712 unsigned RepeatRate = 0;
11714 PI = SchedModel.getWriteProcResBegin(SCDesc),
11715 PE = SchedModel.getWriteProcResEnd(SCDesc);
11717 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11734 if (ST.hasGFX1250Insts())
11741 unsigned Opcode =
MI.getOpcode();
11747 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11748 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11751 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.
const MachineFunction & getMF() const
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.