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>
1321 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1322 return std::nullopt;
1324 if (Def && Def->isMoveImmediate()) {
1326 if (ImmSrc.
isImm()) {
1333 return std::nullopt;
1336std::optional<int64_t>
1345 if (RI.isAGPRClass(DstRC))
1346 return AMDGPU::COPY;
1347 if (RI.getRegSizeInBits(*DstRC) == 16) {
1350 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1352 if (RI.getRegSizeInBits(*DstRC) == 32)
1353 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1354 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1355 return AMDGPU::S_MOV_B64;
1356 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1357 return AMDGPU::V_MOV_B64_PSEUDO;
1358 return AMDGPU::COPY;
1363 bool IsIndirectSrc)
const {
1364 if (IsIndirectSrc) {
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1368 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1370 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1372 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1374 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1376 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1378 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1380 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1382 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1384 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1386 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1388 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1390 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1391 if (VecSize <= 1024)
1392 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1400 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1402 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1404 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1406 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1408 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1410 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1412 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1414 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1416 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1418 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1420 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1422 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1423 if (VecSize <= 1024)
1424 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1433 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1435 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1437 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1439 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1441 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1443 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1445 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1447 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1449 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1451 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1453 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1455 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1456 if (VecSize <= 1024)
1457 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1466 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1468 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1470 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1472 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1474 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1476 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1478 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1480 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1482 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1484 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1486 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1488 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1489 if (VecSize <= 1024)
1490 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1497 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1499 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1501 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1503 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1504 if (VecSize <= 1024)
1505 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1512 bool IsSGPR)
const {
1524 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1531 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1533 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1535 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1537 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1538 : AMDGPU::SI_SPILL_S128_SAVE;
1540 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1541 : AMDGPU::SI_SPILL_S160_SAVE;
1543 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1544 : AMDGPU::SI_SPILL_S192_SAVE;
1546 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1547 : AMDGPU::SI_SPILL_S224_SAVE;
1549 return AMDGPU::SI_SPILL_S256_SAVE;
1551 return AMDGPU::SI_SPILL_S288_SAVE;
1553 return AMDGPU::SI_SPILL_S320_SAVE;
1555 return AMDGPU::SI_SPILL_S352_SAVE;
1557 return AMDGPU::SI_SPILL_S384_SAVE;
1559 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1560 : AMDGPU::SI_SPILL_S512_SAVE;
1562 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1563 : AMDGPU::SI_SPILL_S1024_SAVE;
1572 return AMDGPU::SI_SPILL_V16_SAVE;
1574 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1576 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1580 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1581 : AMDGPU::SI_SPILL_V128_SAVE;
1583 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1584 : AMDGPU::SI_SPILL_V160_SAVE;
1586 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1587 : AMDGPU::SI_SPILL_V192_SAVE;
1589 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1590 : AMDGPU::SI_SPILL_V224_SAVE;
1592 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1593 : AMDGPU::SI_SPILL_V256_SAVE;
1595 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1596 : AMDGPU::SI_SPILL_V288_SAVE;
1598 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1599 : AMDGPU::SI_SPILL_V320_SAVE;
1601 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1602 : AMDGPU::SI_SPILL_V352_SAVE;
1604 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1605 : AMDGPU::SI_SPILL_V384_SAVE;
1607 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1608 : AMDGPU::SI_SPILL_V512_SAVE;
1610 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1611 : AMDGPU::SI_SPILL_V1024_SAVE;
1620 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1621 : AMDGPU::SI_SPILL_AV32_SAVE;
1623 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1624 : AMDGPU::SI_SPILL_AV64_SAVE;
1626 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1627 : AMDGPU::SI_SPILL_AV96_SAVE;
1629 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1630 : AMDGPU::SI_SPILL_AV128_SAVE;
1632 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1633 : AMDGPU::SI_SPILL_AV160_SAVE;
1635 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1636 : AMDGPU::SI_SPILL_AV192_SAVE;
1638 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1639 : AMDGPU::SI_SPILL_AV224_SAVE;
1641 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1642 : AMDGPU::SI_SPILL_AV256_SAVE;
1644 return AMDGPU::SI_SPILL_AV288_SAVE;
1646 return AMDGPU::SI_SPILL_AV320_SAVE;
1648 return AMDGPU::SI_SPILL_AV352_SAVE;
1650 return AMDGPU::SI_SPILL_AV384_SAVE;
1652 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1653 : AMDGPU::SI_SPILL_AV512_SAVE;
1655 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1656 : AMDGPU::SI_SPILL_AV1024_SAVE;
1663 bool IsVectorSuperClass) {
1668 if (IsVectorSuperClass)
1669 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1671 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1677 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1684 if (ST.hasMAIInsts())
1690void SIInstrInfo::storeRegToStackSlotImpl(
1703 FrameInfo.getObjectAlign(FrameIndex));
1704 unsigned SpillSize = RI.getSpillSize(*RC);
1710 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1711 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1712 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1721 if (SrcReg.
isVirtual() && SpillSize == 4) {
1735 SpillSize, *MFI, NeedsCFI);
1750 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1759 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1766 return AMDGPU::SI_SPILL_S32_RESTORE;
1768 return AMDGPU::SI_SPILL_S64_RESTORE;
1770 return AMDGPU::SI_SPILL_S96_RESTORE;
1772 return AMDGPU::SI_SPILL_S128_RESTORE;
1774 return AMDGPU::SI_SPILL_S160_RESTORE;
1776 return AMDGPU::SI_SPILL_S192_RESTORE;
1778 return AMDGPU::SI_SPILL_S224_RESTORE;
1780 return AMDGPU::SI_SPILL_S256_RESTORE;
1782 return AMDGPU::SI_SPILL_S288_RESTORE;
1784 return AMDGPU::SI_SPILL_S320_RESTORE;
1786 return AMDGPU::SI_SPILL_S352_RESTORE;
1788 return AMDGPU::SI_SPILL_S384_RESTORE;
1790 return AMDGPU::SI_SPILL_S512_RESTORE;
1792 return AMDGPU::SI_SPILL_S1024_RESTORE;
1801 return AMDGPU::SI_SPILL_V16_RESTORE;
1803 return AMDGPU::SI_SPILL_V32_RESTORE;
1805 return AMDGPU::SI_SPILL_V64_RESTORE;
1807 return AMDGPU::SI_SPILL_V96_RESTORE;
1809 return AMDGPU::SI_SPILL_V128_RESTORE;
1811 return AMDGPU::SI_SPILL_V160_RESTORE;
1813 return AMDGPU::SI_SPILL_V192_RESTORE;
1815 return AMDGPU::SI_SPILL_V224_RESTORE;
1817 return AMDGPU::SI_SPILL_V256_RESTORE;
1819 return AMDGPU::SI_SPILL_V288_RESTORE;
1821 return AMDGPU::SI_SPILL_V320_RESTORE;
1823 return AMDGPU::SI_SPILL_V352_RESTORE;
1825 return AMDGPU::SI_SPILL_V384_RESTORE;
1827 return AMDGPU::SI_SPILL_V512_RESTORE;
1829 return AMDGPU::SI_SPILL_V1024_RESTORE;
1838 return AMDGPU::SI_SPILL_AV32_RESTORE;
1840 return AMDGPU::SI_SPILL_AV64_RESTORE;
1842 return AMDGPU::SI_SPILL_AV96_RESTORE;
1844 return AMDGPU::SI_SPILL_AV128_RESTORE;
1846 return AMDGPU::SI_SPILL_AV160_RESTORE;
1848 return AMDGPU::SI_SPILL_AV192_RESTORE;
1850 return AMDGPU::SI_SPILL_AV224_RESTORE;
1852 return AMDGPU::SI_SPILL_AV256_RESTORE;
1854 return AMDGPU::SI_SPILL_AV288_RESTORE;
1856 return AMDGPU::SI_SPILL_AV320_RESTORE;
1858 return AMDGPU::SI_SPILL_AV352_RESTORE;
1860 return AMDGPU::SI_SPILL_AV384_RESTORE;
1862 return AMDGPU::SI_SPILL_AV512_RESTORE;
1864 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1871 bool IsVectorSuperClass) {
1876 if (IsVectorSuperClass)
1877 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1879 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1885 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1892 if (ST.hasMAIInsts())
1895 assert(!RI.isAGPRClass(RC));
1909 unsigned SpillSize = RI.getSpillSize(*RC);
1916 FrameInfo.getObjectAlign(FrameIndex));
1918 if (RI.isSGPRClass(RC)) {
1921 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1922 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1923 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1928 if (DestReg.
isVirtual() && SpillSize == 4) {
1957 unsigned Quantity)
const {
1959 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1960 while (Quantity > 0) {
1961 unsigned Arg = std::min(Quantity, MaxSNopCount);
1972 constexpr unsigned DoorbellIDMask = 0x3ff;
1973 constexpr unsigned ECQueueWaveAbort = 0x400;
1978 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1979 MBB.splitAt(
MI,
false);
1983 MBB.addSuccessor(TrapBB);
1993 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1997 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2002 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2003 .
addUse(DoorbellRegMasked)
2004 .
addImm(ECQueueWaveAbort);
2005 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2006 .
addUse(SetWaveAbortBit);
2009 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2020 return MBB.getNextNode();
2024 switch (
MI.getOpcode()) {
2026 if (
MI.isMetaInstruction())
2031 return MI.getOperand(0).getImm() + 1;
2042 switch (
MI.getOpcode()) {
2044 case AMDGPU::S_MOV_B64_term:
2047 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2050 case AMDGPU::S_MOV_B32_term:
2053 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2056 case AMDGPU::S_XOR_B64_term:
2059 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2062 case AMDGPU::S_XOR_B32_term:
2065 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2067 case AMDGPU::S_OR_B64_term:
2070 MI.setDesc(
get(AMDGPU::S_OR_B64));
2072 case AMDGPU::S_OR_B32_term:
2075 MI.setDesc(
get(AMDGPU::S_OR_B32));
2078 case AMDGPU::S_ANDN2_B64_term:
2081 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2084 case AMDGPU::S_ANDN2_B32_term:
2087 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2090 case AMDGPU::S_AND_B64_term:
2093 MI.setDesc(
get(AMDGPU::S_AND_B64));
2096 case AMDGPU::S_AND_B32_term:
2099 MI.setDesc(
get(AMDGPU::S_AND_B32));
2102 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2105 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2108 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2111 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2114 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2115 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2117 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2118 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2121 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2122 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2125 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2126 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2128 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2132 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2135 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2138 int64_t
Imm =
MI.getOperand(1).getImm();
2140 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2141 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2146 MI.eraseFromParent();
2152 case AMDGPU::V_MOV_B64_PSEUDO: {
2154 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2155 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2163 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2164 MI.setDesc(Mov64Desc);
2168 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2171 if (
SrcOp.isGlobal()) {
2176 unsigned BaseFlags, LoReloc, HiReloc;
2177 std::tie(BaseFlags, LoReloc, HiReloc) =
2184 }
else if (
SrcOp.isImm()) {
2186 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2187 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2211 if (ST.hasPkMovB32() &&
2230 MI.eraseFromParent();
2233 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2237 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2241 if (ST.has64BitLiterals()) {
2242 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2246 if (
SrcOp.isGlobal()) {
2248 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2249 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2252 unsigned BaseFlags, LoReloc, HiReloc;
2253 std::tie(BaseFlags, LoReloc, HiReloc) =
2260 MI.eraseFromParent();
2267 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2272 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2273 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2275 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2276 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2281 MI.eraseFromParent();
2284 case AMDGPU::V_SET_INACTIVE_B32: {
2288 .
add(
MI.getOperand(3))
2289 .
add(
MI.getOperand(4))
2290 .
add(
MI.getOperand(1))
2291 .
add(
MI.getOperand(2))
2292 .
add(
MI.getOperand(5));
2293 MI.eraseFromParent();
2296 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2297 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2298 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2299 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2300 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2301 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2302 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2303 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2304 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2305 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2306 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2307 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2308 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2309 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2310 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2311 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2312 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2313 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2314 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2315 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2316 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2317 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2318 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2319 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2320 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2321 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2322 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2323 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2324 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2325 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2326 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2327 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2328 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2332 if (RI.hasVGPRs(EltRC)) {
2333 Opc = AMDGPU::V_MOVRELD_B32_e32;
2335 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2336 : AMDGPU::S_MOVRELD_B32;
2341 bool IsUndef =
MI.getOperand(1).isUndef();
2342 unsigned SubReg =
MI.getOperand(3).getImm();
2343 assert(VecReg ==
MI.getOperand(1).getReg());
2348 .
add(
MI.getOperand(2))
2352 const int ImpDefIdx =
2354 const int ImpUseIdx = ImpDefIdx + 1;
2356 MI.eraseFromParent();
2359 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2360 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2361 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2362 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2363 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2364 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2365 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2366 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2367 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2368 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2369 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2370 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2371 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2372 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2373 assert(ST.useVGPRIndexMode());
2375 bool IsUndef =
MI.getOperand(1).isUndef();
2384 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2388 .
add(
MI.getOperand(2))
2392 const int ImpDefIdx =
2394 const int ImpUseIdx = ImpDefIdx + 1;
2401 MI.eraseFromParent();
2404 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2405 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2406 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2407 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2408 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2409 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2410 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2411 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2412 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2413 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2414 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2415 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2416 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2417 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2418 assert(ST.useVGPRIndexMode());
2421 bool IsUndef =
MI.getOperand(1).isUndef();
2425 .
add(
MI.getOperand(2))
2438 MI.eraseFromParent();
2441 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2444 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2445 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2464 if (ST.hasGetPCZeroExtension()) {
2468 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2475 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2485 MI.eraseFromParent();
2488 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2498 Op.setOffset(
Op.getOffset() + 4);
2500 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2504 MI.eraseFromParent();
2507 case AMDGPU::ENTER_STRICT_WWM: {
2513 case AMDGPU::ENTER_STRICT_WQM: {
2520 MI.eraseFromParent();
2523 case AMDGPU::EXIT_STRICT_WWM:
2524 case AMDGPU::EXIT_STRICT_WQM: {
2530 case AMDGPU::SI_RETURN: {
2544 MI.eraseFromParent();
2548 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2549 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2550 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2553 case AMDGPU::S_GETPC_B64_pseudo:
2554 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2555 if (ST.hasGetPCZeroExtension()) {
2557 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2566 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2567 assert(ST.hasBF16PackedInsts());
2568 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2579 case AMDGPU::GET_STACK_BASE:
2582 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2589 Register DestReg =
MI.getOperand(0).getReg();
2599 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2600 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2601 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2604 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2607 MI.getNumExplicitOperands());
2625 case AMDGPU::S_MOV_B64:
2626 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2635 if (UsedLanes.
all())
2640 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2641 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2643 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2644 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2646 if (NeedLo && NeedHi)
2650 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2652 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2661 case AMDGPU::S_LOAD_DWORDX16_IMM:
2662 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2675 for (
auto &CandMO :
I->operands()) {
2676 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2684 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2688 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2694 unsigned NewOpcode = -1;
2695 if (SubregSize == 256)
2696 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2697 else if (SubregSize == 128)
2698 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2708 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2713 MI->getOperand(0).setReg(DestReg);
2714 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2718 OffsetMO->
setImm(FinalOffset);
2724 MI->setMemRefs(*MF, NewMMOs);
2737std::pair<MachineInstr*, MachineInstr*>
2739 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2741 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2744 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2745 return std::pair(&
MI,
nullptr);
2756 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2758 if (Dst.isPhysical()) {
2759 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2766 for (
unsigned I = 1;
I <= 2; ++
I) {
2769 if (
SrcOp.isImm()) {
2771 Imm.ashrInPlace(Part * 32);
2772 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2776 if (Src.isPhysical())
2777 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2784 MovDPP.addImm(MO.getImm());
2786 Split[Part] = MovDPP;
2790 if (Dst.isVirtual())
2797 MI.eraseFromParent();
2798 return std::pair(Split[0], Split[1]);
2801std::optional<DestSourcePair>
2803 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2806 return std::nullopt;
2810 AMDGPU::OpName Src0OpName,
2812 AMDGPU::OpName Src1OpName)
const {
2819 "All commutable instructions have both src0 and src1 modifiers");
2821 int Src0ModsVal = Src0Mods->
getImm();
2822 int Src1ModsVal = Src1Mods->
getImm();
2824 Src1Mods->
setImm(Src0ModsVal);
2825 Src0Mods->
setImm(Src1ModsVal);
2834 bool IsKill = RegOp.
isKill();
2836 bool IsUndef = RegOp.
isUndef();
2837 bool IsDebug = RegOp.
isDebug();
2839 if (NonRegOp.
isImm())
2841 else if (NonRegOp.
isFI())
2862 int64_t NonRegVal = NonRegOp1.
getImm();
2865 NonRegOp2.
setImm(NonRegVal);
2872 unsigned OpIdx1)
const {
2877 unsigned Opc =
MI.getOpcode();
2878 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2888 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2891 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2896 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2902 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2917 unsigned Src1Idx)
const {
2918 assert(!NewMI &&
"this should never be used");
2920 unsigned Opc =
MI.getOpcode();
2922 if (CommutedOpcode == -1)
2925 if (Src0Idx > Src1Idx)
2928 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2929 static_cast<int>(Src0Idx) &&
2930 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2931 static_cast<int>(Src1Idx) &&
2932 "inconsistency with findCommutedOpIndices");
2957 Src1, AMDGPU::OpName::src1_modifiers);
2960 AMDGPU::OpName::src1_sel);
2972 unsigned &SrcOpIdx0,
2973 unsigned &SrcOpIdx1)
const {
2978 unsigned &SrcOpIdx0,
2979 unsigned &SrcOpIdx1)
const {
2980 if (!
Desc.isCommutable())
2983 unsigned Opc =
Desc.getOpcode();
2984 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2988 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2992 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2996 int64_t BrOffset)
const {
3013 return MI.getOperand(0).getMBB();
3018 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3019 MI.getOpcode() == AMDGPU::SI_LOOP)
3031 "new block should be inserted for expanding unconditional branch");
3034 "restore block should be inserted for restoring clobbered registers");
3042 if (ST.useAddPC64Inst()) {
3044 MCCtx.createTempSymbol(
"offset",
true);
3048 MCCtx.createTempSymbol(
"post_addpc",
true);
3049 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3053 Offset->setVariableValue(OffsetExpr);
3057 assert(RS &&
"RegScavenger required for long branching");
3065 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3066 ST.hasVALUReadSGPRHazard();
3067 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3068 if (FlushSGPRWrites)
3076 ApplyHazardWorkarounds();
3079 MCCtx.createTempSymbol(
"post_getpc",
true);
3083 MCCtx.createTempSymbol(
"offset_lo",
true);
3085 MCCtx.createTempSymbol(
"offset_hi",
true);
3088 .
addReg(PCReg, {}, AMDGPU::sub0)
3092 .
addReg(PCReg, {}, AMDGPU::sub1)
3094 ApplyHazardWorkarounds();
3135 if (LongBranchReservedReg) {
3136 RS->enterBasicBlock(
MBB);
3137 Scav = LongBranchReservedReg;
3139 RS->enterBasicBlockEnd(
MBB);
3140 Scav = RS->scavengeRegisterBackwards(
3145 RS->setRegUsed(Scav);
3153 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3170unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3172 case SIInstrInfo::SCC_TRUE:
3173 return AMDGPU::S_CBRANCH_SCC1;
3174 case SIInstrInfo::SCC_FALSE:
3175 return AMDGPU::S_CBRANCH_SCC0;
3176 case SIInstrInfo::VCCNZ:
3177 return AMDGPU::S_CBRANCH_VCCNZ;
3178 case SIInstrInfo::VCCZ:
3179 return AMDGPU::S_CBRANCH_VCCZ;
3180 case SIInstrInfo::EXECNZ:
3181 return AMDGPU::S_CBRANCH_EXECNZ;
3182 case SIInstrInfo::EXECZ:
3183 return AMDGPU::S_CBRANCH_EXECZ;
3189SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3191 case AMDGPU::S_CBRANCH_SCC0:
3193 case AMDGPU::S_CBRANCH_SCC1:
3195 case AMDGPU::S_CBRANCH_VCCNZ:
3197 case AMDGPU::S_CBRANCH_VCCZ:
3199 case AMDGPU::S_CBRANCH_EXECNZ:
3201 case AMDGPU::S_CBRANCH_EXECZ:
3213 bool AllowModify)
const {
3214 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3216 TBB =
I->getOperand(0).getMBB();
3220 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3221 if (Pred == INVALID_BR)
3226 Cond.push_back(
I->getOperand(1));
3230 if (
I ==
MBB.end()) {
3236 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3238 FBB =
I->getOperand(0).getMBB();
3248 bool AllowModify)
const {
3256 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3257 switch (
I->getOpcode()) {
3258 case AMDGPU::S_MOV_B64_term:
3259 case AMDGPU::S_XOR_B64_term:
3260 case AMDGPU::S_OR_B64_term:
3261 case AMDGPU::S_ANDN2_B64_term:
3262 case AMDGPU::S_AND_B64_term:
3263 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3264 case AMDGPU::S_MOV_B32_term:
3265 case AMDGPU::S_XOR_B32_term:
3266 case AMDGPU::S_OR_B32_term:
3267 case AMDGPU::S_ANDN2_B32_term:
3268 case AMDGPU::S_AND_B32_term:
3269 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3270 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3271 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3274 case AMDGPU::SI_ELSE:
3275 case AMDGPU::SI_KILL_I1_TERMINATOR:
3276 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3293 int *BytesRemoved)
const {
3295 unsigned RemovedSize = 0;
3298 if (
MI.isBranch() ||
MI.isReturn()) {
3300 MI.eraseFromParent();
3306 *BytesRemoved = RemovedSize;
3323 int *BytesAdded)
const {
3324 if (!FBB &&
Cond.empty()) {
3328 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3335 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3347 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3365 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3372 if (
Cond.size() != 2) {
3376 if (
Cond[0].isImm()) {
3397 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3401 std::optional<bool> createTripCountGreaterCondition(
3402 int TC, MachineBasicBlock &
MBB,
3403 SmallVectorImpl<MachineOperand> &CondParam)
override {
3404 CondParam = this->
Cond;
3408 void adjustTripCount(
int TripCountAdjust)
override {}
3410 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3414std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3423 if (
TBB == LoopBB && FBB == LoopBB)
3430 assert((
TBB == LoopBB || FBB == LoopBB) &&
3431 "The Loop must be a single-basic-block loop");
3434 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3435 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3440 if (
MI.isCall() ||
MI.isInlineAsm())
3455 if (CmpI == Instructions.end() || CmpI->isPHI())
3459 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3465 Register FalseReg,
int &CondCycles,
3466 int &TrueCycles,
int &FalseCycles)
const {
3476 CondCycles = TrueCycles = FalseCycles = NumInsts;
3479 return RI.hasVGPRs(RC) && NumInsts <= 6;
3493 if (NumInsts % 2 == 0)
3496 CondCycles = TrueCycles = FalseCycles = NumInsts;
3497 return RI.isSGPRClass(RC);
3508 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3509 if (Pred == VCCZ || Pred == SCC_FALSE) {
3510 Pred =
static_cast<BranchPredicate
>(-Pred);
3516 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3518 if (DstSize == 32) {
3520 if (Pred == SCC_TRUE) {
3535 if (DstSize == 64 && Pred == SCC_TRUE) {
3545 static const int16_t Sub0_15[] = {
3546 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3547 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3548 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3549 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3552 static const int16_t Sub0_15_64[] = {
3553 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3554 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3555 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3556 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3559 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3561 const int16_t *SubIndices = Sub0_15;
3562 int NElts = DstSize / 32;
3566 if (Pred == SCC_TRUE) {
3568 SelOp = AMDGPU::S_CSELECT_B32;
3569 EltRC = &AMDGPU::SGPR_32RegClass;
3571 SelOp = AMDGPU::S_CSELECT_B64;
3572 EltRC = &AMDGPU::SGPR_64RegClass;
3573 SubIndices = Sub0_15_64;
3579 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3584 for (
int Idx = 0; Idx != NElts; ++Idx) {
3588 unsigned SubIdx = SubIndices[Idx];
3591 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3593 .
addReg(FalseReg, {}, SubIdx)
3594 .addReg(TrueReg, {}, SubIdx);
3597 .
addReg(TrueReg, {}, SubIdx)
3598 .addReg(FalseReg, {}, SubIdx);
3611 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3614 switch (
MI.getOpcode()) {
3615 case AMDGPU::S_ENDPGM:
3616 case AMDGPU::S_ENDPGM_SAVED:
3617 case AMDGPU::S_TRAP:
3618 case AMDGPU::S_GETREG_B32:
3619 case AMDGPU::S_SETREG_B32:
3620 case AMDGPU::S_SETREG_B32_mode:
3621 case AMDGPU::S_SETREG_IMM32_B32:
3622 case AMDGPU::S_SETREG_IMM32_B32_mode:
3623 case AMDGPU::S_SENDMSG:
3624 case AMDGPU::S_SENDMSGHALT:
3625 case AMDGPU::S_SENDMSG_RTN_B32:
3626 case AMDGPU::S_SENDMSG_RTN_B64:
3627 case AMDGPU::S_BARRIER_WAIT:
3628 case AMDGPU::S_BARRIER_SIGNAL_M0:
3629 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3630 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3631 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3639 switch (
MI.getOpcode()) {
3640 case AMDGPU::V_MOV_B16_t16_e32:
3641 case AMDGPU::V_MOV_B16_t16_e64:
3642 case AMDGPU::V_MOV_B32_e32:
3643 case AMDGPU::V_MOV_B32_e64:
3644 case AMDGPU::V_MOV_B64_PSEUDO:
3645 case AMDGPU::V_MOV_B64_e32:
3646 case AMDGPU::V_MOV_B64_e64:
3647 case AMDGPU::S_MOV_B32:
3648 case AMDGPU::S_MOV_B64:
3649 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3651 case AMDGPU::WWM_COPY:
3652 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3653 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3654 case AMDGPU::V_ACCVGPR_MOV_B32:
3655 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3656 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3664 switch (
MI.getOpcode()) {
3665 case AMDGPU::V_MOV_B16_t16_e32:
3666 case AMDGPU::V_MOV_B16_t16_e64:
3668 case AMDGPU::V_MOV_B32_e32:
3669 case AMDGPU::V_MOV_B32_e64:
3670 case AMDGPU::V_MOV_B64_PSEUDO:
3671 case AMDGPU::V_MOV_B64_e32:
3672 case AMDGPU::V_MOV_B64_e64:
3673 case AMDGPU::S_MOV_B32:
3674 case AMDGPU::S_MOV_B64:
3675 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3677 case AMDGPU::WWM_COPY:
3678 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3679 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3680 case AMDGPU::V_ACCVGPR_MOV_B32:
3681 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3682 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3690 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3691 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3692 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3695 unsigned Opc =
MI.getOpcode();
3697 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3699 MI.removeOperand(Idx);
3705 MI.setDesc(NewDesc);
3711 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3712 Desc.implicit_defs().size();
3714 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3715 MI.removeOperand(
I);
3719 unsigned SubRegIndex) {
3720 switch (SubRegIndex) {
3721 case AMDGPU::NoSubRegister:
3731 case AMDGPU::sub1_lo16:
3733 case AMDGPU::sub1_hi16:
3736 return std::nullopt;
3744 case AMDGPU::V_MAC_F16_e32:
3745 case AMDGPU::V_MAC_F16_e64:
3746 case AMDGPU::V_MAD_F16_e64:
3747 return AMDGPU::V_MADAK_F16;
3748 case AMDGPU::V_MAC_F32_e32:
3749 case AMDGPU::V_MAC_F32_e64:
3750 case AMDGPU::V_MAD_F32_e64:
3751 return AMDGPU::V_MADAK_F32;
3752 case AMDGPU::V_FMAC_F32_e32:
3753 case AMDGPU::V_FMAC_F32_e64:
3754 case AMDGPU::V_FMA_F32_e64:
3755 return AMDGPU::V_FMAAK_F32;
3756 case AMDGPU::V_FMAC_F16_e32:
3757 case AMDGPU::V_FMAC_F16_e64:
3758 case AMDGPU::V_FMAC_F16_t16_e64:
3759 case AMDGPU::V_FMAC_F16_fake16_e64:
3760 case AMDGPU::V_FMAC_F16_t16_e32:
3761 case AMDGPU::V_FMAC_F16_fake16_e32:
3762 case AMDGPU::V_FMA_F16_e64:
3763 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3764 ? AMDGPU::V_FMAAK_F16_t16
3765 : AMDGPU::V_FMAAK_F16_fake16
3766 : AMDGPU::V_FMAAK_F16;
3767 case AMDGPU::V_FMAC_F64_e32:
3768 case AMDGPU::V_FMAC_F64_e64:
3769 case AMDGPU::V_FMA_F64_e64:
3770 return AMDGPU::V_FMAAK_F64;
3778 case AMDGPU::V_MAC_F16_e32:
3779 case AMDGPU::V_MAC_F16_e64:
3780 case AMDGPU::V_MAD_F16_e64:
3781 return AMDGPU::V_MADMK_F16;
3782 case AMDGPU::V_MAC_F32_e32:
3783 case AMDGPU::V_MAC_F32_e64:
3784 case AMDGPU::V_MAD_F32_e64:
3785 return AMDGPU::V_MADMK_F32;
3786 case AMDGPU::V_FMAC_F32_e32:
3787 case AMDGPU::V_FMAC_F32_e64:
3788 case AMDGPU::V_FMA_F32_e64:
3789 return AMDGPU::V_FMAMK_F32;
3790 case AMDGPU::V_FMAC_F16_e32:
3791 case AMDGPU::V_FMAC_F16_e64:
3792 case AMDGPU::V_FMAC_F16_t16_e64:
3793 case AMDGPU::V_FMAC_F16_fake16_e64:
3794 case AMDGPU::V_FMAC_F16_t16_e32:
3795 case AMDGPU::V_FMAC_F16_fake16_e32:
3796 case AMDGPU::V_FMA_F16_e64:
3797 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3798 ? AMDGPU::V_FMAMK_F16_t16
3799 : AMDGPU::V_FMAMK_F16_fake16
3800 : AMDGPU::V_FMAMK_F16;
3801 case AMDGPU::V_FMAC_F64_e32:
3802 case AMDGPU::V_FMAC_F64_e64:
3803 case AMDGPU::V_FMA_F64_e64:
3804 return AMDGPU::V_FMAMK_F64;
3818 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3821 if (
Opc == AMDGPU::COPY) {
3822 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3829 if (HasMultipleUses) {
3832 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3835 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3843 if (ImmDefSize == 32 &&
3848 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3849 RI.getSubRegIdxSize(UseSubReg) == 16;
3852 if (RI.hasVGPRs(DstRC))
3855 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3861 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3868 for (
unsigned MovOp :
3869 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3870 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3878 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3882 if (MovDstPhysReg) {
3886 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3893 if (MovDstPhysReg) {
3894 if (!MovDstRC->
contains(MovDstPhysReg))
3910 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3918 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3922 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3924 UseMI.getOperand(0).setReg(MovDstPhysReg);
3929 UseMI.setDesc(NewMCID);
3930 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3931 UseMI.addImplicitDefUseOperands(*MF);
3935 if (HasMultipleUses)
3938 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3939 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3940 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3941 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3942 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3943 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3944 Opc == AMDGPU::V_FMAC_F64_e64) {
3953 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3964 auto CopyRegOperandToNarrowerRC =
3967 if (!
MI.getOperand(OpNo).isReg())
3971 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3974 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3975 get(AMDGPU::COPY), Tmp)
3977 MI.getOperand(OpNo).setReg(Tmp);
3978 MI.getOperand(OpNo).setIsKill();
3985 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
3986 if (!RegSrc->
isReg())
3989 ST.getConstantBusLimit(
Opc) < 2)
4004 if (Def && Def->isMoveImmediate() &&
4019 unsigned SrcSubReg = RegSrc->
getSubReg();
4024 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4025 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4026 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4027 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4028 UseMI.untieRegOperand(
4029 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4036 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4037 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4041 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4042 UseMI.getOperand(0).getReg())
4044 UseMI.getOperand(0).setReg(Tmp);
4045 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4046 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4051 DefMI.eraseFromParent();
4058 if (ST.getConstantBusLimit(
Opc) < 2) {
4061 bool Src0Inlined =
false;
4062 if (Src0->
isReg()) {
4067 if (Def && Def->isMoveImmediate() &&
4072 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4073 RI.isSGPRReg(*MRI, Src0->
getReg())) {
4079 if (Src1->
isReg() && !Src0Inlined) {
4082 if (Def && Def->isMoveImmediate() &&
4086 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
4099 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4100 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4101 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4102 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4103 UseMI.untieRegOperand(
4104 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4106 const std::optional<int64_t> SubRegImm =
4116 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4117 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4121 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4122 UseMI.getOperand(0).getReg())
4124 UseMI.getOperand(0).setReg(Tmp);
4125 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4126 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4136 DefMI.eraseFromParent();
4148 if (BaseOps1.
size() != BaseOps2.
size())
4150 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4151 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4159 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4160 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4161 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4163 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4166bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4169 int64_t Offset0, Offset1;
4172 bool Offset0IsScalable, Offset1IsScalable;
4186 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4187 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4194 "MIa must load from or modify a memory location");
4196 "MIb must load from or modify a memory location");
4218 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4225 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4235 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4249 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4261 unsigned NumOps =
MI.getNumOperands();
4264 if (
Op.isReg() &&
Op.isKill())
4272 case AMDGPU::V_MAC_F16_e32:
4273 case AMDGPU::V_MAC_F16_e64:
4274 return AMDGPU::V_MAD_F16_e64;
4275 case AMDGPU::V_MAC_F32_e32:
4276 case AMDGPU::V_MAC_F32_e64:
4277 return AMDGPU::V_MAD_F32_e64;
4278 case AMDGPU::V_MAC_LEGACY_F32_e32:
4279 case AMDGPU::V_MAC_LEGACY_F32_e64:
4280 return AMDGPU::V_MAD_LEGACY_F32_e64;
4281 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4282 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4283 return AMDGPU::V_FMA_LEGACY_F32_e64;
4284 case AMDGPU::V_FMAC_F16_e32:
4285 case AMDGPU::V_FMAC_F16_e64:
4286 case AMDGPU::V_FMAC_F16_t16_e64:
4287 case AMDGPU::V_FMAC_F16_fake16_e64:
4288 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4289 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4290 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4291 : AMDGPU::V_FMA_F16_gfx9_e64;
4292 case AMDGPU::V_FMAC_F32_e32:
4293 case AMDGPU::V_FMAC_F32_e64:
4294 return AMDGPU::V_FMA_F32_e64;
4295 case AMDGPU::V_FMAC_F64_e32:
4296 case AMDGPU::V_FMAC_F64_e64:
4297 return AMDGPU::V_FMA_F64_e64;
4317 if (
MI.isBundle()) {
4320 if (
MI.getBundleSize() != 1)
4322 CandidateMI =
MI.getNextNode();
4326 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4330 if (
MI.isBundle()) {
4335 MI.untieRegOperand(MO.getOperandNo());
4343 if (Def.isEarlyClobber() && Def.isReg() &&
4348 auto UpdateDefIndex = [&](
LiveRange &LR) {
4349 auto *S = LR.find(OldIndex);
4350 if (S != LR.end() && S->start == OldIndex) {
4351 assert(S->valno && S->valno->def == OldIndex);
4352 S->start = NewIndex;
4353 S->valno->def = NewIndex;
4357 for (
auto &SR : LI.subranges())
4363 if (U.RemoveMIUse) {
4366 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4370 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4371 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4372 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4373 U.RemoveMIUse->removeOperand(
I);
4378 if (
MI.isBundle()) {
4382 if (MO.isReg() && MO.getReg() == DefReg) {
4383 assert(MO.getSubReg() == 0 &&
4384 "tied sub-registers in bundles currently not supported");
4385 MI.removeOperand(MO.getOperandNo());
4402 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4403 MIOp.setIsUndef(
true);
4404 MIOp.setReg(DummyReg);
4408 if (
MI.isBundle()) {
4412 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4413 MIOp.setIsUndef(
true);
4414 MIOp.setReg(DummyReg);
4427 return MI.isBundle() ? &
MI : NewMI;
4432 ThreeAddressUpdates &U)
const {
4434 unsigned Opc =
MI.getOpcode();
4438 if (NewMFMAOpc != -1) {
4441 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4442 MIB.
add(
MI.getOperand(
I));
4450 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4455 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4456 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4457 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4461 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4462 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4463 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4464 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4465 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4466 bool Src0Literal =
false;
4471 case AMDGPU::V_MAC_F16_e64:
4472 case AMDGPU::V_FMAC_F16_e64:
4473 case AMDGPU::V_FMAC_F16_t16_e64:
4474 case AMDGPU::V_FMAC_F16_fake16_e64:
4475 case AMDGPU::V_MAC_F32_e64:
4476 case AMDGPU::V_MAC_LEGACY_F32_e64:
4477 case AMDGPU::V_FMAC_F32_e64:
4478 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4479 case AMDGPU::V_FMAC_F64_e64:
4481 case AMDGPU::V_MAC_F16_e32:
4482 case AMDGPU::V_FMAC_F16_e32:
4483 case AMDGPU::V_MAC_F32_e32:
4484 case AMDGPU::V_MAC_LEGACY_F32_e32:
4485 case AMDGPU::V_FMAC_F32_e32:
4486 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4487 case AMDGPU::V_FMAC_F64_e32: {
4488 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4489 AMDGPU::OpName::src0);
4490 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4501 MachineInstrBuilder MIB;
4504 const MachineOperand *Src0Mods =
4507 const MachineOperand *Src1Mods =
4510 const MachineOperand *Src2Mods =
4516 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4517 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4519 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4521 MachineInstr *
DefMI =
nullptr;
4523 std::optional<int64_t> ImmOpt;
4558 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4574 if (Src0Literal && !ST.hasVOP3Literal())
4602 switch (
MI.getOpcode()) {
4603 case AMDGPU::S_SET_GPR_IDX_ON:
4604 case AMDGPU::S_SET_GPR_IDX_MODE:
4605 case AMDGPU::S_SET_GPR_IDX_OFF:
4623 if (
MI.isTerminator() ||
MI.isPosition())
4627 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4630 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4636 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4637 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4638 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4639 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4640 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4645 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4646 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4647 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4661 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4666 if (
MI.memoperands_empty())
4671 unsigned AS = Memop->getAddrSpace();
4672 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4673 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4674 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4675 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4690 if (
MI.memoperands_empty())
4699 unsigned AS = Memop->getAddrSpace();
4709 bool TgSplit)
const {
4722 if (
MI.memoperands_empty())
4727 unsigned AS = Memop->getAddrSpace();
4743 unsigned Opcode =
MI.getOpcode();
4758 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4759 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4760 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4761 Opcode == AMDGPU::S_SETHALT)
4764 if (
MI.isCall() ||
MI.isInlineAsm())
4780 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4781 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4782 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4783 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4791 if (
MI.isMetaInstruction())
4795 if (
MI.isCopyLike()) {
4796 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4800 return MI.readsRegister(AMDGPU::EXEC, &RI);
4811 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4815 switch (
Imm.getBitWidth()) {
4821 ST.hasInv2PiInlineImm());
4824 ST.hasInv2PiInlineImm());
4826 return ST.has16BitInsts() &&
4828 ST.hasInv2PiInlineImm());
4835 APInt IntImm =
Imm.bitcastToAPInt();
4837 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4845 return ST.has16BitInsts() &&
4848 return ST.has16BitInsts() &&
4858 switch (OperandType) {
4868 int32_t Trunc =
static_cast<int32_t
>(
Imm);
4912 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4913 return ST.has16BitInsts() &&
4922 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4923 return ST.has16BitInsts() &&
4974 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4980 return ST.hasVOP3Literal();
4984 int64_t ImmVal)
const {
4986 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
4987 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
4988 OpNo ==
static_cast<unsigned>(Src1Idx))
4993 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4994 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
4995 AMDGPU::OpName::src2))
4998 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5005 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5017 "unexpected imm-like operand kind");
5030 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5048 AMDGPU::OpName
OpName)
const {
5050 return Mods && Mods->
getImm();
5063 switch (
MI.getOpcode()) {
5064 default:
return false;
5066 case AMDGPU::V_ADDC_U32_e64:
5067 case AMDGPU::V_SUBB_U32_e64:
5068 case AMDGPU::V_SUBBREV_U32_e64: {
5071 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
5076 case AMDGPU::V_MAC_F16_e64:
5077 case AMDGPU::V_MAC_F32_e64:
5078 case AMDGPU::V_MAC_LEGACY_F32_e64:
5079 case AMDGPU::V_FMAC_F16_e64:
5080 case AMDGPU::V_FMAC_F16_t16_e64:
5081 case AMDGPU::V_FMAC_F16_fake16_e64:
5082 case AMDGPU::V_FMAC_F32_e64:
5083 case AMDGPU::V_FMAC_F64_e64:
5084 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5085 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5090 case AMDGPU::V_CNDMASK_B32_e64:
5096 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5109 if (Src0 && Src0->
isImm()) {
5112 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5134 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5143 unsigned Op32)
const {
5157 Inst32.
add(
MI.getOperand(
I));
5161 int Idx =
MI.getNumExplicitDefs();
5163 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5168 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5190 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5198 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5201 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5202 AMDGPU::SReg_64RegClass.contains(Reg);
5230 switch (MO.getReg()) {
5232 case AMDGPU::VCC_LO:
5233 case AMDGPU::VCC_HI:
5235 case AMDGPU::FLAT_SCR:
5248 switch (
MI.getOpcode()) {
5249 case AMDGPU::V_READLANE_B32:
5250 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5251 case AMDGPU::V_WRITELANE_B32:
5252 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5259 if (
MI.isPreISelOpcode() ||
5260 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5278 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5289 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5290 ErrInfo =
"illegal copy from vector register to SGPR";
5308 if (!MRI.
isSSA() &&
MI.isCopy())
5309 return verifyCopy(
MI, MRI, ErrInfo);
5311 if (SIInstrInfo::isGenericOpcode(Opcode))
5314 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5315 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5316 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5318 if (Src0Idx == -1) {
5320 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5321 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5322 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5323 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5328 if (!
Desc.isVariadic() &&
5329 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5330 ErrInfo =
"Instruction has wrong number of operands.";
5334 if (
MI.isInlineAsm()) {
5347 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5348 ErrInfo =
"inlineasm operand has incorrect register class.";
5356 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5357 ErrInfo =
"missing memory operand from image instruction.";
5362 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5365 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5366 "all fp values to integers.";
5371 int16_t RegClass = getOpRegClassID(OpInfo);
5373 switch (OpInfo.OperandType) {
5375 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5376 ErrInfo =
"Illegal immediate value for operand.";
5409 ErrInfo =
"Illegal immediate value for operand.";
5418 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5421 OpInfo.OperandType ==
5423 ErrInfo =
"illegal 64-bit immediate value for operand.";
5430 ErrInfo =
"Expected inline constant for operand.";
5444 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5445 ErrInfo =
"Expected immediate, but got non-immediate";
5454 if (OpInfo.isGenericType())
5469 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5470 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5472 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5474 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5475 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5482 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5483 ErrInfo =
"Subtarget requires even aligned vector registers";
5488 if (RegClass != -1) {
5489 if (Reg.isVirtual())
5494 ErrInfo =
"Operand has incorrect register class.";
5502 if (!ST.hasSDWA()) {
5503 ErrInfo =
"SDWA is not supported on this target";
5507 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5508 AMDGPU::OpName::dst_sel}) {
5514 ErrInfo =
"Invalid SDWA selection";
5519 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5521 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5526 if (!ST.hasSDWAScalar()) {
5528 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5529 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5536 "Only reg allowed as operands in SDWA instructions on GFX9+";
5542 if (!ST.hasSDWAOmod()) {
5545 if (OMod !=
nullptr &&
5547 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5552 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5553 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5554 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5555 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5558 unsigned Mods = Src0ModsMO->
getImm();
5561 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5567 if (
isVOPC(BasicOpcode)) {
5568 if (!ST.hasSDWASdst() && DstIdx != -1) {
5571 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5572 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5575 }
else if (!ST.hasSDWAOutModsVOPC()) {
5578 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5579 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5585 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5586 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5593 if (DstUnused && DstUnused->isImm() &&
5596 if (!Dst.isReg() || !Dst.isTied()) {
5597 ErrInfo =
"Dst register should have tied register";
5602 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5605 "Dst register should be tied to implicit use of preserved register";
5609 ErrInfo =
"Dst register should use same physical register as preserved";
5615 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5617 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5618 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5621 if (Src1MO.
isImm()) {
5622 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5628 if (
isImage(Opcode) && !
MI.mayStore()) {
5633 uint64_t DMaskImm = DMask->
getImm();
5640 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5648 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5652 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5653 if (RegCount > DstSize) {
5654 ErrInfo =
"Image instruction returns too many registers for dst "
5664 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5665 unsigned ConstantBusCount = 0;
5666 bool UsesLiteral =
false;
5669 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5673 LiteralVal = &
MI.getOperand(ImmIdx);
5682 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5693 }
else if (!MO.
isFI()) {
5700 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5710 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5711 return !RI.regsOverlap(SGPRUsed, SGPR);
5720 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5721 Opcode != AMDGPU::V_WRITELANE_B32) {
5722 ErrInfo =
"VOP* instruction violates constant bus restriction";
5726 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5727 ErrInfo =
"VOP3 instruction uses literal";
5734 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5735 unsigned SGPRCount = 0;
5738 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5746 if (MO.
getReg() != SGPRUsed)
5751 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5752 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5759 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5760 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5767 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5777 ErrInfo =
"ABS not allowed in VOP3B instructions";
5790 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5797 if (
Desc.isBranch()) {
5799 ErrInfo =
"invalid branch target for SOPK instruction";
5803 uint64_t
Imm =
Op->getImm();
5806 ErrInfo =
"invalid immediate for SOPK instruction";
5811 ErrInfo =
"invalid immediate for SOPK instruction";
5818 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5819 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5820 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5821 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5822 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5823 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5825 const unsigned StaticNumOps =
5826 Desc.getNumOperands() +
Desc.implicit_uses().size();
5827 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5833 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5834 ErrInfo =
"missing implicit register operands";
5840 if (!Dst->isUse()) {
5841 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5846 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5847 UseOpIdx != StaticNumOps + 1) {
5848 ErrInfo =
"movrel implicit operands should be tied";
5855 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5857 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5858 ErrInfo =
"src0 should be subreg of implicit vector use";
5866 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5867 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5873 if (
MI.mayStore() &&
5878 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5879 ErrInfo =
"scalar stores must use m0 as offset register";
5885 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5887 if (
Offset->getImm() != 0) {
5888 ErrInfo =
"subtarget does not support offsets in flat instructions";
5893 if (
isDS(
MI) && !ST.hasGDS()) {
5895 if (GDSOp && GDSOp->
getImm() != 0) {
5896 ErrInfo =
"GDS is not supported on this subtarget";
5904 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5905 AMDGPU::OpName::vaddr0);
5906 AMDGPU::OpName RSrcOpName =
5907 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5908 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5916 ErrInfo =
"dim is out of range";
5921 if (ST.hasR128A16()) {
5923 IsA16 = R128A16->
getImm() != 0;
5924 }
else if (ST.hasA16()) {
5926 IsA16 = A16->
getImm() != 0;
5929 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5931 unsigned AddrWords =
5934 unsigned VAddrWords;
5936 VAddrWords = RsrcIdx - VAddr0Idx;
5937 if (ST.hasPartialNSAEncoding() &&
5939 unsigned LastVAddrIdx = RsrcIdx - 1;
5940 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5948 if (VAddrWords != AddrWords) {
5950 <<
" but got " << VAddrWords <<
"\n");
5951 ErrInfo =
"bad vaddr size";
5961 unsigned DC = DppCt->
getImm();
5962 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5963 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5964 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5965 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5966 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5967 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5968 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5969 ErrInfo =
"Invalid dpp_ctrl value";
5972 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5973 !ST.hasDPPWavefrontShifts()) {
5974 ErrInfo =
"Invalid dpp_ctrl value: "
5975 "wavefront shifts are not supported on GFX10+";
5978 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5979 !ST.hasDPPBroadcasts()) {
5980 ErrInfo =
"Invalid dpp_ctrl value: "
5981 "broadcasts are not supported on GFX10+";
5984 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5986 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5987 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5988 !ST.hasGFX90AInsts()) {
5989 ErrInfo =
"Invalid dpp_ctrl value: "
5990 "row_newbroadcast/row_share is not supported before "
5994 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5995 ErrInfo =
"Invalid dpp_ctrl value: "
5996 "row_share and row_xmask are not supported before GFX10";
6001 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6004 ErrInfo =
"Invalid dpp_ctrl value: "
6005 "DP ALU dpp only support row_newbcast";
6012 AMDGPU::OpName DataName =
6013 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6019 if (!ST.hasGFX90AInsts()) {
6020 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6021 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6022 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6023 ErrInfo =
"Invalid register class: "
6024 "agpr loads and stores not supported on this GPU";
6030 if (ST.needsAlignedVGPRs()) {
6031 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6036 if (Reg.isPhysical())
6037 return !(RI.getHWRegIndex(Reg) & 1);
6039 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6040 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6043 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
6044 Opcode == AMDGPU::DS_GWS_BARRIER) {
6046 if (!isAlignedReg(AMDGPU::OpName::data0)) {
6047 ErrInfo =
"Subtarget requires even aligned vector registers "
6048 "for DS_GWS instructions";
6054 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6055 ErrInfo =
"Subtarget requires even aligned vector registers "
6056 "for vaddr operand of image instructions";
6062 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6064 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6065 ErrInfo =
"Invalid register class: "
6066 "v_accvgpr_write with an SGPR is not supported on this GPU";
6071 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6074 ErrInfo =
"pseudo expects only physical SGPRs";
6081 if (!ST.hasScaleOffset()) {
6082 ErrInfo =
"Subtarget does not support offset scaling";
6086 ErrInfo =
"Instruction does not support offset scaling";
6094 for (
unsigned I = 0;
I < 3; ++
I) {
6100 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6101 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6103 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6104 &AMDGPU::SReg_64RegClass) ||
6105 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6106 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6115 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6117 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6119 : AMDGPU::V_MOV_B32_e32;
6129 default:
return AMDGPU::INSTRUCTION_LIST_END;
6130 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6131 case AMDGPU::COPY:
return AMDGPU::COPY;
6132 case AMDGPU::PHI:
return AMDGPU::PHI;
6133 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6134 case AMDGPU::WQM:
return AMDGPU::WQM;
6135 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6136 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6137 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6138 case AMDGPU::S_ADD_I32:
6139 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6140 case AMDGPU::S_ADDC_U32:
6141 return AMDGPU::V_ADDC_U32_e32;
6142 case AMDGPU::S_SUB_I32:
6143 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6146 case AMDGPU::S_ADD_U32:
6147 return AMDGPU::V_ADD_CO_U32_e32;
6148 case AMDGPU::S_SUB_U32:
6149 return AMDGPU::V_SUB_CO_U32_e32;
6150 case AMDGPU::S_ADD_U64_PSEUDO:
6151 return AMDGPU::V_ADD_U64_PSEUDO;
6152 case AMDGPU::S_SUB_U64_PSEUDO:
6153 return AMDGPU::V_SUB_U64_PSEUDO;
6154 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6155 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6156 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6157 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6158 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6159 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6160 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6161 case AMDGPU::S_XNOR_B32:
6162 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6163 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6164 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6165 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6166 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6167 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6168 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6169 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6170 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6171 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6172 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6173 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6174 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6175 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6176 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6177 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6178 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6179 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6180 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6181 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6182 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6183 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6184 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6185 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6186 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6187 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6188 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6189 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6190 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6191 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6192 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6193 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6194 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6195 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6196 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6197 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6198 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6199 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6200 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6201 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6202 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6203 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6204 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6205 case AMDGPU::S_CVT_F32_F16:
6206 case AMDGPU::S_CVT_HI_F32_F16:
6207 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6208 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6209 case AMDGPU::S_CVT_F16_F32:
6210 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6211 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6212 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6213 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6214 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6215 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6216 case AMDGPU::S_CEIL_F16:
6217 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6218 : AMDGPU::V_CEIL_F16_fake16_e64;
6219 case AMDGPU::S_FLOOR_F16:
6220 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6221 : AMDGPU::V_FLOOR_F16_fake16_e64;
6222 case AMDGPU::S_TRUNC_F16:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6224 : AMDGPU::V_TRUNC_F16_fake16_e64;
6225 case AMDGPU::S_RNDNE_F16:
6226 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6227 : AMDGPU::V_RNDNE_F16_fake16_e64;
6228 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6229 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6230 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6231 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6232 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6233 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6234 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6235 case AMDGPU::S_ADD_F16:
6236 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6237 : AMDGPU::V_ADD_F16_fake16_e64;
6238 case AMDGPU::S_SUB_F16:
6239 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6240 : AMDGPU::V_SUB_F16_fake16_e64;
6241 case AMDGPU::S_MIN_F16:
6242 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6243 : AMDGPU::V_MIN_F16_fake16_e64;
6244 case AMDGPU::S_MAX_F16:
6245 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6246 : AMDGPU::V_MAX_F16_fake16_e64;
6247 case AMDGPU::S_MINIMUM_F16:
6248 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6249 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6250 case AMDGPU::S_MAXIMUM_F16:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6252 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6253 case AMDGPU::S_MUL_F16:
6254 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6255 : AMDGPU::V_MUL_F16_fake16_e64;
6256 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6257 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6258 case AMDGPU::S_FMAC_F16:
6259 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6260 : AMDGPU::V_FMAC_F16_fake16_e64;
6261 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6262 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6263 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6264 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6265 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6266 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6267 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6268 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6269 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6270 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6271 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6272 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6273 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6274 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6275 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6276 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6277 case AMDGPU::S_CMP_LT_F16:
6278 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6279 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6280 case AMDGPU::S_CMP_EQ_F16:
6281 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6282 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6283 case AMDGPU::S_CMP_LE_F16:
6284 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6285 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6286 case AMDGPU::S_CMP_GT_F16:
6287 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6288 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6289 case AMDGPU::S_CMP_LG_F16:
6290 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6291 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6292 case AMDGPU::S_CMP_GE_F16:
6293 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6294 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6295 case AMDGPU::S_CMP_O_F16:
6296 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6297 : AMDGPU::V_CMP_O_F16_fake16_e64;
6298 case AMDGPU::S_CMP_U_F16:
6299 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6300 : AMDGPU::V_CMP_U_F16_fake16_e64;
6301 case AMDGPU::S_CMP_NGE_F16:
6302 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6303 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6304 case AMDGPU::S_CMP_NLG_F16:
6305 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6306 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6307 case AMDGPU::S_CMP_NGT_F16:
6308 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6309 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6310 case AMDGPU::S_CMP_NLE_F16:
6311 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6312 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6313 case AMDGPU::S_CMP_NEQ_F16:
6314 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6315 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6316 case AMDGPU::S_CMP_NLT_F16:
6317 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6318 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6319 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6320 case AMDGPU::V_S_EXP_F16_e64:
6321 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6322 : AMDGPU::V_EXP_F16_fake16_e64;
6323 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6324 case AMDGPU::V_S_LOG_F16_e64:
6325 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6326 : AMDGPU::V_LOG_F16_fake16_e64;
6327 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6328 case AMDGPU::V_S_RCP_F16_e64:
6329 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6330 : AMDGPU::V_RCP_F16_fake16_e64;
6331 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6332 case AMDGPU::V_S_RSQ_F16_e64:
6333 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6334 : AMDGPU::V_RSQ_F16_fake16_e64;
6335 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6336 case AMDGPU::V_S_SQRT_F16_e64:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6338 : AMDGPU::V_SQRT_F16_fake16_e64;
6341 "Unexpected scalar opcode without corresponding vector one!");
6390 "Not a whole wave func");
6393 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6394 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6401 unsigned OpNo)
const {
6403 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6404 Desc.operands()[OpNo].RegClass == -1) {
6407 if (Reg.isVirtual()) {
6411 return RI.getPhysRegBaseClass(Reg);
6414 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6415 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6420 constexpr AMDGPU::OpName OpNames[] = {
6421 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6424 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6425 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6437 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6439 unsigned Size = RI.getRegSizeInBits(*RC);
6440 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6441 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6442 : AMDGPU::V_MOV_B32_e32;
6444 Opcode = AMDGPU::COPY;
6445 else if (RI.isSGPRClass(RC))
6446 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6471 .
addImm(AMDGPU::sub0_sub1)
6473 .
addImm(AMDGPU::sub2_sub3);
6486 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6492 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6503 if (SubIdx == AMDGPU::sub0)
6505 if (SubIdx == AMDGPU::sub1)
6517void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6533 if (Reg.isPhysical())
6540 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6543 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6546 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6553 unsigned Opc =
MI.getOpcode();
6556 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6566 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6567 if (IsAGPR && !ST.hasMAIInsts())
6573 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6574 const int DataIdx = AMDGPU::getNamedOperandIdx(
6575 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6576 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6577 MI.getOperand(DataIdx).isReg() &&
6578 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6580 if ((
int)OpIdx == DataIdx) {
6581 if (VDstIdx != -1 &&
6582 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6585 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6586 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6587 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6592 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6593 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6594 RI.isSGPRReg(MRI, MO.
getReg()))
6597 if (ST.hasFlatScratchHiInB64InstHazard() &&
6604 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6607 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6608 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6628 constexpr unsigned NumOps = 3;
6629 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6630 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6631 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6632 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6637 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6640 MO = &
MI.getOperand(SrcIdx);
6643 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6647 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6651 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6655 return !OpSel && !OpSelHi;
6664 int64_t RegClass = getOpRegClassID(OpInfo);
6666 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6668 MO = &
MI.getOperand(OpIdx);
6672 if (
isVALU(
MI,
true) && !IsInlineConst &&
6676 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6677 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6681 if (!LiteralLimit--)
6691 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6699 if (--ConstantBusLimit <= 0)
6711 if (!LiteralLimit--)
6713 if (--ConstantBusLimit <= 0)
6719 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6723 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6725 !
Op.isIdenticalTo(*MO))
6735 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6750 bool Is64BitOp = Is64BitFPOp ||
6758 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6767 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6785 bool IsGFX950Only = ST.hasGFX950Insts();
6786 bool IsGFX940Only = ST.hasGFX940Insts();
6788 if (!IsGFX950Only && !IsGFX940Only)
6806 unsigned Opcode =
MI.getOpcode();
6808 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6809 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6810 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6811 case AMDGPU::V_MQSAD_U32_U8_e64:
6812 case AMDGPU::V_PK_ADD_F16:
6813 case AMDGPU::V_PK_ADD_F32:
6814 case AMDGPU::V_PK_ADD_I16:
6815 case AMDGPU::V_PK_ADD_U16:
6816 case AMDGPU::V_PK_ASHRREV_I16:
6817 case AMDGPU::V_PK_FMA_F16:
6818 case AMDGPU::V_PK_FMA_F32:
6819 case AMDGPU::V_PK_FMAC_F16_e32:
6820 case AMDGPU::V_PK_FMAC_F16_e64:
6821 case AMDGPU::V_PK_LSHLREV_B16:
6822 case AMDGPU::V_PK_LSHRREV_B16:
6823 case AMDGPU::V_PK_MAD_I16:
6824 case AMDGPU::V_PK_MAD_U16:
6825 case AMDGPU::V_PK_MAX_F16:
6826 case AMDGPU::V_PK_MAX_I16:
6827 case AMDGPU::V_PK_MAX_U16:
6828 case AMDGPU::V_PK_MIN_F16:
6829 case AMDGPU::V_PK_MIN_I16:
6830 case AMDGPU::V_PK_MIN_U16:
6831 case AMDGPU::V_PK_MOV_B32:
6832 case AMDGPU::V_PK_MUL_F16:
6833 case AMDGPU::V_PK_MUL_F32:
6834 case AMDGPU::V_PK_MUL_LO_U16:
6835 case AMDGPU::V_PK_SUB_I16:
6836 case AMDGPU::V_PK_SUB_U16:
6837 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6846 unsigned Opc =
MI.getOpcode();
6849 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6852 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6858 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6859 RI.isSGPRReg(MRI, Src0.
getReg()))
6865 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6867 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6873 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6884 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6885 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6886 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6898 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6899 RI.isVGPR(MRI, Src1.
getReg())) {
6912 if (HasImplicitSGPR || !
MI.isCommutable()) {
6929 if (CommutedOpc == -1) {
6934 MI.setDesc(
get(CommutedOpc));
6938 bool Src0Kill = Src0.
isKill();
6942 else if (Src1.
isReg()) {
6957 unsigned Opc =
MI.getOpcode();
6960 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6961 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6962 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6965 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6966 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6967 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6968 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6969 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6970 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6971 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6981 if (VOP3Idx[2] != -1) {
6993 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
6994 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6996 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
6998 SGPRsUsed.
insert(SGPRReg);
7002 for (
int Idx : VOP3Idx) {
7011 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7023 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7030 if (ConstantBusLimit > 0) {
7042 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
7043 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7049 for (
unsigned I = 0;
I < 3; ++
I) {
7062 SRC = RI.getCommonSubClass(SRC, DstRC);
7065 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7067 if (RI.hasAGPRs(VRC)) {
7068 VRC = RI.getEquivalentVGPRClass(VRC);
7071 get(TargetOpcode::COPY), NewSrcReg)
7078 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7084 for (
unsigned i = 0; i < SubRegs; ++i) {
7087 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7088 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7094 get(AMDGPU::REG_SEQUENCE), DstReg);
7095 for (
unsigned i = 0; i < SubRegs; ++i) {
7097 MIB.
addImm(RI.getSubRegFromChannel(i));
7110 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7112 SBase->setReg(SGPR);
7115 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7123 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7124 if (OldSAddrIdx < 0)
7137 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7140 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7141 if (NewVAddrIdx < 0)
7144 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7148 if (OldVAddrIdx >= 0) {
7162 if (OldVAddrIdx == NewVAddrIdx) {
7173 assert(OldSAddrIdx == NewVAddrIdx);
7175 if (OldVAddrIdx >= 0) {
7176 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7177 AMDGPU::OpName::vdst_in);
7181 if (NewVDstIn != -1) {
7182 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7188 if (NewVDstIn != -1) {
7189 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7230 unsigned OpSubReg =
Op.getSubReg();
7233 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7240 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7241 .
addReg(OpReg, {}, OpSubReg);
7243 Op.setSubReg(AMDGPU::NoSubRegister);
7250 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7253 bool ImpDef = Def->isImplicitDef();
7254 while (!ImpDef && Def && Def->isCopy()) {
7255 if (Def->getOperand(1).getReg().isPhysical())
7258 ImpDef = Def && Def->isImplicitDef();
7260 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7276 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7281 bool UseNewExecInstructions =
7290 if (UseNewExecInstructions) {
7325 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7326 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7327 unsigned NumSubRegs =
RegSize / 32;
7328 Register VScalarOp = ScalarOp->getReg();
7331 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7333 if (NumSubRegs == 1) {
7336 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7337 Common != VScalarOpRC) {
7344 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7347 if (UseNewExecInstructions) {
7349 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7352 if (
I == LoopBB.
end())
7357 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7363 CondReg = NewCondReg;
7374 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7375 ScalarOp->setReg(CurReg);
7378 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7379 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7381 ScalarOp->setReg(PhySGPRs[Idx]);
7383 ScalarOp->setIsKill();
7387 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7388 "Unhandled register size");
7390 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7397 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7398 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7401 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7402 .
addReg(VScalarOp, VScalarOpUndef,
7403 TRI->getSubRegFromChannel(Idx + 1));
7410 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7417 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7419 if (UseNewExecInstructions) {
7421 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7423 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7424 if (
I == LoopBB.
end())
7428 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7430 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7434 CondReg = NewCondReg;
7445 const auto *SScalarOpRC =
7451 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7452 unsigned Channel = 0;
7453 for (
Register Piece : ReadlanePieces) {
7454 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7458 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7459 ScalarOp->setReg(SScalarOp);
7461 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7462 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7464 ScalarOp->setReg(PhySGPRs[Idx]);
7466 ScalarOp->setIsKill();
7474 if (!UseNewExecInstructions) {
7486 if (UseNewExecInstructions) {
7510 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7511 "Physical SGPRs must be empty or match the number of scalar operands");
7517 if (!Begin.isValid())
7519 if (!End.isValid()) {
7525 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7534 std::numeric_limits<unsigned>::max()) !=
7552 for (
auto I = Begin;
I != AfterMI;
I++) {
7553 for (
auto &MO :
I->all_uses())
7589 for (
auto &Succ : RemainderBB->
successors()) {
7614static std::tuple<unsigned, unsigned>
7622 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7623 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7630 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7647 .
addImm(AMDGPU::sub0_sub1)
7653 return std::tuple(RsrcPtr, NewSRsrc);
7664 if (ST.useRealTrue16Insts())
7694 if (
MI.getOpcode() == AMDGPU::PHI) {
7696 assert(!RI.isSGPRClass(VRC));
7699 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7701 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7717 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7720 if (RI.hasVGPRs(DstRC)) {
7724 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7726 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7744 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7749 if (DstRC != Src0RC) {
7758 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7760 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7766 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7767 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7768 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7769 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7770 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7771 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7772 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7774 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7787 ? AMDGPU::OpName::rsrc
7788 : AMDGPU::OpName::srsrc;
7793 AMDGPU::OpName SampOpName =
7794 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7803 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7811 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7815 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7825 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7826 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7827 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7828 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7830 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7837 bool isSoffsetLegal =
true;
7839 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7840 if (SoffsetIdx != -1) {
7844 isSoffsetLegal =
false;
7848 bool isRsrcLegal =
true;
7850 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7851 if (RsrcIdx != -1) {
7853 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7854 isRsrcLegal =
false;
7858 if (isRsrcLegal && isSoffsetLegal)
7886 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7890 unsigned RsrcPtr, NewSRsrc;
7897 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7898 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7904 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7905 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7918 }
else if (!VAddr && ST.hasAddr64()) {
7922 "FIXME: Need to emit flat atomics here");
7924 unsigned RsrcPtr, NewSRsrc;
7950 MIB.
addImm(CPol->getImm());
7955 MIB.
addImm(TFE->getImm());
7975 MI.removeFromParent();
7980 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7981 .addImm(AMDGPU::sub0)
7982 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7983 .addImm(AMDGPU::sub1);
7986 if (!isSoffsetLegal) {
7997 if (!isSoffsetLegal) {
8006 if (InSet.insert(
MI).second)
8010 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8011 if (RsrcIdx != -1) {
8012 DeferredList.insert(
MI);
8017 return DeferredList.contains(
MI);
8027 if (!ST.useRealTrue16Insts())
8030 unsigned Opcode =
MI.getOpcode();
8033 if (OpIdx >=
MI.getNumExplicitOperands() ||
8034 OpIdx >=
get(Opcode).getNumOperands() ||
8035 get(Opcode).operands()[OpIdx].RegClass == -1)
8039 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8043 if (!RI.isVGPRClass(CurrRC))
8046 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8048 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8050 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8051 Op.setSubReg(AMDGPU::lo16);
8056 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8057 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8067 Op.setReg(NewDstReg);
8068 Op.setSubReg(AMDGPU::NoSubRegister);
8073 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8081 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8082 "This only handle waterfall for SI_CALL_ISEL");
8089 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8092 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8097 while (End !=
MBB.end() && End->isCopy() &&
8098 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8108 while (!Worklist.
empty()) {
8114 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8120 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8122 "Deferred MachineInstr are not supposed to re-populate worklist");
8125 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8126 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8128 Entry.second.SGPRs);
8131 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8133 Entry.first->eraseFromParent();
8141 if (SubRegIndices.
size() <= 1) {
8144 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8151 for (int16_t Indice : SubRegIndices) {
8154 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8161 get(AMDGPU::REG_SEQUENCE), DstReg);
8162 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8164 MIB.
addImm(RI.getSubRegFromChannel(i));
8174 if (DstReg == AMDGPU::M0) {
8187 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8189 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8190 if (
UseMI->getOperand(i).isReg() &&
8191 UseMI->getOperand(i).getReg() == DstReg) {
8195 V2SCopyInfo.MOs.push_back(MO);
8196 V2SCopyInfo.SGPRs.push_back(DstReg);
8200 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8201 I->getOperand(0).isReg() &&
8202 I->getOperand(0).getReg() == DstReg) {
8205 }
else if (
I->readsRegister(DstReg, &RI)) {
8207 V2SPhyCopiesToErase[&Inst] =
false;
8209 if (
I->findRegisterDefOperand(DstReg, &RI))
8231 case AMDGPU::S_ADD_I32:
8232 case AMDGPU::S_SUB_I32: {
8236 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8244 case AMDGPU::S_MUL_U64:
8245 if (ST.hasVMulU64Inst()) {
8246 NewOpcode = AMDGPU::V_MUL_U64_e64;
8250 splitScalarSMulU64(Worklist, Inst, MDT);
8254 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8255 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8258 splitScalarSMulPseudo(Worklist, Inst, MDT);
8262 case AMDGPU::S_AND_B64:
8263 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8267 case AMDGPU::S_OR_B64:
8268 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8272 case AMDGPU::S_XOR_B64:
8273 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8277 case AMDGPU::S_NAND_B64:
8278 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8282 case AMDGPU::S_NOR_B64:
8283 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8287 case AMDGPU::S_XNOR_B64:
8288 if (ST.hasDLInsts())
8289 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8291 splitScalar64BitXnor(Worklist, Inst, MDT);
8295 case AMDGPU::S_ANDN2_B64:
8296 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8300 case AMDGPU::S_ORN2_B64:
8301 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8305 case AMDGPU::S_BREV_B64:
8306 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8310 case AMDGPU::S_NOT_B64:
8311 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8315 case AMDGPU::S_BCNT1_I32_B64:
8316 splitScalar64BitBCNT(Worklist, Inst);
8320 case AMDGPU::S_BFE_I64:
8321 splitScalar64BitBFE(Worklist, Inst);
8325 case AMDGPU::S_FLBIT_I32_B64:
8326 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8329 case AMDGPU::S_FF1_I32_B64:
8330 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8334 case AMDGPU::S_LSHL_B32:
8335 if (ST.hasOnlyRevVALUShifts()) {
8336 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8340 case AMDGPU::S_ASHR_I32:
8341 if (ST.hasOnlyRevVALUShifts()) {
8342 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8346 case AMDGPU::S_LSHR_B32:
8347 if (ST.hasOnlyRevVALUShifts()) {
8348 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8352 case AMDGPU::S_LSHL_B64:
8353 if (ST.hasOnlyRevVALUShifts()) {
8355 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8356 : AMDGPU::V_LSHLREV_B64_e64;
8360 case AMDGPU::S_ASHR_I64:
8361 if (ST.hasOnlyRevVALUShifts()) {
8362 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8366 case AMDGPU::S_LSHR_B64:
8367 if (ST.hasOnlyRevVALUShifts()) {
8368 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8373 case AMDGPU::S_ABS_I32:
8374 lowerScalarAbs(Worklist, Inst);
8378 case AMDGPU::S_ABSDIFF_I32:
8379 lowerScalarAbsDiff(Worklist, Inst);
8383 case AMDGPU::S_CBRANCH_SCC0:
8384 case AMDGPU::S_CBRANCH_SCC1: {
8387 bool IsSCC = CondReg == AMDGPU::SCC;
8395 case AMDGPU::S_BFE_U64:
8396 case AMDGPU::S_BFM_B64:
8399 case AMDGPU::S_PACK_LL_B32_B16:
8400 case AMDGPU::S_PACK_LH_B32_B16:
8401 case AMDGPU::S_PACK_HL_B32_B16:
8402 case AMDGPU::S_PACK_HH_B32_B16:
8403 movePackToVALU(Worklist, MRI, Inst);
8407 case AMDGPU::S_XNOR_B32:
8408 lowerScalarXnor(Worklist, Inst);
8412 case AMDGPU::S_NAND_B32:
8413 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8417 case AMDGPU::S_NOR_B32:
8418 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8422 case AMDGPU::S_ANDN2_B32:
8423 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8427 case AMDGPU::S_ORN2_B32:
8428 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8436 case AMDGPU::S_ADD_CO_PSEUDO:
8437 case AMDGPU::S_SUB_CO_PSEUDO: {
8438 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8439 ? AMDGPU::V_ADDC_U32_e64
8440 : AMDGPU::V_SUBB_U32_e64;
8441 const auto *CarryRC = RI.getWaveMaskRegClass();
8463 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8467 case AMDGPU::S_UADDO_PSEUDO:
8468 case AMDGPU::S_USUBO_PSEUDO: {
8474 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8475 ? AMDGPU::V_ADD_CO_U32_e64
8476 : AMDGPU::V_SUB_CO_U32_e64;
8488 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8492 case AMDGPU::S_LSHL1_ADD_U32:
8493 case AMDGPU::S_LSHL2_ADD_U32:
8494 case AMDGPU::S_LSHL3_ADD_U32:
8495 case AMDGPU::S_LSHL4_ADD_U32: {
8499 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8500 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8501 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8515 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8519 case AMDGPU::S_CSELECT_B32:
8520 case AMDGPU::S_CSELECT_B64:
8521 lowerSelect(Worklist, Inst, MDT);
8524 case AMDGPU::S_CMP_EQ_I32:
8525 case AMDGPU::S_CMP_LG_I32:
8526 case AMDGPU::S_CMP_GT_I32:
8527 case AMDGPU::S_CMP_GE_I32:
8528 case AMDGPU::S_CMP_LT_I32:
8529 case AMDGPU::S_CMP_LE_I32:
8530 case AMDGPU::S_CMP_EQ_U32:
8531 case AMDGPU::S_CMP_LG_U32:
8532 case AMDGPU::S_CMP_GT_U32:
8533 case AMDGPU::S_CMP_GE_U32:
8534 case AMDGPU::S_CMP_LT_U32:
8535 case AMDGPU::S_CMP_LE_U32:
8536 case AMDGPU::S_CMP_EQ_U64:
8537 case AMDGPU::S_CMP_LG_U64:
8538 case AMDGPU::S_CMP_LT_F32:
8539 case AMDGPU::S_CMP_EQ_F32:
8540 case AMDGPU::S_CMP_LE_F32:
8541 case AMDGPU::S_CMP_GT_F32:
8542 case AMDGPU::S_CMP_LG_F32:
8543 case AMDGPU::S_CMP_GE_F32:
8544 case AMDGPU::S_CMP_O_F32:
8545 case AMDGPU::S_CMP_U_F32:
8546 case AMDGPU::S_CMP_NGE_F32:
8547 case AMDGPU::S_CMP_NLG_F32:
8548 case AMDGPU::S_CMP_NGT_F32:
8549 case AMDGPU::S_CMP_NLE_F32:
8550 case AMDGPU::S_CMP_NEQ_F32:
8551 case AMDGPU::S_CMP_NLT_F32: {
8556 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8570 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8574 case AMDGPU::S_CMP_LT_F16:
8575 case AMDGPU::S_CMP_EQ_F16:
8576 case AMDGPU::S_CMP_LE_F16:
8577 case AMDGPU::S_CMP_GT_F16:
8578 case AMDGPU::S_CMP_LG_F16:
8579 case AMDGPU::S_CMP_GE_F16:
8580 case AMDGPU::S_CMP_O_F16:
8581 case AMDGPU::S_CMP_U_F16:
8582 case AMDGPU::S_CMP_NGE_F16:
8583 case AMDGPU::S_CMP_NLG_F16:
8584 case AMDGPU::S_CMP_NGT_F16:
8585 case AMDGPU::S_CMP_NLE_F16:
8586 case AMDGPU::S_CMP_NEQ_F16:
8587 case AMDGPU::S_CMP_NLT_F16: {
8609 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8613 case AMDGPU::S_CVT_HI_F32_F16: {
8616 if (ST.useRealTrue16Insts()) {
8621 .
addReg(TmpReg, {}, AMDGPU::hi16)
8637 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8641 case AMDGPU::S_MINIMUM_F32:
8642 case AMDGPU::S_MAXIMUM_F32: {
8654 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8658 case AMDGPU::S_MINIMUM_F16:
8659 case AMDGPU::S_MAXIMUM_F16: {
8661 ? &AMDGPU::VGPR_16RegClass
8662 : &AMDGPU::VGPR_32RegClass);
8673 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8677 case AMDGPU::V_S_EXP_F16_e64:
8678 case AMDGPU::V_S_LOG_F16_e64:
8679 case AMDGPU::V_S_RCP_F16_e64:
8680 case AMDGPU::V_S_RSQ_F16_e64:
8681 case AMDGPU::V_S_SQRT_F16_e64: {
8683 ? &AMDGPU::VGPR_16RegClass
8684 : &AMDGPU::VGPR_32RegClass);
8695 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8701 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8709 if (NewOpcode == Opcode) {
8716 V2SPhyCopiesToErase);
8724 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8731 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8737 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8738 UseMO.setReg(NewDstReg);
8757 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8770 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8774 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8780 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8787 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8789 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8794 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8802 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8812 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8813 AMDGPU::OpName::src0_modifiers) >= 0)
8817 NewInstr->addOperand(Src);
8820 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8823 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8825 NewInstr.addImm(
Size);
8826 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8830 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8835 "Scalar BFE is only implemented for constant width and offset");
8843 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8844 AMDGPU::OpName::src1_modifiers) >= 0)
8846 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8848 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8849 AMDGPU::OpName::src2_modifiers) >= 0)
8851 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8853 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8855 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8857 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8863 NewInstr->addOperand(
Op);
8870 if (
Op.getReg() == AMDGPU::SCC) {
8872 if (
Op.isDef() && !
Op.isDead())
8873 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8875 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8880 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8881 Register DstReg = NewInstr->getOperand(0).getReg();
8894 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8898std::pair<bool, MachineBasicBlock *>
8901 if (ST.hasAddNoCarryInsts()) {
8913 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8915 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8916 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8927 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8928 return std::pair(
true, NewBB);
8931 return std::pair(
false,
nullptr);
8948 bool IsSCC = (CondReg == AMDGPU::SCC);
8956 for (MachineOperand &UseMO :
8958 MachineInstr &
UseMI = *UseMO.getParent();
8959 switch (
UseMI.getOpcode()) {
8960 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8961 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8962 case AMDGPU::V_CNDMASK_B16_t16_e32:
8963 case AMDGPU::V_CNDMASK_B16_t16_e64:
8964 case AMDGPU::V_CNDMASK_B32_e32:
8965 case AMDGPU::V_CNDMASK_B32_e64:
8966 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8967 if (UseMO.isImplicit() ||
8969 UseMO.setReg(CondReg);
8983 bool CopyFound =
false;
8984 for (MachineInstr &CandI :
8987 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
8989 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8991 .
addReg(CandI.getOperand(1).getReg());
9003 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9012 MachineInstr *NewInst;
9013 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9014 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9029 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9044 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9045 : AMDGPU::V_SUB_CO_U32_e32;
9056 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9073 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9074 : AMDGPU::V_SUB_CO_U32_e32;
9087 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9101 if (ST.hasDLInsts()) {
9111 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9117 bool Src0IsSGPR = Src0.
isReg() &&
9119 bool Src1IsSGPR = Src1.
isReg() &&
9133 }
else if (Src1IsSGPR) {
9151 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9157 unsigned Opcode)
const {
9181 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9186 unsigned Opcode)
const {
9210 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9225 const MCInstrDesc &InstDesc =
get(Opcode);
9228 &AMDGPU::SGPR_32RegClass;
9231 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9234 AMDGPU::sub0, Src0SubRC);
9239 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9242 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9245 AMDGPU::sub1, Src0SubRC);
9248 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9262 Worklist.
insert(&LoHalf);
9263 Worklist.
insert(&HiHalf);
9269 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9293 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9294 if (RI.isSGPRClass(Src0SubRC))
9295 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9297 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9298 if (RI.isSGPRClass(Src1SubRC))
9299 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9303 MachineOperand Op0L =
9305 MachineOperand Op1L =
9307 MachineOperand Op0H =
9309 MachineOperand Op1H =
9328 MachineInstr *Op1L_Op0H =
9334 MachineInstr *Op1H_Op0L =
9340 MachineInstr *Carry =
9345 MachineInstr *LoHalf =
9355 MachineInstr *HiHalf =
9378 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9402 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9403 if (RI.isSGPRClass(Src0SubRC))
9404 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9406 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9407 if (RI.isSGPRClass(Src1SubRC))
9408 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9412 MachineOperand Op0L =
9414 MachineOperand Op1L =
9418 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9419 ? AMDGPU::V_MUL_HI_U32_e64
9420 : AMDGPU::V_MUL_HI_I32_e64;
9421 MachineInstr *HiHalf =
9424 MachineInstr *LoHalf =
9443 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9459 const MCInstrDesc &InstDesc =
get(Opcode);
9462 &AMDGPU::SGPR_32RegClass;
9465 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9468 &AMDGPU::SGPR_32RegClass;
9471 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9474 AMDGPU::sub0, Src0SubRC);
9476 AMDGPU::sub0, Src1SubRC);
9478 AMDGPU::sub1, Src0SubRC);
9480 AMDGPU::sub1, Src1SubRC);
9485 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9488 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9493 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9506 Worklist.
insert(&LoHalf);
9507 Worklist.
insert(&HiHalf);
9510 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9530 MachineOperand* Op0;
9531 MachineOperand* Op1;
9533 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9566 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9569 &AMDGPU::SGPR_32RegClass;
9575 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9578 AMDGPU::sub0, SrcSubRC);
9580 AMDGPU::sub1, SrcSubRC);
9590 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9609 Offset == 0 &&
"Not implemented");
9632 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9642 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9645 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9651 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9670 const MCInstrDesc &InstDesc =
get(Opcode);
9672 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9675 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9677 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9679 MachineOperand SrcRegSub0 =
9681 MachineOperand SrcRegSub1 =
9695 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9699 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9703 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9706void SIInstrInfo::addUsersToMoveToVALUWorklist(
9710 MachineInstr &
UseMI = *MO.getParent();
9714 switch (
UseMI.getOpcode()) {
9717 case AMDGPU::SOFT_WQM:
9718 case AMDGPU::STRICT_WWM:
9719 case AMDGPU::STRICT_WQM:
9720 case AMDGPU::REG_SEQUENCE:
9722 case AMDGPU::INSERT_SUBREG:
9725 OpNo = MO.getOperandNo();
9732 if (!RI.hasVectorRegisters(OpRC))
9749 if (ST.useRealTrue16Insts()) {
9751 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9754 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9760 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9763 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9772 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9774 case AMDGPU::S_PACK_LL_B32_B16:
9776 .addReg(SrcReg0, {},
9777 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9778 .addImm(AMDGPU::lo16)
9779 .addReg(SrcReg1, {},
9780 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9781 .addImm(AMDGPU::hi16);
9783 case AMDGPU::S_PACK_LH_B32_B16:
9785 .addReg(SrcReg0, {},
9786 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9787 .addImm(AMDGPU::lo16)
9788 .addReg(SrcReg1, {}, AMDGPU::hi16)
9789 .addImm(AMDGPU::hi16);
9791 case AMDGPU::S_PACK_HL_B32_B16:
9792 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9793 .addImm(AMDGPU::lo16)
9794 .addReg(SrcReg1, {},
9795 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9796 .addImm(AMDGPU::hi16);
9798 case AMDGPU::S_PACK_HH_B32_B16:
9799 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9800 .addImm(AMDGPU::lo16)
9801 .addReg(SrcReg1, {}, AMDGPU::hi16)
9802 .addImm(AMDGPU::hi16);
9810 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9815 case AMDGPU::S_PACK_LL_B32_B16: {
9834 case AMDGPU::S_PACK_LH_B32_B16: {
9844 case AMDGPU::S_PACK_HL_B32_B16: {
9855 case AMDGPU::S_PACK_HH_B32_B16: {
9875 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9884 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9885 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9886 SmallVector<MachineInstr *, 4> CopyToDelete;
9889 for (MachineInstr &
MI :
9893 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9897 Register DestReg =
MI.getOperand(0).getReg();
9904 MI.getOperand(SCCIdx).setReg(NewCond);
9910 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9913 for (
auto &Copy : CopyToDelete)
9914 Copy->eraseFromParent();
9922void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9928 for (MachineInstr &
MI :
9931 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9933 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9950 case AMDGPU::REG_SEQUENCE:
9951 case AMDGPU::INSERT_SUBREG:
9953 case AMDGPU::SOFT_WQM:
9954 case AMDGPU::STRICT_WWM:
9955 case AMDGPU::STRICT_WQM: {
9957 if (RI.isAGPRClass(SrcRC)) {
9958 if (RI.isAGPRClass(NewDstRC))
9963 case AMDGPU::REG_SEQUENCE:
9964 case AMDGPU::INSERT_SUBREG:
9965 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9968 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9974 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9977 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9991 int OpIndices[3])
const {
9992 const MCInstrDesc &
Desc =
MI.getDesc();
10010 for (
unsigned i = 0; i < 3; ++i) {
10011 int Idx = OpIndices[i];
10015 const MachineOperand &MO =
MI.getOperand(Idx);
10022 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10023 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10024 if (IsRequiredSGPR)
10030 if (RI.isSGPRClass(RegRC))
10031 UsedSGPRs[i] =
Reg;
10047 if (UsedSGPRs[0]) {
10048 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10049 SGPRReg = UsedSGPRs[0];
10052 if (!SGPRReg && UsedSGPRs[1]) {
10053 if (UsedSGPRs[1] == UsedSGPRs[2])
10054 SGPRReg = UsedSGPRs[1];
10061 AMDGPU::OpName OperandName)
const {
10062 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10065 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10069 return &
MI.getOperand(Idx);
10083 if (ST.isAmdHsaOS()) {
10086 RsrcDataFormat |= (1ULL << 56);
10091 RsrcDataFormat |= (2ULL << 59);
10094 return RsrcDataFormat;
10104 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10109 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10116 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10122 unsigned Opc =
MI.getOpcode();
10128 return get(
Opc).mayLoad() &&
10135 if (!Addr || !Addr->
isFI())
10144 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10146 return MI.getOperand(VDataIdx).getReg();
10156 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10158 return MI.getOperand(DataIdx).getReg();
10179 if (!
MI.mayStore())
10192 unsigned Opc =
MI.getOpcode();
10194 unsigned DescSize =
Desc.getSize();
10199 unsigned Size = DescSize;
10203 if (
MI.isBranch() && ST.hasOffset3fBug())
10214 bool HasLiteral =
false;
10215 unsigned LiteralSize = 4;
10216 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10221 if (ST.has64BitLiterals()) {
10222 switch (OpInfo.OperandType) {
10247 return HasLiteral ? DescSize + LiteralSize : DescSize;
10252 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10256 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10257 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10261 case TargetOpcode::BUNDLE:
10262 return getInstBundleSize(
MI);
10263 case TargetOpcode::INLINEASM:
10264 case TargetOpcode::INLINEASM_BR: {
10266 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10270 if (
MI.isMetaInstruction())
10274 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10277 unsigned LoInstOpcode = D16Info->LoOp;
10279 DescSize =
Desc.getSize();
10283 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10286 DescSize =
Desc.getSize();
10295 if (
MI.isBranch() && ST.hasOffset3fBug())
10296 return InstSizeVerifyMode::NoVerify;
10297 return InstSizeVerifyMode::ExactSize;
10304 if (
MI.memoperands_empty())
10316 static const std::pair<int, const char *> TargetIndices[] = {
10356std::pair<unsigned, unsigned>
10363 static const std::pair<unsigned, const char *> TargetFlags[] = {
10381 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10397 return AMDGPU::WWM_COPY;
10399 return AMDGPU::COPY;
10416 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10420 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10421 return IsLRSplitInst;
10434 bool IsNullOrVectorRegister =
true;
10438 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10441 return IsNullOrVectorRegister &&
10443 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10444 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10452 if (ST.hasAddNoCarryInsts())
10468 if (ST.hasAddNoCarryInsts())
10472 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10474 : RS.scavengeRegisterBackwards(
10475 *RI.getBoolRC(),
I,
false,
10488 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10489 case AMDGPU::SI_KILL_I1_TERMINATOR:
10498 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10499 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10500 case AMDGPU::SI_KILL_I1_PSEUDO:
10501 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10513 const unsigned OffsetBits =
10515 return (1 << OffsetBits) - 1;
10519 if (!ST.isWave32())
10522 if (
MI.isInlineAsm())
10525 if (
MI.getNumOperands() <
MI.getNumExplicitOperands())
10528 for (
auto &
Op :
MI.implicit_operands()) {
10529 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10530 Op.setReg(AMDGPU::VCC_LO);
10539 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10543 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10544 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10560 if (
Imm > MaxImm) {
10561 if (
Imm <= MaxImm + 64) {
10563 Overflow =
Imm - MaxImm;
10578 Overflow =
High - Alignment.value();
10582 if (Overflow > 0) {
10590 if (ST.hasRestrictedSOffset())
10595 SOffset = Overflow;
10633 if (!ST.hasFlatInstOffsets())
10637 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10642 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10643 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10654std::pair<int64_t, int64_t>
10657 int64_t RemainderOffset = COffsetVal;
10658 int64_t ImmField = 0;
10663 if (AllowNegative) {
10665 int64_t
D = 1LL << NumBits;
10666 RemainderOffset = (COffsetVal /
D) *
D;
10667 ImmField = COffsetVal - RemainderOffset;
10669 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10671 (ImmField % 4) != 0) {
10673 RemainderOffset += ImmField % 4;
10674 ImmField -= ImmField % 4;
10676 }
else if (COffsetVal >= 0) {
10678 RemainderOffset = COffsetVal - ImmField;
10682 assert(RemainderOffset + ImmField == COffsetVal);
10683 return {ImmField, RemainderOffset};
10688 if (ST.hasNegativeScratchOffsetBug() &&
10696 switch (ST.getGeneration()) {
10725 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10726 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10727 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10728 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10729 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10730 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10731 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10732 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10739#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10740 case OPCODE##_dpp: \
10741 case OPCODE##_e32: \
10742 case OPCODE##_e64: \
10743 case OPCODE##_e64_dpp: \
10744 case OPCODE##_sdwa:
10758 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10759 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10760 case AMDGPU::V_FMA_F16_gfx9_e64:
10761 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10762 case AMDGPU::V_INTERP_P2_F16:
10763 case AMDGPU::V_MAD_F16_e64:
10764 case AMDGPU::V_MAD_U16_e64:
10765 case AMDGPU::V_MAD_I16_e64:
10774 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10788 switch (ST.getGeneration()) {
10801 if (
isMAI(Opcode)) {
10809 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10812 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10819 if (ST.hasGFX90AInsts()) {
10820 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10821 if (ST.hasGFX940Insts())
10823 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10825 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10827 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10833 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10852 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10853 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10854 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10866 switch (
MI.getOpcode()) {
10868 case AMDGPU::REG_SEQUENCE:
10872 case AMDGPU::INSERT_SUBREG:
10873 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10890 if (!
P.Reg.isVirtual())
10895 while (
auto *
MI = DefInst) {
10897 switch (
MI->getOpcode()) {
10899 case AMDGPU::V_MOV_B32_e32: {
10900 auto &Op1 =
MI->getOperand(1);
10929 auto *DefBB =
DefMI.getParent();
10933 if (
UseMI.getParent() != DefBB)
10936 const int MaxInstScan = 20;
10940 auto E =
UseMI.getIterator();
10941 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10942 if (
I->isDebugInstr())
10945 if (++NumInst > MaxInstScan)
10948 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10961 auto *DefBB =
DefMI.getParent();
10963 const int MaxUseScan = 10;
10967 auto &UseInst = *
Use.getParent();
10970 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10973 if (++NumUse > MaxUseScan)
10980 const int MaxInstScan = 20;
10984 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
10987 if (
I->isDebugInstr())
10990 if (++NumInst > MaxInstScan)
11003 if (Reg == VReg && --NumUse == 0)
11005 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11014 auto Cur =
MBB.begin();
11015 if (Cur !=
MBB.end())
11017 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11020 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11029 if (InsPt !=
MBB.end() &&
11030 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11031 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11032 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11033 InsPt->definesRegister(Src,
nullptr)) {
11037 .
addReg(Src, {}, SrcSubReg)
11080 if (isFullCopyInstr(
MI)) {
11081 Register DstReg =
MI.getOperand(0).getReg();
11082 Register SrcReg =
MI.getOperand(1).getReg();
11104 unsigned *PredCost)
const {
11105 if (
MI.isBundle()) {
11108 unsigned Lat = 0,
Count = 0;
11109 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11111 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11113 return Lat +
Count - 1;
11116 return SchedModel.computeInstrLatency(&
MI);
11123 return *CallAddrOp;
11130 unsigned Opcode =
MI.getOpcode();
11132 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11135 :
MI.getOperand(1).getReg();
11139 unsigned SrcAS = SrcTy.getAddressSpace();
11142 ST.hasGloballyAddressableScratch()
11150 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11151 return HandleAddrSpaceCast(
MI);
11154 auto IID = GI->getIntrinsicID();
11161 case Intrinsic::amdgcn_addrspacecast_nonnull:
11162 return HandleAddrSpaceCast(
MI);
11163 case Intrinsic::amdgcn_if:
11164 case Intrinsic::amdgcn_else:
11178 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11179 Opcode == AMDGPU::G_SEXTLOAD) {
11180 if (
MI.memoperands_empty())
11184 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11185 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11193 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11194 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11195 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11201 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11204 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11212 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11213 return Formatter.get();
11221 unsigned opcode =
MI.getOpcode();
11222 if (opcode == AMDGPU::V_READLANE_B32 ||
11223 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11224 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11229 if (
MI.isInlineAsm()) {
11235 if (!RC || !RI.isSGPRClass(RC))
11240 if (isCopyInstr(
MI)) {
11244 RI.getPhysRegBaseClass(srcOp.
getReg());
11252 if (
MI.isPreISelOpcode())
11267 if (
MI.memoperands_empty())
11271 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11272 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11287 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11289 if (!
SrcOp.isReg())
11293 if (!Reg || !
SrcOp.readsReg())
11299 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11326 F,
"ds_ordered_count unsupported for this calling conv"));
11340 Register &SrcReg2, int64_t &CmpMask,
11341 int64_t &CmpValue)
const {
11342 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11345 switch (
MI.getOpcode()) {
11348 case AMDGPU::S_CMP_EQ_U32:
11349 case AMDGPU::S_CMP_EQ_I32:
11350 case AMDGPU::S_CMP_LG_U32:
11351 case AMDGPU::S_CMP_LG_I32:
11352 case AMDGPU::S_CMP_LT_U32:
11353 case AMDGPU::S_CMP_LT_I32:
11354 case AMDGPU::S_CMP_GT_U32:
11355 case AMDGPU::S_CMP_GT_I32:
11356 case AMDGPU::S_CMP_LE_U32:
11357 case AMDGPU::S_CMP_LE_I32:
11358 case AMDGPU::S_CMP_GE_U32:
11359 case AMDGPU::S_CMP_GE_I32:
11360 case AMDGPU::S_CMP_EQ_U64:
11361 case AMDGPU::S_CMP_LG_U64:
11362 SrcReg =
MI.getOperand(0).getReg();
11363 if (
MI.getOperand(1).isReg()) {
11364 if (
MI.getOperand(1).getSubReg())
11366 SrcReg2 =
MI.getOperand(1).getReg();
11368 }
else if (
MI.getOperand(1).isImm()) {
11370 CmpValue =
MI.getOperand(1).getImm();
11376 case AMDGPU::S_CMPK_EQ_U32:
11377 case AMDGPU::S_CMPK_EQ_I32:
11378 case AMDGPU::S_CMPK_LG_U32:
11379 case AMDGPU::S_CMPK_LG_I32:
11380 case AMDGPU::S_CMPK_LT_U32:
11381 case AMDGPU::S_CMPK_LT_I32:
11382 case AMDGPU::S_CMPK_GT_U32:
11383 case AMDGPU::S_CMPK_GT_I32:
11384 case AMDGPU::S_CMPK_LE_U32:
11385 case AMDGPU::S_CMPK_LE_I32:
11386 case AMDGPU::S_CMPK_GE_U32:
11387 case AMDGPU::S_CMPK_GE_I32:
11388 SrcReg =
MI.getOperand(0).getReg();
11390 CmpValue =
MI.getOperand(1).getImm();
11400 if (S->isLiveIn(AMDGPU::SCC))
11409bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11412 bool SCCIsDead =
false;
11415 constexpr unsigned ScanLimit = 12;
11416 unsigned Count = 0;
11417 for (MachineInstr &
MI :
11419 if (++
Count > ScanLimit)
11421 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11422 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11423 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11424 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11425 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11430 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11443 for (MachineInstr *
MI : InvertInstr) {
11444 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11445 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11447 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11448 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11449 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11450 ? AMDGPU::S_CBRANCH_SCC1
11451 : AMDGPU::S_CBRANCH_SCC0));
11464 bool NeedInversion)
const {
11465 MachineInstr *KillsSCC =
nullptr;
11470 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11472 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11475 if (NeedInversion && !invertSCCUse(SCCRedefine))
11477 if (MachineOperand *SccDef =
11479 SccDef->setIsDead(
false);
11487 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11488 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11490 bool Op1IsNonZeroImm =
11491 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11492 bool Op2IsZeroImm =
11493 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11494 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11500 unsigned &NewDefOpc) {
11503 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11504 Def.getOpcode() != AMDGPU::S_ADD_U32)
11510 Def.getMF()->getSubtarget().getInstrInfo());
11512 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11513 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11514 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11517 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11519 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11522 NewDefOpc = AMDGPU::S_ADD_U32;
11524 NeedInversion = !NeedInversion;
11529 Register SrcReg2, int64_t CmpMask,
11539 CmpValue = *ImmOpt;
11542 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11543 this](
bool NeedInversion) ->
bool {
11567 unsigned NewDefOpc = Def->getOpcode();
11573 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11576 if (NewDefOpc != Def->getOpcode())
11577 Def->setDesc(
get(NewDefOpc));
11586 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11593 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11601 optimizeSCC(
Select, Def,
false);
11608 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11609 this](int64_t ExpectedValue,
unsigned SrcSize,
11610 bool IsReversible,
bool IsSigned) ->
bool {
11638 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11639 Def->getOpcode() != AMDGPU::S_AND_B64)
11643 const auto isMask = [&Mask, SrcSize, MRI,
11655 SrcOp = &Def->getOperand(2);
11656 else if (isMask(&Def->getOperand(2)))
11657 SrcOp = &Def->getOperand(1);
11665 if (IsSigned && BitNo == SrcSize - 1)
11668 ExpectedValue <<= BitNo;
11670 bool IsReversedCC =
false;
11671 if (CmpValue != ExpectedValue) {
11674 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11679 Register DefReg = Def->getOperand(0).getReg();
11680 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11683 if (!optimizeSCC(Def, &CmpInstr,
false))
11686 if (!MRI->use_nodbg_empty(DefReg)) {
11694 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11695 : AMDGPU::S_BITCMP1_B32
11696 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11697 : AMDGPU::S_BITCMP1_B64;
11702 Def->eraseFromParent();
11710 case AMDGPU::S_CMP_EQ_U32:
11711 case AMDGPU::S_CMP_EQ_I32:
11712 case AMDGPU::S_CMPK_EQ_U32:
11713 case AMDGPU::S_CMPK_EQ_I32:
11714 return optimizeCmpAnd(1, 32,
true,
false) ||
11715 optimizeCmpSelect(
true);
11716 case AMDGPU::S_CMP_GE_U32:
11717 case AMDGPU::S_CMPK_GE_U32:
11718 return optimizeCmpAnd(1, 32,
false,
false);
11719 case AMDGPU::S_CMP_GE_I32:
11720 case AMDGPU::S_CMPK_GE_I32:
11721 return optimizeCmpAnd(1, 32,
false,
true);
11722 case AMDGPU::S_CMP_EQ_U64:
11723 return optimizeCmpAnd(1, 64,
true,
false);
11724 case AMDGPU::S_CMP_LG_U32:
11725 case AMDGPU::S_CMP_LG_I32:
11726 case AMDGPU::S_CMPK_LG_U32:
11727 case AMDGPU::S_CMPK_LG_I32:
11728 return optimizeCmpAnd(0, 32,
true,
false) ||
11729 optimizeCmpSelect(
false);
11730 case AMDGPU::S_CMP_GT_U32:
11731 case AMDGPU::S_CMPK_GT_U32:
11732 return optimizeCmpAnd(0, 32,
false,
false);
11733 case AMDGPU::S_CMP_GT_I32:
11734 case AMDGPU::S_CMPK_GT_I32:
11735 return optimizeCmpAnd(0, 32,
false,
true);
11736 case AMDGPU::S_CMP_LG_U64:
11737 return optimizeCmpAnd(0, 64,
true,
false) ||
11738 optimizeCmpSelect(
false);
11745 AMDGPU::OpName
OpName)
const {
11746 if (!ST.needsAlignedVGPRs())
11749 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11761 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11763 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11767 : &AMDGPU::VReg_64_Align2RegClass);
11769 .
addReg(DataReg, {},
Op.getSubReg())
11774 Op.setSubReg(AMDGPU::sub0);
11779 if (!SchedModel.hasInstrSchedModel())
11785 unsigned RepeatRate = 0;
11787 PI = SchedModel.getWriteProcResBegin(SCDesc),
11788 PE = SchedModel.getWriteProcResEnd(SCDesc);
11790 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11807 if (ST.hasGFX1250Insts())
11814 unsigned Opcode =
MI.getOpcode();
11820 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11821 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11824 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 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.
This class is the base class for the comparison instructions.
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.
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
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
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)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
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)
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.
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)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
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.
Object returned by analyzeLoopForPipelining.
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
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
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 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.